Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

Article.cc

Go to the documentation of this file.
00001 /* Copyright (C) 2003 Herbert Straub
00002  * Original Author (Article.h) Thomas Gschwind
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 #include "Article.h"
00019 
00020 #ifdef HAVE_SSTREAM
00021 #include <sstream>
00022 #else
00023 #include <strstream>
00024 #endif
00025 
00026 using namespace std;
00027 
00028 InvalidArticleError::InvalidArticleError(const char *txt, const char *file,
00029                             const char *function, int line):NSError(txt,
00030                                                                     file,
00031                                                                     function,
00032                                                                     line)
00033 {
00034 }
00035 
00036 InvalidArticleError::InvalidArticleError(const string & txt, const char *file,
00037                               const char *function, int line):NSError(txt,
00038                                                                       file,
00039                                                                       function,
00040                                                                       line)
00041 {
00042 }
00043 
00044 void InvalidArticleError::print(void) 
00045 {
00046         slog << "Exception!\n"
00047             << "  Type: InvalidArticle\n"
00048             << "  Desc: " << _errtext << "\n";
00049 }
00050 
00051 Article::Article()
00052 {
00053 }
00054 
00055 Article::Article(Article * a)
00056         //: _nbr(a->getnbr()), _text(a->GetText()), _ctext(_text.c_str())
00057 {
00058         _nbr = a->getnbr();
00059         _text = a->GetText();
00060         _ctext = _text.c_str();
00061 
00062 }
00063 
00064 Article::Article(int artnbr)
00065 {
00066         setnbr(artnbr);
00067 }
00068 
00069 Article::Article(int artnbr, const char *text, int textlen)
00070         //: setnbr(artnbr), _text.assign(text, textlen), _ctext = _text.c_str()
00071 {
00072         setnbr(artnbr);
00073         _text.assign(text, textlen);
00074         _ctext = _text.c_str();
00075 }
00076 
00077 Article::~Article ()
00078 {
00079 }
00080 
00081 void Article::read(std::istream & is)
00082 {
00083         DEBUG(slog.p(Logger::Debug) << "Article::read(&is)\n");
00084         _text = "";
00085         readtext(is, _text);
00086         _ctext = _text.c_str();
00087 }
00088 
00089 void Article::setnbr(int nbr)
00090 {
00091         _nbr = nbr;
00092 }
00093         
00094 void Article::clear(void)
00095 {
00096         _nbr = 0;
00097         _text = "";
00098         _ctext = _text.c_str();
00099 }
00100 
00101 void Article::settext(const std::string & text)
00102 {
00103         _text = text;
00104         _ctext = _text.c_str();
00105 }
00106 
00107 int Article::getnbr(void) const
00108 {
00109         return _nbr;
00110 }
00111 
00112 string Article::GetText (void)
00113 {
00114         return _text;
00115 }       
00116         
00117 const char* Article::c_str(void)
00118 {
00119         return _ctext;
00120 }
00121         
00122 int Article::length(void) const
00123 {
00124         return _text.length();
00125 }
00126         
00127 int Article::has_field(const char *ifld)
00128 {
00129         char c;
00130 
00131         c = *find_field(ifld);
00132         if (!c || c == '\r' || c == '\n')
00133                 return 0;
00134         return 1;
00135 }
00136 
00137 const char* Article::find_field(const char *ifld) const
00138 {
00139         char hdrbuf[513], *p;
00140         const char *q, *fld;
00141         const char *ifp;
00142         unsigned int i;
00143 
00144         i = 1;
00145         p = hdrbuf;
00146         ifp = ifld;
00147         while (i < sizeof(hdrbuf) && (*p = tolower(*ifp))) {
00148                 i++;
00149                 p++;
00150                 ifp++;
00151         }
00152         if (i == sizeof(hdrbuf)) {
00153                 p--;
00154                 VERB(slog.
00155                      p(Logger::
00156                        Error) <<
00157                      "Article::find_field: field exceeds 512 characters! Contact maintainer!\n");
00158         }
00159         *p = '\0';
00160 
00161         q = _ctext;
00162         for (;;) {
00163                 p = hdrbuf;
00164                 fld = q;
00165                 while (*p && *p == tolower(*q)) {
00166                         p++;
00167                         q++;
00168                 }
00169                 if (*p == '\0')
00170                         return fld;
00171 
00172                 // bad luck find next line
00173                 while (*q && *q != '\r' && *q != '\n')
00174                         q++;
00175                 if (!*q) {
00176                         VERB(slog.
00177                              p(Logger::
00178                                Error) <<
00179                              "Article::find_field: unterminated header, no body\n");
00180                         throw
00181                             InvalidArticleError
00182                             ("unterminated header, no body",
00183                              ERROR_LOCATION);
00184                 }
00185                 // Skip first CRLF
00186                 if (*q == '\r' && *(q + 1) == '\n') {
00187                         q += 2;
00188                 } else if (*q == '\n') {
00189                         ++q;
00190                 } else {
00191                         VERB(slog.
00192                              p(Logger::
00193                                Error) <<
00194                              "Article::find_field: line not terminated with CRLF\n");
00195                         throw
00196                             InvalidArticleError
00197                             ("line not terminated with CRLF/LF",
00198                              ERROR_LOCATION);
00199                 }
00200                 if (*q == '\r' || *q == '\n')
00201                         return q;
00202         }
00203 }
00204 
00205 string Article::getfield(const char *ifld, int Full) const
00206 {
00207         string rfld;
00208         const char *p, *fld;
00209 
00210         if (strcasecmp(ifld, "bytes:") == 0) {
00211 #ifdef HAVE_SSTREAM
00212                 stringstream sb;
00213 #else
00214                 strstream sb;
00215 #endif
00216                 sb << _text.length();
00217                 return sb.rdbuf()->str();
00218         }
00219 
00220         fld = find_field(ifld);
00221         if (*fld == '\r' || *fld == '\n') {
00222                 // Bad luck, did not find the header
00223                 throw NoSuchFieldError(ifld, ERROR_LOCATION);
00224         }
00225         // found header
00226         p = fld + strlen(ifld);
00227         while (*p == ' ' || *p == '\t')
00228                 p++;
00229         if (!Full)
00230                 fld = p;
00231         while (*p && *p != '\r' && *p != '\n')
00232                 p++;
00233         rfld.assign(fld, p - fld);
00234 
00235         if (*p == '\n')
00236                 p++;
00237         else if (*p == '\r') {
00238                 if (*(p + 1) != '\n')
00239                         throw
00240                             InvalidArticleError
00241                             ("illegaly terminated line, neither <lf> nor <cr><lf>",
00242                              ERROR_LOCATION);
00243                 p += 2;
00244         }
00245         if (!(*p))
00246                 throw InvalidArticleError("article without body",
00247                                           ERROR_LOCATION);
00248 
00249         // multi-line header?
00250         while (*p == ' ' || *p == '\t') {
00251                 do {
00252                         p++;
00253                 } while (*p == ' ' || *p == '\t');
00254                 fld = p;
00255                 while (*p && *p != '\r' && *p != '\n')
00256                         p++;
00257                 rfld.append(fld, p - fld);
00258 
00259                 if (*p == '\n')
00260                         p++;
00261                 else if (*p == '\r') {
00262                         if (*(p + 1) != '\n')
00263                                 throw
00264                                     InvalidArticleError
00265                                     ("illegaly terminated line, neither <lf> nor <cr><lf>",
00266                                      ERROR_LOCATION);
00267                         p += 2;
00268                 }
00269                 if (!(*p))
00270                         throw
00271                             InvalidArticleError
00272                             ("article without body", ERROR_LOCATION);
00273         }
00274         return rfld;
00275 }
00276 
00277 void Article::setfield(const char *ifld, const char *field_data)
00278 {
00279         const char *p, *fld;
00280 
00281         fld = find_field(ifld);
00282         if (*fld == '\r' || *fld == '\n') {
00283                 // Bad luck, did not find the header
00284                 _text.insert(fld - _ctext, field_data);
00285                 _ctext = _text.c_str();
00286                 return;
00287         }
00288         // We have found the header
00289         p = fld + strlen(ifld);
00290         while (isspace(*p))
00291                 p++;
00292         while (*p && *p != '\r' && *p != '\n')
00293                 p++;
00294         ASSERT(if (!(*p)) {
00295                slog.p(Logger::Error) << "Article without body.\n";}
00296                if (*p == '\r' && !(*(p + 1))) {
00297                slog.p(Logger::Error) << "Article ended with <CR><NULL>.\n";}
00298         );
00299         if (*p == '\n')
00300                 p++;
00301         if (*p == '\r' && *(p + 1) == '\n')
00302                 p += 2;
00303 
00304         // Multiline header?
00305         while (isspace(*p) && *p != '\n' && *p != '\r') {
00306                 while (isspace(*p))
00307                         p++;
00308                 while (*p != '\r' && *p != '\n')
00309                         p++;
00310                 ASSERT(if (!(*p)) {
00311                        slog.p(Logger::Error) << "Article without body.\n";}
00312                        if (*p == '\r' && !(*(p + 1))) {
00313                        slog.
00314                        p(Logger::
00315                          Error) << "Article ended with <CR><NULL>.\n";}
00316                 );
00317                 if (*p == '\n')
00318                         p++;
00319                 if (*p == '\r' && *(p + 1) == '\n')
00320                         p += 2;
00321         }
00322         _text.replace(fld - _ctext, p - fld, field_data);
00323         _ctext = _text.c_str();
00324 }
00325 
00326 ostream & Article::write(ostream & os, int flags)
00327 {
00328         const char *p, *q;
00329 
00330         if ((flags & (Head | Body)) == (Head | Body)) {
00331                 os << _text;
00332                 return os;
00333         }
00334 
00335         p = q = _ctext;
00336         for (;;) {
00337                 while (*q && *q != '\r' && *q != '\n')
00338                         q++;
00339                 if (!*q) {
00340                         VERB(slog.
00341                              p(Logger::
00342                                Notice) <<
00343                              "Article::write: Article without body!\n");
00344                         break;
00345                 }
00346                 if (*q == '\r' && *(q + 1) == '\n'
00347                     && *(q + 2) == '\r' && *(q + 3) == '\n') {
00348                         q += 2;
00349                         break;
00350                 }
00351                 if (*q == '\n' && *(q + 1) == '\n') {
00352                         q++;
00353                         break;
00354                 }
00355                 while (*q == '\n' || *q == '\r')
00356                         q++;
00357         }
00358         if (flags & Head) {
00359                 os.write(p, q - p);
00360         } else if (flags & Body) {
00361                 if (*q == '\n')
00362                         p++;
00363                 else if (*q == '\r' && *(q + 1) == '\n')
00364                         q += 2;
00365 
00366                 os.write(q, _text.length() - (q - p));
00367         }
00368         return os;
00369 }
00370 
00371 ostream & operator <<(ostream & os, Article & art)
00372 {
00373         os << art._text;
00374         return os;
00375 }

Generated on Sun Oct 24 21:08:17 2004 for NewsCache by doxygen 1.3.6-20040222