/[BackupPC]/trunk/lib/BackupPC/SearchLib.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/lib/BackupPC/SearchLib.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 128 by dpavlin, Thu Sep 22 13:31:04 2005 UTC revision 186 by dpavlin, Wed Oct 12 12:53:27 2005 UTC
# Line 68  sub dates_from_form($) { Line 68  sub dates_from_form($) {
68                  $mm =~ s/\D//g;                  $mm =~ s/\D//g;
69                  $dd =~ s/\D//g;                  $dd =~ s/\D//g;
70    
71                    my $h = my $m = my $s = 0;
72                    if ($suffix eq 'to') {
73                            $h = 23;
74                            $m = 59;
75                            $s = 59;
76                    }
77    
78                  my $dt = new DateTime(                  my $dt = new DateTime(
79                          year => $yyyy,                          year => $yyyy,
80                          month => $mm,                          month => $mm,
81                          day => $dd                          day => $dd,
82                            hour => $h,
83                            minute => $m,
84                            second => $s,
85                  );                  );
86                  print STDERR "mk_epoch_date($name,$suffix) [$yyyy-$mm-$dd] = " . $dt->ymd . " " . $dt->hms . "\n";                  print STDERR "mk_epoch_date($name,$suffix) [$yyyy-$mm-$dd] = " . $dt->ymd . " " . $dt->hms . "\n";
87                  return $dt->epoch || 'NULL';                  return $dt->epoch || 'NULL';
# Line 100  sub getWhere($) { Line 110  sub getWhere($) {
110          push @conditions, qq{ files.date >= $files_from } if ($files_from);          push @conditions, qq{ files.date >= $files_from } if ($files_from);
111          push @conditions, qq{ files.date <= $files_to } if ($files_to);          push @conditions, qq{ files.date <= $files_to } if ($files_to);
112    
113          print STDERR "backup: $backup_from - $backup_to files: $files_from - $files_to cond:" . join(" | ",@conditions);          print STDERR "backup: $backup_from - $backup_to files: $files_from - $files_to cond:" . join(" and ",@conditions);
114    
115          push( @conditions, ' files.shareid = ' . $param->{'search_share'} ) if ($param->{'search_share'});          push( @conditions, ' files.shareid = ' . $param->{'search_share'} ) if ($param->{'search_share'});
116          push (@conditions, " upper(files.path) LIKE upper('%".$param->{'search_filename'}."%')") if ($param->{'search_filename'});          push (@conditions, " upper(files.path) LIKE upper('%".$param->{'search_filename'}."%')") if ($param->{'search_filename'});
# Line 288  sub getGzipName($$$) Line 298  sub getGzipName($$$)
298          $ret =~ s/\\h/$host/ge;          $ret =~ s/\\h/$host/ge;
299          $ret =~ s/\\s/$share/ge;          $ret =~ s/\\s/$share/ge;
300          $ret =~ s/\\n/$backupnum/ge;          $ret =~ s/\\n/$backupnum/ge;
301            
302            $ret =~ s/__+/_/g;
303    
304          return $ret;          return $ret;
305                    
306  }  }
307    
308    sub getGzipSize($$)
309    {
310            my ($hostID, $backupNum) = @_;
311            my $ret;
312            my $sql;
313            my $dbh = get_dbh();
314            
315            $sql = q{
316                                    SELECT hosts.name  as host,
317                                               shares.name as share,
318                                               backups.num as backupnum
319                                    FROM hosts, backups, shares
320                                    WHERE shares.id=backups.shareid AND
321                                              hosts.id =backups.hostid AND
322                                              hosts.id=? AND
323                                              backups.num=?
324                            };
325            my $sth = $dbh->prepare($sql);
326            $sth->execute($hostID, $backupNum);
327    
328            my $row = $sth->fetchrow_hashref();
329            
330            my (undef,undef,undef,undef,undef,undef,undef,$ret,undef,undef,undef,undef,undef) =
331                            stat( $Conf{InstallDir}.'/'.$Conf{GzipTempDir}.'/'.
332                                    getGzipName($row->{'host'}, $row->{share}, $row->{'backupnum'}));
333            
334            return $ret;    
335    }
336    
337  sub getBackupsNotBurned() {  sub getBackupsNotBurned() {
338    
339          my $dbh = get_dbh();          my $dbh = get_dbh();
# Line 302  sub getBackupsNotBurned() { Line 343  sub getBackupsNotBurned() {
343                          backups.hostID AS hostID,                          backups.hostID AS hostID,
344                          hosts.name AS host,                          hosts.name AS host,
345                          shares.name AS share,                          shares.name AS share,
346                          backups.id AS backupnum,                          backups.num AS backupnum,
347                          backups.type AS type,                          backups.type AS type,
348                          backups.date AS date,                          backups.date AS date,
349                          backups.size AS size                          backups.size AS size,
350                            backups.id AS id,
351                            backups.inc_size AS inc_size
352                  FROM backups                  FROM backups
353                  INNER JOIN shares       ON backups.shareID=shares.ID                  INNER JOIN shares       ON backups.shareID=shares.ID
354                  INNER JOIN hosts        ON backups.hostID = hosts.ID                  INNER JOIN hosts        ON backups.hostID = hosts.ID
355                  LEFT OUTER JOIN archive_backup ON archive_backup.backup_id = backups.id AND archive_backup.backup_id IS NULL                  LEFT OUTER JOIN archive_backup ON archive_backup.backup_id = backups.id
356                  WHERE backups.size > 0                  WHERE backups.inc_size > 0 AND backups.inc_deleted is false AND archive_backup.backup_id IS NULL
357                  GROUP BY                  GROUP BY
358                          backups.hostID,                          backups.hostID,
359                          hosts.name,                          hosts.name,
# Line 320  sub getBackupsNotBurned() { Line 363  sub getBackupsNotBurned() {
363                          backups.id,                          backups.id,
364                          backups.type,                          backups.type,
365                          backups.date,                          backups.date,
366                          backups.size                          backups.size,
367                            backups.inc_size
368                  ORDER BY backups.date                  ORDER BY backups.date
369          };          };
370          my $sth = $dbh->prepare( $sql );          my $sth = $dbh->prepare( $sql );
# Line 330  sub getBackupsNotBurned() { Line 374  sub getBackupsNotBurned() {
374          while ( my $row = $sth->fetchrow_hashref() ) {          while ( my $row = $sth->fetchrow_hashref() ) {
375                  $row->{'age'} = sprintf("%0.1f", ( (time() - $row->{'date'}) / 86400 ) );                  $row->{'age'} = sprintf("%0.1f", ( (time() - $row->{'date'}) / 86400 ) );
376                  $row->{'size'} = sprintf("%0.2f", $row->{'size'} / 1024 / 1024);                  $row->{'size'} = sprintf("%0.2f", $row->{'size'} / 1024 / 1024);
377                  my (undef,undef,undef,undef,undef,undef,undef,$fs_size,undef,undef,undef,undef,undef) =  
378                          stat( $Conf{InstallDir}.'/'.$Conf{GzipTempDir}.'/'.                  # do some cluster calculation (approximate) and convert to kB
379                                  getGzipName($row->{'host'}, $row->{share}, $row->{'backupnum'}));                  $row->{'inc_size'} = int(($row->{'inc_size'} + 1023 ) / ( 2 * 1024 ) * 2);
                 $row->{'fs_size'} = $fs_size;  
380                  push @ret, $row;                  push @ret, $row;
381          }          }
382                
# Line 343  sub getBackupsNotBurned() { Line 386  sub getBackupsNotBurned() {
386  sub displayBackupsGrid() {  sub displayBackupsGrid() {
387    
388          my $retHTML .= q{          my $retHTML .= q{
389                  <form id="forma" method="POST" action=};                  <form id="forma" method="POST" action="}.$MyURL.q{?action=burn">
                 $retHTML .= "\"".$MyURL."\"";  
                 $retHTML .= q{?action=burn>  
390          };          };
391    
392          $retHTML .= <<'EOF3';          $retHTML .= <<'EOF3';
393  <style>  <style type="text/css">
394  <!--  <!--
395    DIV#fixedBox {
 div#fixedBox {  
396          position: absolute;          position: absolute;
397          bottom: 1em;          top: 50em;
398          left: 0.5em;          left: -24%;
399          padding: 0.5em;          padding: 0.5em;
400          width: 10em;          width: 20%;
401          background: #e0f0e0;          background-color: #E0F0E0;
402          border: 1px solid #00ff00;          border: 1px solid #00C000;
 }  
 @media screen {  
         div#fixedBox {  
                 position: fixed;  
         }  
         /* Don't do this at home */  
         * html {  
                 overflow-y: hidden;  
         }  
         * html body {  
                 overflow-y: auto;  
                 height: 100%;  
                 padding: 0 1em 0 12em;  
                 font-size: 100%;  
         }  
         * html div#fixedBox {  
                 position: absolute;      
         }  
         /* All done. */  
