File Coverage

blib/lib/Search/Circa/Indexer.pm
Criterion Covered Total %
statement 37 359 10.3
branch 4 138 2.9
condition 0 32 0.0
subroutine 10 33 30.3
pod 25 27 92.5
total 76 589 12.9


line stmt bran cond sub pod time code
1             package Search::Circa::Indexer;
2              
3             # module Circa::Indexer : provide function to administrate Circa
4             # Copyright 2000 A.Barbet alian@alianwebserver.com. All rights reserved.
5              
6             # $Log: Indexer.pm,v $
7             # Revision 1.39 2003/01/02 12:07:48 alian
8             # Rewrite set_host_indexed method, update POD doc
9             #
10             # Revision 1.38 2002/12/31 09:59:36 alian
11             # Update call of look_at to use hash in place of list
12             #
13             # Revision 1.37 2002/12/29 14:35:09 alian
14             # Some minor fixe suite to last update
15             #
16             # Revision 1.36 2002/12/29 13:55:17 alian
17             # Another update of pod documentation
18             #
19             # Revision 1.35 2002/12/29 03:18:37 alian
20             # Update POD documentation
21             #
22             # Revision 1.34 2002/12/29 00:45:50 alian
23             # Don't use last_update with parse_new
24             #
25             # Revision 1.33 2002/12/28 22:25:03 alian
26             # Merge addSite / addLocaleSite, use hash for parameters
27             #
28             # Revision 1.32 2002/12/27 12:56:16 alian
29             # Add cleandb method
30              
31 7     7   174065 use strict;
  7         18  
  7         275  
32 7     7   17541 use DBI;
  7         213284  
  7         555  
33 7     7   9939 use Search::Circa;
  7         29  
  7         351  
34 7     7   6999 use Search::Circa::Parser;
  7         333  
  7         585  
35              
36 7     7   51 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
  7         14  
  7         6982  
