wb-2_10_x / branches / main / framework / DseTwo.php @ 10
1 |
<?php
|
---|---|
2 |
/**
|
3 |
* @category ISTeasy
|
4 |
* @package DatabaseSearchEngine 1
|
5 |
* @author Werner von der Decken
|
6 |
* @copyright 2011, ISTeasy-project
|
7 |
* @license http://www.gnu.org/licenses/gpl.html
|
8 |
* @version $Id: DseTwo.php 2 2017-07-02 15:14:29Z Manuela $
|
9 |
* @filesource $HeadURL: svn://isteam.dynxs.de/wb/2.10.x/branches/main/framework/DseTwo.php $
|
10 |
* @description Searchengine to browse whoole database for text.
|
11 |
* Black- or whitelist is possible
|
12 |
* min requirements: PHP 5.3.6, mySQL 5.1
|
13 |
* this is a authorisised GPL-lizensed derivate from the original
|
14 |
* ISTeasy class DseOne which is available under a cc-by-sa-3.0 license
|
15 |
*/
|
16 |
/* -------------------------------------------------------- */
|
17 |
// Must include code to stop this file being accessed directly
|
18 |
if(!defined('WB_PATH')) { |
19 |
require_once(dirname(__FILE__).'/globalExceptionHandler.php'); |
20 |
throw new IllegalFileException(); |
21 |
} |
22 |
/* -------------------------------------------------------- */
|
23 |
|
24 |
class DseTwo { |
25 |
|
26 |
const USE_ALL = 0; |
27 |
const USE_BLACKLIST = 1; |
28 |
const USE_WHITELIST = 2; |
29 |
|
30 |
const RETURN_UNUSED = 0; |
31 |
const RETURN_USED = 1; |
32 |
/**
|
33 |
*
|
34 |
* @var res database handle
|
35 |
*/
|
36 |
private $_db; |
37 |
/**
|
38 |
* @var object Database object
|
39 |
*/
|
40 |
private $_oDb = null; |
41 |
/**
|
42 |
*
|
43 |
* @var string prefix of tables to search for
|
44 |
*/
|
45 |
private $_TablePrefix; |
46 |
/**
|
47 |
*
|
48 |
* @var string name of the database
|
49 |
*/
|
50 |
private $_db_name; |
51 |
/**
|
52 |
*
|
53 |
* @var array list of unneeded tables.fields
|
54 |
*/
|
55 |
private $_ControllList; |
56 |
private $_ControllListTyp; |
57 |
private $_ControllListTypen = array('All','BlackList','WhiteList'); |
58 |
|
59 |
private $_Queries; |
60 |
private $_BasePath = ''; |
61 |
private $_CachePath = ''; |
62 |
private $_TCacheFile = ''; |
63 |
private $_DCachePrefix = ''; |
64 |
private $_bUseCache = true; |
65 |
/**
|
66 |
*
|
67 |
* @param object $database global database object
|
68 |
*/
|
69 |
public function __construct() |
70 |
{ |
71 |
$this->_oDb = $GLOBALS['database']; |
72 |
$this->_ControllList = array(); |
73 |
$this->_TCacheFile = 'Ie'.__CLASS__.'CacheTables'; |
74 |
$this->_DCachePrefix = 'Ie'.__CLASS__.'CacheDir'; |
75 |
$this->_Queries = array(); |
76 |
} |
77 |
/**
|
78 |
*
|
79 |
* @param string $name name of the property
|
80 |
* (db_handle, db_name, table_prefix, base_dir, cache_dir, use_cache)
|
81 |
* @param mixed $value value of the property
|
82 |
*/
|
83 |
public function __set($name, $value) { |
84 |
|
85 |
switch(strtolower($name)): |
86 |
case 'db_handle': |
87 |
if($value) { $this->_db = $value; } |
88 |
break;
|
89 |
case 'db_name': |
90 |
if($value != '') { $this->_db_name = $value; } |
91 |
break;
|
92 |
case 'table_prefix': |
93 |
if($value != '') { $this->_TablePrefix = $value; } |
94 |
break;
|
95 |
case 'base_dir': |
96 |
if($value != '') { |
97 |
$this->_BasePath = rtrim(str_replace('\\', '/', $value) , '/'); |
98 |
} |
99 |
break;
|
100 |
case 'cache_dir': |
101 |
$value = rtrim(str_replace('\\', '/', $value) , '/'); |
102 |
if(!is_dir($value)) { |
103 |
if(!mkdir($value, 0777, true)) { |
104 |
$this->_CachePath = ''; |
105 |
$this->_bUseCache = false; |
106 |
break;
|
107 |
} |
108 |
} |
109 |
if(is_writable($value)) { |
110 |
$this->_CachePath = $value; |
111 |
$this->_bUseCache = true; |
112 |
}else {
|
113 |
$this->_CachePath = ''; |
114 |
$this->_bUseCache = false; |
115 |
} |
116 |
break;
|
117 |
default:
|
118 |
throw new InvalidArgumentException( __CLASS__.'::'.$name ); |
119 |
break;
|
120 |
endswitch;
|
121 |
} |
122 |
|
123 |
/**
|
124 |
* delete all table cache files
|
125 |
*/
|
126 |
public function clearCache() |
127 |
{ |
128 |
foreach($this->_ControllListTypen as $type) { |
129 |
$cFile = $this->_CachePath.'/'.$this->_TCacheFile.$type; |
130 |
if(file_exists($cFile)) { @unlink($cFile); } |
131 |
} |
132 |
} |
133 |
/**
|
134 |
*
|
135 |
* @param string $blacklist path/filename of the blacklist
|
136 |
* @param int $type const USE_NO_LIST / USE_BLACKLIST / USE_WHITELIST
|
137 |
* @return bool false if no or empty list is available
|
138 |
*/
|
139 |
public function addControllList($sControllList, $type = self::USE_BLACKLIST) |
140 |
{ |
141 |
$this->_ControllList = array(); |
142 |
$this->_ControllListTyp = $type; |
143 |
if(is_readable($sControllList)) { |
144 |
if(($list = file($sControllList, FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES)) !== false) |
145 |
{ |
146 |
$list = preg_grep('/^\s*?[^#;]/', $list); |
147 |
$this->_ControllList = preg_replace('/^\s*?(.*)\s*?$/', $this->_TablePrefix.'$1', $list); |
148 |
unset($list); |
149 |
} |
150 |
}else {
|
151 |
$this->_ControllListTyp = self::USE_ALL; |
152 |
} |
153 |
if(($type == self::USE_BLACKLIST) && (sizeof($this->_ControllList) > 0)) { |
154 |
$this->_ControllListTyp = self::USE_ALL; |
155 |
} |
156 |
return (sizeof($this->_ControllList) > 0); |
157 |
} |
158 |
/**
|
159 |
*
|
160 |
* @param string $sDirToSearch directory to scan (relative to base_dir)
|
161 |
* @param integer $bRetunMode select matching or unmatching files
|
162 |
* @return array list of matching files
|
163 |
*/
|
164 |
public function getMatchesFromDir($sDirToSearch, $bRetunMode = self::RETURN_USED) |
165 |
{ |
166 |
$aResultFileList = array(); |
167 |
$aNewFileList = array(); |
168 |
$sDirToSearch = trim(str_replace('\\', '/', $sDirToSearch) , '/'); |
169 |
$sPathToSearch = $this->_BasePath.'/'.$sDirToSearch; |
170 |
$sCacheFile = $this->_DCachePrefix.$bRetunMode.urlencode('/'.$sDirToSearch); |
171 |
$sCacheFile = $this->_CachePath.'/'.$sCacheFile; |
172 |
if(sizeof($this->_Queries) <= 0) { $this->_getTableQueries(); } |
173 |
// read fileList from directory
|
174 |
try{
|
175 |
foreach( new DirectoryIterator($sPathToSearch) as $fileinfo ) { |
176 |
// at first collect all files from target directory
|
177 |
$fileName = $fileinfo->getFilename(); |
178 |
if(($fileinfo->isFile()) && |
179 |
(!$fileinfo->isDot()) &&
|
180 |
($fileinfo->getFilename() != 'index.php')) { |
181 |
$aNewFileList[] = $fileinfo->getFilename(); |
182 |
} |
183 |
} |
184 |
}catch(UnexpectedValueException $e) {} |
185 |
// make checksum of current directory
|
186 |
$bCacheValid = false; |
187 |
if($this->_bUseCache) { |
188 |
$checkSum = crc32(serialize($aNewFileList)); |
189 |
if(is_readable($sCacheFile)){ |
190 |
// read cachefile if available
|
191 |
$aResultFileList = unserialize(file_get_contents($sCacheFile)); |
192 |
if($checkSum == array_shift($aResultFileList)) { |
193 |
// compare new checksum against checksum from cachefile
|
194 |
$bCacheValid = true; |
195 |
} |
196 |
} |
197 |
} |
198 |
if(!$bCacheValid) { |
199 |
// skip this loop if valid cache is available
|
200 |
$aResultFileList = array(); |
201 |
while (list( , $sFilename) = each($aNewFileList)) { |
202 |
// iterate all tables and search for filename
|
203 |
if( $this->_getMatch($sDirToSearch.'/'.$sFilename) !== false) { |
204 |
if($bRetunMode == self::RETURN_USED) { $aResultFileList[] = $sFilename; } |
205 |
}else {
|
206 |
if($bRetunMode == self::RETURN_UNUSED) { $aResultFileList[] = $sFilename; } |
207 |
} |
208 |
} |
209 |
// calculate new checksum
|
210 |
$newCheckSum = crc32(serialize($aResultFileList)); |
211 |
// add checksum to array
|
212 |
array_unshift($aResultFileList, $newCheckSum); |
213 |
// try to write serialized array into new cachefile
|
214 |
if(file_put_contents($sCacheFile, serialize($aResultFileList)) === false) { |
215 |
throw new RuntimeException(); |
216 |
} |
217 |
// remove checksum again
|
218 |
array_shift($aResultFileList); |
219 |
} |
220 |
unset($aNewFileList); |
221 |
return $aResultFileList; |
222 |
} |
223 |
/**
|
224 |
*
|
225 |
* @param <type> $sFilename
|
226 |
* @return bool true if file found in db
|
227 |
*/
|
228 |
private function _getMatch($sFilename) |
229 |
{ |
230 |
$result = 0; |
231 |
$sFilename = str_replace('_', '\_', $sFilename); |
232 |
$sSearch = '%'.str_replace('/', '_', $sFilename).'%'; |
233 |
while (list( , $sQuery) = each($this->_Queries)) { |
234 |
$sql = sprintf($sQuery, $sSearch); |
235 |
if( ($res = $this->_oDb->query($sql)) ) { |
236 |
if( ($result = intval($res->fetchRow(MYSQL_ASSOC))) > 0 ) { break; } |
237 |
} |
238 |
} |
239 |
return ($result != 0); |
240 |
} |
241 |
/**
|
242 |
*
|
243 |
*/
|
244 |
private function _getTableQueries() |
245 |
{ |
246 |
if($this->_bUseCache) { |
247 |
// try to read queries from cace
|
248 |
$sCacheFile = $this->_CachePath.'/'.$this->_TCacheFile.$this->_ControllListTypen[$this->_ControllListTyp]; |
249 |
try {
|
250 |
if(is_readable($sCacheFile)) { |
251 |
$this->_Queries = unserialize(file_get_contents($sCacheFile)); |
252 |
} |
253 |
}catch(Exception $e) { |
254 |
$this->_Queries = array(); |
255 |
} |
256 |
} |
257 |
if(sizeof($this->_Queries) > 0) { return; } // queries alreade loaded from cache |
258 |
$TP = str_replace('_','\_', $this->_TablePrefix); |
259 |
$sql = 'SELECT TABLE_NAME `table`, COLUMN_NAME `column` '; |
260 |
$sql .= 'FROM INFORMATION_SCHEMA.COLUMNS '; |
261 |
$sql .= 'WHERE `table_schema` = \''.$this->_db_name.'\' AND '; |
262 |
$sql .= '`table_name` LIKE \''.$TP.'%\' AND '; |
263 |
$sql .= '(`data_type` LIKE \'%text\' OR '; |
264 |
$sql .= '(`data_type` = \'varchar\' AND `character_maximum_length` > 20)'; |
265 |
$sql .= ')' ; |
266 |
$sql .= 'ORDER BY `table`, `column`'; |
267 |
if(($res = $this->_oDb->query($sql))) { |
268 |
$lastTable = ''; |
269 |
$aOrStatements = array(); |
270 |
$sPrefix = ''; |
271 |
while($rec = $res->fetchRow(MYSQL_ASSOC)) |
272 |
{ // loop through all found tables/fields
|
273 |
$sTableColumn = $rec['table'].'.'.$rec['column']; |
274 |
switch($this->_ControllListTyp): |
275 |
// test against controll list
|
276 |
case self::USE_BLACKLIST: |
277 |
$needRecord = true; |
278 |
if(in_array($rec['table'], $this->_ControllList) || |
279 |
in_array($sTableColumn, $this->_ControllList)) |
280 |
{ |
281 |
$needRecord = false; |
282 |
} |
283 |
break;
|
284 |
case self::USE_WHITELIST: |
285 |
$needRecord = false; |
286 |
if(in_array($rec['table'], $this->_ControllList) || |
287 |
in_array($sTableColumn, $this->_ControllList)) |
288 |
{ |
289 |
$needRecord = true; |
290 |
} |
291 |
break;
|
292 |
default: // self::USE_ALL |
293 |
$needRecord = true; |
294 |
break;
|
295 |
endswitch;
|
296 |
if($needRecord) { |
297 |
if($lastTable != $rec['table']) { |
298 |
if(sizeof($aOrStatements)!= 0){ |
299 |
// close previous table
|
300 |
$this->_Queries[] = $sPrefix.implode(') OR (', $aOrStatements).')'; |
301 |
} |
302 |
// start a new table
|
303 |
$sPrefix = 'SELECT COUNT(*) `count` FROM `'.$rec['table'].'` WHERE( '; |
304 |
$aOrStatements = array(); |
305 |
$lastTable = $rec['table']; |
306 |
} |
307 |
// add table.column to query
|
308 |
$aOrStatements[] = '`'.$rec['table'].'`.`'.$rec['column'].'` LIKE \'%1$s\''; |
309 |
} |
310 |
} |
311 |
if(sizeof($aOrStatements)!= 0){ |
312 |
// close last table
|
313 |
$this->_Queries[] = $sPrefix.implode(') OR (', $aOrStatements).')'; |
314 |
} |
315 |
unset($res); |
316 |
} |
317 |
if($this->_bUseCache) { |
318 |
// try to write queries into the cache
|
319 |
if(file_put_contents($sCacheFile, serialize($this->_Queries)) === false) { |
320 |
throw new RuntimeException('unable to write file ['.$sCacheFile.']'); |
321 |
} |
322 |
} |
323 |
} |
324 |
|
325 |
} |