It would be cool to post code as attachement in text utf-8 formatted. HTML in message is just EVIL :-)
On 10/27/2010 11:30 AM, ladolf wrote: > I managed to create PHP script that searches for file or folder. It is > written for MySQL database and tested on Bacula 3 with Firefox browser. It > supports case insensitive search for file or folder, with or without regular > expressions and possibility to specify date range. Don't set too high number > for "Results per page". I have about 20 milions filenames in database and > search tool works fast enough for not too complex search. > > To use the sript create folder somewhere in your apache folder (there must be > access to bacula database from this server), and create empty files > config.php, index.php, script.js, search.php and style.css. > > Here is the code: > ------------------- > config.php (don't forget to set the values for your environment) > > <?php > //Database data > $DB_HOST = "localhost"; > $DB_NAME = "baculdatabasename"; > $DB_USER = "baculamysqluser"; > $DB_PASS = "baculamysqlpass"; > $DB_SET_NAMES = "UTF8"; > > //Character encoding for WEB page > $WEB_CHARSET = "UTF-8"; > > //Maximum number of seconds for script execution > $TIME_LIMIT_SECONDS = 300; > ?> > > > ------------------- > index.php > > <?php > include(dirname(__FILE__)."/config.php"); > > $today = date("Y-m-d"); > ?> > <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" > "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> > <html xmlns="http://www.w3.org/1999/xhtml"> > <head> > <title>Bacula search tool</title> > <meta http-equiv="Content-Type" content="text/html; > charset=<?php echo $WEB_CHARSET; ?>" /> > <link href="style.css" rel="stylesheet" type="text/css" /> > <script type="text/javascript" src="./script.js"></script> > </head> > <body> > <h1>Bacula search tool</h1> > <form method="get" action="<?php echo basename( > __FILE__); ?>"> > <table cellspacing="0" cellpadding="5" > id="searchformtable"> > <tr> > <td>Type of > search:</td> > <td> > <input > type="radio" name="searchobject" value="folder" checked />Search for > folder<br /> > <input > type="radio" name="searchobject" value="file" />Search for file > </td> > </tr> > <tr> > <td>Search > for:</td> > <td> > <input > type="text" name="searchstr" id="searchstr" size="30" maxlength="255" > value="" /> > <input > type="checkbox" id="regexp" /> Regular expression > </td> > </tr> > <tr> > <td>Date range</td> > <td> > <input > type="checkbox" id="daterange" />Only search for files that were created > between selected dates:<br /> > <table> > > <tr><td>Start date:</td><td><input type="text" name="startdate" > id="startdate" size="10" maxlength="10" value="<?php echo $today; ?>" /> > (e.g. 2010-05-28)</td></tr> > > <tr><td>End date:</td><td><input type="text" name="enddate" > id="enddate" size="10" maxlength="10" value="<?php echo $today; ?>" > /></td></tr> > </table> > </td> > </tr> > <tr><td valign="top">Results per > page:</td><td><input type="text" name="limit" id="limit" value="20" > size="5" maxlength="5" /></td></tr> > <tr><td> </td><td><input > type="button" value="Search" onclick="javascript: > get_search_results('<?php echo $WEB_CHARSET; ?>', 0);" /></td></tr> > </table> > </form> > > <br /> > > <!-- Here comes previous and next button --> > <div id="prev_next"></div> > > <!-- Here comes search results --> > <div id="search_results"></div> > </body> > </html> > > > ------------------- > script.js > > /** > * Use AJAX to get data > */ > function get_search_results(charset, limitstart) { > //Div for results > var res_div = document.getElementById("search_results"); > > //Are we looking for folder or for a file > if > (document.getElementsByName("searchobject")[0].checked) > { > var so = "folder"; > } else { > var so = "file"; > } > > //Get number of pages per page > var limit = > parseInt(document.getElementById("limit").value); > > //Get search string > var search_str = > document.getElementById("searchstr").value; > > //Is search string regular expression > if (document.getElementById("regexp").checked) > { > var is_regexp = "1"; > } else { > var is_regexp = "0"; > } > > //Search between two dates > if > (document.getElementById("daterange").checked) { > var start_date = > document.getElementById("startdate").value; > var end_date = > document.getElementById("enddate").value; > var use_dates = true; > } else { > var use_dates = false; > } > > //Build POST parameters > var params = "searchstr=" + escape(search_str) + > "&searchobject=" + so + "&start=" + limitstart + "&limit=" + limit; > params += "&isregexp=" + is_regexp; > if (use_dates) { > params += "&startdate=" + > escape(start_date) + "&enddate=" + escape(end_date); > } > > res_div.innerHTML = "Loading ... (Please be patient)"; > > //Create AJAX object > if (window.XMLHttpRequest) { > xmlhttp = new XMLHttpRequest(); > } else { > xmlhttp = new > ActiveXObject("Microsoft.XMLHTTP"); > } > > xmlhttp.onreadystatechange = function() { > if (xmlhttp.readyState == 4 && xmlhttp.status > == 200) { > //Display search results > res_div.innerHTML = > xmlhttp.responseText; > > //Get number of results > var result_rows = > document.getElementById('resulttable').getElementsByTagName("TR").length > - 1; > > //Display previous and next button > display_prev_next_btn(charset, > limitstart, limit, result_rows); > } > } > xmlhttp.open("POST", "search.php", true); > xmlhttp.setRequestHeader("Content-type", > "application/x-www-form-urlencoded; Charset= " + charset) > xmlhttp.send(params); > } > > /** > * Display previous and next button > */ > function display_prev_next_btn(charset, limitstart, limit, > result_rows) { > //Div for buttons > var pn_div = document.getElementById("prev_next"); > > > > //Display buttons > pn_div.innerHTML = ''; > if (limitstart >= 1) { //Previous page > var prev_limitstart = limitstart - limit; > pn_div.innerHTML += '<input type="button" > value="<" onclick="get_search_results(' + "'" + charset + "'" + ', ' + > prev_limitstart + ',' + limit + ')" />'; > } > pn_div.innerHTML += ' '; > pn_div.innerHTML += 'Page ' + ((limitstart / limit) > + 1); > pn_div.innerHTML += ' '; > > if (result_rows == limit) { //Next page > var next_limitstart = limitstart + limit; > pn_div.innerHTML += '<input type="button" > value=">" onclick="get_search_results(' + "'" + charset + "'" + ', ' + > next_limitstart + ',' + limit + ')" />'; > } > } > > > ------------------- > search.php > > <?php > > include(dirname(__FILE__)."/config.php"); > > //Set higher time limit than normal > set_time_limit($TIME_LIMIT_SECONDS); > > if (isset($_POST["searchstr"]) && > $_POST["searchstr"] != "") { > $searchstr = $_POST["searchstr"]; > > if > (isset($_POST["searchobject"])) { //Search for > path or search for file must be set > > //Get start for limit > if > (isset($_POST["start"]) && > is_numeric($_POST["start"])) { > > $start = > $_POST["start"]; > } else { > $start = 0; > } > > //Get limit > if > (isset($_POST["limit"]) && > is_numeric($_POST["limit"])) { > > $limit = > $_POST["limit"]; > } else { > $limit = 20; > } > > //Connect to mysql database > $c = @mysql_connect($DB_HOST, > $DB_USER, $DB_PASS) or die ("<br />Error: <b>Cannot connect to > database</b>: ".mysql_error().""); > @mysql_select_db ($DB_NAME, > $c) or die("<br />Error: ".mysql_error()); > @mysql_query("SET NAMES > {$DB_SET_NAMES}"); > > //Use date range? > if > (isset($_POST["startdate"]) && > isset($_POST["enddate"])) { > $startdate = > $_POST["startdate"]; > $enddate = > $_POST["enddate"]; > $date_qubquery = " > AND J.StartTime >= '{$startdate} 00:00:00' AND J.EndTime <= > '{$enddate} 23:59:59'"; > } > > //Escape search string > $searchstr_esc = > mysql_real_escape_string($searchstr, $c); > > //If the search string is regular > expression, use "REXEXP" instead "LIKE" > if > (isset($_POST["isregexp"]) && > ($_POST["isregexp"] == "1")) { > $comparison = "REGEXP > '{$searchstr_esc}'"; > } else { //not regular > expression > $comparison = "LIKE > '%{$searchstr_esc}%'"; > } > > //Build SQL statement > if > ($_POST["searchobject"] == "file") { > //SELECT By Filename > $query_string = " > SELECT > DISTINCT CONCAT(P.Path, FN.Name), F.JobId AS JID, J.Name, > J.StartTime, J.EndTime > FROM > Filename FN, File F, Path P, Job J > WHERE > FN.FilenameId=F.FilenameId AND F.PathId=P.PathId{$date_qubquery} > > AND J.JobId=F.JobId AND CONVERT(FN.Name USING > {$DB_SET_NAMES}) {$comparison} > > LIMIT {$start},{$limit}"; > } else { > //Select By Folder > name > $query_string = " > SELECT > DISTINCT P.Path, F.JobId AS JID, J.Name, J.StartTime, J.EndTime > FROM > Path P, File F, Job J > WHERE > P.PathId=F.PathId AND J.JobId=F.JobId{$date_qubquery} > > AND CONVERT(P.Path USING {$DB_SET_NAMES}) > {$comparison} > LIMIT > {$start},{$limit}"; > } > > //Execute query > $result = > @mysql_query($query_string, $c) or die("<br />SQL Error: > ".mysql_error()."<br />QUERY: ".$query); > > //Display search results > if > (mysql_num_rows($result) > 0) { > > > $DATA_ARR = > array(); //Temporary array of data > $JOB_IDS = > array(); //Array of job IDs for current limit > while ($row = > mysql_fetch_array($result)) { > > array_push($DATA_ARR, $row); > if > (is_numeric($row["JID"]) && > !in_array($row["JID"], $JOB_IDS)) { > > array_push($JOB_IDS, $row["JID"]); > } > } > > //Get volume names > for media used by job ids > $query = "Select > DISTINCT JM.JobId, M.VolumeName FROM JobMedia JM LEFT JOIN Media M ON > M.MediaId=JM.MediaId WHERE JM.JobId IN (".implode(",", > $JOB_IDS).")"; > $r2 = > @mysql_query($query, $c) or die("<br />SQL Error: > ".mysql_error()."<br />QUERY: ".$query); > $JOBMEDIA = > array(); > while > (list($jobid, $volname) = mysql_fetch_array($r2)) > { > > $JOBMEDIA[$jobid] = $volname; > } > > //Display table of > data > echo "\n\t<table > cellspacing=\"0\" cellpadding=\"2\" id=\"resulttable\" width=\"100%\">"; > echo "\n\t\t<tr > class=\"thead\"><td>Path</td><td>JobID</td><td>Job name</td><td>Job > time</td><td>Media</td></tr>"; > foreach > ($DATA_ARR as $row) { > > list($path, $jobid, $jobname, $jobstart, $jobend) = $row; > > //Mark > folder/file in green color > $path = > preg_replace("/({$searchstr})/iU", "<font > style=\"color: #090;\">\\1</font>", $path); > > //Get > media name > if > (isset($JOBMEDIA[$jobid])) { > > $medianame = $JOBMEDIA[$jobid]; > } > else { > > $medianame = "???"; > } > > > //Display result row > echo > "\n\t\t<tr > class=\"datarow\"><td>{$path}</td><td><b>{$jobid}</b></td><td>{$jobname}</td><td>{$jobstart}<br > />{$jobend}</td><td>{$medianame}</td></tr>"; > } > echo "\n\t</table>"; > > echo "<br > /><b>Displaying results {$start} - ".($start + > $limit)."</b>"; > > } else { > echo "<br />No > records has been found!"; > } > > //Close connection to mysql > @mysql_close($c); > > } else { > echo "<br /><b>Please select > "Search file" or "Search folder".</b>"; > } > } else { > echo "Search string has not been submitted!"; > } > > ?> > > > ------------------- > style.css > > body { > background-color: #ddf; > font-family: Verdana, Helvetica, Tahoma, Arial; > font-size: 10px; > color: #000; > } > > input { > border: solid 1px #aaa; > background-color: #feb; > margin-left: 0px; > } > > input[type="button"] { > border: solid 2px #aaa; > border-right: solid 2px #777; > border-bottom: solid 2px #777; > background-color: #eee; > } > > #searchformtable { > background-color: #ddd; > border: 1px solid #000; > } > > #searchformtable td { > vertical-align: top; > } > > #resulttable { > border: 1px solid #000; > } > > .thead { > background-color: #ffbb1d; > font-weight: bold; > } > > .datarow { > background-color: #eee; > } > > .datarow td { > border-top: 1px solid #000; > vertical-align: top; > } > [/code] -- Bruno Friedmann (irc:tigerfoot) Ioda-Net Sàrl www.ioda-net.ch openSUSE Member User www.ioda.net/r/osu Blog www.ioda.net/r/blog fsfe fellowship www.fsfe.org GPG KEY : D5C9B751C4653227 vcard : http://it.ioda-net.ch/ioda-net.vcf ------------------------------------------------------------------------------ Nokia and AT&T present the 2010 Calling All Innovators-North America contest Create new apps & games for the Nokia N8 for consumers in U.S. and Canada $10 million total in prizes - $4M cash, 500 devices, nearly $6M in marketing Develop with Nokia Qt SDK, Web Runtime, or Java and Publish to Ovi Store http://p.sf.net/sfu/nokia-dev2dev _______________________________________________ Bacula-users mailing list Bacula-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/bacula-users