37             require Exporter;
38              
39             @ISA = qw(Exporter Search::Circa);
40             @EXPORT = qw();
41             $VERSION = ('$Revision: 1.39 $ ' =~ /(\d+\.\d+)/)[0];
42              
43             # Path of mysql binary
44             my @path_mysql = qw!/usr/bin /usr/local/bin /opt/bin /opt/local/bin
45             /usr/pkg/bin /usr/local/mysql/bin /opt/mysql/bin!;
46             push(@path_mysql, split(/:/,$ENV{PATH})) if ($ENV{PATH});
47              
48              
49             #------------------------------------------------------------------------------
50             # new
51             #------------------------------------------------------------------------------
52             sub new {
53 1     1 1 590 my $class = shift;
54 1         16 my $self = $class->SUPER::new;
55 1         2 bless $self, $class;
56 1         3 $self->{SIZE_MAX} = 1000000; # Size max of file read
57 1         3 $self->{HOST_INDEXED} = undef;
58 1         2 $self->{PROXY} = undef;
59 1         5 $self->{ConfigMoteur} = \%CircaConf::conf;
60 1 50       5 if (@_) {
61 0         0 my %vars =@_;
62 0         0 while (my($n,$v)= each (%vars))
  0         0  
63             {$self->{'ConfigMoteur'}{$n}=$v;}
64             }
65 1         3 return $self;
66             }
67              
68             #------------------------------------------------------------------------------
69             #
70             #------------------------------------------------------------------------------
71             sub connect {
72 0     0 1 0 my $self=shift;
73 0         0 $self->{PARSER} = Search::Circa::Parser->new($self);
74 0         0 return $self->SUPER::connect(@_);
75             }
76              
77             #------------------------------------------------------------------------------
78             #
79             #------------------------------------------------------------------------------
80 16     16 0 6284 sub Parser { return $_[0]->{PARSER}; }
81              
82             #------------------------------------------------------------------------------
83             # size_max
84             #------------------------------------------------------------------------------
85             sub size_max {
86 0     0 1 0 my $self = shift;
87 0 0       0 if (@_) {$self->{SIZE_MAX}=shift;}
  0         0  
88 0         0 return $self->{SIZE_MAX};
89             }
90              
91             #------------------------------------------------------------------------------
92             # cleandb
93             #------------------------------------------------------------------------------
94             sub cleandb {
95 0     0 0 0 my $self = shift;
96 0         0 my $id = shift;
97 0         0 my $r = 1;
98 0         0 my ($x) = ($self->fetch_first
99             ("select count(*) from ".$self->pre_tbl.$id."links ".
100             "where parse='1' and valide ='1'"))/2;
101 0 0       0 if ($x !=0) {
102 0         0 my $requete = "select mot,count(1) from ".
103             $self->pre_tbl.$id."relation r group by r.mot order by 2 desc limit 200";
104 0         0 my $sth = $self->{DBH}->prepare($requete);
105 0         0 $sth->execute;
106 0         0 while (my ($word,$nb)=$sth->fetchrow_array) {
107 0 0       0 $self->{DBH}->do("delete from ".$self->pre_tbl.$id."relation ".
108             "where mot = '$word'") if ($nb>$x);
109             }
110 0         0 $sth->finish;
111 0         0 return $r;
112 0         0 } else { return 0;}
113             }
114              
115             #------------------------------------------------------------------------------
116             # host_indexed
117             #------------------------------------------------------------------------------
118             sub host_indexed {
119 17     17 1 22 my $self = shift;
120 17 100       40 if (@_) {$self->{HOST_INDEXED}=shift;}
  1         4  
121 17         42 return $self->{HOST_INDEXED};
122             }
123              
124             #------------------------------------------------------------------------------
125             # set_host_indexed
126             #------------------------------------------------------------------------------
127             sub set_host_indexed {
128 1     1 1 20 my $this=shift;
129 1         3 my $url=$_[0];
130 1         5 $this->trace(3, "Circa::Indexer::set_host_indexed $url");
131 1 50       15 if ($url=~m!^(http://[^/]*)!) {$this->host_indexed($1);}
  1 0       6  
  0 0          
132 0           elsif ($url=~m!^(http://[^/]*)!) {$this->host_indexed($1);}
133 0           elsif ($url=~m!^(file:///[^/]*)!) {$this->host_indexed($1);}
134             else {$this->host_indexed($url);}
135             }
136              
137             #------------------------------------------------------------------------------
138             # proxy
139             #------------------------------------------------------------------------------
140             sub proxy {
141 0     0 1   my $self = shift;
142 0 0         if (@_) {$self->{PROXY}=shift;}
  0            
143 0           return $self->{PROXY};
144             }
145              
146             #------------------------------------------------------------------------------
147             # addSite
148             #------------------------------------------------------------------------------
149             sub addSite {
150 0     0 1   my ($self,$rc)=@_;
151             #print "$url,$email,$titre,$categorieAuto,$cgi,$rep,$file\n";
152 0   0       my $file = $rc->{masque} || ' ';
153 0 0 0       if ($rc->{cgi} and $rc->{cgi}->param('file')) {
154 0           $file=$rc->{cgi}->param('file');
155 0           my $tmpfile=$rc->{cgi}->tmpFileName($file); # chemin du fichier temp
156 0 0         if ($file=~/.*\\(.*)$/) {$file=$1;}
  0            
157 0           $file = $CircaConf::TemplateDir.$file;
158 7     7   8485 use File::Copy;
  7         20972  
  7         34217  
159 0 0         copy($tmpfile,$file)
160             or die "Impossible de creer $file avec $tmpfile:$!\n
";
161             }
162 0 0         if (!$rc->{email}) {$rc->{email}='Inconnu';}
  0            
163 0 0         if (!$rc->{titre}) {$rc->{titre}='Non fourni';}
  0            
164 0 0         if (!$rc->{categorieAuto}) {$rc->{categorieAuto}=0;}
  0            
165              
166 0           my $requete = "
167             insert into ".$self->pre_tbl."responsable (email,titre,categorieAuto,masque)
168             values ('$rc->{email}',
169             '$rc->{titre}',
170             '$rc->{categorieAuto}',
171             '$file')";
172 0           my $sth = $self->{DBH}->prepare($requete);
173 0 0         $sth->execute || $self->trace(3, $DBI::errstr.$requete);
174 0           $sth->finish;
175 0           my $id = $sth->{'mysql_insertid'};
176 0           $self->create_table_circa_id($id);
177 0           my %h = (url => $rc->{url}, valide =>1);
178              
179             # Site avec double url
180             # Params orig, dest
181 0 0         if ($rc->{orig}) {
182 0           $h{urllocal} = $rc->{url};
183 0           $h{urllocal}=~s/$rc->{dest}/$rc->{orig}/;
184 0           my $requete = "insert into ".$self->pre_tbl."local_url
185             values($id,'$rc->{orig}','$rc->{dest}')";
186 0           $self->trace(3, $requete);
187 0           $self->{DBH}->do($requete);
188             }
189              
190 0           $self->URL->add($id,%h);
191 0           return $id;
192             }
193              
194             #------------------------------------------------------------------------------
195             # parse_new_url
196             #------------------------------------------------------------------------------
197             sub parse_new_url {
198 0     0 1   my ($self,$idp)=@_;
199 0 0         print "Indexer::parse_new_url\n" if ($self->{DEBUG});
200 0           my ($nb,$nbAjout,$nbWords,$nbWordsGood)=(0,0,0,0);
201 0           my $tab = $self->URL->need_parser($idp);
202 0           my $categorieAuto = $self->categorie->auto($idp);
203 0           $self->Parser->{toindex} = scalar keys %{$tab};
  0            
204 0           $self->Parser->{inindex} = 0;
205              
206 0           foreach my $id (keys %$tab) {
207 0           $self->Parser->{inindex}++;
208 0           my ($url,$local_url,$niveau,$categorie,$lu)=$$tab{$id};
209 0   0       my ($res,$nbw,$nbwg) =
210             $self->Parser->look_at({ url => $$tab{$id}[0],
211             idc => $id,
212             idr => $idp,
213             url_local => $$tab{$id}[1] || undef,
214             categorieAuto => $categorieAuto,
215             niveau => $$tab{$id}[2],
216             categorie => $$tab{$id}[3]});
217 0 0         if ($res==-1) {$self->URL->non_valide($idp,$id);}
  0            
  0            
218 0           else {$nbAjout+=$res;$nbWords+=$nbw;$nb++;$nbWordsGood+=$nbwg;}
  0            
  0            
219             }
220 0           return ($nb,$nbAjout,$nbWords,$nbWordsGood);
221             }
222              
223              
224             #------------------------------------------------------------------------------
225             # update
226             #------------------------------------------------------------------------------
227             sub update {
228 0     0 1   my ($this,$xj,$idp)=@_;
229 0 0         $idp = 1 if (!$idp);
230 0           $this->parse_new_url($idp);
231 0           my ($nb,$nbAjout,$nbWords,$nbWordsGood)=(0,0,0,0);
232 0           my $tab = $this->URL->need_update($idp,$xj);
233 0           my $categorieAuto = $this->categorie->auto($idp);
234 0           $this->Parser->{toindex} = scalar keys %{$tab};
  0            
235 0           $this->Parser->{inindex} = 0;
236 0           foreach my $id (keys %$tab) {
237 0           $this->Parser->{inindex}++;
238 0           my ($url,$local_url,$niveau,$categorie,$lu) = $$tab{$id};
239 0   0       my ($res,$nbw,$nbwg) =
      0        
240             $this->Parser->look_at( { url => $$tab{$id}[0],
241             idc => $id,
242             idr => $idp,
243             lastModif => $$tab{$id}[4] || undef,
244             url_local => $$tab{$id}[1] ||undef,
245             categorieAuto => $categorieAuto,
246             niveau => $$tab{$id}[2],
247             categorie => $$tab{$id}[3]});
248 0 0         if ($res==-1) {$this->URL->non_valide($idp,$id);}
  0            
  0            
249 0           else {$nbAjout+=$res;$nbWords+=$nbw;$nb++;$nbWordsGood+=$nbwg;}
  0            
  0            
250             }
251 0           return ($nb,$nbAjout,$nbWords,$nbWordsGood);
252             }
253              
254             #------------------------------------------------------------------------------
255             # create_table_circa
256             #------------------------------------------------------------------------------
257             sub create_table_circa
258             {
259 0     0 1   my $self = shift;
260 0           my $r = 1;
261 0           my $requete="
262             CREATE TABLE ".$self->pre_tbl."responsable (
263             id int(11) DEFAULT '0' NOT NULL auto_increment,
264             email char(25) NOT NULL,
265             titre char(50) NOT NULL,
266             categorieAuto tinyint DEFAULT '0' NOT NULL,
267             masque char(150) NOT NULL,
268             PRIMARY KEY (id)
269             )";
270              
271 0 0         $self->{DBH}->do($requete) || ($r = 0 && print $DBI::errstr,"
\n");
272 0           $requete="
273             CREATE TABLE ".$self->pre_tbl."inscription (
274             email char(25) NOT NULL,
275             url varchar(255) NOT NULL,
276             titre char(50) NOT NULL,
277             dateins date
278             )";
279 0 0         $self->{DBH}->do($requete) || ($r = 0 && print $DBI::errstr,"
\n");
280              
281 0           $requete="
282             CREATE TABLE ".$self->pre_tbl."local_url (
283             id int(11) NOT NULL,
284             path varchar(255) NOT NULL,
285             url varchar(255) NOT NULL
286             )";
287 0 0         $self->{DBH}->do($requete) || ($r = 0 && print $DBI::errstr,"
\n");
288 0           return $r;
289             }
290              
291             #------------------------------------------------------------------------------
292             # drop_table_circa
293             #------------------------------------------------------------------------------
294             sub drop_table_circa {
295 0     0 1   my $self = shift;
296 0           my $sth = $self->{DBH}->prepare
297             ("select id from ".$self->pre_tbl."responsable");
298 0 0         if ($sth->execute()) {
299 0           while (my @row=$sth->fetchrow_array) {
300 0 0         $self->drop_table_circa_id($row[0]) if ($row[0]);
301             }
302 0           $sth->finish;
303 0 0         $self->{DBH}->do("drop table ".$self->pre_tbl."responsable")
304             || print $DBI::errstr,"
\n";
305 0 0         $self->{DBH}->do("drop table ".$self->pre_tbl."inscription")
306             || print $DBI::errstr,"
\n";
307 0 0         $self->{DBH}->do("drop table ".$self->pre_tbl."local_url")
308             || print $DBI::errstr,"
\n";
309 0           } else { $self->trace(1,"drop_table_circa $DBI::errstr\n"); }
310             }
311              
312             #------------------------------------------------------------------------------
313             # drop_table_circa_id
314             #------------------------------------------------------------------------------
315             sub drop_table_circa_id
316             {
317 0     0 1   my $self = shift;
318 0           my $id=$_[0];
319 0 0         $self->{DBH}->do("drop table ".$self->pre_tbl.$id."categorie")
320             || return 0;
321 0 0         $self->{DBH}->do("drop table ".$self->pre_tbl.$id."links")
322             || return 0;
323 0 0         $self->{DBH}->do("drop table ".$self->pre_tbl.$id."relation")
324             || return 0;
325 0 0         $self->{DBH}->do("drop table ".$self->pre_tbl.$id."stats")
326             || return 0;
327 0 0         $self->{DBH}->do
328             ("delete from ".$self->pre_tbl."local_url where id=$id")
329             || return 0;
330 0 0         $self->{DBH}->do
331             ("delete from ".$self->pre_tbl."responsable where id=$id")
332             || return 0;
333 0           return 1;
334             }
335              
336             #------------------------------------------------------------------------------
337             # create_table_circa_id
338             #------------------------------------------------------------------------------
339             sub create_table_circa_id
340             {
341 0     0 1   my $self = shift;
342 0           my $id=$_[0];
343 0           my $requete="
344             CREATE TABLE ".$self->pre_tbl.$id."categorie (
345             id int(11) DEFAULT '0' NOT NULL auto_increment,
346             nom char(50) NOT NULL,
347             parent int(11) DEFAULT '0' NOT NULL,
348             masque varchar(255),
349             PRIMARY KEY (id)
350             )";
351 0 0         $self->{DBH}->do($requete) || print $DBI::errstr,"
\n";
352              
353 0           $requete="
354             CREATE TABLE ".$self->pre_tbl.$id."links (
355             id int(11) DEFAULT '0' NOT NULL auto_increment,
356             url varchar(255) NOT NULL,
357             local_url varchar(255),
358             titre varchar(255) NOT NULL,
359             description blob NOT NULL,
360             langue char(6) NOT NULL,
361             valide tinyint DEFAULT '0' NOT NULL,
362             categorie int(11) DEFAULT '0' NOT NULL,
363             last_check datetime DEFAULT '0000-00-00' NOT NULL,
364             last_update datetime DEFAULT '0000-00-00' NOT NULL,
365             parse ENUM('0','1') DEFAULT '0' NOT NULL,
366             browse_categorie ENUM('0','1') DEFAULT '0' NOT NULL,
367             niveau tinyint DEFAULT '0' NOT NULL,
368             PRIMARY KEY (id),
369             KEY id (id),
370             UNIQUE id_2 (id),
371             KEY id_3 (id),
372             KEY url (url),
373             UNIQUE url_2 (url),
374             KEY categorie (categorie)
375             )";
376 0 0         $self->{DBH}->do($requete) || print $DBI::errstr,"
\n";
377              
378 0           $requete="
379             CREATE TABLE ".$self->pre_tbl.$id."relation (
380             mot char(30) NOT NULL,
381             id_site int(11) DEFAULT '0' NOT NULL,
382             facteur tinyint(4) DEFAULT '0' NOT NULL,
383             KEY mot (mot)
384             )";
385 0 0         $self->{DBH}->do($requete) || print $DBI::errstr,"
\n";
386 0           $requete="
387             CREATE TABLE ".$self->pre_tbl.$id."stats (
388             id int(11) DEFAULT '0' NOT NULL auto_increment,
389             requete varchar(255) NOT NULL,
390             quand datetime NOT NULL,
391             PRIMARY KEY (id)
392             )";
393 0 0         $self->{DBH}->do($requete) || print $DBI::errstr,"
\n";
394             }
395              
396             #------------------------------------------------------------------------------
397             # export
398             #------------------------------------------------------------------------------
399             sub export {
400 0     0 1   my ($self,$dump,$path,$id)=@_;
401 0           my ($pass, $file, $host, $user);
402 0 0         if (!$path) { $path=$CircaConf::export; }
  0            
403 0 0         if (!$path) { $path="/tmp"; }
  0            
404 0           $file=$path."/circa";
405 0 0         $file.=$id unless !$id;
406 0           $file.=".sql";
407 0           $file=~s/\/\//\//g;
408              
409 0 0 0       if ( (! -w $path) || ( ( -e $file) && (!-w $file)))
  0   0        
410 0           {$self->close; die "Can't create $file (not enough rights ?):$!\n";}
411 0 0 0       if ( (!$dump) || (! -x $dump)) {
412 0           foreach (@path_mysql) {
413 0 0         if (-x $_."/mysqldump") {$dump = "$_/mysqldump" ; last; }
  0            
  0            
414             }
415             }
416 0 0 0       if ( (!$dump) || (! -x $dump)) {
417 0           $self->close; die "Can't find mysqldump.\n";
  0            
418             }
419 0 0 0       if ((-e $file) && (!(unlink $file)))
420 0           { $self->close; die "Can't unlink $file:$!\n";}
  0            
421              
422 0           my (@t,@exec);
423              
424 0 0         if (!$id) {
425 0           my $requete = "select id from ".$self->pre_tbl."responsable";
426 0 0         $requete.= " where id = $id" unless (!$id);
427 0           my $sth = $self->{DBH}->prepare($requete);
428 0           $sth->execute;
429 0           while (my ($id)=$sth->fetchrow_array) {push(@t,$id);}
  0            
430 0           $sth->finish;
431             }
432 0           else { push(@t,$id); }
433              
434 0 0         if ($self->{_PASSWORD}) {$pass=" -p".$self->{_PASSWORD}.' ';}
  0            
  0            
435             else {$pass=' ';}
436              
437 0 0         if ($self->{_HOST}) {$host=" -h".$self->{_HOST}.' ';}
  0            
  0            
438             else {$host=' ';}
439 0           my $option = " -u".$self->{_USER}.
440             $pass.$host.$self->{_DB}." ".$self->pre_tbl;
441 0 0         if (!$id)
442             {
443 0           $option=" --add-drop-table ".$option;
444 0           push(@exec,$dump.$option."responsable >> $file");
445 0           push(@exec,$dump.$option."local_url >> $file");
446 0           push(@exec,$dump.$option."inscription >> $file");
447             }
448 0           else { $option=" --no-create-info ".$option; }
449              
450 0           foreach my $id (@t)
451             {
452 0           my $opt = $option.$id;
453 0           my $p = $self->pre_tbl.$id;
454 0           push(@exec,"echo 'DELETE FROM ".$p."categorie;'>> $file");
455 0           push(@exec,$dump.$opt."categorie >> $file");
456 0           push(@exec,"echo 'DELETE FROM ".$p."links;'>> $file");
457 0           push(@exec,$dump.$opt."links >> $file");
458 0           push(@exec,"echo 'DELETE FROM ".$p."relation;'>> $file");
459 0           push(@exec,$dump.$opt."relation >> $file");
460             }
461 0           $|=1;
462 0           print "En cours d'export ...";
463 0           $self->trace(2," ");
464 0           foreach (@exec)
465             {
466 0           $self->trace(2,"\t$_");
467 0 0         system($_) ==0 or print "Fail:$?-$!\n";
468             }
469 0           print "$file done.\n";
470             }
471              
472              
473             #------------------------------------------------------------------------------
474             # import_data
475             #------------------------------------------------------------------------------
476             sub import_data
477             {
478 0     0 1   my ($self,$dump,$path)=@_;
479 0           my ($pass,$file);
480 0 0         if (!$path) { $path=$CircaConf::export; }
  0            
481 0 0         if (!$path) { $path="/tmp"; }
  0            
482 0           $file=$path."/circa.sql";$file=~s/\/\//\//g;
  0            
483 0 0         if (! -r $file) {$self->close; die "Can't find $file:$!\n";}
  0            
  0            
484 0 0 0       if ( (!$dump) || (! -x $dump)) {
485 0           foreach (@path_mysql) {
486 0 0         if (-x $_."/mysql") {$dump = "$_/mysql" ; last; }
  0            
  0            
487             }
488             }
489 0 0 0       if ( (!$dump) || (! -x $dump)) {
490 0           $self->close; die "Can't find mysql.\n";
  0            
491             }
492 0           $|=1;
493 0           print "En cours d'import ...";
494 0           my $c = $dump." -u".$self->{_USER};
495 0 0         $c.=" -p".$self->{_PASSWORD}." " if ($self->{_PASSWORD});
496 0 0         $c.=" -h".$self->{_HOST}." " if ($self->{_HOST});
497 0           $c.=" ".$self->{_DB}." < ".$file;
498 0 0         system($c) == 0 or print "Fail:$c:$?\n";
499 0           print "$file imported.\n";
500             }
501              
502             #------------------------------------------------------------------------------
503             # admin_compte
504             #------------------------------------------------------------------------------
505             sub admin_compte
506             {
507 0     0 1   my ($self,$compte)=@_;
508 0           my %rep;
509 0           my $pre = $self->pre_tbl.$compte;
510 0           ($rep{'responsable'},$rep{'titre'}) =
511             $self->fetch_first("select email,titre from ". $self->pre_tbl.
512             "responsable where id=$compte");
513             # there is no account $compte defined
514 0 0         if (!$rep{'responsable'}) {return (undef);}
  0            
515             # First url added
516 0           ($rep{'racine'})=$self->fetch_first("select min(id) from ".$pre."links");
517 0 0         if ($rep{'racine'}) {
518 0           ($rep{'racine'})=$self->fetch_first("select url from ".$pre."links ".
519             "where id=".$rep{'racine'});
520             }
521             # Number of links
522 0           ($rep{'nb_links'}) = $self->fetch_first("select count(1) from ".$pre."links");
523             # Number of parsed links
524 0           ($rep{'nb_links_parsed'}) =
525             $self->fetch_first("select count(1) from ".$pre."links where parse='1'");
526             # Number of parsed valid links
527 0           ($rep{'nb_links_valide'}) =
528             $self->fetch_first("select count(1) from ".$pre."links ".
529             "where parse='1' and valide ='1'");
530             # Max depth reached
531 0           $rep{'depth_max'} = $self->fetch_first("select max(niveau) ".
532             "from ".$pre."links");
533             # Account last indexed on
534 0           ($rep{'last_index'}) =
535             $self->fetch_first("select max(last_check) from ".$pre."links");
536             # Stats ... how many request ?
537 0           ($rep{'nb_request'}) =
538             $self->fetch_first("select count(1) from ".$pre."stats");
539             # Number of word
540 0           ($rep{"nb_words"}) =
541             $self->fetch_first("select count(1) from ".$pre."relation");
542 0           ($rep{"orig"},$rep{"dest"}) =
543             $self->fetch_first("select path, url from ".$self->pre_tbl."local_url ".
544             "where id = $compte");
545             # Return reference of hash
546 0           return \%rep;
547             }
548              
549              
550             #------------------------------------------------------------------------------
551             # most_popular_word
552             #------------------------------------------------------------------------------
553             sub most_popular_word
554             {
555 0     0 1   my $self = shift;
556 0           my ($max,$id)=@_;
557 0 0         $id =1 if (!$id);
558 0           my %l;
559 0           my $requete = "select mot,count(1) from ".
560             $self->pre_tbl.$id."relation r group by r.mot order by 2 ".
561             "desc limit 0,$max";
562 0           my $sth = $self->{DBH}->prepare($requete);
563 0           $sth->execute;
564 0           while (my ($word,$nb)=$sth->fetchrow_array) {$l{$word}=$nb;}
  0            
565 0           $sth->finish;
566 0           return \%l;
567             }
568              
569              
570             #------------------------------------------------------------------------------
571             # stat_request
572             #------------------------------------------------------------------------------
573             sub stat_request
574             {
575 0     0 1   my ($self,$id)=@_;
576 0           my (%l1,%l2);
577 0           my $requete = "select count(1), DATE_FORMAT(quand, '%e/%m/%y') as d ".
578             "from ".$self->pre_tbl.$_[1]."stats group by d order by d";
579 0           my $sth = $self->{DBH}->prepare($requete);
580 0           $sth->execute;
581 0           while (my ($nb,$word)=$sth->fetchrow_array) {$l1{$word}=$nb;}
  0            
582 0           $sth->finish;
583              
584 0           $requete = "select requete,count(requete) ".
585             "from ".$self->pre_tbl.$_[1]."stats ".
586             "group by 1 order by 2 desc limit 0,10";
587 0           $sth = $self->{DBH}->prepare($requete);
588 0           $sth->execute;
589 0           while (my ($word,$nb)=$sth->fetchrow_array) {$l2{$word}=$nb;}
  0            
590 0           $sth->finish;
591              
592 0           return (\%l1,\%l2);
593             }
594              
595             #------------------------------------------------------------------------------
596             # inscription
597             #------------------------------------------------------------------------------
598 0     0 1   sub inscription {$_[0]->do("insert into ".$_[0]->pre_tbl."inscription values ('$_[1]','$_[2]','$_[3]',CURRENT_DATE)");}
599              
600              
601             #------------------------------------------------------------------------------
602             # header_compte
603             #------------------------------------------------------------------------------
604             sub header_compte
605             {
606 0     0 1   my ($self,$cgi,$id,$script)=@_;
607 0           my $v = "
608 0           my $buf='
    '."\n".
609             $cgi->li($v."\">Infos générales")."\n" .
610             $cgi->li($v."&ecran_stats=1\">Statistiques")."\n".
611             $cgi->li($v."&ecran_urls=1\">Gestion des url")."\n".
612             $cgi->li($v."&ecran_validation=1\">Validation des url")."\n".
613             $cgi->li($v."&ecran_categorie=1\">Gestion des categories")."\n".
614             ''."\n";
615 0           return $buf;
616             }
617              
618             #------------------------------------------------------------------------------
619             # Get_liste_liens
620             #------------------------------------------------------------------------------
621             sub get_liste_liens
622             {
623 0     0 1   my ($self,$id,$cgi)=@_;
624 0           my $tab = $self->URL->liens($id);
625 0           my @l =sort { $$tab{$a} cmp $$tab{$b} } keys %$tab;
  0            
626             # Get down size of url with length>80
627 0           foreach my $v (keys %$tab)
628             {
629 0           my $l = length($$tab{$v});
630 0 0         if ($l>80)
631 0           { $$tab{$v} =
632             substr($$tab{$v},0,30) .
633             '...'.
634             substr($$tab{$v},$l-50);
635             }
636             }
637 0           return $cgi->scrolling_list( -'name' =>'id',
638             -'values' =>\@l,
639             -'size' =>1,
640             -'labels' =>$tab);
641             }
642              
643             #------------------------------------------------------------------------------
644             # get_liste_liens_a_valider
645             #------------------------------------------------------------------------------
646             sub get_liste_liens_a_valider
647             {
648 0     0 1   my ($self,$id,$cgi)=@_;
649 0           my $tab = $self->URL->a_valider($id);
650 0           my $buf='';
651 0           my @l =sort { $$tab{$a} cmp $$tab{$b} } keys %$tab;
  0            
652 0           foreach (@l)
653             {
654 0           $buf.=$cgi->Tr(
655             $cgi->td(""),
656             $cgi->td("$$tab{$_}")
657             )."\n";
658             }
659 0           $buf.='
';
660 0           return $buf;
661             }
662              
663             #------------------------------------------------------------------------------
664             # get_liste_site
665             #------------------------------------------------------------------------------
666             sub get_liste_site {
667 0     0 1   my ($self,$cgi)=@_;
668 0           my %tab;
669 0           my $sth = $self->{DBH}->prepare("select id,email,titre from ".
670             $self->pre_tbl."responsable");
671 0 0         if ($sth->execute()) {
672 0           while (my @row=$sth->fetchrow_array) {$tab{$row[0]}="$row[1]/$row[2]";}
  0            
673 0           $sth->finish;
674 0           my @l =sort { $tab{$a} cmp $tab{$b} } keys %tab;
  0            
675 0           return $cgi->scrolling_list( -'name'=>'id',
676             -'values'=>\@l,
677             -'size'=>1,
678             -'labels'=>\%tab);
679             }
680             else {
681 0           $self->trace(1,"Circa::Indexer->get_liste_site $DBI::errstr\n");
682 0           return undef;
683             }
684             }
685              
686             #------------------------------------------------------------------------------
687             # get_liste_mot
688             #------------------------------------------------------------------------------
689             sub get_liste_mot
690             {
691 0     0 1   my ($self,$compte,$id)=@_;
692 0           my @l;
693 0           my $sth = $self->{DBH}->prepare("select mot from ".$self->pre_tbl.$compte."relation where id_site=$id");
694 0 0         $sth->execute() || print "Erreur: $DBI::errstr\n";
695 0           while (my ($l)=$sth->fetchrow_array) {push(@l,$l);}
  0            
696 0           return join(' ',@l);
697             }
698              
699             #------------------------------------------------------------------------------
700             # get_liste_langues
701             #------------------------------------------------------------------------------
702             sub get_liste_langues
703             {
704 0     0 1   my ($self,$id,$valeur,$cgi)=@_;
705 0           my @l;
706 0           my $sth = $self->{DBH}->prepare("select distinct langue ".
707             "from ".$self->pre_tbl.$id."links");
708 0 0         $sth->execute() || print "Erreur: $DBI::errstr\n";
709 0           while (my ($l)=$sth->fetchrow_array) {push(@l,$l);}
  0            
710 0           $sth->finish;
711 0           my %langue=(
712             'unkno'=>'unkno',
713             'da'=>'Dansk',
714             'de'=>'Deutsch',
715             'en'=>'English',
716             'eo'=>'Esperanto',
717             'es'=>'Espanõl',
718             'fi'=>'Suomi',
719             'fr'=>'Francais',
720             'hr'=>'Hrvatski',
721             'hu'=>'Magyar',
722             'it'=>'Italiano',
723             'nl'=>'Nederlands',
724             'no'=>'Norsk',
725             'pl'=>'Polski',
726             'pt'=>'Portuguese',
727             'ro'=>'Românã',
728             'sv'=>'Svenska',
729             'tr'=>'TurkCe',
730             '0'=>'All'
731             );
732 0           my $scrollLangue =
733             $cgi->scrolling_list( -'name'=>'langue',
734             -'values'=>\@l,
735             -'size'=>1,
736             -'default'=>$valeur,
737             -'labels'=>\%langue);
738             }
739              
740             #------------------------------------------------------------------------------
741             # POD DOCUMENTATION
742             #------------------------------------------------------------------------------
743              
744             =head1 NAME
745              
746             Circa::Indexer - provide functions to administrate Circa,
747             a www search engine running with Mysql
748              
749             =head1 SYNOPSIS
750              
751             use Circa::Indexer;
752             my $indexor = new Circa::Indexer;
753            
754             die "Erreur à la connection MySQL:$DBI::errstr\n"
755             if (!$indexor->connect);
756            
757             $indexor->create_table_circa;
758            
759             $indexor->drop_table_circa;
760            
761             $indexor->addSite({url => "http://www.alianwebserver.com/",
762             email => 'alian@alianwebserver.com',
763             title => "Alian Web Server"});
764            
765             my ($nbIndexe,$nbAjoute,$nbWords,$nbWordsGood) = $indexor->parse_new_url(1);
766             print "$nbIndexe pages indexées,"
767             "$nbAjoute pages ajoutées,"
768             "$nbWordsGood mots indexés,"
769             "$nbWords mots lus\n";
770            
771             $indexor->update(30,1);
772              
773             Look too in L,admin.cgi,admin_compte.cgi
774              
775             =head1 DESCRIPTION
776              
777             This is Circa::Indexer, a module who provide functions
778             to administrate Circa, a www search engine running with
779             Mysql. Circa is for your Web site, or for a list of sites.
780             It indexes like Altavista does. It can read, add and
781             parse all url's found in a page. It add url and word
782             to MySQL for use it at search.
783              
784             This module provide routine to :
785              
786             =over
787              
788             =item *
789              
790             Add url
791              
792             =item *
793              
794             Create and update each account
795              
796             =item *
797              
798             Parse url, Index words, and so on.
799              
800             =item *
801              
802             Provide routine to administrate present url
803              
804             =back
805              
806             Remarques:
807              
808             =over
809              
810             =item *
811              
812             This file are not added : doc,zip,ps,gif,jpg,gz,pdf,eps,png,
813             deb,xls,ppt,class,GIF,css,js,wav,mid
814              
815             =item *
816              
817             Weight for each word is in hash $ConfigMoteur
818              
819             =back
820              
821             =head2 How it's work ?
822              
823             Circa parse html document. convert it to text. It count all
824             word found and put result in hash key. In addition of that,
825             it read title, keywords, description and add a weight to
826             all word found.
827              
828             Example:
829             A config:
830              
831             my %ConfigMoteur=(
832             'author' => 'circa@alianwebserver.com', # Responsable du moteur
833             'temporate' => 1, # Temporise les requetes sur le serveur de 8s.
834             'facteur_keyword' => 15, #
835             'facteur_description' => 10, #
836             'facteur_titre' => 10, #
837             'facteur_full_text' => 1, # reste
838             'facteur_url' => 15, # Mots trouvés dans l'url
839             'nb_min_mots' => 2, # facteur min pour garder un mot
840             'niveau_max' => 7, # Niveau max à indexer
841             'indexCgi' => 0, # Index lien des CGI (ex: ?nom=toto&riri=eieiei)
842             );
843              
844             A html document:
845              
846            
847            
848            
849             CONTENT="informatique,computing,javascript,CGI,perl">
850            
851             CONTENT="Rubriques Informatique (Internet,Java,Javascript, CGI, Perl)">
852             Alian Web Server:Informatique,Société,Loisirs,Voyages
853            
854            
855             different word: cgi, perl, cgi
856            
857            
858              
859             After parsing I've a hash with that:
860              
861             $words{'informatique'}= 15 + 10 + 10 =35
862             $words{'cgi'} = 15 + 10 +1
863             $words{'different'} = 1
864              
865             Words is add to database if total found is > $ConfigMoteur{'nb_min_mots'}
866             (2 by default). But if you set to 1, database will grow very quicly but
867             allow you to perform very exact search with many worlds so you can do phrase
868             searches. But if you do that, think to take a look at size of table
869             relation.
870              
871             After page is read, it's look into html link. And so on. At each time, the level
872             grow to one. So if < to $Config{'niveau_max'}, url is added.
873              
874             =head1 Class Interface
875              
876             =head2 Constructors and Instance Methods
877              
878             =over
879              
880             =item B I
881              
882             You can use the following keys in PARAMHASH:
883              
884             =over
885              
886             =item author
887              
888             Default: 'circa@alianwebserver.com', appear in log file of web server indexed (as agent)
889              
890             =item temporate
891              
892             Default: 1, boolean. If true, wait 8s between request on same server and
893             LWP::RobotUA will be used. Else this is LWP::UserAgent (more quick because it
894             doesn't request and parse robots.txt rules, but less clean because a robot must always
895             say who he is, and heavy server load is avoid).
896              
897             =item facteur_keyword
898              
899             Default: 15, weight of word found on meta KeyWords
900              
901             =item facteur_description
902              
903             Default:10, weight of word found on meta description"
904              
905             =item facteur_titre
906              
907             Default:10, weight of word found on
908              
909             =item facteur_full_text
910              
911             Default:1, weight of word found on rest of page
912              
913             =item facteur_url
914              
915             Default: 15, weight of word found in url
916              
917             =item nb_min_mots
918              
919             Default: 2, minimal number of times a word must be found to be added
920              
921             =item niveau_max
922              
923             Default: 7, Maximal number of level of links to follow
924              
925             =item indexCgi
926              
927             Default 0, follow of not links of CGI (ex: ?nom=toto&riri=eieiei)
928              
929             =back
930              
931             =item B I
932              
933             Get or set size max of file read by indexer (For avoid memory pb).
934              
935             =item B I
936              
937             Get or set the host indexed.
938              
939             =item B I
940              
941             Set base directory with $url. It's used for restrict access
942             only to files found on sub-directory on this serveur.
943              
944             =item B I
945              
946             Get or set proxy for LWP::Robot or LWP::Agent
947              
948             Ex: $circa->proxy('http://proxy.sn.no:8001/');
949              
950             =back
951              
952             =head2 Methods use for global adminstration
953              
954             =over
955              
956             =item B I
957              
958             I can have these keys: url, email, title, categorieAuto,
959             cgi, rep, file
960              
961             Create account with first url I. Return id of account created
962              
963             =item B I
964              
965             Parse les pages qui viennent d'être ajoutée. Le programme va analyser toutes
966             les pages dont la colonne 'parse' est égale à 0.
967              
968             Retourne le nombre de pages analysées, le nombre de page ajoutées, le
969             nombre de mots indexés.
970              
971             =item B I
972              
973             Update url not visited since I for account I.
974             If idp is not given, 1 will be used. Url never parsed will be indexed.
975              
976             Return ($nb,$nbAjout,$nbWords,$nbWordsGood)
977              
978             =over
979              
980             =item *
981              
982             $nb: Number of links find
983              
984             =item *
985              
986             $nbAjout: Number of links added
987              
988             =item *
989              
990             $nbWords: Number of word find
991              
992             =item *
993              
994             $nbWordsGood: Number of word added
995              
996             =back
997              
998             =cut
999              
1000             =item B
1001              
1002             Create tables needed by Circa - Cree les tables necessaires à Circa:
1003              
1004             =over
1005              
1006             =item *
1007              
1008             categorie : Catégories de sites
1009              
1010             =item *
1011              
1012             links : Liste d'url
1013              
1014             =item *
1015              
1016             responsable : Lien vers personne responsable de chaque lien
1017              
1018             =item *
1019              
1020             relations : Liste des mots / id site indexes
1021              
1022             =item *
1023              
1024             inscription : Inscriptions temporaires
1025              
1026             =back
1027              
1028             =cut
1029              
1030             =item B
1031              
1032             Drop all table in Circa ! Be careful ! - Detruit touted les tables de Circa
1033              
1034             =cut
1035              
1036             =item B I
1037              
1038             Drop table for account I
1039              
1040             =cut
1041              
1042             =item B I
1043              
1044             Create tables needed by Circa for account I
1045              
1046             =over
1047              
1048             =item categorie
1049              
1050             Catégories de sites
1051              
1052             =item links
1053              
1054             Liste d'url
1055              
1056             =item relations
1057              
1058             Liste des mots / id site indexes
1059              
1060             =item stats
1061              
1062             Liste des requetes
1063              
1064             =back
1065              
1066             =item B I<[mysqldump], [directory of export]>
1067              
1068             Export data from Mysql in I/circa.sql with
1069             I.
1070              
1071             I: path of bin of mysqldump. If not given, search in
1072             /usr/bin/mysqldump, /usr/local/bin/mysqldump, /opt/bin/mysqldump.
1073              
1074             : path of directory where circa.sql will be created.
1075             If not given, create it in $CircaConf::export, else in /tmp directory.
1076              
1077             =item B I<[path_of_bin_mysql], [path_of_circa_file]>
1078              
1079             Import data in Mysql from circa.sql
1080              
1081             I : path to reach bin of mysql. If not given, search in
1082             /usr/bin/mysql, /usr/local/bin/mysql, /opt/bin/mysql, ENV{PATH}
1083              
1084             I : path of directory where circa.sql will be read.
1085             If not given, read it from $CircaConf::export, else /tmp directory.
1086              
1087             =back
1088              
1089             =head2 Method for administrate each account
1090              
1091             =over
1092              
1093             =item B I
1094              
1095             Return hash with some informations account I
1096             Keys are:
1097              
1098             =over
1099              
1100             =item responsable
1101              
1102             Email address given with account creation
1103              
1104             =item titre
1105              
1106             Title given with account creation
1107              
1108             =item nb_links
1109              
1110             Number of url for this account
1111              
1112             =item nb_words
1113              
1114             Number of world stored
1115              
1116             =item last_index
1117              
1118             Date of last index process
1119              
1120             =item nb_request
1121              
1122             Number of request asked
1123              
1124             =item racine
1125              
1126             Url given with account creation
1127              
1128             =back
1129              
1130             =item B I
1131              
1132             Retourne la reference vers un hash representant la liste
1133             des $max mots les plus présents dans la base de reponsable $id
1134              
1135             =item B I
1136              
1137             Return some statistics about request make on Circa
1138              
1139             =item B I
1140              
1141             Inscrit un site dans une table temporaire
1142              
1143             =back
1144              
1145             =head2 HTML functions
1146              
1147             =over
1148              
1149             =item B I
1150              
1151             Function use with CGI admin_compte.cgi. Display list of features of
1152             admin_compte.cgi for this account
1153              
1154             =item B I
1155              
1156             Return a html select buffer with list of url for account I
1157              
1158             =item B I,I
1159              
1160             Return a html select buffer with link to valid for account I
1161              
1162             =item B I
1163              
1164             Return a html select buffer with list of account
1165              
1166             =item B I
1167              
1168             Return a html select buffer with distinct known languages found at index time
1169              
1170             =item B I, I
1171              
1172             Return a html buffer with words found at index time for url I.
1173              
1174             =back
1175              
1176             =head1 SEE ALSO
1177              
1178             L, Root class for circa
1179              
1180             L, Manage Parser of Indexer
1181              
1182             L, command line to use indexer
1183              
1184             =head1 VERSION
1185              
1186             $Revision: 1.39 $
1187              
1188             =head1 AUTHOR
1189              
1190             Alain BARBET alian@alianwebserver.com
1191              
1192             =cut