00001 #include<ctype.h>
00002 #include<sys/stat.h>
00003 #include<sys/types.h>
00004 #include<stdio.h>
00005 #include<utime.h>
00006 #include<unistd.h>
00007
00008 #include"Logger.h"
00009 #include"Error.h"
00010 #include"NVNewsgroup.h"
00011
00012 using namespace std;
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef ENABLE_ASSERTIONS
00024 void NVNewsgroup::testdb(void)
00025 {
00026
00027 char *data;
00028 size_t szdata;
00029 unsigned long f, i, l;
00030
00031 int corr = 0;
00032
00033 NVArray::lock(NVcontainer::ShrdLock);
00034 NVArray::getsize(&f, &l);
00035 for (i = f; i <= l; i++) {
00036 NVArray::sget(i, &data, &szdata);
00037 if (data && *data != overview && *data != article
00038 && *data != bigarticle) {
00039 corr++;
00040 }
00041 }
00042 if (corr) {
00043 slog.
00044 p(Logger::
00045 Alert) << "NVNewsgroup::testdb: Oops, " << corr <<
00046 " errors found in database!\n";
00047 }
00048 NVArray::lock(NVcontainer::UnLock);
00049 }
00050 #endif
00051
00052 void NVNewsgroup::sprintover(ostream & os, unsigned int nbr)
00053 {
00054 char *data;
00055 size_t szdata;
00056 unsigned long f, l;
00057 string over;
00058
00059 NVArray::getsize(&f, &l);
00060 if (f <= nbr && nbr <= l) {
00061 NVArray::sget(nbr, &data, &szdata);
00062 if (data) {
00063 if (*data == article) {
00064 Article *art;
00065
00066
00067
00068
00069
00070 art =
00071 new Article(nbr, data + sizeof(char),
00072 szdata - sizeof(char) - 1);
00073 _OverviewFormat->convert(*art, over);
00074 os << over << "\r\n";
00075 delete art;
00076 } else if (*data == bigarticle
00077 || *data == overview) {
00078 os << data + sizeof(char) << "\r\n";
00079 } else {
00080
00081 VERB(slog.
00082 p(Logger::
00083 Alert) <<
00084 "NVN::sprintover(...): inconsistent newsgroup database!\n");
00085 }
00086 }
00087 }
00088 }
00089
00090 void NVNewsgroup::setsize(unsigned int f, unsigned int l)
00091 {
00092 VERB(slog.
00093 p(Logger::
00094 Debug) << "NVNewsgroup::setsize(" << f << "," << l <<
00095 ")\n");
00096 char fn[MAXPATHLEN];
00097 long n1, n2, i;
00098
00099 lock(NVcontainer::ShrdLock);
00100 if (f != arrfst || l != arrlst) {
00101 lock(NVcontainer::ExclLock);
00102 if (arrfst <= arrlst) {
00103
00104 i = 0;
00105 n1 = f - arrfst;
00106 n2 = arrlst - arrfst + 1;
00107 if (n2 < n1)
00108 n1 = n2;
00109 while ((long) i < n1) {
00110 if (arrtab[i]) {
00111 if (*
00112 (mem_p + arrtab[i] +
00113 sizeof(long)) == bigarticle) {
00114
00115 sprintf(fn, "%s/.art%lu",
00116 _SpoolDirectory,
00117 arrfst + i);
00118 unlink(fn);
00119 }
00120 nvfree(arrtab[i]);
00121 }
00122 i++;
00123 }
00124
00125
00126 i = l - arrfst + 1;
00127 if (i < 0)
00128 i = 0;
00129 n1 = arrlst - arrfst + 1;
00130 while ((long) i < n1) {
00131 if (arrtab[i]) {
00132 if (*
00133 (mem_p + arrtab[i] +
00134 sizeof(long)) == bigarticle) {
00135
00136 sprintf(fn, "%s/.art%lu",
00137 _SpoolDirectory,
00138 arrfst + i);
00139 unlink(fn);
00140 }
00141 nvfree(arrtab[i]);
00142 }
00143 i++;
00144 }
00145 }
00146
00147 NVArray::ssetsize(f, l);
00148 lock(NVcontainer::UnLock);
00149 }
00150 lock(NVcontainer::UnLock);
00151 }
00152
00153 Article *NVNewsgroup::getarticle(unsigned int nbr)
00154 {
00155 VERB(slog.
00156 p(Logger::
00157 Debug) << "NVNewsgroup::getarticle(" << nbr << ")\n");
00158 char *data;
00159 size_t szdata;
00160 unsigned long f, l;
00161 Article *art = NULL;
00162
00163 NVArray::lock(NVcontainer::ShrdLock);
00164 NVArray::getsize(&f, &l);
00165 if (nbr >= f && nbr <= l) {
00166 NVArray::sget(nbr, &data, &szdata);
00167 if (data) {
00168 if (*data == article) {
00169
00170 art =
00171 new Article(nbr, data + sizeof(char),
00172 szdata - sizeof(char) - 1);
00173 } else if (*data == bigarticle) {
00174 char fn[MAXPATHLEN];
00175 ifstream fs;
00176 sprintf(fn, "%s/.art%u", _SpoolDirectory,
00177 nbr);
00178 fs.open(fn);
00179 if (!fs.good() && errno == ENOENT) {
00180 if ((art =
00181 retrievearticle(nbr)) != NULL)
00182 setarticle(art);
00183 } else {
00184 art = new Article(nbr);
00185 art->read(fs);
00186 }
00187 fs.close();
00188 } else {
00189
00190 if ((art = retrievearticle(nbr)) != NULL)
00191 setarticle(art);
00192 }
00193 } else {
00194
00195 if ((art = retrievearticle(nbr)) != NULL)
00196 setarticle(art);
00197 }
00198 }
00199 NVArray::lock(NVcontainer::UnLock);
00200 return art;
00201 }
00202
00203 void NVNewsgroup::setarticle(Article * art)
00204 {
00205 unsigned long f, l;
00206 unsigned int nbr;
00207
00208 VERB(char buf[1024];
00209 sprintf(buf, "NVNewsgroup::setarticle(*art(nbr=%d))\n",
00210 art->getnbr()); slog.p(Logger::Debug) << buf);
00211 ASSERT2(testdb());
00212
00213 nbr = art->getnbr();
00214 NVArray::lock(NVcontainer::ExclLock);
00215 NVArray::getsize(&f, &l);
00216 if (f <= nbr && nbr <= l) {
00217 char *data;
00218 size_t szdata;
00219 unsigned long i;
00220
00221 i = nbr - arrfst;
00222 NVArray::sget(nbr, &data, &szdata);
00223 if (art->length() <= 15360) {
00224
00225 nvoff_t x;
00226 if (data) {
00227 nvfree(arrtab[i]);
00228 }
00229 szdata = art->length() + 1 + sizeof(char);
00230 x = nvalloc(szdata + sizeof(unsigned long));
00231 arrtab[i] = x;
00232 data = mem_p + x;
00233 *((unsigned long *) data) = szdata;
00234 data += sizeof(unsigned long);
00235 *data = article;
00236
00237
00238 ASSERT2(testdb());
00239 memcpy(data + sizeof(char), art->c_str(),
00240 art->length() + 1);
00241 } else if (art->length() > 15360) {
00242
00243 if (data && *data != overview
00244 && *data != bigarticle) {
00245 nvfree(arrtab[i]);
00246 data = NULL;
00247 }
00248 if (!data) {
00249 string over;
00250 nvoff_t x;
00251 _OverviewFormat->convert(*art, over);
00252 szdata = over.length() + 1 + sizeof(char);
00253 x = nvalloc(szdata +
00254 sizeof(unsigned long));
00255 arrtab[i] = x;
00256 data = mem_p + x;
00257 *((unsigned long *) (data)) = szdata;
00258 data += sizeof(unsigned long);
00259 memcpy(data + sizeof(char), over.c_str(),
00260 over.length() + 1);
00261 }
00262 *data = bigarticle;
00263 char fn[MAXPATHLEN];
00264 ofstream fs;
00265 sprintf(fn, "%s/.art%u", _SpoolDirectory, nbr);
00266 fs.open(fn);
00267 fs << *art;
00268 fs.close();
00269 *data = bigarticle;
00270 } else {
00271 VERB(slog.
00272 p(Logger::
00273 Debug) <<
00274 "NVNewsgroup::setarticle: Tried to store an existing article\n");
00275 }
00276 }
00277 lock(NVcontainer::UnLock);
00278 ASSERT2(testdb());
00279 }
00280
00281 void NVNewsgroup::printarticle(ostream & os, unsigned int nbr)
00282 {
00283 char *data;
00284 size_t szdata;
00285 unsigned long f, l;
00286
00287 NVArray::lock(NVcontainer::ShrdLock);
00288 NVArray::getsize(&f, &l);
00289 if (nbr >= f && nbr <= l) {
00290 NVArray::sget(nbr, &data, &szdata);
00291 if (data) {
00292 if (*data == article) {
00293 os << data + sizeof(char);
00294 } else if (*data == bigarticle) {
00295 Article art(nbr);
00296 char fn[MAXPATHLEN];
00297 ifstream fs;
00298 sprintf(fn, "%s/.art%u", _SpoolDirectory,
00299 nbr);
00300 fs.open(fn);
00301 art.read(fs);
00302 fs.close();
00303 os << art;
00304 } else {
00305
00306 Article *art;
00307 if ((art = retrievearticle(nbr)) != NULL)
00308 setarticle(art);
00309 os << *art;
00310 delete art;
00311 }
00312 }
00313 }
00314 NVArray::lock(NVcontainer::UnLock);
00315 }
00316
00317
00318
00319 const char *NVNewsgroup::getover(unsigned int nbr)
00320 {
00321
00322
00323 char *data;
00324 size_t szdata;
00325 unsigned long f, l;
00326 static string over;
00327
00328 over = "";
00329 NVArray::lock(NVcontainer::ShrdLock);
00330 NVArray::getsize(&f, &l);
00331 if (f <= nbr && nbr <= l) {
00332 NVArray::sget(nbr, &data, &szdata);
00333 if (data) {
00334 if (*data == article) {
00335 Article *art;
00336
00337
00338
00339
00340
00341 art =
00342 new Article(nbr, data + sizeof(char),
00343 szdata - sizeof(char) - 1);
00344 _OverviewFormat->convert(*art, over);
00345 delete art;
00346 } else if (*data == bigarticle
00347 || *data == overview) {
00348 over = data + sizeof(char);
00349 } else {
00350
00351 VERB(slog.
00352 p(Logger::
00353 Critical) <<
00354 "NVNewsgroup::getover. Oops, reached ?dead? code 936!!!\n");
00355 }
00356 }
00357 }
00358 NVArray::lock(NVcontainer::UnLock);
00359 return over.c_str();
00360 }
00361
00362 void NVNewsgroup::setover(const string & over)
00363 {
00364
00365
00366 unsigned long f, l, nbr;
00367
00368 nbr = atoi((const char *) over.c_str());
00369 NVArray::lock(NVcontainer::ExclLock);
00370 NVArray::getsize(&f, &l);
00371 if (f <= nbr && nbr <= l) {
00372 char *data;
00373 size_t szdata;
00374 unsigned long i;
00375
00376 i = nbr - arrfst;
00377 NVArray::sget(nbr, &data, &szdata);
00378 if (!data) {
00379 szdata = over.length() + 1 + sizeof(char);
00380 nvoff_t x =
00381 nvalloc(szdata + sizeof(unsigned long));
00382 arrtab[i] = x;
00383 data = mem_p + x;
00384 *((unsigned long *) (data)) = szdata;
00385 data += sizeof(unsigned long);
00386 memcpy(data + sizeof(char), over.c_str(),
00387 over.length() + 1);
00388 *data = overview;
00389 }
00390 }
00391 NVArray::lock(NVcontainer::UnLock);
00392 ASSERT2(testdb());
00393 }
00394
00395 void NVNewsgroup::readoverdb(istream & is)
00396 {
00397 VERB(slog.p(Logger::Debug) << "NVNewsgroup::readoverdb(&is)\n");
00398
00399 string line1, line2;
00400 time_t now;
00401
00402 lock(NVcontainer::ExclLock);
00403 for (;;) {
00404 nlreadline(is, line1, 0);
00405 if (line1 == "." || is.eof())
00406 break;
00407 if (_OverviewFormat->dotrans) {
00408
00409 _OverviewFormat->convert(line1, line2);
00410 setover(line2);
00411 } else {
00412 setover(line1);
00413 }
00414 }
00415
00416 time(&now);
00417 setmtime(now);
00418 lock(NVcontainer::UnLock);
00419 }
00420
00421 void NVNewsgroup::printoverdb(ostream & os, unsigned int f, unsigned int l)
00422 {
00423 VERB(slog.p(Logger::Debug) << "NVNewsgroup::printoverdb(os,"
00424 << f << "," << l << ")\n");
00425 unsigned int i;
00426 lock(NVcontainer::ShrdLock);
00427 if (f < arrfst)
00428 f = arrfst;
00429 if (arrlst < l)
00430 l = arrlst;
00431 for (i = f; i <= l; i++)
00432 sprintover(os, i);
00433 lock(NVcontainer::UnLock);
00434 }
00435
00436 void NVNewsgroup::printheaderdb(ostream & os,
00437 const char *header,
00438 unsigned int f, unsigned int l)
00439 {
00440 char *data, xheader[512], *p;
00441 string fld;
00442 const char *q;
00443 size_t szdata;
00444 unsigned long gf, i, gl;
00445
00446 p = xheader;
00447 q = header;
00448 while ((*p++ = *q++));
00449 *(p - 1) = ':';
00450 *p = '\0';
00451 NVArray::lock(NVcontainer::ShrdLock);
00452 NVArray::getsize(&gf, &gl);
00453 if (f < gf)
00454 f = gf;
00455 if (l > gl)
00456 l = gl;
00457 for (i = f; i <= l; i++) {
00458 NVArray::sget(i, &data, &szdata);
00459 if (data) {
00460 if (*data == article) {
00461 Article *art;
00462
00463
00464
00465
00466
00467
00468 art =
00469 new Article(i, data + sizeof(char),
00470 szdata - sizeof(char));
00471 try {
00472 fld = art->getfield(xheader, 0);
00473 os << i << " " << fld << "\r\n";
00474 } catch(NoSuchFieldError & nfe) {
00475 os << i << " (none)\r\n";
00476 }
00477 delete art;
00478 } else if (*data == bigarticle
00479 || *data == overview) {
00480 const char *over = data + sizeof(char);
00481 try {
00482 fld =
00483 _OverviewFormat->getfield(over,
00484 xheader,
00485 0);
00486 os << i << " " << fld << "\r\n";
00487 } catch(NoSuchFieldError & nfe) {
00488 os << i << " (none)\r\n";
00489 }
00490 }
00491 }
00492 }
00493 NVArray::lock(NVcontainer::UnLock);
00494 }
00495
00496 void NVNewsgroup::printlistgroup(ostream & os)
00497 {
00498 VERB(slog.
00499 p(Logger::Debug) << "NVNewsgroup::printlistgroup(&os)\n");
00500
00501 unsigned int i;
00502 lock(NVcontainer::ShrdLock);
00503 for (i = arrfst; i <= arrlst; i++) {
00504 if (shas_element(i))
00505 os << i << "\r\n";
00506 }
00507 lock(NVcontainer::UnLock);
00508 }