Improved entropy for report file urls.
[fa-stable.git] / includes / main.inc
1 <?php
2 /**********************************************************************
3     Copyright (C) FrontAccounting, LLC.
4         Released under the terms of the GNU General Public License, GPL, 
5         as published by the Free Software Foundation, either version 3 
6         of the License, or (at your option) any later version.
7     This program is distributed in the hope that it will be useful,
8     but WITHOUT ANY WARRANTY; without even the implied warranty of
9     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
10     See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
11 ***********************************************************************/
12 include_once($path_to_root . "/includes/db/connect_db.inc");
13
14 include_once($path_to_root . "/includes/types.inc");
15 include_once($path_to_root . "/includes/systypes.inc");
16 include_once($path_to_root . "/includes/references.inc");
17 include_once($path_to_root . "/includes/db/comments_db.inc");
18 include_once($path_to_root . "/includes/db/sql_functions.inc");
19 include_once($path_to_root . "/includes/db/audit_trail_db.inc");
20 //include_once($path_to_root . "/includes/validation.inc");
21
22 include_once($path_to_root . "/admin/db/users_db.inc");
23 include_once($path_to_root . "/includes/ui/ui_view.inc");
24 include_once($path_to_root . "/includes/ui/ui_controls.inc");
25         
26 function page($title, $no_menu=false, $is_index=false, $onload="", $js="", $script_only=false, $css='')
27 {
28
29         global $path_to_root, $page_security;
30
31
32         $hide_menu = $no_menu;
33
34         include($path_to_root . "/includes/page/header.inc");
35
36         page_header($title, $no_menu, $is_index, $onload, $js, $css);
37         check_page_security($page_security);
38 //      error_box();
39         if($script_only) {              
40                 echo '<noscript>';
41                 echo display_heading(_('This page is usable only with javascript enabled browsers.'));
42                 echo '</noscript>';
43                 div_start('_page_body', null, true);
44         } else {
45                 div_start('_page_body'); // whole page content for ajax reloading
46         }
47 }
48
49 function end_page($no_menu=false, $is_index=false, $final_screen=false, $type_no=0, $trans_no=0)
50 {
51         global $path_to_root;
52
53         if (!$is_index && function_exists('hyperlink_back'))
54                 hyperlink_back(true, $no_menu, $type_no, $trans_no, $final_screen);
55         div_end();      // end of _page_body section
56
57         include($path_to_root . "/includes/page/footer.inc");
58         page_footer($no_menu, $is_index);
59 }
60
61 function cache_js_file($fpath, $text) 
62 {
63         global $go_debug;
64
65         if(!$go_debug) $text = js_compress($text);
66
67         $file = fopen($fpath, 'w');
68         if (!$file) return false;
69         if (!fwrite($file, $text)) return false;
70         return fclose($file);
71
72 }
73
74 function add_js_file($filename) 
75 {
76           global $js_static;
77
78           $search = array_search($filename, $js_static);
79           if ($search === false || $search === null) // php>4.2.0 returns null
80                 $js_static[] = $filename;       
81 }
82
83 function add_js_ufile($filename) 
84 {
85           global $js_userlib;
86
87           $search = array_search($filename, $js_userlib);
88           if ($search === false || $search === null) // php>4.2.0 returns null
89                 $js_userlib[] = $filename;
90 }
91
92 function add_js_source($text) 
93 {
94           global $js_lib;
95           
96           $search = array_search($text, $js_lib);
97           if ($search === false || $search === null) // php>4.2.0 returns null
98                 $js_lib[] = $text;
99 }
100
101 /**
102  * Compresses the Javascript code for more efficient delivery.
103  * copyright (c) 2005 by Jared White & J. Max Wilson
104  * http://www.xajaxproject.org
105  * Added removing comments from output.
106  * Warning: Fails on RegExp with quotes - use new RegExp() in this case.
107  */
108 function js_compress($sJS)
109 {
110         //remove windows cariage returns
111         $sJS = str_replace("\r","",$sJS);
112         
113         //array to store replaced literal strings
114         $literal_strings = array();
115         
116         //explode the string into lines
117         $lines = explode("\n",$sJS);
118         //loop through all the lines, building a new string at the same time as removing literal strings
119         $clean = "";
120         $inComment = false;
121         $literal = "";
122         $inQuote = false;
123         $escaped = false;
124         $quoteChar = "";
125         
126         for($i=0;$i<count($lines);$i++)
127         {
128                 $line = $lines[$i];
129                 $inNormalComment = false;
130         
131                 //loop through line's characters and take out any literal strings, replace them with ___i___ where i is the index of this string
132                 $len = strlen($line);
133                 for($j=0;$j<$len;$j++)
134                 {
135                         $c = $line[$j];         // this is _really_ faster than subst
136                         $d = $c.$line[$j+1];
137         
138                         //look for start of quote
139                         if(!$inQuote && !$inComment)
140                         {
141                                 //is this character a quote or a comment
142                                 if(($c=="\"" || $c=="'") && !$inComment && !$inNormalComment)
143                                 {
144                                         $inQuote = true;
145                                         $inComment = false;
146                                         $escaped = false;
147                                         $quoteChar = $c;
148                                         $literal = $c;
149                                 }
150                                 else if($d=="/*" && !$inNormalComment)
151                                 {
152                                         $inQuote = false;
153                                         $inComment = true;
154                                         $escaped = false;
155                                         $quoteChar = $d;
156                                         $literal = $d;  
157                                         $j++;   
158                                 }
159                                 else if($d=="//") //ignore string markers that are found inside comments
160                                 {
161                                         $inNormalComment = true;
162                                         $clean .= $c;
163                                 }
164                                 else
165                                 {
166                                         $clean .= $c;
167                                 }
168                         }
169                         else //allready in a string so find end quote
170                         {
171                                 if($c == $quoteChar && !$escaped && !$inComment)
172                                 {
173                                         $inQuote = false;
174                                         $literal .= $c;
175         
176                                         //subsitute in a marker for the string
177                                         $clean .= "___" . count($literal_strings) . "___";
178         
179                                         //push the string onto our array
180                                         array_push($literal_strings,$literal);
181         
182                                 }
183                                 else if($inComment && $d=="*/")
184                                 {
185                                         $inComment = false;
186                                         $literal .= $d;
187         
188                                         //subsitute in a marker for the string
189                                         $clean .= "___" . count($literal_strings) . "___";
190         
191                                         //push the string onto our array
192                                         array_push($literal_strings,$literal);
193         
194                                         $j++;
195                                 }
196                                 else if($c == "\\" && !$escaped)
197                                         $escaped = true;
198                                 else
199                                         $escaped = false;
200         
201                                 $literal .= $c;
202                         }
203                 }
204                 if($inComment) $literal .= "\n";
205                 $clean .= "\n";
206         }
207         //explode the clean string into lines again
208         $lines = explode("\n",$clean);
209         
210         //now process each line at a time
211         for($i=0;$i<count($lines);$i++)
212         {
213                 $line = $lines[$i];
214         
215                 //remove comments
216                 $line = preg_replace("/\/\/(.*)/","",$line);
217         
218                 //strip leading and trailing whitespace
219                 $line = trim($line);
220         
221                 //remove all whitespace with a single space
222                 $line = preg_replace("/\s+/"," ",$line);
223         
224                 //remove any whitespace that occurs after/before an operator
225                 $line = preg_replace("/\s*([!\}\{;,&=\|\-\+\*\/\)\(:])\s*/","\\1",$line);
226         
227                 $lines[$i] = $line;
228         }
229         
230         //implode the lines
231         $sJS = implode("\n",$lines);
232         
233         //make sure there is a max of 1 \n after each line
234         $sJS = preg_replace("/[\n]+/","\n",$sJS);
235         
236         //strip out line breaks that immediately follow a semi-colon
237         $sJS = preg_replace("/;\n/",";",$sJS);
238         
239         //curly brackets aren't on their own
240         $sJS = preg_replace("/[\n]*\{[\n]*/","{",$sJS);
241         
242         //finally loop through and replace all the literal strings:
243         for($i=0;$i<count($literal_strings);$i++) {
244             if (strpos($literal_strings[$i],"/*")!==false) 
245                 $literal_strings[$i]= '';
246                 $sJS = str_replace("___".$i."___",$literal_strings[$i],$sJS);
247         }
248         return $sJS;
249 }
250
251 /*
252         Check if file can be updated, restoring subdirectories 
253         if needed. Returns 1 when no confilcts, -1 when file exists and is writable
254 */
255 function check_write($path)
256 {
257         if ($path == ''//|| $path == '.' || $path == '..'
258         ) return 0;
259
260         return is_writable($path) ? (is_dir($path) ? 1 : -1) 
261                 : (is_file($path) ? 0 : ($path == '.' || $path == '..' ? 0 : check_write(dirname($path))));
262 }
263
264 /*
265         Copies set of files. When $strict is set
266         also removes files from the $to which 
267         does not exists in $from directory but arelisted in $flist.
268 */
269 function copy_files($flist, $from, $to, $strict=false)
270 {
271         foreach ($flist as $file) {
272                 if (file_exists($from.'/'.$file)) {
273                         if (!copy_file($file, $from, $to))
274                                 return false;
275                 } else if ($strict) {
276                                 unlink($to.'/'.$file);
277                 }
278         }
279         return true;
280 }
281
282 /*
283         Copies file from base to target directory, restoring subdirectories 
284         if needed.
285 */
286 function copy_file($file, $from, $to)
287 {
288
289         if (!is_dir(dirname($file=='.' ? $to : ($to.'/'.$file)))) {
290                 if (!copy_file(dirname($file), null, $to))
291                         return false;
292         }
293         if (!$from) {
294         //              error_log( 'dodanie katalogu '.$to.'/'.$file);
295                 return @mkdir($file=='.' ? $to : ($to.'/'.$file));
296         }
297         else {
298         //              error_log( 'skopiowanie '.$to.'/'.$file);
299                 return @copy($from.'/'.$file, $to.'/'.$file);
300         }
301 }
302 /*
303         Search for file, looking first for company specific version, then for 
304         version provided by any extension module, finally in main FA directory.
305         Also adds include path for any related files, and sets $local_path_to_root 
306         to enable local translation domains.
307         
308         Returns found file path or null.
309 */
310 function find_custom_file($rep)
311 {
312         global $installed_extensions, $path_to_root, $local_path_to_root;
313
314         // customized per company version
315         $path = company_path();
316         $file = $path.$rep;
317         if (file_exists($file)) {
318                 // add local include path
319                 $local_path_to_root = $path;
320                 set_include_path(dirname($file).PATH_SEPARATOR.get_include_path());
321                 return $file;
322         }
323         // file added by active extension modules
324         if (count($installed_extensions) > 0)
325         {
326                 $extensions = $installed_extensions;
327                 foreach ($extensions as $ext)
328                         if (($ext['active'] && $ext['type'] == 'extension')) {
329                                 $path = $path_to_root.'/'.$ext['path'];
330                                 $file = $path.$rep;
331                                 if (file_exists($file)) {
332                                         set_include_path($path.PATH_SEPARATOR.get_include_path());
333                                         $local_path_to_root = $path;
334                                         return $file;
335                                 }
336                         }
337         }
338         // standard location
339         $file = $path_to_root.$rep;
340         if (file_exists($file))
341                 return $file;
342
343         return null;
344 }
345 /*
346         
347         Protect against directory traversal.
348         Changes all not POSIX compatible chars to underscore.
349 */
350 function clean_file_name($filename) {
351     $filename = str_replace(chr(0), '', $filename);
352     return preg_replace('/[^a-zA-Z0-9.\-_]/', '_', $filename);
353 }
354
355 /*
356         This function aims to generate cryptographically strong random identifier.
357         Result identifier has length 4[strength/8/3] 
358 */
359 function random_id($strength = 128)
360 {
361         $n = ceil($strength/8);
362
363         if (function_exists('openssl_random_pseudo_bytes'))
364                 $bin = openssl_random_pseudo_bytes($n, $cstrong);       // openssl on php 5.3 and up
365         else if (file_exists('/dev/urandom'))
366                 $bin = file_get_contents('/dev/urandom', false, null, -1, $n);  // linux std random device
367         else {
368                 $bin = '';
369                 for($i=0; $i < $n; $i++)
370                         $bin .= chr(mt_rand(0, 255));   // Mersene Twister generator
371         }
372         $id = strtr(base64_encode($bin), '+/', '-_');   // see RFC 4648 Section 5
373
374         return $id;
375 }