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

📄 msgc.c

📁 linux下的E_MAIL客户端源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: MsgC.C,v 1.3 2000/09/19 16:42: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 "MsgC.h"#include "AddressC.h"#include "HeaderC.h"#include "HeaderValC.h"#include "MsgPartC.h"#include "FolderC.h"#include "IshAppC.h"#include "HeadPrefC.h"#include "MsgItemC.h"#include "MainWinC.h"#include "RuleDictC.h"#include "date.h"#include "ReplyPrefC.h"#include "TermFn.h"#include "SendWinC.h"#include <hgl/RegexC.h>#include <hgl/StringC.h>#include <hgl/CharC.h>#include <hgl/PtrListC.h>#include <hgl/StringListC.h>#include <hgl/SysErr.h>#include <unistd.h>#include <errno.h>RegexC  *MsgC::rePat = NULL;extern int	debuglev;/*--------------------------------------------------------------- *  Constructor */MsgC::MsgC(FolderC *fld){   if ( !rePat ) rePat = new RegexC("^[ \t]*[Rr][Ee][[(]?[0-9]*[])]?:[ \t]*");   status        = MSG_NEW;   epochTime     = 0;   folder	 = fld;   from          = NULL;   to            = NULL;   cc            = NULL;   replyTo       = NULL;   returnPath    = NULL;   sender        = NULL;   thread        = NULL;   indexOffset   = -1;   number        = 0;   headWritePos  = 0;   bodyWritePos  = 0;   icon		 = NULL;   bodySizeKnown = False;   body = new MsgPartC;   body->parentMsg = this;} // End constructor/*--------------------------------------------------------------- *  Destructor */MsgC::~MsgC(){//// Notify all composition windows//   u_int	count = ishApp->sendWinList.size();   for (int i=0; i<count; i++) {      SendWinC	*win = (SendWinC*)*ishApp->sendWinList[i];      if ( win->IsShown() ) win->MessageDeleted(this);   }   delete from;   delete to;   delete cc;   delete replyTo;   delete returnPath;   delete sender;   delete thread;   delete icon;   delete body;}/*--------------------------------------------------------------- *  Method to add a new header to the linked list and check it's *     attributes. */voidMsgC::CheckHeader(HeaderC *head){//// Check for Content- headers//   if ( head->key.StartsWith("Content-",   IGNORE_CASE) ||	head->key.StartsWith("X-Content-", IGNORE_CASE) ) {//// Look for sun attachments//      if ( head->key.Equals("content-type", IGNORE_CASE) ) {	 CharC	full(head->full);	 if ( full.Contains("X-Sun-Attachment", IGNORE_CASE) )	    SetStatus(MSG_SUN_ATTACH);	 else if ( full.Contains("message/partial", IGNORE_CASE) )	    SetStatus(MSG_PARTIAL);      }   } // End if this is a Content- header//// Check for other special headers//   else switch (head->key.Length()) {      case 2:	 if ( head->key.Equals("To", IGNORE_CASE) )	    AddAddress(head, &to);	 else if ( head->key.Equals("Cc", IGNORE_CASE) )	    AddAddress(head, &cc);	 break;      case 4:	 if ( head->key.Equals("From", IGNORE_CASE) )	    AddAddress(head, &from);	 else if ( head->key.Equals("Date", IGNORE_CASE) ) {	    StringC	tmp;	    head->GetValueText(tmp);	    epochTime = parsedate(tmp, NULL);	 }	 break;      case 6:	 if ( head->key.Equals("Sender", IGNORE_CASE) )	    AddAddress(head, &sender);	 else if ( head->key.Equals("Status", IGNORE_CASE) ) {	    ClearStatus(MSG_NEW);	    CharC	full(head->full);	    if ( full.Contains('R') ) SetStatus(MSG_READ);	    else		      ClearStatus(MSG_READ);	 }	 break;      case 7:	 if ( head->key.Equals("Subject", IGNORE_CASE) && !thread )	    GetThread(head);	 break;      case 8:	 if ( head->key.Equals("Reply-To", IGNORE_CASE) )	    AddAddress(head, &replyTo);	 break;      case 10:	 if ( head->key.Equals("Message-Id", IGNORE_CASE) )	    head->GetValueText(msgId);	 break;      case 11:	 if ( head->key.Equals("Return-Path", IGNORE_CASE) )	    AddAddress(head, &returnPath);	 break;      case 12:	 if ( head->key.Equals("Mime-Version", IGNORE_CASE) )	    SetStatus(MSG_MIME);	 break;   } // End switch length} // End CheckHeader/*--------------------------------------------------------------- *  Method to add a new header to the linked list and check it's *     attributes. */voidMsgC::AddAddress(HeaderC *head, AddressC **addr){   AddressC	*newAddr = new AddressC(head->value->full);   if ( !*addr )      *addr = newAddr;   else {      AddressC	*last = *addr;      while ( last->next ) last = last->next;      last->next = newAddr;   }} // End AddAddress/*------------------------------------------------------------------------ * Method to extract the thread string.  This is the subject without any *    Re's or (fwd)'s */voidMsgC::GetThread(HeaderC *head){//// Remove Re's at the beginning//   StringC	threadStr;   head->GetValueText(threadStr);   Boolean	done = False;   while ( !done ) {      if ( rePat->match(threadStr) )	 threadStr.CutBeg((*rePat)[0].length());      else if ( threadStr.StartsWith("fwd:", IGNORE_CASE) )	 threadStr.CutBeg(4);      else if ( threadStr.StartsWith("(fwd)", IGNORE_CASE) )	 threadStr.CutBeg(5);      else if ( threadStr.EndsWith("(fwd)", IGNORE_CASE) )	 threadStr.CutEnd(5);      else	 done = True;      threadStr.Trim();   }   thread = new char[threadStr.size()+1];   strcpy(thread, threadStr);} // End GetThread/*--------------------------------------------------------------- *  Method to print message to stream. */voidMsgC::Print(ostream& strm) const{   if ( body->headers && debuglev > 1 ) {      strm <<"........................................" <<endl;      HeaderC	*head = body->headers;      while ( head ) {	 strm <<*head;	 head = head->next;      }      strm <<"........................................" <<endl;   }   if ( from ) strm <<"  From: " <<*from <<endl;   if ( to   ) strm <<"    To: " <<*to <<endl;   if ( cc   ) strm <<"    Cc: " <<*cc <<endl;   if ( debuglev > 1 ) {      if ( replyTo    ) strm <<"   Reply-To: " <<*replyTo <<endl;      if ( returnPath ) strm <<"Return-Path: " <<*returnPath <<endl;      if ( sender     ) strm <<"     Sender: " <<*sender <<endl;      if ( thread     ) strm <<"     Thread: " <<thread <<endl;   }   HeaderValC	*val = Date();   if ( val ) strm <<"  Date: " <<*val <<endl;   strm <<"Status: ";   if ( IsSet(MSG_NEW)	         ) strm <<"New ";   if ( IsSet(MSG_READ)	         ) strm <<"Read ";   if ( IsSet(MSG_DELETED)	 ) strm <<"Deleted ";   if ( IsSet(MSG_SAVED)	 ) strm <<"Saved ";   if ( IsSet(MSG_REPLIED)	 ) strm <<"Replied ";   if ( IsSet(MSG_FORWARDED)	 ) strm <<"Forwarded ";   if ( IsSet(MSG_RESENT)	 ) strm <<"Resent ";   if ( IsSet(MSG_PRINTED)	 ) strm <<"Printed ";   if ( IsSet(MSG_FILTERED)	 ) strm <<"Filtered ";   if ( IsSet(MSG_FLAGGED)	 ) strm <<"Flagged ";   if ( IsSet(MSG_MIME)	         ) strm <<"Mime ";   if ( IsSet(MSG_SUN_ATTACH)    ) strm <<"Sun ";   if ( IsSet(MSG_OPEN_FROMS)    ) strm <<"Open-froms ";   if ( IsSet(MSG_SAFE_FROMS)    ) strm <<"Safe-froms ";   if ( IsSet(MSG_FROMS_CHECKED) ) strm <<"Froms-checked ";   if ( IsSet(MSG_VIEWED)	 ) strm <<"Viewed ";   if ( IsSet(MSG_IN_USE)	 ) strm <<"In-use ";   if ( IsSet(MSG_CHANGED)	 ) strm <<"Changed ";   if ( IsSet(MSG_PARTIAL)	 ) strm <<"Partial ";   if (!body->IsPlainText()	 ) strm <<"Not-plain ";   if ( body->IsEncoded()	 ) strm <<"Encoded ";   strm <<endl;   strm <<"........................................" <<endl;   strm <<*body;   strm <<"........................................" <<endl;}/*------------------------------------------------------------------------ * Method to set number */voidMsgC::SetNumber(int num){   number = num;   if ( icon ) icon->UpdateStatus();}/*------------------------------------------------------------------------ * Method to set status flags.  If VIEWED is being set, we will also set *    READ. */voidMsgC::SetStatus(MsgStatusT val, Boolean write){   if ( (status & (u_int)val) != 0 ) return;	// Already set   status |= (u_int)val;   if ( !folder ) return;//// Viewed implies read//   if ( val == MSG_VIEWED ) {      if ( IsRead() )	 write = False;      else {	 status |= (u_int) MSG_READ;	 status &= (u_int)~MSG_NEW;	 status |= (u_int) MSG_CHANGED;	 folder->MsgStatusChanged(this);      }   }   else {      if      ( val == MSG_READ ) status &= (u_int)~MSG_NEW;      else if ( val == MSG_NEW  ) status &= (u_int)~MSG_READ;      if ( val == MSG_DELETED )	 folder->MsgDeleted(this);      else if ( val == MSG_NEW || val == MSG_READ )	 folder->MsgStatusChanged(this);      status |= (u_int)MSG_CHANGED;      //folder->SetChanged(True);   }//// Update index file//   if ( write && indexOffset >= 0 && folder && folder->writable )      folder->UpdateIndexEntry(this);//// Update visible icon//   if ( icon ) icon->UpdateStatus();} // End SetStatus/*------------------------------------------------------------------------ * Method to clear status flags */voidMsgC::ClearStatus(MsgStatusT val, Boolean write){   if ( (status & (u_int)val) == 0 ) return;	// Already clear   status &= ~(u_int)val;   if ( !folder ) return;   if ( val != MSG_VIEWED ) {      if ( val == MSG_DELETED )	 folder->MsgUndeleted(this);      else if ( val == MSG_NEW || val == MSG_READ )	 folder->MsgStatusChanged(this);      if ( val != MSG_CHANGED ) {	 status |= (u_int)MSG_CHANGED;	 //folder->SetChanged(True);      }//// Update index file//      if ( write && indexOffset >= 0 && folder && folder->writable )	 folder->UpdateIndexEntry(this);   } // End if not clearing VIEWED//// Update visible icon//   if ( icon ) icon->UpdateStatus();} // End ClearStatus/*------------------------------------------------------------------------ * Method to check status flags */BooleanMsgC::IsSet(MsgStatusT val) const{   return ((status & (u_int)val) != 0);}/*------------------------------------------------------------------------ * Method to return the string representation of the status */voidMsgC::GetStatusString(StringC& val) const{   val.Clear();   if ( IsSet(MSG_VIEWED)	 ) val += '*';   if ( IsSet(MSG_PARTIAL)	 ) val += 'm';   else if ( IsSet(MSG_MIME)	 ) val += 'M';   if ( IsSet(MSG_NEW)	         ) val += 'N';   else if ( !IsSet(MSG_READ)    ) val += 'U';   if ( IsSet(MSG_DELETED)	 ) val += 'D';   if ( IsSet(MSG_SAVED)	 ) val += 'S';   if ( IsSet(MSG_REPLIED)	 ) val += '>';   if ( IsSet(MSG_FORWARDED)	 ) val += 'F';   if ( IsSet(MSG_RESENT)	 ) val += 'B';   if ( IsSet(MSG_PRINTED)	 ) val += 'P';   if ( IsSet(MSG_FILTERED)	 ) val += '|';} // End GetStatusString/*------------------------------------------------------------------------ * Method to build address structure for a header */AddressC*MsgC::AddressOf(const char *head) const{   HeaderC	*data = Header(head);   if ( !data ) return NULL;   AddressC	*addr = new AddressC(data->value->full);   return addr;}/*------------------------------------------------------------------------ * Method to return text of subject header */voidMsgC::GetSubjectText(StringC& substr) const{   substr.Clear();   HeaderValC	*sub = Subject();   if ( sub  ) sub->GetValueText(substr);   else        substr = "[No subject]";}/*--------------------------------------------------------------- *  Header query */HeaderC*	MsgC::Headers()		const { return body->headers; }HeaderC*	MsgC::Header(CharC key) const { return body->Header(key); }HeaderValC*	MsgC::HeaderValue(CharC key) const					  { return body->HeaderValue(key); }u_int	MsgC::HeadOffset() { return body->offset;    }int	MsgC::HeadBytes()  { return body->headBytes; }int	MsgC::HeadLines()  { return body->headLines; }/*--------------------------------------------------------------- *  Methods to return the size of the body */intMsgC::BodyBytes(){   //if ( !bodySizeKnown ) ScanBody();   if ( !bodySizeKnown && body->bodyBytes < 0 ) ScanBody();   return body->bodyBytes;}intMsgC::BodyLines(){   //   // It's so painfully slow to scan all messages just to count   // the body line, the function is disabled.   //   if (folder->IsImap()) return 0;   //if ( !bodySizeKnown ) ScanBody();   if ( !bodySizeKnown && body->bodyLines < 0 ) ScanBody();   return body->bodyLines;}/*--------------------------------------------------------------- *  Method to return a pointer to the body structure */MsgPartC*MsgC::Body(){   if ( !body->bodyScanned ) ScanBody();   return body;}/*--------------------------------------------------------------- *  Method to return the offset to the start of the body */u_intMsgC::BodyOffset(){   return body->bodyOffset;}/*--------------------------------------------------------------- *  Method to return a pointer to the specified body part */MsgPartC*MsgC::Part(CharC partNum){   if ( !body->bodyScanned ) ScanBody();   return body->FindPart(partNum);}/*--------------------------------------------------------------- *  Method to replace any header variables in the given string with *     their value. */voidMsgC::ReplaceHeaders(StringC& str){//// Loop through string, substituting for header variables.//   CharC	key;   StringC	valStr;   int		pos;   u_int	off = 0;   while ( (pos=str.PosOf('%', off)) >= 0 ) {//// Replace %% with %//      if ( str[pos+1] == '%' ) {	 str(pos+1,0) = "";	 off = pos+1;      }//// Replace %header with value//      else {//// Look for next non-alphanum//	 int	len = 0;	 char	c = str[pos+1];	 while ( !isspace(c) && (isalnum(c) || c == '-') ) {	    len++;	    c = str[pos+1+len];	 }	 key = str.Range(pos+1, len);	 valStr.Clear();//// Look up value for header//	 if ( key.Length() > 0 ) {//// Check for special cases//	    if      ( key.Equals("fromname", IGNORE_CASE) ) {	       if ( from ) {		  if ( from->name ) from->name->GetValueText(valStr);		  else		    valStr = from->addr;	       }	       else		  valStr = "Unknown";	    }	    else if ( key.Equals("fromaddr", IGNORE_CASE) ) {	       if ( from ) valStr = from->addr;	       else	   valStr = "Unknown";	    }//// Look up value//	    else {	       HeaderValC	*val = HeaderValue(key);	       if ( val ) val->GetValueText(valStr);	       else	  valStr = "Unknown";	    }//// Escape '<'s since this string will be used in enriched text//

⌨️ 快捷键说明

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