Пример #1
0
static int
do_vals2text(
	LDAP			*ld,
	char			*buf,		/* NULL for "use internal" */
	char			**vals,
	char			*label,
	int			labelwidth,	/* 0 means use default */
	unsigned int		syntaxid,
	writeptype		writeproc,
	void			*writeparm,
	char			*eol,
	int			rdncount,
	char			*urlprefix
)
{
    int		i, html, writeoutval, freebuf, notascii;
    char	*p, *s, *outval;


    if ( vals == NULL ) {
	return( LDAP_SUCCESS );
    }

    html = ( urlprefix != NULL );

    switch( LDAP_GET_SYN_TYPE( syntaxid )) {
    case LDAP_SYN_TYPE_TEXT:
    case LDAP_SYN_TYPE_BOOLEAN:
	break;		/* we only bother with these two types... */
    default:
	return( LDAP_SUCCESS );
    }

    if ( labelwidth == 0 || labelwidth < 0 ) {
	labelwidth = DEF_LABEL_WIDTH;
    }

    if ( buf == NULL ) {
	if (( buf = malloc( LDAP_DTMPL_BUFSIZ )) == NULL ) {
	    ld->ld_errno = LDAP_NO_MEMORY;
	    return( ld->ld_errno );
	}
	freebuf = 1;
    } else {
	freebuf = 0;
    }

    output_label( buf, label, labelwidth, writeproc, writeparm, eol, html );

    for ( i = 0; vals[ i ] != NULL; ++i ) {
	for ( p = vals[ i ]; *p != '\0'; ++p ) {
	    if ( !isascii( *p )) {
		break;
	    }
	}
	notascii = ( *p != '\0' );
	outval = notascii ? "(unable to display non-ASCII text value)"
		: vals[ i ];

	writeoutval = 0;	/* if non-zero, write outval after switch */

	switch( syntaxid ) {
	case LDAP_SYN_CASEIGNORESTR:
	    ++writeoutval;
	    break;

	case LDAP_SYN_RFC822ADDR:
	    if ( html ) {
		strcpy( buf, "<DD><A HREF=\"mailto:" );
		strcat_escaped( buf, outval );
		sprintf( buf + strlen( buf ), "\">%s</A><BR>%s", outval, eol );
		(*writeproc)( writeparm, buf, strlen( buf ));
	    } else {
		++writeoutval;
	    }
	    break;

	case LDAP_SYN_DN:	/* for now */
	    output_dn( buf, outval, labelwidth, rdncount, writeproc,
		    writeparm, eol, urlprefix );
	    break;

	case LDAP_SYN_MULTILINESTR:
	    if ( i > 0 && !html ) {
		output_label( buf, label, labelwidth, writeproc,
			writeparm, eol, html );
	    }

	    p = s = outval;
	    while (( s = strchr( s, '$' )) != NULL ) {
		*s++ = '\0';
		while ( isspace( *s )) {
		    ++s;
		}
		if ( html ) {
		    sprintf( buf, "<DD>%s<BR>%s", p, eol );
		} else {
		    sprintf( buf, "%-*s%s%s", labelwidth, " ", p, eol );
		}
		(*writeproc)( writeparm, buf, strlen( buf ));
		p = s;
	    }
	    outval = p;
	    ++writeoutval;
	    break;

	case LDAP_SYN_BOOLEAN:
	    outval = toupper( outval[ 0 ] ) == 'T' ? "TRUE" : "FALSE";
	    ++writeoutval;
	    break;

	case LDAP_SYN_TIME:
	case LDAP_SYN_DATE:
	    outval = time2text( outval, syntaxid == LDAP_SYN_DATE );
	    ++writeoutval;
	    break;

	case LDAP_SYN_LABELEDURL:
	    if ( !notascii && ( p = strchr( outval, '$' )) != NULL ) {
		*p++ = '\0';
		while ( isspace( *p )) {
		    ++p;
		}
		s = outval;
	    } else if ( !notascii && ( s = strchr( outval, ' ' )) != NULL ) {
		*s++ = '\0';
		while ( isspace( *s )) {
		    ++s;
		}
		p = outval;
	    } else {
		s = "URL";
		p = outval;
	    }

	    /*
	     * at this point `s' points to the label & `p' to the URL
	     */
	    if ( html ) {
		sprintf( buf, "<DD><A HREF=\"%s\">%s</A><BR>%s", p, s, eol );
	    } else {
		sprintf( buf, "%-*s%s%s%-*s%s%s", labelwidth, " ",
		    s, eol, labelwidth + 2, " ",p , eol );
	    }
	    (*writeproc)( writeparm, buf, strlen( buf ));
	    break;

	default:
	    sprintf( buf, " Can't display item type %ld%s",
		    syntaxid, eol );
	    (*writeproc)( writeparm, buf, strlen( buf ));
	}

	if ( writeoutval ) {
	    if ( html ) {
		sprintf( buf, "<DD>%s<BR>%s", outval, eol );
	    } else {
		sprintf( buf, "%-*s%s%s", labelwidth, " ", outval, eol );
	    }
	    (*writeproc)( writeparm, buf, strlen( buf ));
	}
    }

    if ( freebuf ) {
	free( buf );
    }

    return( LDAP_SUCCESS );
}
Пример #2
0
void CIcqProto::handleUserOnline(BYTE *buf, size_t wLen, serverthread_info*)
{
	DWORD dwPort = 0;
	DWORD dwRealIP = 0;
	DWORD dwUIN;
	uid_str szUID;
	DWORD dwDirectConnCookie = 0;
	DWORD dwWebPort = 0;
	DWORD dwFT1 = 0, dwFT2 = 0, dwFT3 = 0;
	const char *szClient = NULL;
	BYTE bClientId = 0;
	WORD wVersion = 0;
	WORD wTLVCount;
	WORD wWarningLevel;
	WORD wStatusFlags;
	WORD wStatus = 0, wOldStatus = 0;
	BYTE nTCPFlag = 0;
	char szStrBuf[MAX_PATH];

	// Unpack the sender's user ID
	if (!unpackUID(&buf, &wLen, &dwUIN, &szUID))
		return;

	// Syntax check
	if (wLen < 4)
		return;

	// Warning level?
	unpackWord(&buf, &wWarningLevel);
	wLen -= 2;

	// TLV count
	unpackWord(&buf, &wTLVCount);
	wLen -= 2;

	// Ignore status notification if the user is not already on our list
	MCONTACT hContact = HContactFromUID(dwUIN, szUID, NULL);
	if (hContact == INVALID_CONTACT_ID) {
		debugLogA("Ignoring user online (%s)", strUID(dwUIN, szUID));
		return;
	}

	// Read user info TLVs
	oscar_tlv_chain *pChain;
	oscar_tlv *pTLV;

	// Syntax check
	if (wLen < 4)
		return;

	// Get chain
	if (!(pChain = readIntoTLVChain(&buf, wLen, wTLVCount)))
		return;

	// Get Class word
	WORD wClass = pChain->getWord(0x01, 1);
	int nIsICQ = wClass & CLASS_ICQ;

	if (dwUIN) {
		// Get DC info TLV
		pTLV = pChain->getTLV(0x0C, 1);
		if (pTLV && (pTLV->wLen >= 15)) {
			BYTE *pBuffer = pTLV->pData;

			nIsICQ = TRUE;

			unpackDWord(&pBuffer, &dwRealIP);
			unpackDWord(&pBuffer, &dwPort);
			unpackByte(&pBuffer,  &nTCPFlag);
			unpackWord(&pBuffer,  &wVersion);
			unpackDWord(&pBuffer, &dwDirectConnCookie);
			unpackDWord(&pBuffer, &dwWebPort); // Web front port
			pBuffer += 4; // Client features

			// Get faked time signatures, used to identify clients
			if (pTLV->wLen >= 0x23) {
				unpackDWord(&pBuffer, &dwFT1);
				unpackDWord(&pBuffer, &dwFT2);
				unpackDWord(&pBuffer, &dwFT3);
			}
		}

		// Get Status info TLV
		pTLV = pChain->getTLV(0x06, 1);
		if (pTLV && (pTLV->wLen >= 4)) {
			BYTE *pBuffer = pTLV->pData;
			unpackWord(&pBuffer, &wStatusFlags);
			unpackWord(&pBuffer, &wStatus);
		}
		else if (!nIsICQ) {
			// Connected thru AIM client, guess by user class
			if (wClass & CLASS_AWAY)
				wStatus = ID_STATUS_AWAY;
			else if (wClass & CLASS_WIRELESS)
				wStatus = ID_STATUS_ONTHEPHONE;
			else
				wStatus = ID_STATUS_ONLINE;

			wStatusFlags = 0;
		}
		else {
			// Huh? No status TLV? Lets guess then...
			wStatusFlags = 0;
			wStatus = ICQ_STATUS_ONLINE;
		}
	}
	else {
		nIsICQ = FALSE;

		if (wClass & CLASS_AWAY)
			wStatus = ID_STATUS_AWAY;
		else if (wClass & CLASS_WIRELESS)
			wStatus = ID_STATUS_ONTHEPHONE;
		else
			wStatus = ID_STATUS_ONLINE;

		wStatusFlags = 0;
	}

	debugLogA("Flags are %x", wStatusFlags);
	debugLogA("Status is %x", wStatus);

	// Get IP TLV
	DWORD dwIP = pChain->getDWord(0x0A, 1);

	// Get Online Since TLV
	DWORD dwOnlineSince = pChain->getDWord(0x03, 1);

	// Get Away Since TLV
	DWORD dwAwaySince = pChain->getDWord(0x29, 1);

	// Get Member Since TLV
	DWORD dwMemberSince = pChain->getDWord(0x05, 1);

	// Get Idle timer TLV
	WORD wIdleTimer = pChain->getWord(0x04, 1);
	time_t tIdleTS = 0;
	if (wIdleTimer) {
		time(&tIdleTS);
		tIdleTS -= (wIdleTimer*60);
	}

	if (wIdleTimer)
		debugLogA("Idle timer is %u.", wIdleTimer);
	debugLogA("Online since %s", time2text(dwOnlineSince));
	if (dwAwaySince)
		debugLogA("Status was set on %s", time2text(dwAwaySince));

	// Check client capabilities
	if (hContact != NULL) {
		wOldStatus = getContactStatus(hContact);

		// Collect all Capability info from TLV chain
		BYTE *capBuf = NULL;
		WORD capLen = 0;

		// Get Location Capability Info TLVs
		oscar_tlv *pFullTLV = pChain->getTLV(0x0D, 1);
		oscar_tlv *pShortTLV = pChain->getTLV(0x19, 1);

		if (pFullTLV && (pFullTLV->wLen >= BINARY_CAP_SIZE))
			capLen += pFullTLV->wLen;

		if (pShortTLV && (pShortTLV->wLen >= 2))
			capLen += (pShortTLV->wLen * 8);

		capBuf = (BYTE*)_alloca(capLen + BINARY_CAP_SIZE);

		if (capLen) {
			BYTE *pCapability = capBuf;

			capLen = 0; // we need to recount that

			if (pFullTLV && (pFullTLV->wLen >= BINARY_CAP_SIZE)) {
				// copy classic Capabilities
				BYTE *cData = pFullTLV->pData;
				int cLen = pFullTLV->wLen;

				while (cLen) {
					// be impervious to duplicates (AOL sends them sometimes)
					if (!capLen || !MatchCapability(capBuf, capLen, (capstr*)cData, BINARY_CAP_SIZE)) {
						// not present, add
						memcpy(pCapability, cData, BINARY_CAP_SIZE);
						capLen += BINARY_CAP_SIZE;
						pCapability += BINARY_CAP_SIZE;
					}
					cData += BINARY_CAP_SIZE;
					cLen -= BINARY_CAP_SIZE;
				}
			}

			if (pShortTLV && (pShortTLV->wLen >= 2)) {
				// copy short Capabilities
				capstr tmp;
				BYTE *cData = pShortTLV->pData;
				int cLen = pShortTLV->wLen;

				memcpy(tmp, capShortCaps, BINARY_CAP_SIZE);
				while (cLen) {
					// be impervious to duplicates (AOL sends them sometimes)
					tmp[2] = cData[0];
					tmp[3] = cData[1];

					if (!capLen || !MatchCapability(capBuf, capLen, &tmp, BINARY_CAP_SIZE)) {
						// not present, add
						memcpy(pCapability, tmp, BINARY_CAP_SIZE);
						capLen += BINARY_CAP_SIZE;
						pCapability += BINARY_CAP_SIZE;
					}
					cData += 2;
					cLen -= 2;
				}
			}
			debugLogA("Detected %d capability items.", capLen / BINARY_CAP_SIZE);
		}

		if (capLen) {
			// Update the contact's capabilies if present in packet
			SetCapabilitiesFromBuffer(hContact, capBuf, capLen, wOldStatus == ID_STATUS_OFFLINE);

			char *szCurrentClient = wOldStatus == ID_STATUS_OFFLINE ? NULL : getSettingStringUtf(hContact, "MirVer", NULL);

			szClient = detectUserClient(hContact, nIsICQ, wClass, dwOnlineSince, szCurrentClient, wVersion, dwFT1, dwFT2, dwFT3, dwDirectConnCookie, dwWebPort, capBuf, capLen, &bClientId, szStrBuf);
			// Check if the client changed, if not do not change
			if (szCurrentClient && !strcmpnull(szCurrentClient, szClient))
				szClient = (const char*)-1;
			SAFE_FREE(&szCurrentClient);
		}
		else if (wOldStatus == ID_STATUS_OFFLINE) {
			// Remove the contact's capabilities if coming from offline
			ClearAllContactCapabilities(hContact);

			// no capability
			debugLogA("No capability info TLVs");

			szClient = detectUserClient(hContact, nIsICQ, wClass, dwOnlineSince, NULL, wVersion, dwFT1, dwFT2, dwFT3, dwDirectConnCookie, dwWebPort, NULL, capLen, &bClientId, szStrBuf);
		}
		else  // Capabilities not present in update packet, do not touch
			szClient = (const char*)-1; // we don't want to client be overwritten

		// handle Xtraz status
		char *moodData = NULL;
		WORD moodSize = 0;

		unpackSessionDataItem(pChain, 0x0E, (BYTE**)&moodData, &moodSize, NULL);
		if (capLen || wOldStatus == ID_STATUS_OFFLINE)
			handleXStatusCaps(dwUIN, szUID, hContact, capBuf, capLen, moodData, moodSize);
		else
			handleXStatusCaps(dwUIN, szUID, hContact, NULL, 0, moodData, moodSize);

		// Determine support for extended status messages
		if (pChain->getWord(0x08, 1) == 0x0A06)
			SetContactCapabilities(hContact, CAPF_STATUS_MESSAGES);
		else if (wOldStatus == ID_STATUS_OFFLINE)
			ClearContactCapabilities(hContact, CAPF_STATUS_MESSAGES);

		if (wOldStatus == ID_STATUS_OFFLINE) {
			if (CheckContactCapabilities(hContact, CAPF_SRV_RELAY))
				debugLogA("Supports advanced messages");
			else
				debugLogA("Does NOT support advanced messages");
		}

		if (!nIsICQ) {
			// AIM clients does not advertise these, but do support them
			SetContactCapabilities(hContact, CAPF_UTF | CAPF_TYPING);
			// Server relayed messages are only supported by ICQ clients
			ClearContactCapabilities(hContact, CAPF_SRV_RELAY);

			if (dwUIN && wOldStatus == ID_STATUS_OFFLINE)
				debugLogA("Logged in with AIM client");
		}

		if (nIsICQ && wVersion < 8) {
			ClearContactCapabilities(hContact, CAPF_SRV_RELAY);
			if (wOldStatus == ID_STATUS_OFFLINE)
				debugLogA("Forcing simple messages due to compability issues");
		}

		// Process Avatar Hash
		pTLV = pChain->getTLV(0x1D, 1);
		if (pTLV)
			handleAvatarContactHash(dwUIN, szUID, hContact, pTLV->pData, pTLV->wLen);
		else
			handleAvatarContactHash(dwUIN, szUID, hContact, NULL, 0);

		// Process Status Note
		parseStatusNote(dwUIN, szUID, hContact, pChain);
	}
	// Free TLV chain
	disposeChain(&pChain);

	// Save contacts details in database
	if (hContact != NULL) {
		setDword(hContact, "LogonTS", dwOnlineSince);
		setDword(hContact, "AwayTS", dwAwaySince);
		setDword(hContact, "IdleTS", tIdleTS);

		if (dwMemberSince)
			setDword(hContact, "MemberTS", dwMemberSince);

		if (nIsICQ) {
			// on AIM these are not used
			setDword(hContact, "DirectCookie", dwDirectConnCookie);
			setByte(hContact, "DCType", (BYTE)nTCPFlag);
			setWord(hContact, "UserPort", (WORD)(dwPort & 0xffff));
			setWord(hContact, "Version", wVersion);
		}
		else {
			delSetting(hContact, "DirectCookie");
			delSetting(hContact, "DCType");
			delSetting(hContact, "UserPort");
			delSetting(hContact, "Version");
		}

		// if no detection, set uknown
		if (!szClient)
			szClient = (nIsICQ ? "Unknown" : "Unknown AIM");		

		if (szClient != (char*)-1) {
			db_set_utf(hContact, m_szModuleName, "MirVer", szClient);
			setByte(hContact, "ClientID", bClientId);
		}

		if (wOldStatus == ID_STATUS_OFFLINE) {
			setDword(hContact, "IP", dwIP);
			setDword(hContact, "RealIP", dwRealIP);
		}
		else {
			// if not first notification only write significant information
			if (dwIP)
				setDword(hContact, "IP", dwIP);
			if (dwRealIP)
				setDword(hContact, "RealIP", dwRealIP);
		}
		setWord(hContact,  "Status", (WORD)IcqStatusToMiranda(wStatus));

		// Update info?
		if (dwUIN) {
			// check if the local copy of user details is up-to-date
			if (IsMetaInfoChanged(hContact))
				icq_QueueUser(hContact);
		}
	}

	LPCTSTR ptszStatus = pcli->pfnGetStatusModeDescription(IcqStatusToMiranda(wStatus), 0);
	if (wOldStatus != IcqStatusToMiranda(wStatus)) {
		// And a small log notice... if status was changed
		if (nIsICQ)
			debugLogA("%u changed status to %S (v%d).", dwUIN, ptszStatus, wVersion);
		else
			debugLogA("%s changed status to %S.", strUID(dwUIN, szUID), ptszStatus);
	}

	if (szClient == cliSpamBot) {
		if (getByte("KillSpambots", DEFAULT_KILLSPAM_ENABLED) && db_get_b(hContact, "CList", "NotOnList", 0)) {
			// kill spammer
			icq_DequeueUser(dwUIN);
			icq_sendRemoveContact(dwUIN, NULL);
			AddToSpammerList(dwUIN);
			if (getByte("PopupsSpamEnabled", DEFAULT_SPAM_POPUPS_ENABLED))
				ShowPopupMsg(hContact, LPGEN("Spambot Detected"), LPGEN("Contact deleted & further events blocked."), POPTYPE_SPAM);
			CallService(MS_DB_CONTACT_DELETE, hContact, 0);

			debugLogA("Contact %u deleted", dwUIN);
		}
	}
}
Пример #3
0
static void SetValue(CIcqProto* ppro, HWND hwndDlg, int idCtrl, MCONTACT hContact, char* szModule, char* szSetting, int special)
{
	DBVARIANT dbv = { 0 };
	char str[MAX_PATH];
	char* pstr = NULL;
	int unspecified = 0;
	int bUtf = 0, bDbv = 0, bAlloc = 0;

	dbv.type = DBVT_DELETED;

	if ((hContact == NULL) && ((int)szModule < 0x100)) {
		dbv.type = (BYTE)szModule;

		switch ((int)szModule) {
		case DBVT_BYTE:
			dbv.cVal = (BYTE)szSetting;
			break;
		case DBVT_WORD:
			dbv.wVal = (WORD)szSetting;
			break;
		case DBVT_DWORD:
			dbv.dVal = (DWORD)szSetting;
			break;
		case DBVT_ASCIIZ:
			dbv.pszVal = pstr = szSetting;
			break;
		default:
			unspecified = 1;
			dbv.type = DBVT_DELETED;
		}
	}
	else {
		if (szModule == NULL)
			unspecified = 1;
		else {
			unspecified = db_get(hContact, szModule, szSetting, &dbv);
			bDbv = 1;
		}
	}

	if (!unspecified) {
		switch (dbv.type) {
		case DBVT_BYTE:
			unspecified = (special == SVS_ZEROISUNSPEC && dbv.bVal == 0);
			pstr = _itoa(special == SVS_SIGNED ? dbv.cVal : dbv.bVal, str, 10);
			break;

		case DBVT_WORD:
			if (special == SVS_ICQVERSION) {
				if (dbv.wVal != 0) {
					char szExtra[80];

					mir_snprintf(str, "%d", dbv.wVal);
					pstr = str;

					if (hContact && ppro->IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD, 1)) {
						ICQTranslateUtfStatic(LPGEN(" (DC Established)"), szExtra, _countof(szExtra));
						mir_strcat(str, (char*)szExtra);
						bUtf = 1;
					}
				}
				else
					unspecified = 1;
			}
			else if (special == SVS_STATUSID) {
				char *pszStatus = MirandaStatusToStringUtf(dbv.wVal);
				BYTE bXStatus = ppro->getContactXStatus(hContact);

				if (bXStatus) {
					char *pXName = ppro->getSettingStringUtf(hContact, DBSETTING_XSTATUS_NAME, NULL);
					if (pXName == NULL) // give default name
						pXName = ICQTranslateUtf(nameXStatus[bXStatus - 1]);

					mir_snprintf(str, "%s (%s)", pszStatus, pXName);
					SAFE_FREE((void**)&pXName);
				}
				else strncpy_s(str, pszStatus, _TRUNCATE);

				bUtf = 1;
				SAFE_FREE(&pszStatus);
				pstr = str;
				unspecified = 0;
			}
			else {
				unspecified = (special == SVS_ZEROISUNSPEC && dbv.wVal == 0);
				pstr = _itoa(special == SVS_SIGNED ? dbv.sVal : dbv.wVal, str, 10);
			}
			break;

		case DBVT_DWORD:
			unspecified = (special == SVS_ZEROISUNSPEC && dbv.dVal == 0);
			if (special == SVS_IP) {
				struct in_addr ia;
				ia.S_un.S_addr = htonl(dbv.dVal);
				pstr = inet_ntoa(ia);
				if (dbv.dVal == 0)
					unspecified = 1;
			}
			else if (special == SVS_TIMESTAMP) {
				if (dbv.dVal == 0)
					unspecified = 1;
				else
					pstr = time2text(dbv.dVal);
			}
			else
				pstr = _itoa(special == SVS_SIGNED ? dbv.lVal : dbv.dVal, str, 10);
			break;

		case DBVT_ASCIIZ:
		case DBVT_WCHAR:
			unspecified = (special == SVS_ZEROISUNSPEC && dbv.pszVal[0] == '\0');
			if (!unspecified && pstr != szSetting) {
				pstr = ppro->getSettingStringUtf(hContact, szModule, szSetting, NULL);
				bUtf = 1;
				bAlloc = 1;
			}
			if (idCtrl == IDC_UIN)
				SetDlgItemText(hwndDlg, IDC_UINSTATIC, TranslateT("ScreenName:"));
			break;

		default:
			pstr = str;
			mir_strcpy(str, "???");
			break;
		}
	}

	EnableDlgItem(hwndDlg, idCtrl, !unspecified);
	if (unspecified)
		SetDlgItemText(hwndDlg, idCtrl, TranslateT("<not specified>"));
	else if (bUtf)
		SetDlgItemTextUtf(hwndDlg, idCtrl, pstr);
	else
		SetDlgItemTextA(hwndDlg, idCtrl, pstr);

	if (bDbv)
		db_free(&dbv);

	if (bAlloc)
		SAFE_FREE(&pstr);
}