403  }  }
404    
405  #mContainer {  DIV#fixedBox, DIV#fixedBox INPUT, DIV#fixedBox TEXTAREA {
406          position: relative;          font-size: 10pt;
         width: 100%;  
         height: 1.1em;  
         padding: 0px;  
         border: 1px solid #000000;  
407  }  }
408    
409  #gradient {  FORM>DIV#fixedBox {
410          position: absolute;          position: fixed !important;
411          top: 0px;          left: 0.5em !important;
412          left: 0px;          top: auto !important;
413          width: 100%;          bottom: 1em !important;
414          height: 100%;          width: 15% !important;
415    }
416    
417    DIV#fixedBox INPUT[type=text], DIV#fixedBox TEXTAREA {
418            border: 1px solid #00C000;
419    }
420    
421    DIV#fixedBox #note {
422          display: block;          display: block;
423          background-color: #ffff00;          width: 100%;
424  }  }
425    
426  #mask {  DIV#fixedBox #submitBurner {
427          position: absolute;          display: block;
         top: 0px;  
         left: 0px;  
428          width: 100%;          width: 100%;
429            margin-top: 0.5em;
430            cursor: pointer;
431    }
432    
433    * HTML {
434            overflow-y: hidden;
435    }
436    
437    * HTML BODY {
438            overflow-y: auto;
439          height: 100%;          height: 100%;
440          display: block;          font-size: 100%;
         font-size: 1px;  
         background-color: #FFFFFF;  
         overflow: hidden;  
441  }  }
442    
443  #progressIndicator {  * HTML DIV#fixedBox {
444          position: absolute;          position: absolute;
445          top: 0px;  }
446          left: 0px;  
447          width: 100%;  #mContainer, #gradient, #mask, #progressIndicator {
         height: 100%;  
