📄 imapserverc.c
字号:
{ StringC cmd = "RENAME "; cmd += oldname; cmd += " "; cmd += newname; Boolean success = RunCommand(cmd, output); if ( success && oldname == folder ) folder = newname; return success;}/*------------------------------------------------------------------------ * Function to send SELECT command and wait for response. */BooleanImapServerC::Select(CharC mailbox, StringListC& output){ // If the folder has been opened, and the server doesn't answer // duplicate SELECT correctly (UW, for one) close the folder first if ( bugs & IMAP_BUG_DUPLICATE_SELECT && folder == mailbox ) { StringListC output; if ( !Close(output) ) return False; } StringC cmd = "SELECT "; cmd += mailbox; Boolean success = RunCommand(cmd, output); if ( success ) folder = mailbox; return success;}/*------------------------------------------------------------------------ * Function to send CLOSE command and wait for response. */BooleanImapServerC::Close(StringListC& output){ return RunCommand("CLOSE", output);}/*------------------------------------------------------------------------ * Function to send EXPUNGE command and wait for response. */BooleanImapServerC::Expunge(StringListC& output){ return RunCommand("EXPUNGE", output);}/*------------------------------------------------------------------------ * Function to send FETCH command and wait for response. */BooleanImapServerC::Fetch(int msgnum, ImapFolderC* fld, CharC key, char **output, char **flags, StringC& response){ *output = NULL; *flags = NULL; response.Clear(); StringC saveFolderName = folder; StringC folderName = fld->name; //// May need to select the named folder first// if ( folderName != saveFolderName ) { StringListC output; if ( !Select(folderName, output) ) return False; } //// Build the command we will send// StringC tag; GenTag(tag); StringC cmd(tag); cmd += "FETCH "; cmd += msgnum; cmd += " "; cmd += key;//// Send the command and wait for the response// if ( !PutLine(cmd) ) return False; if ( !GetLine(response) ) return False; StringC expect("* "); expect += msgnum; expect += " FETCH "; while ( !response.StartsWith(expect, IGNORE_CASE) && !response.StartsWith(tag) ) { Unexpected(response); if ( !GetLine(response) ) return False; if ( response.StartsWith(tag) ) { response.CutBeg(tag.size()); return False; } }//// Parse the response// if ( response.StartsWith(expect, IGNORE_CASE) ) response.CutBeg(expect.size()); else if ( response.StartsWith(tag) ) response.CutBeg(tag.size()); if ( response.StartsWith('(') ) response.CutBeg(1); response.Trim();//// These commands send the total size in the first line// if ( response.StartsWith("INTERNALDATE ", IGNORE_CASE) || response.StartsWith("RFC822.HEADER ", IGNORE_CASE) || response.StartsWith("RFC822.SIZE ", IGNORE_CASE) || response.StartsWith("UID ", IGNORE_CASE) || response.StartsWith("BODY[", IGNORE_CASE) || response.StartsWith("RFC822 ", IGNORE_CASE) || response.StartsWith("RFC822.TEXT ", IGNORE_CASE) ) {//// See if there is a length present// int pos = response.PosOf(' '); if ( pos >= 0 ) response.CutBeg(pos+1); response.Trim(); if ( response.StartsWith('{') ) { char *lenp = response; char *cp = ++lenp; while ( *cp != '}' ) cp++; *cp = 0; // Temporary int len = atoi(lenp);//// Allocate buffer of specified length// *output = new char[len+1]; **output = 0;//// Read until buffer is filled// int readlen = 0; char *output_p = *output; while ( readlen < len && GetLine(response) && !response.StartsWith(tag) ) { int space = len - readlen; int response_size = response.size(); if ( response_size >= space ) { strncpy(output_p, response, space); output_p += space; *output_p = '\0'; response.CutBeg(space); readlen = len; } else { strcpy(output_p, response); output_p += response_size; strcpy(output_p, "\n"); output_p += 1; readlen += response_size + 2; // CRLF was stripped } }//// There can also be FLAGS// response.Trim(); if ( response.StartsWith("FLAGS ", IGNORE_CASE) ) { response.CutBeg(6); if ( response.EndsWith(')') ) response.CutEnd(1); *flags = new char[response.size()+1]; **flags = 0; strcpy(*flags, response); response.Clear(); } } // End if length is known //// If the length is not known, the length is whatever's left in the response// line.// else if ( !response.StartsWith("NIL") ) { if ( response.EndsWith(')') ) response.CutEnd(1); *output = new char[response.size()+1]; **output = 0; strcpy(*output, response); response.Clear(); } } // End if the command is recognized//// These commands can contain many sized literals// else if ( response.StartsWith("BODY ", IGNORE_CASE) || response.StartsWith("BODYSTRUCTURE ", IGNORE_CASE) || response.StartsWith("ENVELOPE ", IGNORE_CASE) ) { int pos = response.PosOf(' '); response.CutBeg(pos+1); response.Trim();//// Read lines until we get the tag// StringC buffer = response; if ( !GetLine(response) ) return False; while ( !response.StartsWith(tag) ) {//// Check for FLAGS// response.Trim(); if ( response.StartsWith("FLAGS ", IGNORE_CASE) ) { response.CutBeg(6); if ( response.EndsWith(')') ) response.CutEnd(1); *flags = new char[response.size()+1]; **flags = 0; strcpy(*flags, response); response.Clear(); } else buffer += response; if ( !GetLine(response) ) return False; } // End for each line up to tag *output = new char[buffer.size()+1]; **output = 0; strcpy(*output, buffer); } // End if BODYSTRUCTURE or ENVELOPE command//// Check for flags only// else if ( response.StartsWith("FLAGS ", IGNORE_CASE) ) { response.CutBeg(6); if ( response.EndsWith(')') ) response.CutEnd(1); *flags = new char[response.size()+1]; **flags = 0; strcpy(*flags, response); response.Clear(); } else { Unexpected(response); }//// Continue reading until we get the tag// while ( !response.StartsWith(tag) ) { if ( !GetLine(response) || response.StartsWith("NO ", IGNORE_CASE) ) return False; } response.CutBeg(tag.size());//// Restore the original folder, if any// if ( saveFolderName.IsNull() && folderName != saveFolderName ) { StringListC output; if ( !Select(saveFolderName, output) ) return False; } return True;} // End Fetch/*------------------------------------------------------------------------ * Function to send FETCH command to get a sequence of 1 or more * message headers. */BooleanImapServerC::FetchHdrs(int msgnum, ImapFolderC *fld, int *bytes, char **output, char **flags, StringC& response){ int pos; *output = NULL; *flags = NULL; response.Clear();//// First time through, build the FETCH command we will send.// Save the "tag" prefix in the folder object, so that after the// last message is fetched we can find the trailing tag.// if ( fld->fetchNeeded ) { fld->fetchNeeded = False; GenTag(fld->fetchTag); StringC cmd(fld->fetchTag); cmd += "FETCH "; cmd += msgnum; cmd += ":"; cmd += fld->msgCount; cmd += " (FLAGS RFC822.SIZE";//// For max compatibility with function of other folder types, we want// all the headers. However, the tradeoff is performance. Decision: The// Message-ID and Received headers are least useful, and can take up a // lot of lines, so don't fetch them. Get everything else, though.// //cmd += " RFC822.HEADER.LINES.NOT (MESSAGE-ID RECEIVED))"; cmd += " RFC822.HEADER)";//// Send the command and wait for the response// if ( !PutLine(cmd) ) return False; } if ( !GetLine(response) ) return False; StringC expect("* "); expect += msgnum; expect += " FETCH "; while ( !response.StartsWith(expect, IGNORE_CASE) && !response.StartsWith(fld->fetchTag) ) { Unexpected(response); if ( !GetLine(response) ) return False; if ( response.StartsWith(fld->fetchTag) ) { response.CutBeg(fld->fetchTag.size()); return False; } }// Got a response, set the data pending flag on the server object dataPending = True;//// Parse the response// if ( response.StartsWith(expect, IGNORE_CASE) ) response.CutBeg(expect.size()); else if ( response.StartsWith(fld->fetchTag) ) response.CutBeg(fld->fetchTag.size()); if ( response.StartsWith('(') ) response.CutBeg(1); response.Trim();//// The first thing in the response line should be the flags// if ( response.StartsWith("FLAGS ", IGNORE_CASE) ) { response.CutBeg(6); StringC flgs(response); pos = flgs.PosOf(')'); if ( pos >=0 ) flgs.CutEnd(flgs.size()-pos-1); *flags = new char[flgs.size()+1]; **flags = 0; strcpy(*flags, flgs); // // Skip over the flags // pos = response.PosOf(')'); if ( pos >= 0 ) response.CutBeg(pos+1); response.Trim(); } else { Unexpected(response); return False; }//// Next should be the size of the message// if ( response.StartsWith("RFC822.SIZE", IGNORE_CASE) ) { pos = response.PosOf(' '); if ( pos >= 0 ) response.CutBeg(pos+1); response.Trim(); StringC msgSize(response); pos = msgSize.PosOf(' '); if ( pos >= 0 ) msgSize.CutEnd(msgSize.size()-pos-1); msgSize.Trim(); *bytes = atoi(msgSize); // // Skip over the size info // pos = response.PosOf(' '); if ( pos >= 0 ) response.CutBeg(pos+1); response.Trim(); } else { Unexpected(response); return False; }//// Next should be the header info, with length of headers enclosed// in curly braces. The headers will follow on subsequent lines.// if ( response.StartsWith("RFC822.HEADER", IGNORE_CASE)) { pos = response.PosOf(' '); if ( pos >= 0 ) response.CutBeg(pos+1); response.Trim(); } else { Unexpected(response); return False; }//// See if there is a length present// Boolean seenEnd = False; // flag: closing parenthesis found if ( response.StartsWith('{') ) { char *lenp = response; char *cp = ++lenp; while ( *cp != '}' ) cp++; *cp = 0; // Temporary int len = atoi(lenp);//// Allocate buffer of specified length// *output = new char[len+1]; **output = 0;//// Read until buffer is filled// int readlen = 0; while ( readlen < len && GetLine(response) ) { // // This means that the header length was too big - seems // to happen sometimes... // if (response.StartsWith(')') ) { // Got all the data, clear the data pending flag dataPending = False; seenEnd = True; break; } // // Shouldn't see these yet... // if (response.StartsWith('*') || response.StartsWith(fld->fetchTag) ) { Unexpected(response); return False; } int space = len - readlen; if ( response.size() >= space ) { strncat(*output, response, space); (*output)[len] = 0; response.CutBeg(space); readlen = len; } else { strcat(*output, response); strcat(*output, "\n"); readlen += response.size() + 2; // CRLF was stripped } } } else { Unexpected(response); return False; } //// The last response should have ended with a close parenthesis, indicating// end of the FETCH data. If we haven't seen it yet, it should be on the// next line.// if (!seenEnd) { response.Trim(); if (!response.EndsWith(')')) { GetLine(response); if (!response.EndsWith(')')) { Unexpected(response); return False; } } // Got it all, clear the data pending flag on the server object dataPending = False; } return True;} // End FetchHdrs/*------------------------------------------------------------------------ * Function to flush trailing output from a FETCH command, after * processing one or more headers. */voidImapServerC::FetchFlush( StringC& tag ){//// If last message in the folder, continue reading until we get the tag// StringC response; while ( !response.StartsWith(tag) ) { if (!GetLine(response)) return; } return;} // End FetchFlush/*------------------------------------------------------------------------ * Function to send STORE FLAGS command and wait for response. */Boolean
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -