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

📄 imapmsgc.c

📁 linux下的E_MAIL客户端源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  $Id: ImapMsgC.C,v 1.6 2000/12/31 14:36:02 evgeny Exp $ *   *  Copyright (c) 1994 HAL Computer Systems International, Ltd. *  *          HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. *                  1315 Dell Avenue *                  Campbell, CA  95008 * * Author: Greg Hilton * Contributors: Tom Lang, Frank Bieser, and others * * 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. * * http://www.gnu.org/copyleft/gpl.html * * 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 <config.h>#include "ImapMsgC.h"#include "ImapFolderC.h"#include "ImapServerC.h"#include "MsgPartC.h"#include "IshAppC.h"#include "MsgItemC.h"#include "HeaderC.h"#include <hgl/StringC.h>#include <hgl/SysErr.h>#include <errno.h>#include <unistd.h>/*--------------------------------------------------------------- *  Constructor */ImapMsgC::ImapMsgC(ImapFolderC *fld, ImapServerC *serv, int num) : MsgC(fld){   type   = IMAP_MSG;   server = serv;   number = num;   folder = fld;   ScanHead();}/*--------------------------------------------------------------- *  Destructor */ImapMsgC::~ImapMsgC(){}/*--------------------------------------------------------------- *  Methods to return the header text */BooleanImapMsgC::GetHeaderText(StringC& str) const{   char		*text;   char		*flags;   StringC	response;   if ( !server->FetchHdrs(number, folder, &body->bytes, &text, &flags, response) )         return False;   delete flags;//// Remove the last blank line if present//   str += text;   if ( str.EndsWith("\n\n") ) str.CutEnd(1);   delete text;   return True;} // End GetHeaderTextBooleanImapMsgC::GetHeaderText(StringC& str){   char		*text;   char		*flags;   StringC	response;   if ( !server->FetchHdrs(number, folder, &body->bytes, &text, &flags, response) )         return False;   if ( flags ) ParseFlags(flags);   delete flags;//// Remove the last blank line if present//   str += text;   if ( str.EndsWith("\n\n") ) str.CutEnd(1);   delete text;   return True;} // End GetHeaderText/*--------------------------------------------------------------- *  Methods to return the body text */BooleanImapMsgC::GetBodyText(StringC& str) const{   char		*text;   char		*flags;   StringC	response;   if ( !server->Fetch(number, folder, "RFC822.TEXT", &text, &flags, response) )      return False;   delete flags;   str += text;   delete text;   return True;} // End GetBodyTextBooleanImapMsgC::GetBodyText(StringC& str){   char		*text = NULL;   char		*flags = NULL;   StringC	response;   if ( !server->Fetch(number, folder, "RFC822.TEXT", &text, &flags, response) )      return False;//// Remove closing parenthesis from the FETCH results//   // XXX - FIXME for some reason, text can be NULL here   if (!text) {       cerr << "ERROR!!  text is NULL at " << __FILE__ << ":" << __LINE__ <<		   "\n";       return False;   }   int pos = strlen(text) - 1;   if (text[pos] == '\n' &&       text[pos-1] == ')' &&       text[pos-2] == '\n' )  text[pos-1] = '\0';   if ( strlen(text) != body->bodyBytes ) {      if ( debuglev > 0 && body->bodyBytes >= 0 )	 cout <<"We thought body was " <<body->bodyBytes <<" bytes but we got "	      <<strlen(text) <<" bytes" <<endl;      CharC	textStr(text);      body->bodyBytes = textStr.Length();      body->bodyLines = textStr.NumberOf('\n');      body->ComputeSize();   }   if ( flags ) ParseFlags(flags);   delete flags;   str += text;   delete text;   return True;} // End GetBodyText/*--------------------------------------------------------------- *  Methods to return the body text for the specified part */BooleanImapMsgC::GetPartText(const MsgPartC *part, StringC& str, Boolean getHead,		      Boolean getExtHead, Boolean getBody) const{   char		*text  = NULL;   char		*flags = NULL;   StringC	response;   StringC	cmd;//// Get the headers if necessary//   if ( getHead ) {      cmd = "BODY[";      cmd += part->partNum;      cmd += ".0]";      if ( !server->Fetch(number, folder, cmd, &text, &flags, response) )	 return False;      str += text;      str += '\n';      delete text;      delete flags;   }   text  = NULL;   flags = NULL;   cmd = "BODY[";   cmd += part->partNum;   cmd += "]";   if ( !server->Fetch(number, folder, cmd, &text, &flags, response) )      return False;//// Remove closing parenthesis from the FETCH results//   int pos = strlen(text) - 1;   if (text[pos] == '\n' &&       text[pos-1] == ')' &&       text[pos-2] == '\n' )  text[pos-1] = '\0';//// See if the external headers need to be stripped or extracted//   CharC	textStr = text;   if ( part->IsExternal() && (!getExtHead || !getBody) ) {      int	blankPos = textStr.PosOf("\n\n");      if ( getExtHead ) {	 if ( blankPos >= 0 ) textStr.CutEnd(textStr.Length()-blankPos+1);      }      else {	// getBody	 if ( blankPos >= 0 ) textStr.CutBeg(blankPos+2);      }   }   str += textStr;   delete text;   delete flags;   return True;} // End GetPartText/*--------------------------------------------------------------- *  Method to return the body text for the specified part that can *     be called by non-const objects */BooleanImapMsgC::GetPartText(const MsgPartC *part, StringC& str, Boolean getHead,		      Boolean getExtHead, Boolean getBody){   char		*text  = NULL;   char		*flags = NULL;   StringC	response;   StringC	cmd;//// Get the headers if necessary//   if ( getHead ) {      cmd = "BODY[";      cmd += part->partNum;      cmd += ".0]";      if ( !server->Fetch(number, folder, cmd, &text, &flags, response) )	 return False;      str += text;      str += '\n';      delete text;      if ( flags ) ParseFlags(flags);      delete flags;   } // End if headers requested   text  = NULL;   flags = NULL;   const StringC&	num = part->partNum;   cmd = "BODY[";   cmd += num;   cmd += "]";   if ( !server->Fetch(number, folder, cmd, &text, &flags, response) )      return False;//// Double check body size//   CharC	bodyStr  = text;   int		blankPos = bodyStr.PosOf("\n\n");   if ( blankPos >= 0 ) bodyStr.CutBeg(blankPos+2);   if ( bodyStr.Length() != part->bodyBytes ) {      if ( debuglev > 0 && part->bodyBytes >= 0 )	 cout <<"We thought part was " <<part->bodyBytes <<" bytes but we got "	      <<bodyStr.Length() <<" bytes" <<endl;      MsgPartC	*tmp = (MsgPartC*)part;      tmp->bodyBytes = bodyStr.Length();      tmp->bodyLines = bodyStr.NumberOf('\n');      tmp->ComputeSize();   }//// See if the external headers need to be stripped or extracted//   CharC	textStr = text;   if ( part->IsExternal() && (!getExtHead || !getBody) ) {      if ( getExtHead ) {	 blankPos = textStr.PosOf("\n\n");	 if ( blankPos >= 0 ) textStr.CutEnd(textStr.Length()-blankPos+1);      }      else {	// getBody	 textStr = bodyStr;      }   }   if ( flags ) ParseFlags(flags);   delete flags;   str += textStr;   delete text;   return True;} // End GetPartText/*--------------------------------------------------------------- *  Methods to return the decoded contents of this body part */BooleanImapMsgC::GetFileData(MsgPartC *part, StringC& text) const{   return part->GetData(text);}BooleanImapMsgC::GetFileData(MsgPartC *part, StringC& text){   return part->GetData(text);}/*--------------------------------------------------------------- *  Method to scan the file and determine the header sizes and body byte count */voidImapMsgC::ScanHead(){   StringC	headers;   if ( !GetHeaderText(headers) ) return;//// Read the headers//   body->headLines = 0;   body->headBytes = headers.size();   StringC	headStr;   u_int	offset = 0;   int		nlPos = headers.PosOf('\n', offset);   while ( nlPos >= 0 ) {      body->headLines++;      int	len = nlPos - offset + 1;//// Check for a continuation//      if ( isspace(headers[offset]) ) headStr += headers(offset, len);      else {	 if ( headStr.size() > 0 ) body->AddHeader(headStr);	 headStr = headers(offset, len);      }      offset = nlPos+1;      nlPos = headers.PosOf('\n', offset);   } // End for each header line//// We don't have to read another line because the header text is guaranteed//    to end with a newline////// See if we have a final header//   if ( headStr.size() > 0 ) body->AddHeader(headStr);//// Check for special headers//   HeaderC	*head = body->headers;   while ( head ) {      CheckHeader(head);      head = head->next;   }   body->SetPartNumber("1");//// If this is an external part, read the external headers//   if ( body->IsExternal() )      GetExternalInfo(body);//// Get body size//   body->bodyBytes = body->bytes;   if ( body->headBytes > 0 ) body->bodyBytes -= (body->headBytes + 1);   if ( body->extBytes  > 0 ) body->bodyBytes -= (body->extBytes  + 1);//// See if we found a content-type header//   body->defConType = (body->conStr.size() == 0);   if ( body->defConType ) {      if ( body->parent && body->parent->IsDigest() )	 body->SetType("message/rfc822");      else	 body->SetType("text/plain");   }//// Don't mark plain text as MIME//   if ( IsMime() && body->IsPlainText() &&        !body->IsEncoded() && !body->IsAttachment() && !body->IsExternal() )      ClearStatus(MSG_MIME, False);   ClearStatus(MSG_CHANGED, False);   body->headScanned = True;} // End ScanHead/*--------------------------------------------------------------- *  Method to scan the file and determine the body structure */voidImapMsgC::ScanBody(){   if ( debuglev > 1 ) cout <<"Scanning body in message " <<number <<endl;   char		*text;   char		*flags;   StringC	response;//// If the top-level part is an external body, we already know the structure//    We'll just count the number of lines in the body.//   if ( body->IsExternal() ) {//// Get body text//      if ( !server->Fetch(number, folder, "RFC822.TEXT", &text, &flags, response) )	 return;//// Remove everything up to and including the first blank line//      CharC	bodyStr  = text;      int	blankPos = bodyStr.PosOf("\n\n");      if ( blankPos >= 0 ) bodyStr.CutBeg(blankPos+2);      body->bodyLines = bodyStr.NumberOf('\n');   } // End if body is external//// We need the structure//   else {      if ( !server->Fetch(number, folder, "BODY", &text, &flags, response) )	 return;      if ( flags ) ParseFlags(flags);      delete flags;      body->bodyLines = 0;      ScanPart(text, body);      delete text;      body->SetPartNumber("1");      body->SetPartNumberSize(body->GetPartNumberMaxSize());//// Now we need to traverse the tree and get more information about any//    external parts.  This has to be done after the part numbers are//    calculated.//      GetExternalInfo(body);   } // End if top-level part is not external   body->bodyScanned = True;   bodySizeKnown     = True;} // End ScanBody/*--------------------------------------------------------------- *  Method to parse a body string * * body          : multipart-body or msg-body or other-body * multipart-body: (part) (part) ... (part) type * message-body  : type subtype (params) id {len} desc enc bytes (envelope) (body) lines * other-body    : type subtype (params) {len} id {len} desc enc bytes * params	 : (key {len} val) (key {len} val) ... (key {len} val) * envelope	 : {len} date {len} subj (addr:from) (addr:sender) (addr:reply-to) (addr:to) (addr:cc) (addr:bcc) {len} in-reply-to {len} message-id * addr		 : name route mailbox host * */char*ImapMsgC::ScanPart(char *data, MsgPartC *part){//// Skip initial whitespace//   char	*cp = data;   while ( isspace(*cp) ) cp++;   if ( *cp != '(' ) {      cerr <<"Syntax error.  Expecting body part: "<<cp <<endl;      return cp;   }   cp++;//// Scan to corresponding right paren//   StringC	headStr;   Boolean	done = False;   while ( !done && *cp ) {      while ( isspace(*cp) ) cp++;//// See if this part is a multipart//      if ( *cp == '(' ) {	 if ( !part->IsMultipart() ) part->SetType("multipart/mixed");	 MsgPartC	*newPart = new MsgPartC(part);	 newPart->parentMsg = this;	 if ( !part->child ) {	    if ( debuglev > 1 )	       cout <<"Creating first child in multipart" <<endl;	    part->child = newPart;	 }	 else {	    if ( debuglev > 1 )	       cout <<"Creating another child in multipart" <<endl;	    MsgPartC	*lastPart = part->child;	    while ( lastPart->next ) lastPart = lastPart->next;	    lastPart->next = newPart;	    newPart->prev = lastPart;	 }	 cp = ScanPart(cp, newPart);      }//// See if this is the end of this part//      else if ( *cp == ')' ) {	 done = True;	 cp++;      }//// If we're in a multipart, this must be the type//      else if ( part->IsMultipart() ) {	 CharC	text;	 cp = ScanText(cp, text);	 StringC	type = "multipart/";	 type += text;	 part->SetType(type);      }//// Scan the info for this part//      else {	 CharC	group;	 CharC	subtype;	 cp = ScanText(cp, group);	 cp = ScanText(cp, subtype);	 StringC	type;	 if ( group.Length() > 0 ) type = group;	 else			   type = "text";	 type += '/';	 type.toLower();	 if ( subtype.Length() > 0 )		 type += subtype;	 else if ( type.Equals("text/") )	 type += "plain";	 else if ( type.Equals("image/") )	 type += "gif";	 else if ( type.Equals("audio/") )	 type += "basic";	 else if ( type.Equals("video/") )	 type += "mpeg";	 else if ( type.Equals("message/") )	 type += "rfc822";	 else if ( type.Equals("application/") ) type += "octet-stream";	 else					 type += "x-unknown";	 type.toLower();	 cp = ScanParams(cp, type);	 part->SetType(type);

⌨️ 快捷键说明

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