448          display: block;          display: block;
449          font-weight: bold;          width: 100%;
         color: #404040;  
450          font-size: 10pt;          font-size: 10pt;
451            font-weight: bold;
452          text-align: center;          text-align: center;
453            vertical-align: middle;
454            padding: 1px;
455  }  }
456    
457    #gradient, #mask, #progressIndicator {
458            left: 0;
459            border-width: 1px;
460            border-style: solid;
461            border-color: #000000;
462            color: #404040;
463            margin: 0.4em;
464            position: absolute;
465            margin-left: -1px;
466            margin-top: -1px;
467            margin-bottom: -1px;
468            overflow: hidden;
469    }
470    
471    #mContainer {
472            display: block;
473            position: relative;
474            padding: 0px;
475            margin-top: 0.4em;
476            margin-bottom: 0.5em;
477    }
478    
479    #gradient {
480            z-index: 1;
481            background-color: #FFFF00;
482    }
483    
484    #mask {
485            z-index: 2;
486            background-color: #FFFFFF;
487    }
488    
489    #progressIndicator {
490            z-index: 3;
491            background-color: transparent;
492    }
493  -->  -->
494  </style>  </style>
495  <script language="javascript" type="text/javascript">  <script type="text/javascript">
496  <!--  <!--
497    
498  var debug_div = null;  var debug_div = null;
499  var media_size = 4400 * 1024;  EOF3
500    
501            # take maximum archive size from configuration
502            $retHTML .= 'var media_size = '. $Conf{MaxArchiveSize} .';';
503    
504            $retHTML .= <<'EOF3';
505    
506  function debug(msg) {  function debug(msg) {
507  //      return; // Disable debugging  //      return; // Disable debugging
# Line 460  function element_id(name,element) { Line 531  function element_id(name,element) {
531  }  }
532    
533  function checkAll(location) {  function checkAll(location) {
534          var len = element_id('forma').elements.length;          var f = element_id('forma') || null;
535            if (!f) return false;
536    
537            var len = f.elements.length;
538          var check_all = element_id('allFiles');          var check_all = element_id('allFiles');
539            var suma = check_all.checked ? (parseInt(f.elements['totalsize'].value) || 0) : 0;
540    
541          for (var i = 0; i < len; i++) {          for (var i = 0; i < len; i++) {
542                    var e = f.elements[i];
543                  var e = element_id('forma').elements[i];                  if (e.name != 'all' && e.name.substr(0, 3) == 'fcb') {
                 if ((e.checked || !e.checked) && e.name != 'all') {  
544                          if (check_all.checked) {                          if (check_all.checked) {
545                                  e.checked = true;                                  if (e.checked) continue;
546                                    var el = element_id("fss" + e.name.substr(3));
547                                    var size = parseInt(el.value) || 0;
548                                    debug('suma: '+suma+' size: '+size);
549                                    if ((suma + size) < media_size) {
550                                            suma += size;
551                                            e.checked = true;
552                                    } else {
553                                            break;
554                                    }
555                          } else {                          } else {
556                                  e.checked = false;                                  e.checked = false;
557                          }                          }
558                  }                  }
559          }          }
560            update_sum(suma);
561    }
562    
563          sumiraj();  function update_sum(suma) {
564            element_id('forma').elements['totalsize'].value = suma;
565            pbar_set(suma, media_size);
566            debug('total size: ' + suma);
567  }  }
568        
569  function sumiraj(e) {  function sumiraj(e) {
570          var suma = parseInt(element_id('forma').totalsize.value) || 0;          var suma = parseInt(element_id('forma').elements['totalsize'].value) || 0;
571          var len = element_id('forma').elements.length;          var len = element_id('forma').elements.length;
572          if (e) {          if (e) {
573                  var size = parseInt( element_id("fss" + e.name.substr(3)).value );                  var size = parseInt( element_id("fss" + e.name.substr(3)).value);
574                  if (e.checked) {                  if (e.checked) {
575                          suma += size;                          suma += size;
576                  } else {                  } else {
# Line 498  function sumiraj(e) { Line 586  function sumiraj(e) {
586                          }                          }
587                  }                  }
588          }          }
589          element_id('forma').totalsize.value = suma;          update_sum(suma);
         pbar_set(suma, media_size);  
         debug('total size: '+suma);  
