⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imapserverc.c

📁 linux下的E_MAIL客户端源码
💻 C
📖 第 1 页 / 共 5 页
字号:
// Fix line ending if necessary//   if ( terminate ) {      if ( linebuf.EndsWith('\n') ) linebuf.CutEnd(1);      linebuf += "\r\n";   }#ifdef HAVE_OPENSSL   if ( TLSEnabled ) {      void *buf = (char *) linebuf;      int nbytes = SSL_write(ssl, buf, linebuf.length());      if (nbytes <= 0) {         // FIXME: proper check         // err = SSL_get_error(ssl, nbytes);         if ( Query("Connection dropped. Retry?", *halApp, False) == QUERY_YES ) {            ReConnect();         }         return False;      } else {         return True;      }   }#endif   fd_set	writeSet;   FD_ZERO(&writeSet);   struct timeval timeout;   while ( linebuf.length() > 0 ) {//// See if the socket is available//      int rc;      while (True) {         FD_SET(sock, &writeSet);         timeout.tv_sec  = 5;         timeout.tv_usec = 0;         rc = select(sock+1, NULL, &writeSet, NULL, &timeout);	 //	 // a socket is available for writing	 //	 if ( rc > 0 )		break;	 //	 // error occurred	 //         else if ( rc < 0) {            if ( errno == EINTR ) {		if (debuglev > 0) cout << "Select got SIGINTR, retrying" << endl;            } else if ( errno == EBADF ) {                ReConnect();	    } else {	 	int	err = errno;	 	errmsg = "Could not select socket ";	 	errmsg += sock;	 	errmsg += " for writing to the IMAP server ";	 	errmsg += name;	 	errmsg += ".\n" + SystemErrorMessage(err);	 	halApp->PopupMessage(errmsg);	 	return False;	    }	 }	 //	 // timeout	 //         else if ( rc == 0 ) {	     errmsg = "Timeout trying to select the IMAP server\n";	     errmsg += "\n\nRetry?";	     if ( !RetryLogin(errmsg) ) {	       CloseSocket();	       return False;	     }   	     if ( !(connected = ReConnect()) ) {	       return False;	     }	 }      }      int writeCount;      while ( True ) {         writeCount = write(sock, (const char*) linebuf, linebuf.length());         if ( writeCount <= 0 ) {            if ( errno == EPIPE) {		errmsg = "Lost connection to the IMAP server\n";	 	errmsg += "\n\nTry to re-connect ?";	 	if ( !RetryLogin(errmsg) ) {		  CloseSocket();		  return False;	 	}   		if ( !(connected = ReConnect()) ) {		  return False;		}	    } else {	 	int	err = errno;	 	errmsg = "Could not write socket ";	 	errmsg += sock;	 	errmsg += " for IMAP server ";	 	errmsg += name;	 	errmsg += ".\n" + SystemErrorMessage(err);	 	halApp->PopupMessage(errmsg);	 	return False;	   }        } else {	   break;	// write succeeded	}      }      linebuf.CutBeg(writeCount);   } // End while all bytes not written   return True;} // End PutLine/*------------------------------------------------------------------------ * Method to generate a unique tag */voidImapServerC::GenTag(StringC& tag){   tag = "ISH";   tag += tagCount++;   tag += " ";}/*------------------------------------------------------------------------ * Method to display an error message about an unexpected reply */voidImapServerC::Unexpected(CharC str){   StringC	errmsg = "Unexpected reply from IMAP server ";   errmsg += name;   errmsg += ":\n\"";   errmsg += str;   errmsg += "\"\n";#if 0   halApp->PopupMessage(errmsg);#endif   // Rather than hang the program waiting for a user response,   // just splat these messages to standard error.   cerr << errmsg;}/*------------------------------------------------------------------------ * Function to run a command and wait for the response */BooleanImapServerC::RunCommand(CharC cmd, StringListC& output){   StringC	tag;   GenTag(tag);   StringC	cmdline(tag);   cmdline += cmd;   if ( !PutLine(cmdline) ) return False;   if ( !GetLine(cmdline) ) return False;   while ( !cmdline.StartsWith(tag) ) {      output.add(cmdline);      if ( !GetLine(cmdline) ) return False;   }   cmdline.CutBeg(tag.size());   output.add(cmdline);   return True;} // End RunCommand/*------------------------------------------------------------------------ * Function to run a command and let the supplied hook function process * the response, including dealing with continuation requests from the * server. Any data can be passed to the callback function, if needed */ImapCommandReturnImapServerC::RunCommand2(CharC cmd, RunCommandHook hook, void *cdata){   Boolean 		ok = True;   ImapCommandReturn 	ret;   StringListC 		info, data;   StringC		tag;      GenTag(tag);   StringC	cmdline(tag);   cmdline += cmd;   if ( !PutLine(cmdline) ) {      return ImapCommandNoConnect;   }   while ( True ) {      StringC		response;      ImapResponse	type;            if ( !GetLine(response) ) {         return ImapCommandNoConnect;      }            if ( response.StartsWith(tag) ) {         response.CutBeg(tag.size());         if ( response.StartsWith("OK", IGNORE_CASE) ) {            type = ImapResponseOK;            ret  = ImapCommandOK;            response.CutBeg(2);         } else         if (response.StartsWith("NO", IGNORE_CASE) ) {            type = ImapResponseNO;            ret  = ImapCommandNO;            response.CutBeg(2);         } else         if (response.StartsWith("BAD", IGNORE_CASE) ) {            type = ImapResponseBAD;            ret  = ImapCommandBAD;            response.CutBeg(3);         } else {            // Unknown response            return ImapCommandFailed;         }         if ( hook && !hook(type, response, info, data, &cmdline, cdata) ) {            ok = False;         }         if ( ok ) {            return ret;         } else {            return ImapCommandFailed;         }      } else if ( response.StartsWith("* ") ) {         response.CutBeg(2);         info.add(response);         // TODO: check for BYE here      } else if ( response.StartsWith("+ ") ) {         type = ImapResponseCont;         response.CutBeg(2);         if ( !hook || !hook(type, response, info, data, &cmdline, cdata) ) {            ok = False;         }         if ( !PutLine(cmdline) ) {            return ImapCommandNoConnect;         }      } else {         data.add(response);      }   }      // Should never reach this point   return ImapCommandFailed;} // End RunCommand/*------------------------------------------------------------------------ * Function to send NOOP command and wait for response. */BooleanImapServerC::Noop(StringListC& output){   return RunCommand("NOOP", output);}// Anonymous loginstatic BooleanauthenticationAnonymousHook(   ImapResponse type,   CharC resp,   StringListC info,   StringListC data,   StringC *reply,   void *cdata){   if ( type == ImapResponseCont ) {      // Ignore the server's challenge; it may be an empty string            AuthData *ad = (AuthData *) cdata;      reply->Clear();      // Respond with the password (which is the user's email, probably)      if ( !TextToText64(ad->pass, reply, False, False) ) {         return False;      }      return True;   } else {      // No special action on the command completion      return True;   }}// Base64-encoded plain text login; should be used as the last resortstatic BooleanauthenticationLoginHook(   ImapResponse type,   CharC resp,   StringListC info,   StringListC data,   StringC *reply,   void *cdata){   if ( type == ImapResponseCont ) {      StringC buf;      // Decode the response; it should be either "User Name" or "Password"      if ( !Text64ToText(resp, &buf) ) {         return False;      } else {         AuthData *ad = (AuthData *) cdata;                  reply->Clear();         // NB: below, StartsWith() is used instead of Equals() because the         // base64 strings are explicitly 0-terminated         if ( buf.StartsWith("User Name", IGNORE_CASE) ) {            // Respond with the username            if ( !TextToText64(ad->user, reply, False, False) ) {               return False;            }         } else if ( buf.StartsWith("Password", IGNORE_CASE) ) {            // Respond with the password            if ( !TextToText64(ad->pass, reply, False, False) ) {               return False;            }         } else {            // Unexpected response            return False;         }                  return True;      }   } else {      // No special action on the command completion      return True;   }}#ifdef HAVE_OPENSSL// Print data in hexadecimalsstatic char *hexpt(unsigned char *md){   int i;   static char buf[2*MD5_DIGEST_LENGTH + 1];   for (i = 0; i < MD5_DIGEST_LENGTH; i++) {      sprintf(&(buf[2*i]), "%02x", md[i]);   }      buf[2*MD5_DIGEST_LENGTH] = '\0';      return(buf);}/*------------------------------------------------------------------------ * CRAM-MD5 authentication scheme (RFC 2195) * Based on the keyed-hashing MD5 digest algorithm (aka HMAC) (RFC 2104) * All the hard work is done by the OpenSSL crypto library */static BooleanauthenticationHmacHook(   ImapResponse type,   CharC resp,   StringListC info,   StringListC data,   StringC *reply,   void *cdata){   if ( type == ImapResponseCont ) {      StringC buf;      // Decode the response; its a "challenge"      if ( !Text64ToText(resp, &buf) ) {         return False;      } else {         AuthData *ad = (AuthData *) cdata;                  reply->Clear();                  // Produce the digest & print it in hexadecimals         const char *d = buf;         const char *p;         p = hexpt(HMAC(EVP_md5(),                  ad->pass.Addr(), ad->pass.Length(),                  (const unsigned char *) d, buf.length(),                  NULL, NULL));         // Prepend username         buf = ad->user;         buf += " ";         buf += p;         // Base64 encode everything         if ( !TextToText64(buf, reply, False, False) ) {               return False;         }                  return True;      }   } else {      // No special action on the command completion      return True;   }}#endif/*------------------------------------------------------------------------ * Function to send LOGIN (for IMAP2) or AUTHENTICATE (IMAP4) command and * process response. */ImapCommandReturnImapServerC::Authenticate(CharC user, CharC pass){   ImapCommandReturn 	res;   StringC		cmd;   RunCommandHook 	hook;   Boolean		secure;   AuthData 		ad;   ad.user = user;   ad.pass = pass;      if ( (authMethods & IMAP_AUTH_ANONYMOUS) &&        user.Equals("anonymous", IGNORE_CASE) ) {      // Anonymous login; not really secure, but who cares? ;-)      secure = True;      cmd = "AUTHENTICATE ANONYMOUS";      hook = authenticationAnonymousHook;   } else#ifdef HAVE_OPENSSL   if ( authMethods & IMAP_AUTH_CRAM_MD5 ) {      // MD5 digest      secure = True;      cmd = "AUTHENTICATE CRAM-MD5";      hook = authenticationHmacHook;   } else#endif   if ( authMethods & IMAP_AUTH_LOGIN ) {      // using base64-encoded username & password      secure = False;      cmd = "AUTHENTICATE LOGIN";      hook = authenticationLoginHook;   } else   if ( authMethods & IMAP_AUTH_CLEAR_TEXT ) {      // IMAP2 clear text login      secure = False;      cmd = "LOGIN ";      cmd += user;      cmd += " \"";      cmd += pass;      cmd += "\"";      hook = NULL;   } else {      // should never happen      return ImapCommandFailed;   }      // If the whole session is encrypted, don't worry about secure authentication   if ( TLSEnabled ) {      secure = True;   }      if ( !secure ) {      // If the authentication method is insecure, ask user      // whether (s)he agrees to use a clear text login      StringC str;      str  = "No (supported) secure authentication mechanisms available.";      str += "\n\nDo you want to use a clear text login?";      if ( Query(str, *halApp, False) != QUERY_YES ) {         return ImapCommandCancelled;      }   }      return RunCommand2(cmd, hook, (void *) &ad);}/*------------------------------------------------------------------------ * Function to send LOGOUT command and wait for response. */BooleanImapServerC::Logout(StringListC& output){   if ( !connected ) {      return True;   } else {      return RunCommand("LOGOUT", output);   }}/*------------------------------------------------------------------------ * Function to send CREATE command and wait for response. */BooleanImapServerC::Create(CharC mailbox, StringListC& output){   StringC	cmd = "CREATE ";   cmd += mailbox;   return RunCommand(cmd, output);}/*------------------------------------------------------------------------ * Function to send DELETE command and wait for response. */BooleanImapServerC::Delete(CharC mailbox, StringListC& output){   // If the folder is currently open, close it first   if ( folder == mailbox ) {      StringListC output;      if ( !Close(output) ) return False;   }   StringC	cmd = "DELETE ";   cmd += mailbox;   return RunCommand(cmd, output);}/*------------------------------------------------------------------------ * Function to send RENAME command and wait for response. */BooleanImapServerC::Rename(CharC oldname, CharC newname, StringListC& output)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -