void MSN_MakeDigest(const char* chl, char* dgst) { //Digest it DWORD md5hash[4], md5hashOr[4]; mir_md5_state_t context; mir_md5_init(&context); mir_md5_append(&context, (BYTE*)chl, (int)strlen(chl)); mir_md5_append(&context, (BYTE*)msnProtChallenge, (int)strlen(msnProtChallenge)); mir_md5_finish(&context, (BYTE*)md5hash); memcpy(md5hashOr, md5hash, sizeof(md5hash)); size_t i; for (i=0; i < 4; i++) md5hash[i] &= 0x7FFFFFFF; char chlString[128]; mir_snprintf(chlString, sizeof(chlString), "%s%s00000000", chl, msnProductID); chlString[(strlen(chl)+strlen(msnProductID)+7) & 0xF8] = 0; LONGLONG high=0, low=0; int* chlStringArray = (int*)chlString; for (i=0; i < strlen(chlString) / 4; i += 2) { LONGLONG temp = chlStringArray[i]; temp = (0x0E79A9C1 * temp) % 0x7FFFFFFF; temp += high; temp = md5hash[0] * temp + md5hash[1]; temp = temp % 0x7FFFFFFF; high = chlStringArray[i + 1]; high = (high + temp) % 0x7FFFFFFF; high = md5hash[2] * high + md5hash[3]; high = high % 0x7FFFFFFF; low = low + high + temp; } high = (high + md5hash[1]) % 0x7FFFFFFF; low = (low + md5hash[3]) % 0x7FFFFFFF; md5hashOr[0] ^= high; md5hashOr[1] ^= low; md5hashOr[2] ^= high; md5hashOr[3] ^= low; char* str = arrayToHex((PBYTE)md5hashOr, sizeof(md5hashOr)); strcpy(dgst, str); mir_free(str); }
char* MSN_GetAvatarHash(char* szContext, char** pszUrl) { if (pszUrl) *pszUrl = NULL; if (szContext == NULL) return NULL; char *res = NULL; ezxml_t xmli = ezxml_parse_str(NEWSTR_ALLOCA(szContext), strlen(szContext)); const char *szAvatarHash = ezxml_attr(xmli, "SHA1D"); if (szAvatarHash != NULL) { unsigned hashLen; mir_ptr<BYTE> hash((BYTE*)mir_base64_decode(szAvatarHash, &hashLen)); if (hash) res = arrayToHex(hash, hashLen); if (pszUrl) { const char *pszUrlAttr; for (int i=0; ; i++) { char szSetting[20]; if (i == 0) strcpy(szSetting, "Url"); else mir_snprintf(szSetting, sizeof(szSetting), "Url%d", i); pszUrlAttr = ezxml_attr(xmli, szSetting); if (pszUrlAttr == NULL) break; if (pszUrlAttr[0] != 0) { *pszUrl = mir_strdup(pszUrlAttr); break; } } } } ezxml_free(xmli); return res; }
/** Checks for availability of a valid response packet. * * This function should always be called and return true prior to using results * of a command. * * @returns true if a valid response packet is available */ boolean SM130::available() { // If in SEEK mode and using DREADY pin, check the status if (cmd == CMD_SEEK_TAG && pinDREADY != 0xff) { if (!digitalRead(pinDREADY)) return false; } // Set the maximum length of the expected response packet byte len; switch(cmd) { case CMD_ANTENNA_POWER: case CMD_AUTHENTICATE: case CMD_DEC_VALUE: case CMD_INC_VALUE: case CMD_WRITE_KEY: case CMD_HALT_TAG: case CMD_SLEEP: len = 4; break; case CMD_WRITE4: case CMD_WRITE_VALUE: case CMD_READ_VALUE: len = 8; case CMD_SEEK_TAG: case CMD_SELECT_TAG: len = 11; break; default: len = SIZE_PACKET; } // If valid data received, process the response packet if (receiveData(len) > 0) { // Init response variables tagType = tagLength = *tagString = 0; // If packet length is 2, the command failed. Set error code. errorCode = getPacketLength() < 3 ? data[2] : 0; // Process command response switch (getCommand()) { case CMD_RESET: case CMD_VERSION: // RESET and VERSION commands produce the firmware version len = min(getPacketLength(), sizeof(versionString)) - 1; memcpy(versionString, data + 2, len); versionString[len] = 0; break; case CMD_SEEK_TAG: case CMD_SELECT_TAG: // If no error, get tag number if(errorCode == 0 && getPacketLength() >= 6) { tagLength = getPacketLength() - 2; tagType = data[2]; memcpy(tagNumber, data + 3, tagLength); arrayToHex(tagString, tagNumber, tagLength); } break; case CMD_AUTHENTICATE: break; case CMD_READ16: break; case CMD_WRITE16: case CMD_WRITE4: break; case CMD_ANTENNA_POWER: errorCode = 0; antennaPower = data[2]; break; case CMD_SLEEP: // If in SLEEP mode, no data is available return false; } // Data available return true; } // No data available return false; }
/** Checks for availability of a valid response packet. * * This function should always be called and return true prior to using results * of a command. * * @returns true if a valid response packet is available */ boolean SL018::available() { // Set the maximum length of the expected response packet byte len; switch(cmd) { case CMD_IDLE: case CMD_RESET: len = 0; break; case CMD_LOGIN: case CMD_SET_LED: case CMD_SLEEP: len = 3; break; case CMD_READ4: case CMD_WRITE4: case CMD_READ_VALUE: case CMD_WRITE_VALUE: case CMD_DEC_VALUE: case CMD_INC_VALUE: case CMD_COPY_VALUE: len = 7; break; case CMD_WRITE_KEY: len = 9; break; case CMD_SEEK: case CMD_SELECT: len = 11; break; default: len = SIZE_PACKET; } // If valid data received, process the response packet if (len && receiveData(len) > 0) { // Init response variables tagType = tagLength = *tagString = 0; errorCode = data[2]; // Process command response switch (getCommand()) { case CMD_SEEK: case CMD_SELECT: // If no error, get tag number if(errorCode == 0 && getPacketLength() >= 7) { tagLength = getPacketLength() - 3; tagType = data[getPacketLength()]; memcpy(tagNumber, data + 3, tagLength); arrayToHex(tagString, tagNumber, tagLength); } else if(cmd == CMD_SEEK) { // Continue seek seekTag(); return false; } } // Data is available return true; } // No data available return false; }
int CMsnProto::MSN_SetMyAvatar(const TCHAR* sztFname, void* pData, size_t cbLen) { mir_sha1_ctx sha1ctx; BYTE sha1c[MIR_SHA1_HASH_SIZE], sha1d[MIR_SHA1_HASH_SIZE]; char *szFname = mir_utf8encodeT(sztFname); mir_sha1_init(&sha1ctx); mir_sha1_append(&sha1ctx, (BYTE*)pData, (int)cbLen); mir_sha1_finish(&sha1ctx, sha1d); ptrA szSha1d( mir_base64_encode((PBYTE)sha1d, sizeof(sha1d))); mir_sha1_init(&sha1ctx); ezxml_t xmlp = ezxml_new("msnobj"); mir_sha1_append(&sha1ctx, (PBYTE)"Creator", 7); mir_sha1_append(&sha1ctx, (PBYTE)MyOptions.szEmail, (int)strlen(MyOptions.szEmail)); ezxml_set_attr(xmlp, "Creator", MyOptions.szEmail); char szFileSize[20]; _ultoa((unsigned)cbLen, szFileSize, 10); mir_sha1_append(&sha1ctx, (PBYTE)"Size", 4); mir_sha1_append(&sha1ctx, (PBYTE)szFileSize, (int)strlen(szFileSize)); ezxml_set_attr(xmlp, "Size", szFileSize); mir_sha1_append(&sha1ctx, (PBYTE)"Type", 4); mir_sha1_append(&sha1ctx, (PBYTE)"3", 1); // MSN_TYPEID_DISPLAYPICT ezxml_set_attr(xmlp, "Type", "3"); mir_sha1_append(&sha1ctx, (PBYTE)"Location", 8); mir_sha1_append(&sha1ctx, (PBYTE)szFname, (int)strlen(szFname)); ezxml_set_attr(xmlp, "Location", szFname); mir_sha1_append(&sha1ctx, (PBYTE)"Friendly", 8); mir_sha1_append(&sha1ctx, (PBYTE)"AAA=", 4); ezxml_set_attr(xmlp, "Friendly", "AAA="); mir_sha1_append(&sha1ctx, (PBYTE)"SHA1D", 5); mir_sha1_append(&sha1ctx, (PBYTE)(char*)szSha1d, (int)strlen(szSha1d)); ezxml_set_attr(xmlp, "SHA1D", szSha1d); mir_sha1_finish(&sha1ctx, sha1c); ptrA szSha1c( mir_base64_encode((PBYTE)sha1c, sizeof(sha1c))); // ezxml_set_attr(xmlp, "SHA1C", szSha1c); char* szBuffer = ezxml_toxml(xmlp, false); ezxml_free(xmlp); mir_free(szFname); ptrA szEncodedBuffer(mir_urlEncode(szBuffer)); free(szBuffer); const TCHAR *szExt; int fmt = ProtoGetBufferFormat(pData, &szExt); if (fmt == PA_FORMAT_UNKNOWN) return fmt; TCHAR szFileName[MAX_PATH]; MSN_GetAvatarFileName(NULL, szFileName, SIZEOF(szFileName), NULL); _tremove(szFileName); MSN_GetAvatarFileName(NULL, szFileName, SIZEOF(szFileName), szExt); int fileId = _topen(szFileName, _O_CREAT | _O_TRUNC | _O_WRONLY | O_BINARY, _S_IREAD | _S_IWRITE); if (fileId >= 0) { _write(fileId, pData, (unsigned)cbLen); _close(fileId); char szAvatarHashdOld[41] = ""; db_get_static(NULL, m_szModuleName, "AvatarHash", szAvatarHashdOld, sizeof(szAvatarHashdOld)); char *szAvatarHash = arrayToHex(sha1d, sizeof(sha1d)); if (strcmp(szAvatarHashdOld, szAvatarHash)) { setString("PictObject", szEncodedBuffer); setString("AvatarHash", szAvatarHash); } mir_free(szAvatarHash); } else MSN_ShowError("Cannot set avatar. File '%s' could not be created/overwritten", szFileName); return fmt; }