590          return suma;          return suma;
591  }  }
592    
593  /* progress bar */  /* progress bar */
594    
595  var _pbar_width = 0;  var _pbar_width = null;
596  var _pbar_warn = 10;    // change color in last 10%  var _pbar_warn = 10;    // change color in last 10%
597    
598  function pbar_reset() {  function pbar_reset() {
599          element_id("mask").style.left = "0px";          element_id("mask").style.left = "0px";
600          _pbar_width = element_id("mContainer").offsetWidth - 2;          _pbar_width = element_id("mContainer").offsetWidth - 2;
601          element_id("mask").style.width = _pbar_width + "px";          element_id("mask").style.width = _pbar_width + "px";
         element_id("progressIndicator").style.zIndex  = 10;  
602          element_id("mask").style.display = "block";          element_id("mask").style.display = "block";
603            element_id("progressIndicator").style.zIndex  = 10;
604          element_id("progressIndicator").innerHTML = "0";          element_id("progressIndicator").innerHTML = "0";
605  }  }
606    
607  function dec2hex(d) {  function dec2hex(d) {
608          var hch="0123456789ABCDEF";          var hch = '0123456789ABCDEF';
609          var a=d%16;          var a = d % 16;
610          var q=(d-a)/16;          var q = (d - a) / 16;
611          return hch.charAt(q)+hch.charAt(a);          return hch.charAt(q) + hch.charAt(a);
612  }  }
613    
   
