pop3.cxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <pop3.h>
00033 #include <libspopc.h>
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036 #include <cxxtls/strtool.h>
00037 #include <vector>
00038
00039 using namespace cxxtls;
00040
00041 typedef StrTool::stringlist_t stringlist;
00042
00043
00044 struct POP3::Impl
00045 {
00046 popsession *session_;
00047 int status_;
00048
00049 std::vector<POP3::Message*> messages_;
00050 std::vector<POP3::User*> users_;
00051
00052 char const* fetch_messages();
00053
00054 };
00055
00056 POP3::
00057 POP3()
00058 : impl_( new Impl )
00059 {
00060 impl_->status_ = not_connected;
00061 impl_->session_ = 0;
00062 }
00063
00064 POP3::
00065 ~POP3()
00066 {
00067 if(impl_->status_ == connected)
00068 {
00069 disconnect();
00070 }
00071
00072 size_t i;
00073
00074 for(i=0; i < impl_->messages_.size(); ++i)
00075 delete impl_->messages_[i];
00076
00077 for(i=0; i < impl_->users_.size(); ++i)
00078 delete impl_->users_[i];
00079
00080
00081 delete impl_;
00082 }
00083
00084 char const *
00085 POP3::
00086 connect( string server,
00087 string user,
00088 string password
00089 )
00090 {
00091
00092
00093
00094
00095 if(impl_->status_ == connected )
00096 return 0;
00097
00098 char const *error = popbegin(server.c_str(),
00099 user.c_str(),
00100 password.c_str(),
00101 &impl_->session_
00102 );
00103
00104 if(error)
00105 impl_->status_ = connect_failed;
00106 else
00107 {
00108 impl_->status_ = connected;
00109
00110 error = impl_->fetch_messages();
00111
00112 }
00113
00114 return error;
00115 }
00116
00117 void
00118 POP3::
00119 disconnect()
00120 {
00121 if(impl_->status_ == connected)
00122 {
00123 popend(impl_->session_);
00124 }
00125
00126 impl_->status_ = not_connected;
00127
00128 }
00129
00130 size_t
00131 POP3::
00132 messages() const
00133 {
00134 return impl_->messages_.size();
00135 }
00136
00137 int
00138 POP3::
00139 connect_status() const
00140 {
00141 return impl_->status_;
00142 }
00143
00144 char const *
00145 POP3::message_header(size_t message_index, Header** h)
00146 {
00147
00148 if(message_index > messages())
00149 return "No such message";
00150
00151 *h = &impl_->messages_[message_index]->header_;
00152
00153 return 0;
00154 }
00155
00156 char const *
00157 POP3::message_body(size_t message_index, Body** b)
00158 {
00159
00160 if(message_index > messages())
00161 return "No such message";
00162
00163 *b = &impl_->messages_[message_index]->body_;
00164
00165 return 0;
00166 }
00167
00168
00169 static void cleanse_lines(std::list<std::string> &strings, bool handle_continuations=true)
00170 {
00171
00172
00173
00174
00175
00176
00177 {
00178 int line_count=0;
00179
00180 stringlist::iterator first = strings.begin(),
00181 last = strings.end();
00182
00183 while(first != last)
00184 {
00185 ++line_count;
00186
00187 std::string& cur = *first;
00188
00189
00190
00191 if(cur.size() && cur[cur.size()-1] == '\r')
00192 {
00193 cur.erase( cur.size()-1 );
00194 }
00195
00196
00197 if(handle_continuations &&
00198 line_count != 1 &&
00199 (cur[0] == '\t' || cur[0] == ' ')
00200 )
00201 {
00202
00203
00204
00205 stringlist::iterator prev = first; --prev;
00206
00207 (*prev) += ' ';
00208 (*prev) += cur;
00209
00210 prev = first;
00211
00212 ++first;
00213
00214 strings.erase(prev);
00215
00216 }
00217 else
00218 {
00219 ++first;
00220 }
00221
00222 }
00223
00224 }
00225 }
00226
00227
00228 char const *
00229 POP3::Impl::
00230 fetch_messages()
00231 {
00232
00233
00234
00235 int i;
00236
00237 int message_count = popnum(session_);
00238
00239 for(i=0; i < message_count; ++i)
00240 {
00241
00242
00243
00244
00245
00246
00247 char *msg = popgethead(session_, i+1);
00248
00249 if(msg)
00250 {
00251 POP3::Message *m = new POP3::Message;
00252
00253 messages_.push_back(m);
00254
00255 stringlist strings;
00256
00257 StrTool::parse_lines(msg, &strings);
00258
00259 m->header_.id_ = popmsguid(session_,i+1);
00260
00261 free(msg);
00262
00263 cleanse_lines(strings);
00264
00265
00266
00267
00268 stringlist::iterator first = strings.begin(),
00269 last = strings.end();
00270
00271 while(first != last)
00272 {
00273 FileName cur = *first++;
00274
00275 if( cur.matches("[sS]ubject:*"))
00276 {
00277 cur.erase(0,8);
00278 m->header_.subject_ = cur;
00279 }
00280 else
00281 if(cur.matches("[dD]ate:*"))
00282 {
00283 cur.erase(0,6);
00284 m->header_.date_ = static_cast<std::string const &>(cur);
00285 }
00286 else
00287 if(cur.matches("[fF]rom:*"))
00288 {
00289 cur.erase(0,6);
00290
00291 stringlist fromlist;
00292
00293 StrTool::parse_words(cur, &fromlist);
00294
00295 stringlist::iterator ufirst = fromlist.begin(),
00296 ulast = fromlist.end();
00297
00298
00299
00300 while(ufirst != ulast)
00301 {
00302 string& u = *ufirst++;
00303
00304 m->header_.from_.push_back(u);
00305 }
00306
00307 }
00308 else
00309 if(cur.matches("[tT]o:*"))
00310 {
00311 cur.erase(0,4);
00312 stringlist fromlist;
00313
00314 StrTool::parse_words(cur, &fromlist);
00315
00316 stringlist::iterator ufirst = fromlist.begin(),
00317 ulast = fromlist.end();
00318
00319
00320
00321 while(ufirst != ulast)
00322 {
00323 string& u = *ufirst++;
00324
00325 m->header_.to_.push_back(u);
00326 }
00327 }
00328 else
00329 if(cur.matches("[Bb]cc:*"))
00330 {
00331 cur.erase(0,5);
00332 stringlist fromlist;
00333
00334 StrTool::parse_words(cur, &fromlist);
00335
00336 stringlist::iterator ufirst = fromlist.begin(),
00337 ulast = fromlist.end();
00338
00339
00340
00341 while(ufirst != ulast)
00342 {
00343 string& u = *ufirst++;
00344
00345 m->header_.bcc_.push_back(u);
00346 }
00347 }
00348
00349 }
00350
00351
00352
00353 msg = popgetmsg(session_, i+1);
00354
00355 if(msg)
00356 {
00357 StrTool::parse_lines(msg, &m->body_.lines_);
00358
00359 free(msg);
00360
00361 }
00362
00363
00364
00365
00366
00367
00368 for(;;)
00369 {
00370 stringlist &body = m->body_.lines_;
00371
00372 stringlist::iterator first = body.begin(),
00373 last = body.end();
00374
00375 if(first == last)
00376 break;
00377
00378 string &first_line = body.front();
00379
00380 if(first_line == "\r")
00381 break;
00382
00383 m->header_.options_.push_back(first_line);
00384
00385 body.erase( first );
00386 }
00387
00388
00389
00390 if(m->body_.lines_.begin() != m->body_.lines_.end())
00391 {
00392 if(m->body_.lines_.begin() != m->body_.lines_.end())
00393 {
00394 m->body_.lines_.erase( m->body_.lines_.begin() );
00395 }
00396 }
00397
00398 cleanse_lines(m->header_.options_);
00399 cleanse_lines(m->body_.lines_, false);
00400
00401
00402 }
00403 }
00404
00405 return 0;
00406
00407 }
00408
00409