00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "popclient.h"
00021 #include "emailhandler.h"
00022
00023
00024 extern "C" {
00025 #include "md5.h"
00026 }
00027
00028 #include <qcstring.h>
00029
00030 PopClient::PopClient()
00031 {
00032
00033 socket = new QSocket(this, "popClient");
00034 connect(socket, SIGNAL(error(int)), this, SLOT(errorHandling(int)));
00035 connect(socket, SIGNAL(connected()), this, SLOT(connectionEstablished()));
00036 connect(socket, SIGNAL(readyRead()), this, SLOT(incomingData()));
00037
00038 stream = new QTextStream(socket);
00039
00040 receiving = FALSE;
00041 synchronize = FALSE;
00042 lastSync = 0;
00043 headerLimit = 0;
00044 mailList = 0;
00045 preview = FALSE;
00046 }
00047
00048 PopClient::~PopClient()
00049 {
00050 delete socket;
00051 delete stream;
00052 }
00053
00054 void PopClient::newConnection(const QString &target, int port)
00055 {
00056 if (receiving) {
00057 qWarning("socket in use, connection refused");
00058 return;
00059 }
00060
00061 status = Init;
00062
00063 socket->connectToHost(target, port);
00064 receiving = TRUE;
00065
00066
00067 emit updateStatus(tr("DNS lookup"));
00068 }
00069
00070 void PopClient::setAccount(const QString &popUser, const QString &popPasswd)
00071 {
00072 popUserName = popUser;
00073 popPassword = popPasswd;
00074 }
00075
00076 void PopClient::setSynchronize(int lastCount)
00077 {
00078 synchronize = TRUE;
00079 lastSync = lastCount;
00080 }
00081
00082 void PopClient::removeSynchronize()
00083 {
00084 synchronize = FALSE;
00085 lastSync = 0;
00086 }
00087
00088 void PopClient::headersOnly(bool headers, int limit)
00089 {
00090 preview = headers;
00091 headerLimit = limit;
00092 }
00093
00094 void PopClient::setSelectedMails(MailList *list)
00095 {
00096 selected = TRUE;
00097 mailList = list;
00098 }
00099
00100 void PopClient::connectionEstablished()
00101 {
00102 emit updateStatus(tr("Connection established"));
00103 }
00104
00105 void PopClient::errorHandling(int status)
00106 {
00107 errorHandlingWithMsg( status, QString::null );
00108 }
00109 void PopClient::errorHandlingWithMsg(int status, const QString & Msg )
00110 {
00111 emit updateStatus(tr("Error Occured"));
00112 emit errorOccurred(status, Msg);
00113 socket->close();
00114 receiving = FALSE;
00115 }
00116
00117 void PopClient::incomingData()
00118 {
00119 QString response, temp, temp2, timeStamp;
00120 QString md5Source;
00121 int start, end;
00122
00123 char md5Digest[16];
00124
00125
00126
00127
00128 response = socket->readLine();
00129
00130 switch(status) {
00131
00132 case Init: {
00133 #ifdef APOP_TEST
00134 start = response.find('<',0);
00135 end = response.find('>', start);
00136 if( start >= 0 && end > start )
00137 {
00138 timeStamp = response.mid( start , end - start + 1);
00139 md5Source = timeStamp + popPassword;
00140
00141 md5_buffer( (char const *)md5Source, md5Source.length(),&md5Digest[0]);
00142
00143 for(int j =0;j < MD5_DIGEST_LENGTH ;j++)
00144 {
00145 printf("%x", md5Digest[j]);
00146 }
00147 printf("\n");
00148
00149 *stream << "APOP " << popUserName << " " << md5Digest << "\r\n";
00150
00151 status = Stat;
00152 }
00153 else
00154 #endif
00155 {
00156 timeStamp = "";
00157 *stream << "USER " << popUserName << "\r\n";
00158 status = Pass;
00159 }
00160
00161 break;
00162 }
00163
00164 case Pass: {
00165 *stream << "PASS " << popPassword << "\r\n";
00166 status = Stat;
00167
00168 break;
00169 }
00170
00171 case Stat: {
00172 if (response[0] == '+') {
00173 *stream << "STAT" << "\r\n";
00174 status = Mcnt;
00175 } else errorHandlingWithMsg(ErrLoginFailed, response);
00176 break;
00177 }
00178
00179 case Mcnt: {
00180 if (response[0] == '+') {
00181 temp = response.replace(0, 4, "");
00182 int x = temp.find(" ", 0);
00183 temp.truncate((uint) x);
00184 newMessages = temp.toInt();
00185 messageCount = 1;
00186 status = List;
00187
00188 if (synchronize) {
00189
00190 if (newMessages < lastSync)
00191 lastSync = 0;
00192 messageCount = 1;
00193 }
00194
00195 if (selected && mailList ) {
00196 int *ptr = mailList->first();
00197 if (ptr != 0) {
00198 newMessages++;
00199 messageCount = *ptr;
00200 } else newMessages = 0;
00201 }
00202
00203 } else errorHandlingWithMsg(ErrUnknownResponse, response);
00204 }
00205
00206 case List: {
00207 if (messageCount <= newMessages) {
00208 *stream << "LIST " << messageCount << "\r\n";
00209 status = Size;
00210 temp2.setNum(newMessages - lastSync);
00211 temp.setNum(messageCount - lastSync);
00212 if (!selected) {
00213 emit updateStatus(tr("Retrieving ") + temp + "/" + temp2);
00214 } else {
00215
00216
00217
00218
00219
00220 emit updateStatus(tr("Completing message ") + temp);
00221
00222 }
00223 break;
00224 } else {
00225 emit updateStatus(tr("No new Messages"));
00226 status = Quit;
00227 }
00228 }
00229
00230 case Size: {
00231 if (status != Quit) {
00232 if (response[0] == '+') {
00233 temp = response.replace(0, 4, "");
00234 int x = temp.find(" ", 0);
00235 temp = temp.right(temp.length() - ((uint) x + 1) );
00236 mailSize = temp.toInt();
00237 emit currentMailSize(mailSize);
00238
00239 status = Retr;
00240 } else {
00241
00242 errorHandlingWithMsg(ErrUnknownResponse, response);
00243 }
00244 }
00245 }
00246
00247 case Retr: {
00248 if (status != Quit) {
00249 if ((selected)||(mailSize <= headerLimit))
00250 {
00251 *stream << "RETR " << messageCount << "\r\n";
00252 } else {
00253 *stream << "TOP " << messageCount << " 0\r\n";
00254 }
00255 messageCount++;
00256 status = Ignore;
00257 break;
00258 } }
00259 case Ignore: {
00260 if (status != Quit) {
00261 if (response[0] == '+') {
00262 message = "";
00263 status = Read;
00264 if (!socket->canReadLine())
00265 break;
00266 response = socket->readLine();
00267 } else errorHandlingWithMsg(ErrUnknownResponse, response);
00268 }
00269 }
00270
00271
00272 case Read: {
00273 if (status != Quit) {
00274 message += response;
00275 while ( socket->canReadLine() ) {
00276 response = socket->readLine();
00277 message += response;
00278 }
00279 emit downloadedSize(message.length());
00280 int x = message.find("\r\n.\r\n",-5);
00281 if (x == -1) {
00282 break;
00283 } else {
00284 if ( (selected)||(mailSize <= headerLimit))
00285 {
00286 emit newMessage(message, messageCount-1, mailSize, TRUE);
00287 } else {
00288 emit newMessage(message, messageCount-1, mailSize, FALSE);
00289 }
00290
00291 if ((messageCount > newMessages)||(selected))
00292 {
00293 status = Quit;
00294 if (selected) {
00295 newMessages--;
00296 status = Quit;
00297 }
00298 }
00299 else
00300 {
00301 *stream << "LIST " << messageCount << "\r\n";
00302 status = Size;
00303 temp2.setNum(newMessages - lastSync);
00304 temp.setNum(messageCount - lastSync);
00305 emit updateStatus(tr("Retrieving ") + temp + "/" + temp2);
00306
00307 break;
00308 }
00309 }
00310 }
00311 if (status != Quit)
00312 break;
00313 }
00314 case Quit: {
00315 *stream << "Quit\r\n";
00316 status = Done;
00317 int newM = newMessages - lastSync;
00318 if (newM > 0) {
00319 temp.setNum(newM);
00320 emit updateStatus(temp + tr(" new messages"));
00321 } else {
00322 emit updateStatus(tr("No new messages"));
00323 }
00324
00325 socket->close();
00326 receiving = FALSE;
00327 emit mailTransfered(newM);
00328 break;
00329 }
00330 }
00331
00332 }