614  function pbar_set(amount, max) {  function pbar_set(amount, max) {
615            debug('pbar_set('+amount+', '+max+')');
616    
617          debug('pbar_set( '+amount+' , '+max+' )');          if (_pbar_width == null) {
618                    var _mc = element_id("mContainer");
619          curWidth = parseInt(element_id("mask").offsetWidth);                  if (_pbar_width == null) _pbar_width = parseInt(_mc.offsetWidth ? (_mc.offsetWidth - 2) : 0) || null;
620          curLeft = parseInt(element_id("mask").offsetLeft);                  if (_pbar_width == null) _pbar_width = parseInt(_mc.clientWidth ? (_mc.clientWidth + 2) : 0) || null;
621                    if (_pbar_width == null) _pbar_width = 0;
622            }
623    
624          var pcnt = Math.floor( amount * 100 / max );          var pcnt = Math.floor(amount * 100 / max);
625          var p90 = 100 - _pbar_warn;          var p90 = 100 - _pbar_warn;
626          var pcol = pcnt - p90;          var pcol = pcnt - p90;
627          if (pcol < _pbar_warn) {          if (Math.round(pcnt) <= 100) {
628                  if (pcol < 0) pcol = 0;                  if (pcol < 0) pcol = 0;
629                  var e = element_id("submitBurner");                  var e = element_id("submitBurner");
630                  if (e && e.disabled) {                  debug('enable_button');
631                          debug('enable_button');                  e.disabled = false;
632                          var a = e.getAttributeNode('disabled') || null;                  var a = e.getAttributeNode('disabled') || null;
633                          if (a) e.removeAttributeNode(a);                  if (a) e.removeAttributeNode(a);
634                  }          } else {
         } else if (pcol > _pbar_warn) {  
635                  debug('disable button');                  debug('disable button');
636                  pcol = _pbar_warn;                  pcol = _pbar_warn;
637                  var e = element_id("submitBurner");                  var e = element_id("submitBurner");
638                  if (! e.disabled) e.disabled = true;                  if (!e.disabled) e.disabled = true;
639          }          }
640          var col_g = Math.floor( ( _pbar_warn - pcol ) * 255 / _pbar_warn );          var col_g = Math.floor((_pbar_warn - pcol) * 255 / _pbar_warn);
641          var col = '#ff' + dec2hex( col_g ) + '00';          var col = '#FF' + dec2hex(col_g) + '00';
642    
643          //debug('pcol: '+pcol+' g:'+col_g+' _pbar_warn:'+ _pbar_warn + ' color: '+col);          //debug('pcol: '+pcol+' g:'+col_g+' _pbar_warn:'+ _pbar_warn + ' color: '+col);
644          element_id("gradient").style.backgroundColor = col;          element_id("gradient").style.backgroundColor = col;
645    
         var size = parseInt( _pbar_width * amount / max );  
   
         curWidth = _pbar_width - size;  
         curLeft = size ;  
   
         //debug('size: '+size+' curWidth '+curWidth+' curLeft: '+curLeft);  
   
646          element_id("progressIndicator").innerHTML = pcnt + '%';          element_id("progressIndicator").innerHTML = pcnt + '%';
647          //element_id("progressIndicator").innerHTML = amount;          //element_id("progressIndicator").innerHTML = amount;
648    
649          if (curLeft > _pbar_width) {          element_id("mask").style.clip = 'rect(' + Array(
650                  element_id("mask").style.display = "none";                  '0px',
651                  return;                  element_id("mask").offsetWidth + 'px',
652          } else {                  element_id("mask").offsetHeight + 'px',
653                  element_id("mask").style.display = "";                  Math.round(_pbar_width * amount / max) + 'px'
654          }          ).join(' ') + ')';
   
         //if(parseInt(element_id("mask").offsetWidth)>10)  
         element_id("mask").style.width = curWidth + "px";  
         element_id("mask").style.left = curLeft + "px";  
   
655  }  }
656    
657  if (!self.body) self.body = new Object();  if (!self.body) self.body = new Object();
658  self.onload = self.document.onload = self.body.onload = function() {  self.onload = self.document.onload = self.body.onload = function() {
659          pbar_reset();          //pbar_reset();
660          sumiraj();          sumiraj();
661  }  };
662    
663  //-->  // -->
664  </script>  </script>
665  <div id="fixedBox">  <div id="fixedBox">
666    
667  Size:  Size: <input type="text" name="totalsize" size="7" readonly="readonly" style="text-align:right;" value="0" /> kB
 <input type="text" name="totalsize" size="7" readonly>  
668    
669  <div id="mContainer">  <div id="mContainer">
670          <div id="gradient"></div>          <div id="gradient">&nbsp;</div>
671          <div id="mask"></div>          <div id="mask">&nbsp;</div>
672          <div id="progressIndicator">&nbsp;</div>          <div id="progressIndicator">0%</div>
673  </div>  </div>
   
