00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
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
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
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
00223 throw NoSuchFieldError(ifld, ERROR_LOCATION);
00224 }
00225
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
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
00284 _text.insert(fld - _ctext, field_data);
00285 _ctext = _text.c_str();
00286 return;
00287 }
00288
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
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 }