PageRenderTime 53ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/Miranda IM - CK Release/Miranda/Protocols/IcqOscarJ/src/fam_02location.cpp

http://miranda-dev.googlecode.com/
C++ | 306 lines | 195 code | 50 blank | 61 comment | 36 complexity | 2d568fcbaea3697da73f37ad77bd0dc1 MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, LGPL-3.0, AGPL-1.0, BSD-3-Clause, LGPL-2.1
  1. /*
  2. ICQ plugin for
  3. Miranda IM: the free IM client for Microsoft* Windows*
  4. Authors
  5. Copyright Š 2001-2004 Richard Hughes
  6. Copyright Š 2002-2004 Martin Öberg, Sam Kothari, Robert Rainwater
  7. Copyright Š 2004-2010 Joe Kucera, Bio
  8. Copyright Š 2010-2012 Borkra, Georg Hazan
  9. Copyright 2000-2012 Miranda IM project,
  10. all portions of this codebase are copyrighted to the people
  11. listed in contributors.txt.
  12. This program is free software; you can redistribute it and/or
  13. modify it under the terms of the GNU General Public License
  14. as published by the Free Software Foundation; either version 2
  15. of the License, or (at your option) any later version.
  16. This program is distributed in the hope that it will be useful,
  17. but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. GNU General Public License for more details.
  20. You should have received a copy of the GNU General Public License
  21. along with this program; if not, write to the Free Software
  22. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. ===============================================================================
  24. File name : $HeadURL:
  25. Revision : $Revision:
  26. Last change on : $Date:
  27. Last change by : $Author:
  28. $Id$ : $Id$:
  29. ===============================================================================
  30. * Handles packets from Service family
  31. */
  32. #include "icqoscar.h"
  33. extern const char* cliSpamBot;
  34. void CIcqProto::handleLocationFam(BYTE *pBuffer, WORD wBufferLength, snac_header *pSnacHeader)
  35. {
  36. switch (pSnacHeader->wSubtype) {
  37. case ICQ_LOCATION_RIGHTS_REPLY: // Reply to CLI_REQLOCATION
  38. NetLog_Server("Server sent SNAC(x02,x03) - SRV_LOCATION_RIGHTS_REPLY");
  39. break;
  40. case ICQ_LOCATION_USR_INFO_REPLY: // AIM user info reply
  41. handleLocationUserInfoReply(pBuffer, wBufferLength, pSnacHeader->dwRef);
  42. break;
  43. case ICQ_ERROR:
  44. {
  45. WORD wError;
  46. HANDLE hCookieContact;
  47. cookie_fam15_data *pCookieData;
  48. if (wBufferLength >= 2)
  49. unpackWord(&pBuffer, &wError);
  50. else
  51. wError = 0;
  52. if (wError == 4)
  53. {
  54. if (FindCookie(pSnacHeader->dwRef, &hCookieContact, (void**)&pCookieData) && !getContactUin(hCookieContact) && pCookieData->bRequestType == REQUESTTYPE_PROFILE)
  55. {
  56. BroadcastAck(hCookieContact, ACKTYPE_GETINFO, ACKRESULT_FAILED, (HANDLE)1 ,0);
  57. ReleaseCookie(pSnacHeader->dwRef);
  58. }
  59. }
  60. LogFamilyError(ICQ_LOCATION_FAMILY, wError);
  61. break;
  62. }
  63. default:
  64. NetLog_Server("Warning: Ignoring SNAC(x%02x,x%02x) - Unknown SNAC (Flags: %u, Ref: %u)", ICQ_LOCATION_FAMILY, pSnacHeader->wSubtype, pSnacHeader->wFlags, pSnacHeader->dwRef);
  65. break;
  66. }
  67. }
  68. static char* AimApplyEncoding(char* pszStr, const char* pszEncoding)
  69. { // decode encoding to ANSI only
  70. if (pszStr && pszEncoding)
  71. {
  72. const char *szEnc = strstrnull(pszEncoding, "charset=");
  73. if (szEnc)
  74. { // decode custom encoding to Utf-8
  75. char *szStr = ApplyEncoding(pszStr, szEnc + 9);
  76. // decode utf-8 to ansi
  77. char *szRes = NULL;
  78. SAFE_FREE((void**)&pszStr);
  79. utf8_decode(szStr, &szRes);
  80. SAFE_FREE((void**)&szStr);
  81. return szRes;
  82. }
  83. }
  84. return pszStr;
  85. }
  86. void CIcqProto::handleLocationUserInfoReply(BYTE* buf, WORD wLen, DWORD dwCookie)
  87. {
  88. HANDLE hContact;
  89. DWORD dwUIN;
  90. uid_str szUID;
  91. WORD wTLVCount;
  92. WORD wWarningLevel;
  93. HANDLE hCookieContact;
  94. WORD status;
  95. cookie_message_data *pCookieData;
  96. // Unpack the sender's user ID
  97. if (!unpackUID(&buf, &wLen, &dwUIN, &szUID)) return;
  98. // Syntax check
  99. if (wLen < 4)
  100. return;
  101. // Warning level?
  102. unpackWord(&buf, &wWarningLevel);
  103. wLen -= 2;
  104. // TLV count
  105. unpackWord(&buf, &wTLVCount);
  106. wLen -= 2;
  107. // Determine contact
  108. hContact = HContactFromUID(dwUIN, szUID, NULL);
  109. // Ignore away status if the user is not already on our list
  110. if (hContact == INVALID_HANDLE_VALUE)
  111. {
  112. #ifdef _DEBUG
  113. NetLog_Server("Ignoring away reply (%s)", strUID(dwUIN, szUID));
  114. #endif
  115. return;
  116. }
  117. if (!FindCookie(dwCookie, &hCookieContact, (void**)&pCookieData))
  118. {
  119. NetLog_Server("Error: Received unexpected away reply from %s", strUID(dwUIN, szUID));
  120. return;
  121. }
  122. if (hContact != hCookieContact)
  123. {
  124. NetLog_Server("Error: Away reply Contact does not match Cookie Contact(0x%x != 0x%x)", hContact, hCookieContact);
  125. ReleaseCookie(dwCookie); // This could be a bad idea, but I think it is safe
  126. return;
  127. }
  128. switch (GetCookieType(dwCookie))
  129. {
  130. case CKT_FAMILYSPECIAL:
  131. {
  132. ReleaseCookie(dwCookie);
  133. // Read user info TLVs
  134. {
  135. oscar_tlv_chain* pChain;
  136. BYTE *tmp;
  137. char *szMsg = NULL;
  138. // Syntax check
  139. if (wLen < 4)
  140. return;
  141. tmp = buf;
  142. // Get general chain
  143. if (!(pChain = readIntoTLVChain(&buf, wLen, wTLVCount)))
  144. return;
  145. disposeChain(&pChain);
  146. wLen -= (buf - tmp);
  147. // Get extra chain
  148. if (pChain = readIntoTLVChain(&buf, wLen, 2))
  149. {
  150. oscar_tlv *pTLV;
  151. char *szEncoding = NULL;
  152. // Get Profile encoding TLV
  153. pTLV = pChain->getTLV(0x01, 1);
  154. if (pTLV && (pTLV->wLen >= 1))
  155. {
  156. szEncoding = (char*)_malloca(pTLV->wLen + 1);
  157. memcpy(szEncoding, pTLV->pData, pTLV->wLen);
  158. szEncoding[pTLV->wLen] = '\0';
  159. }
  160. // Get Profile info TLV
  161. pTLV = pChain->getTLV(0x02, 1);
  162. if (pTLV && (pTLV->wLen >= 1))
  163. {
  164. szMsg = (char*)SAFE_MALLOC(pTLV->wLen + 2);
  165. memcpy(szMsg, pTLV->pData, pTLV->wLen);
  166. szMsg[pTLV->wLen] = '\0';
  167. szMsg[pTLV->wLen + 1] = '\0';
  168. szMsg = AimApplyEncoding(szMsg, szEncoding);
  169. szMsg = EliminateHtml(szMsg, pTLV->wLen);
  170. }
  171. // Free TLV chain
  172. disposeChain(&pChain);
  173. }
  174. setSettingString(hContact, "About", szMsg);
  175. BroadcastAck(hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE)1 ,0);
  176. SAFE_FREE((void**)&szMsg);
  177. }
  178. break;
  179. }
  180. default: // away message
  181. {
  182. status = AwayMsgTypeToStatus(pCookieData->nAckType);
  183. if (status == ID_STATUS_OFFLINE)
  184. {
  185. NetLog_Server("SNAC(2.6) Ignoring unknown status message from %s", strUID(dwUIN, szUID));
  186. ReleaseCookie(dwCookie);
  187. return;
  188. }
  189. ReleaseCookie(dwCookie);
  190. // Read user info TLVs
  191. {
  192. oscar_tlv_chain* pChain;
  193. oscar_tlv* pTLV;
  194. BYTE *tmp;
  195. char *szMsg = NULL;
  196. CCSDATA ccs;
  197. PROTORECVEVENT pre;
  198. // Syntax check
  199. if (wLen < 4)
  200. return;
  201. tmp = buf;
  202. // Get general chain
  203. if (!(pChain = readIntoTLVChain(&buf, wLen, wTLVCount)))
  204. return;
  205. disposeChain(&pChain);
  206. wLen -= (buf - tmp);
  207. // Get extra chain
  208. if (pChain = readIntoTLVChain(&buf, wLen, 2))
  209. {
  210. char* szEncoding = NULL;
  211. // Get Away encoding TLV
  212. pTLV = pChain->getTLV(0x03, 1);
  213. if (pTLV && (pTLV->wLen >= 1))
  214. {
  215. szEncoding = (char*)_malloca(pTLV->wLen + 1);
  216. memcpy(szEncoding, pTLV->pData, pTLV->wLen);
  217. szEncoding[pTLV->wLen] = '\0';
  218. }
  219. // Get Away info TLV
  220. pTLV = pChain->getTLV(0x04, 1);
  221. if (pTLV && (pTLV->wLen >= 1))
  222. {
  223. szMsg = (char*)SAFE_MALLOC(pTLV->wLen + 2);
  224. memcpy(szMsg, pTLV->pData, pTLV->wLen);
  225. szMsg[pTLV->wLen] = '\0';
  226. szMsg[pTLV->wLen + 1] = '\0';
  227. szMsg = AimApplyEncoding(szMsg, szEncoding);
  228. szMsg = EliminateHtml(szMsg, pTLV->wLen);
  229. }
  230. // Free TLV chain
  231. disposeChain(&pChain);
  232. }
  233. ccs.szProtoService = PSR_AWAYMSG;
  234. ccs.hContact = hContact;
  235. ccs.wParam = status;
  236. ccs.lParam = (LPARAM)&pre;
  237. pre.flags = 0;
  238. pre.szMessage = szMsg?szMsg:(char *)"";
  239. pre.timestamp = time(NULL);
  240. pre.lParam = dwCookie;
  241. CallService(MS_PROTO_CHAINRECV,0,(LPARAM)&ccs);
  242. SAFE_FREE((void**)&szMsg);
  243. }
  244. break;
  245. }
  246. }
  247. }