📄 imapmsgc.c
字号:
CharC id; cp = ScanText(cp, id); if ( id.Length() > 0 ) { headStr = "Content-Id: "; headStr += id; part->AddHeader(headStr); } CharC desc; cp = ScanText(cp, desc); if ( desc.Length() > 0 ) { headStr = "Content-Description: "; headStr += desc; part->AddHeader(headStr); } CharC enc; cp = ScanText(cp, enc); if ( enc.Length() > 0 ) { headStr = "Content-Transfer-Encoding: "; headStr += enc; part->AddHeader(headStr); } CharC bytes; cp = ScanNum(cp, bytes); StringC byteStr = bytes; part->bodyBytes = atoi(byteStr); if ( part->headBytes >= 0 ) part->bytes = part->bodyBytes + part->headBytes + 1;//// For encapsulated messages, we will scan the body ourself later. For now,// create a temporary child to simplify scanning the input.// if ( part->Is822() ) { cp = ScanEnvelope(cp, part); if ( debuglev > 1 ) cout <<"Creating child in message/rfc822" <<endl; MsgPartC *tmpPart = new MsgPartC(part); tmpPart->parentMsg = this; cp = ScanPart(cp, tmpPart); delete tmpPart; } while ( isspace(*cp) ) cp++; // Skip whitespace if ( isdigit(*cp) ) { // See if line count is present CharC lines; cp = ScanNum(cp, lines); StringC lineStr = lines; part->bodyLines = atoi(lineStr); if ( part->headLines >= 0 ) part->lines = part->bodyLines + part->headLines + 1; } } } // End while not done return cp;} // End ScanPart/*--------------------------------------------------------------- * Method to parse a text string. We will either have: * * {len} text * "text with possible whitespace" * text-with-no-whitespace */char*ImapMsgC::ScanText(char *data, CharC& text){//// Skip initial whitespace// char *cp = data; while ( isspace(*cp) ) cp++;//// See if the length is specified// int len = 0; char *start; if ( *cp == '{' ) { char *lenp = ++cp; while ( *cp != '}' ) cp++; *cp = 0; // Temporary len = atoi(lenp); *cp = '}'; // Restore cp++; // Skip right brace start = cp; cp += len; // Advance pointer }//// Look for the next non-escaped quote// else if ( *cp == '"' ) { start = ++cp; Boolean escape = False; while ( escape || *cp != '"' ) { if ( *cp == '\\' && !escape ) escape = True; else escape = False; cp++; } len = cp - start; cp++; // Advance pointer }//// Scan to the next whitespace or right paren character// else { start = cp; while ( !isspace(*cp) && *cp != ')' ) cp++; len = cp - start; } text.Set(start, len); if ( debuglev > 2 ) cout <<"Found text [" <<text <<"]" <<endl; if ( text.Equals("NIL", IGNORE_CASE) ) text.Set(start, 0); return cp;} // End ScanText/*--------------------------------------------------------------- * Method to parse a number string. * */char*ImapMsgC::ScanNum(char *data, CharC& text){//// Skip initial whitespace// char *cp = data; while ( isspace(*cp) ) cp++;//// Scan to the next non-numeric character// char *start = cp; while ( isdigit(*cp) ) cp++; int len = cp - start; text.Set(start, len); if ( debuglev > 2 ) cout <<"Found number [" <<text <<"]" <<endl; return cp;} // End ScanNum/*--------------------------------------------------------------- * Method to parse a list of MIME parameters. * */char*ImapMsgC::ScanParams(char *data, StringC& typeStr){ if ( debuglev > 2 ) cout <<"Scanning parameters" <<endl;//// Skip initial whitespace// char *cp = data; while ( isspace(*cp) ) cp++; if ( *cp != '(' ) { CharC nil(cp, 3); if ( nil.Equals("NIL", IGNORE_CASE) ) cp += 3; else cerr <<"Syntax error. Expecting parameter list: "<<cp <<endl; return cp; } cp++;//// Scan to corresponding right paren// Boolean done = False; while ( !done && *cp ) { while ( isspace(*cp) ) cp++;//// See if this is the end of this part// if ( *cp == ')' ) { done = True; cp++; }//// Read the next parameter// else { CharC key; CharC val; cp = ScanText(cp, key); cp = ScanText(cp, val); if ( debuglev > 2 ) cout <<"Found param [" <<key <<"=" <<val <<"]" <<endl;#if 0 if ( part->IsExternal() ) part->AddAccParam(key, val); else part->AddConParam(key, val);#else typeStr += "; "; typeStr += key; typeStr += '='; Boolean addQuotes = !val.StartsWith('"'); if ( addQuotes ) typeStr += '"'; typeStr += val; if ( addQuotes ) typeStr += '"';#endif } } // End While not done#if 0 if ( part->IsLocal() ) part->GetFileName(part->dataFile);#endif return cp;} // End ScanParams/*--------------------------------------------------------------- * Method to parse an envelope string * * 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 */char*ImapMsgC::ScanEnvelope(char *data, MsgPartC *part){ if ( debuglev > 2 ) cout <<"Scanning envelope" <<endl;//// Skip initial whitespace// char *cp = data; while ( isspace(*cp) ) cp++; if ( *cp != '(' ) { CharC nil(cp, 3); if ( nil.Equals("NIL", IGNORE_CASE) ) cp += 3; else cerr <<"Syntax error. Expecting envelope: "<<cp <<endl; return cp; } cp++; CharC date; cp = ScanText(cp, date); CharC subj; cp = ScanText(cp, subj); if ( subj.Length() > 0 ) { StringC subStr("Subject: "); subStr += subj; part->SetSubject(subStr); } cp = ScanAddressList(cp, part); // from cp = ScanAddressList(cp, part); // sender cp = ScanAddressList(cp, part); // reply-to cp = ScanAddressList(cp, part); // to cp = ScanAddressList(cp, part); // cc cp = ScanAddressList(cp, part); // bcc CharC reply; cp = ScanText(cp, reply); // In-Reply-To CharC id; cp = ScanText(cp, id); // Message-Id//// Look for closing right paren// while ( *cp && *cp != ')' ) cp++; if ( *cp == ')' ) cp++; return cp;} // End ScanEnvelope/*--------------------------------------------------------------- * Method to parse an address list. Either: * * NIL * or * ((addr) (addr) ... (addr)) */char*ImapMsgC::ScanAddressList(char *data, MsgPartC *part){ if ( debuglev > 2 ) cout <<"Scanning address list" <<endl;//// Skip initial whitespace// char *cp = data; while ( isspace(*cp) ) cp++; if ( *cp != '(' ) { CharC nil(cp, 3); if ( nil.Equals("NIL", IGNORE_CASE) ) cp += 3; else cerr <<"Syntax error. Expecting address list: "<<cp <<endl; return cp; } cp++;//// Scan to corresponding right paren// Boolean done = False; while ( !done && *cp ) { while ( isspace(*cp) ) cp++;//// See if this is another address// if ( *cp == '(' ) { cp = ScanAddress(cp, part); }//// See if this is the end of this part// else if ( *cp == ')' ) { done = True; cp++; } } return cp;} // End ScanAddressList/*--------------------------------------------------------------- * Method to parse an address. * * addr: name route mailbox host */char*ImapMsgC::ScanAddress(char *data, MsgPartC*){ if ( debuglev > 2 ) cout <<"Scanning address" <<endl;//// Skip initial whitespace// char *cp = data; while ( isspace(*cp) ) cp++; if ( *cp != '(' ) { CharC nil(cp, 3); if ( nil.Equals("NIL", IGNORE_CASE) ) cp += 3; else cerr <<"Syntax error. Expecting address: "<<cp <<endl; return cp; } cp++; CharC tmp; cp = ScanText(cp, tmp); // Name cp = ScanText(cp, tmp); // Route cp = ScanText(cp, tmp); // Mailbox cp = ScanText(cp, tmp); // host//// Look for closing right paren// while ( *cp && *cp != ')' ) cp++; if ( *cp == ')' ) cp++; return cp;} // End ScanAddress/*--------------------------------------------------------------- * Method to parse a flag string */voidImapMsgC::ParseFlags(CharC flagStr){ if ( flagStr.Contains("\\seen", IGNORE_CASE) ) { ClearStatus(MSG_NEW, False); SetStatus(MSG_READ, False); } else if ( flagStr.Contains("\\recent", IGNORE_CASE) ) { ClearStatus(MSG_READ, False); SetStatus(MSG_NEW, False); } if ( flagStr.Contains("\\deleted", IGNORE_CASE) ) SetStatus(MSG_DELETED, False); if ( flagStr.Contains("\\answered", IGNORE_CASE) ) SetStatus(MSG_REPLIED, False); if ( flagStr.Contains("\\flagged", IGNORE_CASE) ) SetStatus(MSG_FLAGGED, False); if ( flagStr.Contains("\\saved", IGNORE_CASE) ) SetStatus(MSG_SAVED, False); if ( flagStr.Contains("\\forwarded", IGNORE_CASE) ) SetStatus(MSG_FORWARDED, False); if ( flagStr.Contains("\\resent", IGNORE_CASE) ) SetStatus(MSG_RESENT, False); if ( flagStr.Contains("\\printed", IGNORE_CASE) ) SetStatus(MSG_PRINTED, False); if ( flagStr.Contains("\\filtered", IGNORE_CASE) ) SetStatus(MSG_FILTERED, False);} // End ParseFlags/*------------------------------------------------------------------------ * Method to get the external headers for a body part */voidImapMsgC::GetExternalInfo(MsgPartC *part){//// If this is a multipart, loop through children// if ( part->IsMultipart() ) { MsgPartC *child = part->child; while ( child ) { GetExternalInfo(child); child = child->next; } }//// If this is an external part, get the body text and read the external headers// else if ( part->IsExternal() ) {//// Get body text// char *text; char *flags; StringC response; StringC cmd = "BODY["; cmd += part->partNum; cmd += "]"; if ( !server->Fetch(number, folder, cmd, &text, &flags, response) ) return;//// Remove everything after the first blank line// StringC headers = text; int blankPos = headers.PosOf("\n\n"); if ( blankPos >= 0 ) headers.Clear(blankPos+1); if ( !headers.EndsWith('\n') ) headers += '\n'; part->extLines = 0; part->extBytes = headers.size();//// Loop through external headers// StringC headStr; u_int offset = 0; int nlPos = headers.PosOf('\n', offset); while ( nlPos >= 0 ) { part->extLines++; int len = nlPos - offset + 1;//// Check for a continuation// if ( isspace(headers[offset]) ) headStr += headers(offset, len); else { if ( headStr.size() > 0 ) part->AddExtHeader(headStr); headStr = headers(offset, len); } offset = nlPos+1; nlPos = headers.PosOf('\n', offset); } // End for each header line//// See if we have a final header// if ( headStr.size() > 0 ) part->AddExtHeader(headStr); delete text; delete flags; } // End if part is external} // End GetExternalInfo/*------------------------------------------------------------------------ * Method to set status flags */voidImapMsgC::SetStatus(MsgStatusT val, Boolean write){ if ( (status & (u_int)val) != 0 ) return; // Already set status |= (u_int)val;//// 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 &= ~MSG_NEW; else if ( val == MSG_NEW ) status &= ~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);//// Only these flags need to be written// write = write && (val & (MSG_NEW|MSG_READ|MSG_REPLIED|MSG_DELETED)); }//// Update server if necessary// if ( write ) server->SetFlags(number, status);//// Update visible icon// if ( icon ) icon->UpdateStatus();} // End SetStatus/*------------------------------------------------------------------------ * Method to clear status flags */voidImapMsgC::ClearStatus(MsgStatusT val, Boolean write){ if ( (status & (u_int)val) == 0 ) return; // Already clear status &= ~(u_int)val; 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); }//// Only these flags need to be written// write = write && (val & (MSG_NEW|MSG_READ|MSG_REPLIED|MSG_DELETED)); if ( write ) server->SetFlags(number, status); }//// Update visible icon// if ( icon ) icon->UpdateStatus();} // End ClearStatus/*------------------------------------------------------------------------ * Method to write the body to a file */BooleanImapMsgC::WriteBody(FILE *dstfp, Boolean addBlank, Boolean /*protectFroms*/){ bodyWritePos = ftell(dstfp); StringC textStr; if ( !GetBodyText(textStr) ) return False; Boolean success = textStr.WriteFile(dstfp); if ( success && addBlank ) { CharC nlStr("\n"); success = nlStr.WriteFile(dstfp); } return success;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -