static int sttSaveAvatar()
{
	FILE* in;
	SHA1Context sha;
//	MD5Context md5;
	unsigned char buf[ 512 ];
	char tFileName[ MAX_PATH ];
	int i, pictureType;
	int bIsFirst = 1;
	struct _stat statbuf;
	uint8_t digest[20];

	if (_stat(szFileName, &statbuf)) return 1;
	if (statbuf.st_size > 6 * 1024) return 1;
	
	TlenGetAvatarFileName( NULL, tFileName, sizeof tFileName );
	if ( CopyFileA( szFileName, tFileName, FALSE ) == FALSE ) {
		JabberLog( "Copy failed with error %d", GetLastError() );
		return 1;
	}
	SHA1Reset(&sha);
//	md5_init(&md5);
	in = fopen( tFileName, "rb" );
	if ( in == NULL )
		return 1;

	while( !feof( in )) {
		int bytes = fread( buf, 1, sizeof buf, in );
		if ( bIsFirst ) {
			pictureType = JabberGetPictureType( buf );
			bIsFirst = 0;
		}
		SHA1Input(&sha, buf, bytes);
//		md5_update(&md5, buf, bytes);
	}
	fclose( in );
	if ( pictureType == PA_FORMAT_UNKNOWN )
		return 1;
	SHA1Result(&sha, digest);
//	md5_finalize(&md5);
	for (i=0;i<20;i++) {
//		unsigned int val = (md5.state[i>>2] >> 8*(i%4)) & 0xFF;
		sprintf( buf+( i<<1 ), "%02x", digest[i]);
	}
	DBWriteContactSettingString(NULL, jabberProtoName, "AvatarHash", buf);
	DBWriteContactSettingDword(NULL, jabberProtoName, "AvatarFormat", pictureType);
	if (userAvatarHash != NULL) {
		free (userAvatarHash);
		userAvatarHash = NULL;
	}
	userAvatarHash = strdup(buf);
	userAvatarFormat = pictureType;
	TlenGetAvatarFileName(NULL, szFileName, MAX_PATH);
	if ( strcmp( szFileName, tFileName ))
		MoveFileA( tFileName, szFileName );
	return 0;
}
static void RemoveAvatar(TlenProtocol *proto, HANDLE hContact) {
	TCHAR tFileName[ MAX_PATH ];
	if (hContact == NULL) {
		proto->threadData->avatarHash[0] = '\0';
	}
	TlenGetAvatarFileName( proto, NULL, tFileName, sizeof tFileName );
	DeleteFile(tFileName);
	db_unset(hContact, "ContactPhoto", "File");
	db_unset(hContact, proto->m_szModuleName, "AvatarHash");
	db_unset(hContact, proto->m_szModuleName, "AvatarFormat");
	ProtoBroadcastAck(proto->m_szModuleName, NULL, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, 0);
}
static void RemoveAvatar(HANDLE hContact) {
	char tFileName[ MAX_PATH ];
	if (hContact == NULL) {
		jabberThreadInfo->avatarHash[0] = '\0';
	}
	TlenGetAvatarFileName( NULL, tFileName, sizeof tFileName );
	DeleteFileA(tFileName);
	DBDeleteContactSetting(hContact, "ContactPhoto", "File");
	DBDeleteContactSetting(hContact, jabberProtoName, "AvatarHash");
	DBDeleteContactSetting(hContact, jabberProtoName, "AvatarFormat");
	ProtoBroadcastAck(jabberProtoName, NULL, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL, 0);
}
static void SetAvatar(HANDLE hContact, JABBER_LIST_ITEM *item, char *data, int len, DWORD format) {
	FILE* out;
	char filename[MAX_PATH];
	char md5[33];
	MD5 context;
	int i;
	md5_init(&context);
	md5_update(&context, data, len);
	md5_finalize(&context);
	if (format == PA_FORMAT_UNKNOWN && len > 4) {
		format = JabberGetPictureType(data);
	}
	for (i=0;i<16;i++) {
		char lo, hi;
		unsigned int j=context.state[i>>2];
		j>>=8*(i%4);
		j&=0xFF;
		lo = j & 0x0F;
		hi = j >> 4;
		hi = hi + ((hi > 9) ? 'a' - 10 : '0');
		lo = lo + ((lo > 9) ? 'a' - 10 : '0');
		md5[i*2] = hi;
		md5[i*2+1] = lo;
	}
	md5[i*2] = 0;
	if (item != NULL) {
		char *hash = item->avatarHash;
		item->avatarFormat = format;
		item->avatarHash = mir_strdup(md5);
		mir_free(hash);
	} else {
		jabberThreadInfo->avatarFormat = format;
		strcpy(jabberThreadInfo->avatarHash, md5);
	}
	TlenGetAvatarFileName(item, filename, sizeof filename );
	DeleteFileA(filename);
	out = fopen( filename, "wb" );
	if ( out != NULL ) {
		fwrite( data, len, 1, out );
		fclose( out );
		DBWriteContactSettingString(hContact, "ContactPhoto", "File", filename );
		DBWriteContactSettingString(hContact, jabberProtoName, "AvatarHash",  md5);
		DBWriteContactSettingDword(hContact, jabberProtoName, "AvatarFormat",  format);
	}
	ProtoBroadcastAck( jabberProtoName, hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL , 0);
}
static void SetAvatar(TlenProtocol *proto, HANDLE hContact, TLEN_LIST_ITEM *item, char *data, int len, DWORD format) {
	TCHAR filename[MAX_PATH];
	char md5[33];
	mir_md5_state_t ctx;
	DWORD digest[4];

	if (format == PA_FORMAT_UNKNOWN && len > 4)
		format = ProtoGetBufferFormat(data);

	mir_md5_init( &ctx );
	mir_md5_append( &ctx, ( BYTE* )data, len);
	mir_md5_finish( &ctx, ( BYTE* )digest );

	sprintf( md5, "%08x%08x%08x%08x", (int)htonl(digest[0]), (int)htonl(digest[1]), (int)htonl(digest[2]), (int)htonl(digest[3])); //!!!!!!!!!!!!!!
	if (item != NULL) {
		char *hash = item->avatarHash;
		item->avatarFormat = format;
		item->avatarHash = mir_strdup(md5);
		mir_free(hash);
	} else {
		proto->threadData->avatarFormat = format;
		strcpy(proto->threadData->avatarHash, md5);
	}
	TlenGetAvatarFileName(proto, item, filename, sizeof filename );
	DeleteFile(filename);
	FILE *out = _tfopen(filename, TEXT("wb") );
	if (out != NULL) {
		fwrite(data, len, 1, out);
		fclose(out);
		db_set_ts(hContact, "ContactPhoto", "File", filename );
		db_set_s(hContact, proto->m_szModuleName, "AvatarHash",  md5);
		db_set_dw(hContact, proto->m_szModuleName, "AvatarFormat",  format);
	} else {
		TCHAR buffer[128];
		mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("Can not save new avatar file \"%s\" Error:\n\t%s (Error: %d)"), filename, _tcserror(errno), errno);
		PUShowMessageT(buffer, SM_WARNING);
		proto->debugLog(buffer);
		return;
	}
	ProtoBroadcastAck( proto->m_szModuleName, hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL , 0);
}
static BOOL CALLBACK TlenSetAvatarDlgProc( HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
	switch ( msg ) {
	case WM_INITDIALOG:
		TranslateDialogDefault( hwndDlg );
		avatarChanged = 0;
		hAvatar = NULL;
		szFileName[0] = 0;/*

		BOOL tValue = JGetByte( "EnableAvatars", 1 );
		CheckDlgButton( hwndDlg, IDC_ENABLE_AVATARS,	tValue );
		if ( tValue )*/ 
		{
			char szAvatar[ MAX_PATH ];
			TlenGetAvatarFileName( NULL, szAvatar, sizeof szAvatar );
			hAvatar = (HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (WPARAM)szAvatar );
			if (hAvatar)
	        SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (WPARAM)hAvatar );
		}
		return TRUE;
	case WM_COMMAND:
		if ( HIWORD( wParam ) == BN_CLICKED )
			switch( LOWORD( wParam )) {
			case IDC_SETAVATAR:
				if ( TlenEnterBitmapName( szFileName ) == ERROR_SUCCESS ) {
					if (!sttSaveAvatar()) {
						HBITMAP hBitmap = (HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (WPARAM)szFileName );
						if ( hBitmap != NULL ) {
							hAvatar = hBitmap;
							hBitmap = ( HBITMAP )SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (WPARAM)hBitmap );
							if ( hBitmap )
								DeleteObject( hBitmap );
							RedrawWindow(GetDlgItem(hwndDlg, IDC_AVATAR), NULL, NULL, RDW_INVALIDATE);
						}
						avatarChanged = 1;
					}	

				}
				break;
			case IDC_DELETEAVATAR:
				{
					char tFileName[ MAX_PATH ];
					HBITMAP hBitmap;
					TlenGetAvatarFileName( NULL, tFileName, sizeof tFileName );
					DeleteFileA( tFileName );
					if (userAvatarHash != NULL) {
						free (userAvatarHash);
						userAvatarHash = NULL;
					}
					DBDeleteContactSetting(NULL, jabberProtoName, "AvatarHash");
					DBDeleteContactSetting(NULL, jabberProtoName, "AvatarFormat");
					DeleteObject( hAvatar ); hAvatar = NULL;
					hBitmap = (HBITMAP)SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (WPARAM)NULL );
					if ( hBitmap )
						DeleteObject( hBitmap );
					InvalidateRect( hwndDlg, NULL, TRUE );
					avatarChanged = 1;
					break;
				}

			}
		break;
	case WM_DESTROY:
		if ( hAvatar )
			DeleteObject( hAvatar );
		if (tlenOptions.enableAvatars && avatarChanged && jabberConnected && jabberDesiredStatus != ID_STATUS_INVISIBLE)
			JabberSendPresence(jabberDesiredStatus);
		break;
	}

	return 0;
}