674  <br/>  <br/>
675    
676  Note:  Note:
677  <br/>  <textarea name="note" cols="10" rows="5" id="note"></textarea>
678  <textarea name="note" cols="10" rows="5">  
679  </textarea>  <input type="submit" id="submitBurner" value="Burn selected" name="submitBurner" />
 <br/>  
 <input type="submit" id="submitBurner" value="Burn selected" name="submitBurner">  
680    
681  </div>  </div>
682    <!--
683  <div id="debug" style="float: right; width: 10em; border: 1px #ff0000 solid; background-color: #ffe0e0; -moz-opacity: 0.7;">  <div id="debug" style="float: right; width: 10em; border: 1px #ff0000 solid; background-color: #ffe0e0; -moz-opacity: 0.7;">
684  no debug output yet  no debug output yet
685  </div>  </div>
686    -->
687  EOF3  EOF3
688          $retHTML .= q{          $retHTML .= q{
689                          <input type="hidden" value="burn" name="action">                          <input type="hidden" value="burn" name="action">
# Line 626  EOF3 Line 699  EOF3
699                          <td align="center">date</td>                          <td align="center">date</td>
700                          <td align="center">age/days</td>                          <td align="center">age/days</td>
701                          <td align="center">size/MB</td>                          <td align="center">size/MB</td>
702                          <td align="center">gzip size</td>                          <td align="center">gzip size/kB</td>
703                          </tr>                          </tr>
704    
705          };          };
# Line 644  EOF3 Line 717  EOF3
717                  }                  }
718                  my $ftype = "";                  my $ftype = "";
719    
720                    my $checkbox_key = $backup->{'hostid'}. '_' .$backup->{'backupnum'} . '_' . $backup->{'id'};
721    
722                  $retHTML .=                  $retHTML .=
723                          '<tr' . $color[$i %2 ] . '>                          '<tr' . $color[$i %2 ] . '>
724                          <td class="fview">';                          <td class="fview">';
725                  # FIXME  
726                  $backup->{'fs_size'} = int($backup->{'size'} * 1024);                  if (($backup->{'inc_size'} || 0) > 0) {
                 if (($backup->{'fs_size'} || 0) > 0) {  
727                          $retHTML .= '                          $retHTML .= '
728                          <input type="checkbox" name="fcb' .                          <input type="checkbox" name="fcb' . $checkbox_key . '" value="' . $checkbox_key . '" onClick="sumiraj(this);">';
                         $backup->{'hostid'}.'_'.$backup->{'backupnum'} .  
                         '" value="' . $backup->{'hostid'}.'_'.$backup->{'backupnum'} .  
                         '" onClick="sumiraj(this);">';  
729                  }                  }
730    
731                  $retHTML .=                  $retHTML .=
732                          '</td>' .                          '</td>' .
733                          '<td align="right">' . $backup->{'host'} . ':' . $backup->{'share'} . '</td>' .                          '<td align="right">' . $backup->{'host'} . ':' . $backup->{'share'} . '</td>' .
# Line 664  EOF3 Line 736  EOF3
736                          '<td align="center">' . epoch_to_iso( $backup->{'date'} ) . '</td>' .                          '<td align="center">' . epoch_to_iso( $backup->{'date'} ) . '</td>' .
737                          '<td align="center">' . $backup->{'age'} . '</td>' .                          '<td align="center">' . $backup->{'age'} . '</td>' .
738                          '<td align="right">' . $backup->{'size'} . '</td>' .                          '<td align="right">' . $backup->{'size'} . '</td>' .
739                          '<td align="right">' . $backup->{'fs_size'} .                          '<td align="right">' . $backup->{'inc_size'} .
740                          '<input type="hidden" iD="fss'.$backup->{'hostid'}.'_'.$backup->{'backupnum'} . '" value="'. $backup->{'fs_size'} .'"></td>' .                          '<input type="hidden" iD="fss'.$checkbox_key .'" value="'. $backup->{'inc_size'} .'"></td>' .
741    
742                          "</tr>\n";                          "</tr>\n";
743          }          }

Legend:
Removed from v.128  
changed lines
  Added in v.186

  ViewVC Help
Powered by ViewVC 1.1.26