From cb4a46e7fbe62d788e66ed6121c717a2d22a4d7c Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 21 Apr 2011 14:14:52 +0000 Subject: svn.miranda.im is moving to a new home! git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@7 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- miranda-wine/protocols/MSN/msn_bitmap.cpp | 213 ++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 miranda-wine/protocols/MSN/msn_bitmap.cpp (limited to 'miranda-wine/protocols/MSN/msn_bitmap.cpp') diff --git a/miranda-wine/protocols/MSN/msn_bitmap.cpp b/miranda-wine/protocols/MSN/msn_bitmap.cpp new file mode 100644 index 0000000..fccb6c6 --- /dev/null +++ b/miranda-wine/protocols/MSN/msn_bitmap.cpp @@ -0,0 +1,213 @@ +/* +Plugin of Miranda IM for communicating with users of the MSN Messenger protocol. +Copyright (c) 2003-5 George Hazan. +Copyright (c) 2002-3 Richard Hughes (original version). + +Miranda IM: the free icq client for MS Windows +Copyright (C) 2000-2002 Richard Hughes, Roland Rabien & Tristan Van de Vreede + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "msn_global.h" + +#include "sha1.h" + +///////////////////////////////////////////////////////////////////////////////////////// +// MSN_BitmapToAvatarDibBits - rescales a bitmap to 96x96 pixels and creates a DIB from it + +HBITMAP __stdcall MSN_StretchBitmap( HBITMAP hBitmap ) +{ + BITMAPINFO bmStretch = { 0 }; + bmStretch.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmStretch.bmiHeader.biWidth = 96; + bmStretch.bmiHeader.biHeight = 96; + bmStretch.bmiHeader.biPlanes = 1; + bmStretch.bmiHeader.biBitCount = 32; + + UINT* ptPixels; + HBITMAP hStretchedBitmap = CreateDIBSection( NULL, &bmStretch, DIB_RGB_COLORS, ( void** )&ptPixels, NULL, 0); + if ( hStretchedBitmap == NULL ) { + MSN_DebugLog( "Bitmap creation failed with error %d", GetLastError() ); + return NULL; + } + + BITMAP bmp; + HDC hDC = CreateCompatibleDC( NULL ); + HBITMAP hOldBitmap1 = ( HBITMAP )SelectObject( hDC, hBitmap ); + GetObject( hBitmap, sizeof( BITMAP ), &bmp ); + + HDC hBmpDC = CreateCompatibleDC( hDC ); + HBITMAP hOldBitmap2 = ( HBITMAP )SelectObject( hBmpDC, hStretchedBitmap ); + int side, dx, dy; + + if ( bmp.bmWidth > bmp.bmHeight ) { + side = bmp.bmHeight; + dx = ( bmp.bmWidth - bmp.bmHeight )/2; + dy = 0; + } + else { + side = bmp.bmWidth; + dx = 0; + dy = ( bmp.bmHeight - bmp.bmWidth )/2; + } + + SetStretchBltMode( hBmpDC, HALFTONE ); + StretchBlt( hBmpDC, 0, 0, 96, 96, hDC, dx, dy, side, side, SRCCOPY ); + + SelectObject( hDC, hOldBitmap1 ); + DeleteObject( hBitmap ); + DeleteDC( hDC ); + + SelectObject( hBmpDC, hOldBitmap2 ); + DeleteDC( hBmpDC ); + return hStretchedBitmap; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MSN_SaveBitmapAsAvatar - updates the avatar database settins and file from a bitmap + +int __stdcall MSN_SaveBitmapAsAvatar( HBITMAP hBitmap, const char* szFileName ) +{ + if ( !MSN_LoadPngModule()) + return 1; + + HDC hdc = CreateCompatibleDC( NULL ); + HBITMAP hOldBitmap = ( HBITMAP )SelectObject( hdc, hBitmap ); + + BITMAPINFO* bmi = ( BITMAPINFO* )alloca( sizeof( BITMAPINFO ) + sizeof( RGBQUAD )*256 ); + memset( bmi, 0, sizeof( BITMAPINFO )); + bmi->bmiHeader.biSize = 0x28; + if ( GetDIBits( hdc, hBitmap, 0, 96, NULL, bmi, DIB_RGB_COLORS ) == 0 ) { + TWinErrorCode errCode; + MSN_ShowError( "Unable to get the bitmap: error %d (%s)", errCode.mErrorCode, errCode.getText() ); + return 2; + } + + BITMAPINFOHEADER* pDib; + BYTE* pDibBits; + pDib = ( BITMAPINFOHEADER* )GlobalAlloc( LPTR, sizeof( BITMAPINFO ) + sizeof( RGBQUAD )*256 + bmi->bmiHeader.biSizeImage ); + if ( pDib == NULL ) + return 3; + + memcpy( pDib, bmi, sizeof( BITMAPINFO ) + sizeof( RGBQUAD )*256 ); + pDibBits = (( BYTE* )pDib ) + sizeof( BITMAPINFO ) + sizeof( RGBQUAD )*256; + + GetDIBits( hdc, hBitmap, 0, pDib->biHeight, pDibBits, ( BITMAPINFO* )pDib, DIB_RGB_COLORS ); + SelectObject( hdc, hOldBitmap ); + DeleteDC( hdc ); + + long dwPngSize = 0; + DIB2PNG convertor; + convertor.pbmi = ( BITMAPINFO* )pDib; + convertor.pDiData = pDibBits; + convertor.pResult = NULL; + convertor.pResultLen = &dwPngSize; + if ( !CallService( MS_DIB2PNG, 0, (LPARAM)&convertor )) { + GlobalFree( pDib ); + return 2; + } + + convertor.pResult = new BYTE[ dwPngSize ]; + CallService( MS_DIB2PNG, 0, (LPARAM)&convertor ); + GlobalFree( pDib ); + + SHA1Context sha1ctx; + BYTE sha1c[ SHA1HashSize ], sha1d[ SHA1HashSize ]; + char szSha1c[ 40 ], szSha1d[ 40 ]; + SHA1Reset( &sha1ctx ); + SHA1Input( &sha1ctx, convertor.pResult, dwPngSize ); + SHA1Result( &sha1ctx, sha1d ); + { NETLIBBASE64 nlb = { szSha1d, sizeof szSha1d, ( PBYTE )sha1d, sizeof sha1d }; + MSN_CallService( MS_NETLIB_BASE64ENCODE, 0, LPARAM( &nlb )); + } + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + _splitpath(szFileName, drive, dir, fname, ext ); + SHA1Reset( &sha1ctx ); + + char szEmail[ MSN_MAX_EMAIL_LEN ]; + MSN_GetStaticString( "e-mail", NULL, szEmail, sizeof szEmail ); + SHA1Input( &sha1ctx, ( PBYTE )"Creator", 7 ); + SHA1Input( &sha1ctx, ( PBYTE )szEmail, strlen( szEmail )); + + char szFileSize[ 20 ]; + ltoa( dwPngSize, szFileSize, 10 ); + SHA1Input( &sha1ctx, ( PBYTE )"Size", 4 ); + SHA1Input( &sha1ctx, ( PBYTE )szFileSize, strlen( szFileSize )); + + SHA1Input( &sha1ctx, ( PBYTE )"Type", 4 ); + SHA1Input( &sha1ctx, ( PBYTE )"3", 1 ); + + SHA1Input( &sha1ctx, ( PBYTE )"Location", 8 ); + SHA1Input( &sha1ctx, ( PBYTE )fname, sizeof(fname)); + + SHA1Input( &sha1ctx, ( PBYTE )"Friendly", 8 ); + SHA1Input( &sha1ctx, ( PBYTE )"AAA=", 4 ); + + SHA1Input( &sha1ctx, ( PBYTE )"SHA1D", 5 ); + SHA1Input( &sha1ctx, ( PBYTE )szSha1d, strlen( szSha1d )); + SHA1Result( &sha1ctx, sha1c ); + { NETLIBBASE64 nlb = { szSha1c, sizeof szSha1c, ( PBYTE )sha1c, sizeof sha1c }; + MSN_CallService( MS_NETLIB_BASE64ENCODE, 0, LPARAM( &nlb )); + } + { + char* szBuffer = ( char* )alloca( 1000 ); + mir_snprintf( szBuffer, 1000, + "", + szEmail, dwPngSize,fname, szSha1d, szSha1c ); + + char* szEncodedBuffer = ( char* )alloca( 1000 ); + UrlEncode( szBuffer, szEncodedBuffer, 1000 ); + + MSN_SetString( NULL, "PictObject", szEncodedBuffer ); + } + { char tFileName[ MAX_PATH ]; + MSN_GetAvatarFileName( NULL, tFileName, sizeof tFileName ); + FILE* out = fopen( tFileName, "wb" ); + if ( out != NULL ) { + fwrite( convertor.pResult, dwPngSize, 1, out ); + fclose( out ); + } } + delete convertor.pResult; + return ERROR_SUCCESS; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MSN_EnterBitmapFileName - enters a bitmap filename + +int __stdcall MSN_EnterBitmapFileName( char* szDest ) +{ + *szDest = 0; + + char szFilter[ 512 ]; + MSN_CallService( MS_UTILS_GETBITMAPFILTERSTRINGS, sizeof szFilter, ( LPARAM )szFilter ); + + char str[ MAX_PATH ]; str[0] = 0; + OPENFILENAMEA ofn = {0}; + ofn.lStructSize = sizeof( OPENFILENAME ); + ofn.lpstrFilter = szFilter; + ofn.lpstrFile = szDest; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + ofn.nMaxFile = MAX_PATH; + ofn.nMaxFileTitle = MAX_PATH; + ofn.lpstrDefExt = "bmp"; + if ( !GetOpenFileNameA( &ofn )) + return 1; + + return ERROR_SUCCESS; +} -- cgit v1.2.3