http.c
上传用户:qin5330
上传日期:2007-01-05
资源大小:114k
文件大小:12k
源码类别:

搜索引擎

开发平台:

Perl

  1. /*
  2. ** Copyright (C) 1995, 1996, 1997, 1998 Hewlett-Packard Company
  3. ** Originally by Kevin Hughes, kev@kevcom.com, 3/11/94
  4. **
  5. ** This program and library is free software; you can redistribute it and/or
  6. ** modify it under the terms of the GNU (Library) General Public License
  7. ** as published by the Free Software Foundation; either version 2
  8. ** of the License, or any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU (Library) General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU (Library) General Public License
  16. **  long with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18. **--------------------------------------------------------------------
  19. ** All the code in this file added by Ron Klachko ron@ckm.ucsf.edu 9/98
  20. ** 
  21. */
  22. /*
  23. ** http.c
  24. */
  25. #ifndef _WIN32
  26. #include <unistd.h>
  27. #endif
  28. #include <time.h>
  29. #include <stdarg.h>
  30. #include "swish.h"
  31. #include "index.h"
  32. #include "hash.h"
  33. #include "string.h"
  34. #include "mem.h"
  35. #include "file.h"
  36. #include "http.h"
  37. #include "httpserver.h"
  38. static int maxdepth = 5;
  39. static int delay = 60;
  40. char tmpdir[MAXSTRLEN] = "/var/tmp";
  41. char spiderdirectory[MAXSTRLEN] = "./";
  42. multiswline *equivalentservers = 0;
  43. typedef struct urldepth {
  44.     char *url;
  45.     int depth;
  46.     struct urldepth *next;
  47. } urldepth;
  48. static int already_indexed(char *url);
  49. urldepth *add_url(urldepth *list, char *url, int depth, char *baseurl);
  50. urldepth *add_url(urldepth *list, char *url, int depth, char *baseurl)
  51. {
  52.     urldepth *item;
  53.     if (!equivalentserver(url, baseurl)) {
  54. if (verbose == 3)
  55. printf( "Skipping %s:  %sn", url, "Wrong method or server." );
  56.     } else if (maxdepth && (depth >= maxdepth)) {
  57. if (verbose == 3)
  58. printf( "Skipping %s:  %sn", url, "Too deep." );
  59.     }else if (nocontentslist && isoksuffix(url, nocontentslist)) {
  60.       if (verbose == 3)
  61. printf( "Skipping %s: %sn", url, "Wrong suffix." );
  62.       
  63.     } else if (urldisallowed(url)) {
  64.       if (verbose == 3)
  65. printf( "Skipping %s:  %sn", url, "URL disallowed by robots.txt." );
  66.     } else if (!already_indexed(url)) {
  67.       item = (urldepth *)emalloc(sizeof(urldepth));
  68.       item->url = estrdup(url);
  69.       item->depth = depth;
  70. #if 0
  71.       /* Depth first searching
  72.       **/
  73.       item->next = list;
  74.       list = item;
  75. #else
  76.       /* Breadth first searching
  77.       **/
  78.       item->next = 0;
  79.       if (!list) {
  80. list = item;
  81.       } else {
  82. urldepth *walk;
  83. for (walk = list; walk->next; walk = walk->next) {
  84. }
  85. walk->next = item;
  86.       }
  87. #endif
  88.     }
  89.     
  90.     return list;
  91. }
  92. /* Have we already indexed a file or directory?
  93. ** This function is used to avoid multiple index entries
  94. ** or endless looping due to symbolic links.
  95. */
  96. static int already_indexed(char *url)
  97. {
  98.   static struct url_info {
  99.     char *url;
  100.     struct url_info *next;
  101.   } *url_hash[BIGHASHSIZE], *p;
  102.   
  103.   int len;
  104.   unsigned hashval;
  105.   
  106.   /* Hash with via the uri alone.  Depending on the equivalent
  107.   ** servers, we may or may not make the decision of the entire
  108.   ** url or just the uri.
  109.   */
  110.   hashval = bighash(url_uri(url,&len)); /* Search hash for this file. */
  111.   for ( p = url_hash[hashval]; p != NULL; p = p->next )
  112.     if ( (strcmp(url, p->url ) == 0) ||
  113.  (equivalentserver(url, p->url) &&
  114.   (strcmp(url_uri(url, &len), url_uri(p->url, &len)) == 0)) )
  115.       {                               /* We found it. */
  116. if (verbose == 3)
  117.   printf( "Skipping %s:  %sn",
  118.   url, "Already indexed." );
  119. return 1;
  120.       }
  121.   
  122. /* Not found, make new entry. */
  123.   p = (struct url_info*)emalloc(sizeof(struct url_info));
  124.   p->url = estrdup(url);
  125.   p->next = url_hash[hashval];
  126.   url_hash[hashval] = p;
  127.   return 0;
  128. }
  129. char *url_method(char *url, int *plen)
  130. {
  131.   char *end;
  132.     if ((end = strstr( url, "://" )) == NULL) {
  133.       return NULL;
  134.     }
  135.     *plen = end - url;
  136.     return url;
  137. }
  138. char *url_serverport(char *url, int *plen)
  139. {
  140.   int methodlen;
  141.   char *serverstart;
  142.   char *serverend;
  143.   
  144.   if (url_method(url, &methodlen) == NULL) {
  145.     return NULL;
  146.   }
  147.   
  148.   /* +3 for 
  149.   **/
  150.   serverstart = url + methodlen + 3;
  151.   if ((serverend = strchr(serverstart, '/')) == NULL) {
  152.     *plen = strlen(serverstart);
  153.   } else {
  154.     *plen = serverend - serverstart;
  155.   }
  156.   
  157.   return serverstart;
  158. }
  159. char *url_uri(char *url, int *plen)
  160. {
  161.   if ((url = url_serverport(url, plen)) == 0) {
  162.     return 0;
  163.   }
  164.   url += *plen;
  165.   *plen = strlen(url);
  166.   return url;
  167. }
  168. #ifdef _WIN32
  169. #include <stdlib.h> /* _sleep() */
  170. #include <process.h> /* _getpid() */
  171. #endif
  172. int get(char *contenttype_or_redirect, time_t *plastretrieval, char *url)
  173. {
  174.   char buffer[MAXSTRLEN];
  175.   int code;
  176.   FILE *fp;
  177.   char *command;
  178. #ifdef _WIN32
  179.   char* spiderprog = "swishspider.pl";
  180.   char commandline[] = "perl %s%s %s/swishspider@%ld "%s"";
  181. #else
  182.   char* spiderprog = "swishspider";
  183.   char commandline[] = "%s%s %s/swishspider@%ld '%s'";
  184. #endif
  185.   
  186.   /* Sleep a little so we don't overwhelm the server
  187.   **/
  188.     if ((time(0) - *plastretrieval) < delay )
  189.       {
  190. int num_sec = delay - (time(0) - *plastretrieval);
  191. #ifdef _WIN32
  192. _sleep(num_sec);
  193. #else
  194. sleep(num_sec);
  195. #endif
  196. }
  197.     *plastretrieval = time(0);
  198.     /* URLs can get quite large so don't depend on a fixed size buffer.  The
  199.     ** +32 is for the pid identifier and the trailing null.
  200.     **/
  201.     command = (char *)emalloc(strlen(spiderdirectory) + strlen(url) +
  202.       strlen(tmpdir) + strlen(commandline) + strlen(spiderprog) + 32);
  203.     sprintf(command, commandline, spiderdirectory, spiderprog, tmpdir, lgetpid(), url);
  204.     
  205.     if (system(command) == 0) {
  206.       sprintf(buffer, "%s/swishspider@%ld.response", tmpdir, lgetpid());
  207.       fp = fopen(buffer, "r");
  208.       fgets(buffer, sizeof(buffer), fp);
  209.       code = atoi(buffer);
  210.       if ((code == 200) || ((code /100) == 3)) {
  211. /* read content-type  redirect
  212. **/ 
  213. fgets(contenttype_or_redirect, MAXSTRLEN, fp);
  214. *(contenttype_or_redirect + strlen(contenttype_or_redirect) - 1) = '';
  215.       }
  216.       fclose(fp);
  217.     } else {
  218.       code = 500;
  219.     }
  220.     
  221.     free(command);
  222.     
  223.     return code;
  224. }
  225. int cmdf(int (*cmd)(const char *), char *fmt, ...)
  226. {
  227.     char buffer[MAXSTRLEN];
  228.     va_list vlist;
  229.     
  230.     va_start(vlist, fmt);
  231.     /* vsnprintf(buffer, sizeof buffer, fmt, vlist);*/
  232.     vsprintf(buffer,fmt,vlist);
  233.     va_end(vlist);
  234.     return cmd(buffer);
  235. }
  236. char *readline (FILE *fp)
  237. {
  238. static char *buffer = 0;
  239.     static int buffersize = 512;
  240.     if (buffer == 0) {
  241. buffer = (char *)emalloc(buffersize);
  242.     }
  243.     /*
  244. *Try to read in the line
  245. */
  246.     if (fgets(buffer, buffersize, fp) == NULL) {
  247. return NULL;
  248.     }
  249.     /*
  250. * Make sure we read the entire line.  If not, double the buffer
  251. * size and try to read the rest
  252. */
  253.     while (buffer[strlen(buffer) - 1] != 'n') {
  254. buffer = (char *)erealloc( buffer, buffersize * 2 );
  255. /*
  256. * The easiest way to verify that this line is okay is to consider
  257. * the situation where the buffer is 2 bytes longs.  Since fgets()
  258. * always guarantees to put the trailing NULL, it will have essentially
  259. * used only 1 bytes.  We double it to four, so we now have the left
  260. * over byte (that currently contains NULL) in addition to the doubling
  261. * which gets us to read buffersize + 1.
  262. */ 
  263. if (fgets(buffer + buffersize - 1, buffersize + 1, fp) == 0) {
  264. break;
  265. }
  266. buffersize *= 2;
  267.     }
  268.     return buffer;
  269. }
  270. /* A local version of getpid() so that we don't have to suffer
  271. ** a system call each time we need it.
  272. */
  273. pid_t lgetpid()
  274. {
  275.     static pid_t pid = -1;
  276.     if (pid == -1) {
  277. #ifdef _WIN32
  278. pid = _getpid();
  279. #else
  280. pid = getpid();
  281. #endif
  282.     }
  283.     return pid;
  284. }
  285. #if 0
  286. /* Testing the robot rules parsing code...
  287. **/
  288. void http_indexpath(char *url)
  289. {
  290.     httpserverinfo *server = getserverinfo(url);
  291.     robotrules *robotrule;
  292.     printf("User-agent: %sn", server->useragent ? server->useragent : "(none)");
  293.     for (robotrule = server->robotrules; robotrule; robotrule = robotrule->next ) {
  294. printf("Disallow: %sn", robotrule->disallow);
  295.     }
  296. }
  297. #else
  298. /********************************************************/
  299. /* "Public" functions */
  300. /********************************************************/
  301. /* The main entry point for the module.  For fs.c, decides whether this
  302. ** is a file or directory and routes to the correct routine.
  303. */
  304. void http_indexpath(char *url)
  305. {
  306.     urldepth *urllist = 0;
  307.     urldepth *item;
  308.     char buffer[MAXFILELEN];
  309.     char title[MAXSTRLEN];
  310.     char contenttype[MAXSTRLEN];
  311.     int code;
  312.     FILE *fp;
  313.     int wordcount;
  314.     httpserverinfo *server;
  315.     char *link;
  316.     /* prime the pump with the first url
  317.     **/
  318.     urllist = add_url(urllist, url, 0, url);
  319.     /* retrieve each url and add urls to a certain depth
  320.     **/
  321.     while (urllist) {
  322. item = urllist;
  323. urllist = urllist->next;
  324. if (verbose >= 2) {
  325. printf("retrieving %s (%d)...n", item->url, item->depth);
  326. fflush(stdout);
  327. }
  328. /* We don't check if this url is legal here, because we do that
  329. ** before adding to the list.
  330. **/
  331. server = getserverinfo(item->url);
  332. if ((code = get(contenttype, &server->lastretrieval, item->url)) == 200) {
  333. if (strcmp(contenttype, "text/html") == 0) {
  334. sprintf(buffer, "%s/swishspider@%ld.contents", tmpdir, lgetpid());
  335. strcpy(title, (char *) parsetitle(buffer, item->url));
  336. } else {
  337. if (strrchr(item->url, '/') != NULL)
  338. strcpy(title, strrchr(item->url, '/') + 1);
  339. else
  340. strcpy(title, item->url);
  341. }
  342. /* index the file
  343. **/
  344. sprintf(buffer, "%s/swishspider@%ld.contents", tmpdir, lgetpid());
  345. if ((fp = fopen(buffer, "r")) != NULL) {
  346. wordcount = countwords(fp, item->url, title, strncmp(contenttype, "text/", 5) != 0);
  347. fclose(fp);
  348. if (verbose == 3) {
  349. if (wordcount)
  350. printf(" (%d words)n", wordcount);
  351. else
  352. printf(" (no words)n");
  353. fflush(stdout);
  354. }
  355. }
  356. /* add new links
  357. **/
  358. sprintf (buffer, "%s/swishspider@%ld.links", tmpdir, lgetpid());
  359. if ((fp = fopen(buffer, "r")) != NULL) {
  360. /* URLs can get quite large so don't depend on a fixed size buffer
  361. **/
  362. while ((link = readline(fp)) != NULL) {
  363. *(link + strlen(link) - 1) = '';
  364. urllist = add_url(urllist, link, item->depth + 1, url);
  365. }
  366. fclose (fp);
  367. }
  368. } else if ((code / 100) == 3) {
  369. urllist = add_url(urllist, contenttype, item->depth, url );
  370. }
  371. /* Clean up the files left by swishspider
  372. **/
  373. cmdf(unlink, "%s/swishspider@%ld.response", tmpdir, lgetpid());
  374. cmdf(unlink, "%s/swishspider@%ld.contents", tmpdir, lgetpid());
  375. cmdf(unlink, "%s/swishspider@%ld.links", tmpdir, lgetpid());
  376.     }
  377. }
  378. #endif
  379. int http_vgetc(void *vp)
  380. {
  381. return fgetc((FILE *)vp);
  382. }
  383. int http_vsize(void *vp)
  384. {
  385. struct stat stbuf;
  386. return fstat(fileno((FILE *)vp), &stbuf) ? -1 : stbuf.st_size;
  387. }
  388. #ifdef _WIN32
  389. #define strncasecmp strnicmp
  390. #endif
  391. int http_parseconfline(char *line)
  392. {
  393.     int rv = 0;
  394.     static char es[] = "equivalentserver";
  395.     char *word;
  396.     int skiplen;
  397.     multiswline *list;
  398.     struct swline *slist;
  399. if (grabIntValueField(line, "maxdepth", &maxdepth, 0)) { rv = 1; }
  400. else if (grabIntValueField(line, "delay", &delay, 0)) { rv = 1; }
  401. else if (grabStringValueField(line, "tmpdir", tmpdir)) { rv = 1; }
  402. else if (grabStringValueField(line, "spiderdirectory", spiderdirectory))
  403. {
  404. int len = strlen(spiderdirectory);
  405. rv = 1;
  406. /* Make sure the directory has a trailing slash
  407. **/
  408. if (len && (spiderdirectory[len - 1] != '/')) 
  409. {
  410. strcat(spiderdirectory, "/");
  411. }
  412.     }
  413. else if (strncasecmp(line, es, sizeof(es) - 1) == 0) 
  414. {
  415. rv = 1;
  416. /* Add a new list of equivalent servers
  417. **/
  418. list = (multiswline *)emalloc(sizeof(multiswline));
  419. list->next = equivalentservers;
  420. list->list = 0;
  421. equivalentservers = list;
  422. line += (sizeof(es) - 1);
  423. while (*(word = getword(line, &skiplen)) != '') {
  424. /* Add a new entry to this list
  425. **/
  426. slist = (struct swline *)emalloc(sizeof(struct swline));
  427. slist->line = estrdup(word);
  428. slist->next = list->list;
  429. list->list = slist;
  430. /* Move to the next word
  431. **/
  432. line += skiplen;
  433. }
  434.     }
  435.     return rv;
  436. }
  437. struct _indexing_data_source_def HTTPIndexingDataSource = {
  438.   "HTTP-Crawler",
  439.   "http",
  440.   http_indexpath,
  441.   http_vgetc,
  442.   http_vsize,
  443.   http_parseconfline
  444. };