📄 evauhmanager.cpp
字号:
/*************************************************************************** * Copyright (C) 2004-2005 by yunfan * * yunfan_zg@163.com * * * * 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 "evauhmanager.h"#include "evauhpacket.h"#include "evauhprotocols.h"#include <qfile.h>#include <qdatastream.h>#include <qtextstream.h>#include <qsocketdevice.h>#include <qdns.h>#include <qstringlist.h>#include <qapplication.h>#include <string.h>#define MaxBlockSize 800#define CFACE_SERVER "cface_tms.qq.com"#define CFACE_PORT 4000#define UH_PROFILE_NAME "evauh.profile"#define UH_TIME_OUT 30// UH represents User Head which is used in Tencent QQ, sounds pretty @!#~*!$@# :)class EvaUHFile {public: EvaUHFile(unsigned int id); ~EvaUHFile(); const bool setFileInfo(const char *md5, unsigned int sid); const bool setFileBlock(const unsigned int numPackets, const unsigned int packetNum, const unsigned int fileSize, const unsigned int partStart, const unsigned int partSize, const unsigned char *buf); const QString getMd5String() const; const unsigned int getQQ() const { return mId; } const int getSessionId() const { return mSessionId; } // is this file downloaded sucessfully? const bool isFinished(); // return session id, and assign the start and size, return 0 means md5 wrong, // need redownloading this file again, or no session available const unsigned int nextBlock(unsigned int *start, unsigned int *size); const bool isMD5Correct(); void save(QString &dir); void initSettings();private: unsigned int mId; char md5[16]; bool *flags; unsigned int mFileSize; // total size of this file unsigned int mNumPackets; // number of blocks this file needs unsigned int mSessionId; // the session id used in downloading unsigned char *mBuffer; // the file data};EvaUHFile::EvaUHFile(unsigned int id) : mId(id), flags(NULL), mFileSize(0), mNumPackets(0), mSessionId(0), mBuffer(NULL){}EvaUHFile::~EvaUHFile(){ if(flags) delete flags; if(mBuffer) delete mBuffer;}const bool EvaUHFile::setFileInfo(const char *_md5, unsigned int sid){ if(mSessionId) return false; memcpy(md5, _md5, 16); mSessionId = sid; return true;}const bool EvaUHFile::setFileBlock(const unsigned int numPackets, const unsigned int /*packetNum*/, const unsigned int fileSize, const unsigned int partStart, const unsigned int partSize, const unsigned char *buf){ //if(packetNum >= numPackets) return false; // impossible if(mFileSize && fileSize != mFileSize) return false; // different file size //if(mNumPackets && numPackets != mNumPackets) return false; // num of blocks wrong //if(flags && flags[packetNum] ) return false; // got this block already if(!mFileSize) mFileSize = fileSize; if(!mNumPackets) mNumPackets = numPackets; if(!flags){ flags = new bool[mNumPackets]; for(unsigned int i=0; i<mNumPackets; i++) flags[i] = false; } if(!mBuffer){ mBuffer = new unsigned char[mFileSize]; memset(mBuffer, 0, mFileSize); } memcpy(mBuffer+partStart, buf, partSize); //flags[packetNum] = true; flags[partStart/MaxBlockSize] = true; return true;}const QString EvaUHFile::getMd5String() const{ return EvaHelper::md5ToString(md5);}const bool EvaUHFile::isFinished(){ if(!flags) return false; bool result = true; for(unsigned int i=0; i< mNumPackets; i++){ if(!flags[i]) { result = false; break; } } return result;}// return session id, and assign the start and size, return 0 means md5 wrong, // need redownloading this file again, no session availableconst unsigned int EvaUHFile::nextBlock(unsigned int *start, unsigned int *size){ if(!flags){ *start = 0xffffffff; *size = 0; return mSessionId; } unsigned int index; for(index=0; index<mNumPackets; index++) if(!flags[index]) break; if(index==0 || index== mNumPackets){ *start = 0xffffffff; *size = 0; }else{ *start = (index * MaxBlockSize); if(index == mNumPackets-1) *size = mFileSize - (*start); else *size = MaxBlockSize; } return mSessionId;}const bool EvaUHFile::isMD5Correct(){ if(!mBuffer) return false; char *gMd5 = new char[16]; memcpy(gMd5, EvaUtil::doMd5((char *)mBuffer, mFileSize), 16); if(memcmp(gMd5, md5, 16) != 0){ // which means not equal delete [] gMd5; return false; } delete []gMd5; return true;}// Given a directory, that's enoughvoid EvaUHFile::save(QString &dir){ if(!mBuffer){ fprintf(stderr, "EvaUHFile::save -- NULL file buffer, failed\n"); return; } /* we don't check md5, leave the job to calling function to do, save tiem :) // we check md5 first if(!isMD5Correct()){ fprintf(stderr, "EvaUHFile::save -- MD5 checking, failed\n"); initSettings(); // if md5 wrong, the data is useless, we clear all return; } */ QString filePrefix = dir + "/" + getMd5String(); QFile file(filePrefix + ".bmp"); if(!file.open(IO_WriteOnly | IO_Raw )){ fprintf(stderr, "EvaUHFile::save -- file creating, failed\n"); return; } QDataStream stream(&file); stream.writeRawBytes((char *)mBuffer, mFileSize); file.flush(); file.close(); QImage grayPic; grayPic.loadFromData(mBuffer, mFileSize); EvaQtUtils::convertToGrayscale(&grayPic); grayPic.save(filePrefix +"_off.bmp", "BMP");}// we only re-set the details not the basic information like id, session id and md5 valuevoid EvaUHFile::initSettings(){ if(flags) delete []flags; flags = NULL; if(mBuffer) delete []mBuffer; mBuffer = NULL; mNumPackets = 0; mFileSize = 0;}/************************************************************************************************/ class EvaUHProfile {public: QString dir; // note must set the UH directory first QMap<unsigned int, UHInfoItem> list; bool loadProfile(); void saveProfile(); void updateInfo(UHInfoItem item); void updateInfo(const unsigned int id, char *md5, unsigned int sid); void remove(const unsigned int id); void fileFinished(const unsigned int id); char *strMd5ToChar(const QString &strMd5); char *getMd5(const unsigned int id); // if not exists, NULL return // cuz session id only used within one session and will not be saved as well // but it does help to download the new file :) unsigned int getSession(const unsigned int id); UHInfoItem nextDownload(); // if id is 0, means no file downloading needed QString getStrMd5(const unsigned int id);};bool EvaUHProfile::loadProfile(){ QString filename = dir + "/" + UH_PROFILE_NAME; QFile file(filename); if(!file.open(IO_ReadOnly)){ fprintf(stderr, "EvaUHProfile::loadProfile -- file not exists\n"); return false; } QTextStream stream(&file); while(!stream.atEnd()){ QString line = stream.readLine(); QStringList lines = QStringList::split(":", line); if(lines.size() != 2) continue; bool ok; int id = lines[0].stripWhiteSpace().toInt(&ok); if(!ok) continue; char *md5 = strMd5ToChar(lines[1].stripWhiteSpace()); if(!md5) continue; UHInfoItem item; item.id = id; item.sessionId = 0; memcpy(item.md5, md5, 16); delete [] md5; item.isUpdated = false; list[id] = item; } file.close(); return true;}void EvaUHProfile::updateInfo(UHInfoItem item){ QMap<unsigned int, UHInfoItem>::Iterator it = list.find(item.id); if(it != list.end()){ if(memcmp(it.data().md5, item.md5, 16)!=0){ memcpy(it.data().md5, item.md5, 16); it.data().sessionId = item.sessionId; it.data().isUpdated = true; } } else { item.isUpdated = true; list[item.id] = item; }}void EvaUHProfile::updateInfo(const unsigned int id, char *md5, unsigned int sid){ QMap<unsigned int, UHInfoItem>::Iterator it = list.find(id); if(it != list.end()){ if(memcmp(it.data().md5, md5, 16)!=0){ memcpy(it.data().md5, md5, 16); it.data().sessionId = sid; it.data().isUpdated = true; } } else { UHInfoItem item; item.id = id; memcpy(item.md5, md5, 16); item.sessionId = sid; item.isUpdated = true; list[id] = item; }}void EvaUHProfile::remove(const unsigned int id){ list.erase(id);}void EvaUHProfile::fileFinished(const unsigned int id){ QMap<unsigned int, UHInfoItem>::Iterator it = list.find(id); if(it != list.end()) it.data().isUpdated = false;}void EvaUHProfile::saveProfile(){ QString filename = dir + "/" + UH_PROFILE_NAME; QFile file(filename); if(!file.open(IO_WriteOnly)){ fprintf(stderr, "EvaUHProfile::saveProfile -- cannot open file to write\n"); return; } QTextStream stream(&file); QMap<unsigned int, UHInfoItem>::Iterator it; for(it = list.begin(); it!=list.end(); ++it){ if(it.data().isUpdated) continue; // only save the downloaded ones QString strId = QString::number(it.key()); QString strMd5 = EvaHelper::md5ToString(it.data().md5); stream<<strId << ":" << strMd5 << "\n"; } file.flush(); file.close();}// we new a char[], so calling function should delete the memorychar *EvaUHProfile::strMd5ToChar(const QString &strMd5){ QString ch; bool ok; int tmp; if(strMd5.length() != 32) return NULL; char *md5 = new char[16]; for(uint i=0; i<strMd5.length(); i+=2){ ch = strMd5.mid(i, 2); tmp = ch.toInt(&ok, 16); if(!ok) return NULL; md5[i/2] = tmp & 0xff; } return md5;}// calling function shouldn't delete the memorychar *EvaUHProfile::getMd5(const unsigned int id){ QMap<unsigned int, UHInfoItem>::Iterator it = list.find(id); if(it != list.end()) return it.data().md5; else return NULL;}// 0 means no session id avalibleunsigned int EvaUHProfile::getSession(const unsigned int id){ QMap<unsigned int, UHInfoItem>::Iterator it = list.find(id); if(it != list.end()) return it.data().sessionId; else return 0;}// return item.id == 0 means all finished, no more downloading neededUHInfoItem EvaUHProfile::nextDownload(){ QMap<unsigned int, UHInfoItem>::Iterator it = list.begin(); while(it != list.end()){ if(it.data().isUpdated) return list[it.key()];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -