diff options
Diffstat (limited to 'icqj_mod/tlv.c')
-rw-r--r-- | icqj_mod/tlv.c | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/icqj_mod/tlv.c b/icqj_mod/tlv.c new file mode 100644 index 0000000..98d6c27 --- /dev/null +++ b/icqj_mod/tlv.c @@ -0,0 +1,222 @@ +// ---------------------------------------------------------------------------80
+// ICQ plugin for Miranda Instant Messenger
+// ________________________________________
+//
+// Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
+// Copyright © 2001,2002 Jon Keating, Richard Hughes
+// Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater
+// Copyright © 2004,2005,2006 Joe Kucera
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// -----------------------------------------------------------------------------
+//
+// File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/tlv.c,v $
+// Revision : $Revision: 2874 $
+// Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $
+// Last change by : $Author: ghazan $
+//
+// DESCRIPTION:
+//
+// Helper functions for Oscar TLV chains
+//
+// -----------------------------------------------------------------------------
+
+#include "icqoscar.h"
+
+
+
+/* set maxTlvs<=0 to get all TLVs in length, or a positive integer to get at most the first n */
+oscar_tlv_chain* readIntoTLVChain(BYTE **buf, WORD wLen, int maxTlvs)
+{
+ oscar_tlv_chain *now, *last, *chain = NULL;
+ WORD now_tlv_len;
+ int len = wLen;
+
+ if (!buf || !wLen) return NULL;
+
+ while (len > 0) /* don't use unsigned variable for this check */
+ {
+ now = (oscar_tlv_chain *)SAFE_MALLOC(sizeof(oscar_tlv_chain));
+
+ if (!now)
+ {
+ disposeChain(&chain);
+ return NULL;
+ }
+
+ unpackWord(buf, &(now->tlv.wType));
+ unpackWord(buf, &now_tlv_len);
+ now->tlv.wLen = now_tlv_len;
+ len -= 4;
+
+ if (now_tlv_len < 1)
+ {
+ now->tlv.pData = NULL;
+ }
+ else if (now_tlv_len <= len)
+ {
+ now->tlv.pData = (BYTE *)SAFE_MALLOC(now_tlv_len);
+ if (now->tlv.pData)
+ memcpy(now->tlv.pData, *buf, now_tlv_len);
+ }
+ else
+ { // the packet is shorter than it should be
+ SAFE_FREE(&now);
+ return chain; // give at least the rest of chain
+ }
+
+ if (chain) // keep the original order
+ last->next = now;
+ else
+ chain = now;
+
+ last = now;
+
+ len -= now_tlv_len;
+ *buf += now_tlv_len;
+
+ if (--maxTlvs == 0)
+ break;
+ }
+
+ return chain;
+}
+
+// Returns a pointer to the TLV with type wType and number wIndex in the chain
+// If wIndex = 1, the first matching TLV will be returned, if wIndex = 2,
+// the second matching one will be returned.
+// wIndex must be > 0
+oscar_tlv* getTLV(oscar_tlv_chain *list, WORD wType, WORD wIndex)
+{
+ int i = 0;
+
+ while (list)
+ {
+ if (list->tlv.wType == wType)
+ i++;
+ if (i >= wIndex)
+ return &list->tlv;
+ list = list->next;
+ }
+
+ return NULL;
+}
+
+WORD getLenFromChain(oscar_tlv_chain *list, WORD wType, WORD wIndex)
+{
+ oscar_tlv *tlv;
+ WORD wLen = 0;
+
+ tlv = getTLV(list, wType, wIndex);
+ if (tlv)
+ {
+ wLen = tlv->wLen;
+ }
+
+ return wLen;
+}
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+/* Values are returned in MSB format */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+DWORD getDWordFromChain(oscar_tlv_chain *list, WORD wType, WORD wIndex)
+{
+ oscar_tlv *tlv;
+ DWORD dw = 0;
+
+ tlv = getTLV(list, wType, wIndex);
+ if (tlv && tlv->wLen >= 4)
+ {
+ dw |= (*((tlv->pData)+0) << 24);
+ dw |= (*((tlv->pData)+1) << 16);
+ dw |= (*((tlv->pData)+2) << 8);
+ dw |= (*((tlv->pData)+3));
+ }
+
+ return dw;
+}
+
+WORD getWordFromChain(oscar_tlv_chain *list, WORD wType, WORD wIndex)
+{
+ oscar_tlv *tlv;
+ WORD w = 0;
+
+ tlv = getTLV(list, wType, wIndex);
+ if (tlv && tlv->wLen >= 2)
+ {
+ w |= (*((tlv->pData)+0) << 8);
+ w |= (*((tlv->pData)+1));
+ }
+
+ return w;
+}
+
+BYTE getByteFromChain(oscar_tlv_chain *list, WORD wType, WORD wIndex)
+{
+ oscar_tlv *tlv;
+ BYTE b = 0;
+
+ tlv = getTLV(list, wType, wIndex);
+ if (tlv && tlv->wLen)
+ {
+ b = *(tlv->pData);
+ }
+
+ return b;
+}
+
+BYTE* getStrFromChain(oscar_tlv_chain *list, WORD wType, WORD wIndex)
+{
+ oscar_tlv *tlv;
+ BYTE *str = NULL;
+
+ tlv = getTLV(list, wType, wIndex);
+ if (tlv)
+ {
+ str = (BYTE*)SAFE_MALLOC(tlv->wLen+1); /* For \0 */
+
+ if (!str) return NULL;
+
+ memcpy(str, tlv->pData, tlv->wLen);
+ *(str+tlv->wLen) = '\0';
+ }
+
+ return str;
+}
+
+void disposeChain(oscar_tlv_chain **list)
+{
+ oscar_tlv_chain *now;
+
+ if (!list || !*list)
+ return;
+
+ now = *list;
+
+ while (now)
+ {
+ oscar_tlv_chain *temp;
+
+ SAFE_FREE(&now->tlv.pData);
+
+ temp = now->next;
+ SAFE_FREE(&now);
+ now = temp;
+ }
+
+ *list = NULL;
+}
|