Automatically redirect to logout page if session seems to be expired
[infodrom/hallinta] / ajax / ajax.php
1 <?php
2
3 require_once('../init.php');
4
5 function fetch($mask)
6 {
7   global $db;
8
9   $fields = array(db_format_datetime('sys_edit') . " AS sys_edit", 'sys_user');
10   foreach ($mask['edit'] as $field => $info) {
11     if (isset($info['sql']) && $info['sql'] === false) continue;
12     if ($info['type'] == 'date')
13       $fields[] = db_format_date(empty($info['sql']) ? $field : $info['sql']) .
14         sprintf(" AS %s", $field);
15     elseif ($info['type'] != 'passwd')
16       $fields[] = empty($info['sql']) ? $field : $info['sql'] . ' AS ' . $field;
17   }
18
19   $sql = sprintf('SELECT id,%s FROM %s WHERE id = %d',
20                  implode(',', $fields),
21                  $mask['table'], $_POST['id']);
22
23   $sth = $db->query($sql);
24   if ($sth === false) return false;
25
26   $row = $sth->fetch();
27
28   foreach ($mask['edit'] as $field => $info)
29     if ($info['type'] == 'boolean')
30       $row[$field] = $row[$field]?true:false;
31     elseif ($info['type'] == 'passwd')
32       $row[$field] = '';
33     elseif (array_key_exists('format', $info))
34       $row[$field] = sprintf($info['format'], $row[$field]);
35
36   return $row;
37 }
38
39 function details($mask)
40 {
41   if (empty($_POST['id']))
42     return array('error' => 'Missing ID');
43
44   $fields = array();
45   foreach ($mask['details']['list'] as $field => $info) {
46     if ($info['type'] == 'date')
47       $fields[] = db_format_date(empty($info['sql']) ? $field : $info['sql']) .
48         sprintf(" AS %s", $field);
49     elseif (!array_key_exists('fetch',$info))
50       $fields[] = empty($info['sql']) ? $field : $info['sql'] . ' AS ' . $field;
51   }
52
53   if (count($fields)) {
54     $sql = sprintf('SELECT id,%s FROM %s WHERE id = %d',
55                    implode(',', $fields),
56                    $mask['table'], $_POST['id']);
57
58     $sth = $db->query($sql);
59
60     if (!$sth)
61       return array('error' => db_error(),
62                    'sql' => $sql);
63
64     $row = $sth->fetch();
65   } else {
66     $row = array();
67   }
68
69   foreach ($mask['details']['list'] as $field => $info)
70     if (array_key_exists('format', $info))
71       $row[$field] = sprintf($info['format'], $row[$field]);
72     elseif (array_key_exists('fetch', $info))
73       $row[$field] = $info['fetch']();
74
75   return $row;
76 }
77
78 function format_date($value)
79 {
80   $d = explode('.', $value);
81   if (count($d) == 3)
82     $value = sprintf('%d-%d-%d', $d[2], $d[1], $d[0]);
83   return $value;
84 }
85
86 function format_decimal($value)
87 {
88   $value = str_replace(',','.',$value);
89   return sprintf("%.2f", $value);
90 }
91
92 $upload_error = array(
93                       'There is no error.',
94                       'The uploaded file exceeds the upload_max_filesize directive.',
95                       'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the form.',
96                       'The uploaded file was only partially uploaded.',
97                       'No file was uploaded.',
98                       'Missing a temporary folder.',
99                       'Failed to write file to disk.',
100                       'A PHP extension stopped the file upload.'
101                       );
102
103 function store_file($field, $info)
104 {
105   global $upload_error;
106
107   if (empty($_FILES[$field]['name']))
108     return array('error' => 'Kein Dateiname angegeben',
109                  'errormsg' => 'Kein Dateiname angegeben');
110
111   if ($_FILES[$field]['error'] > 0)
112     return array('error' => "Fehler beim Upload einer Datei:\n" . $upload_error[$_FILES[$field]['error']],
113                  'errormsg' => 'Fehler beim Upload einer Datei');
114
115   if (empty($_FILES[$field]['tmp_name']))
116     return array('error' => 'Keine temporäre Datei erzeugt',
117                  'errormsg' => 'Keine temporäre Datei erzeugt');
118
119   if (empty($info['path']))
120     return array('error' => 'Kein Pfadname konfiguriert',
121                  'errormsg' => 'Kein Pfadname konfiguriert');
122
123   $parts = pathinfo($_FILES[$field]['name']);
124
125   $base = $_SESSION['sys']['basedir'] . 'archive';
126   if (!is_dir($base))
127     return array('error' => 'Archivpfad nicht vorhanden',
128                  'errormsg' => 'Archivpfad nicht vorhanden');
129
130   $base .= '/' . $info['path'];
131   if (!is_dir($base))
132     return array('error' => 'Dokumentenpfad nicht vorhanden',
133                  'errormsg' => 'Dokumentenpfad nicht vorhanden');
134   $base .= '/';
135
136   $path = date('Y');
137   if (!is_dir($base.$path))
138     if (mkdir($base.$path) === false)
139       return array('error' => 'Kann Verzeichnis nicht anlegen: ' . $path,
140                    'errormsg' => 'Kann Verzeichnis nicht anlegen');
141
142   $path .= '/' . date('m');
143   if (!is_dir($base.$path))
144     if (mkdir($base.$path) === false)
145       return array('error' => 'Kann Verzeichnis nicht anlegen: ' . $path,
146                    'errormsg' => 'Kann Verzeichnis nicht anlegen');
147
148   $parts['filename'] = utf8_encode($parts['filename']);
149   $path .= '/' . $parts['filename'];
150
151   $max = 100;
152   for ($i=0; $i < $max; $i++) {
153     $fname = $path;
154     if ($i > 0) $fname .= '('.$i.')';
155     if (!empty($parts['extension']))
156       $fname .= '.' . $parts['extension'];
157
158     if (!is_file($base.$fname)) {
159       if (move_uploaded_file($_FILES[$field]['tmp_name'], $base.$fname) === false)
160         return array('error' => 'Kann Datei nicht speichern ',
161                      'errormsg' => 'Kann Datei nicht speichern');
162
163       chmod($base.$fname, 0640);
164       return $fname;
165     }
166   }
167
168   return array('error' => 'Kann Datei nicht anlegen',
169                'errormsg' => 'Kann Datei nicht anlegen');
170 }
171
172 function save($mask)
173 {
174   global $db;
175
176   if (array_key_exists('save', $mask))
177     return $mask['save']($mask);
178
179   if (empty($_POST['id']))
180     return array('error' => 'Missing ID');
181
182   $update = array(sprintf("sys_user = %s", $db->quote($_SESSION['sys']['login'])),
183                   "sys_edit = now()");
184
185   foreach ($mask['edit'] as $field => $info) {
186     if ($info['type'] == 'html') continue;
187     if ($info['type'] == 'file') continue;
188
189     if (isset($info['required']) && $info['required'] === true && !strlen($_POST[$field]))
190       return array('error' => sprintf('Pflichtfeld %s nicht ausgefüllt', $info['name']),
191                    'errormsg' => 'Pflichtfelder nicht ausgefüllt');
192
193     if ($info['type'] == 'boolean') {
194       $update[] = sprintf("%s=%d", $field, $_POST[$field] == 'on'?1:0);
195     } elseif ($info['type'] == 'hidden') {
196       if (empty($_POST[$field]) && $info['null'] === true)
197         $update[] = sprintf("%s=NULL", $field);
198       else {
199         if ($info['subtype'] == 'string')
200           $update[] = sprintf("%s=%s", $field, $db->quote($_POST[$field]));
201         else
202           $update[] = sprintf("%s=%d", $field, $_POST[$field]);
203       }
204     } elseif ($info['type'] == 'number' || ($info['type'] == 'select' && $info['options_string'] !== true)) {
205       if (empty($_POST[$field]) && $info['null'] === true)
206         $update[] = sprintf("%s=NULL", $field);
207       else
208         $update[] = sprintf("%s=%d", $field, $_POST[$field]);
209     } elseif ($info['type'] == 'decimal') {
210       if (empty($_POST[$field]) && $info['null'] === true)
211         $update[] = sprintf("%s=NULL", $field);
212       else
213         $update[] = sprintf("%s=%s", $field, format_decimal($_POST[$field]));
214     } elseif ($info['type'] == 'date') {
215       if (empty($_POST[$field]) && $info['null'] === true)
216         $update[] = sprintf("%s=NULL", $field);
217       else
218         $update[] = sprintf("%s='%s'", $field, format_date($_POST[$field]));
219     } elseif ($info['type'] == 'passwd') {
220       if (!empty($_POST[$field]))
221         $update[] = sprintf("%s=%s", $field,
222                             $db->quote(passwd(empty($_POST['login'])?$_SESSION['sys']['login']:$_POST['login'],
223                                                     $_POST[$field])));
224     } else {
225       if (empty($_POST[$field]) && $info['null'] === true)
226         $update[] = sprintf("%s=NULL", $field);
227       else
228         $update[] = sprintf("%s=%s", $field, $db->quote($_POST[$field]));
229     }
230   }
231
232   $sql = sprintf('UPDATE %s SET %s WHERE id = %d',
233                  empty($mask['edit_table']) ? $mask['table'] : $mask['edit_table'],
234                  implode(', ', $update),
235                  intval($_POST['id']));
236
237   $sth = $db->query($sql);
238
239   if ($sth === false) {
240     error_log($sql . ': ' . db_error());
241     return array('error' => db_error(),
242                  'sql' => $sql);
243   }
244
245   return array('status' => true);
246 }
247
248 function insert($mask)
249 {
250   global $db;
251
252   if (array_key_exists('insert', $mask))
253     return $mask['insert']($mask);
254
255   $fields = array('sys_user','sys_edit');
256   $values = array($db->quote($_SESSION['sys']['login']), 'now()');
257
258   foreach ($mask['edit'] as $field => $info) {
259     if ($info['type'] == 'html') continue;
260
261     if (isset($info['required']) && $info['required'] === true && !strlen($_POST[$field]))
262       return array('error' => sprintf('Pflichtfeld %s nicht ausgefüllt', $info['name']),
263                    'errormsg' => 'Pflichtfelder nicht ausgefüllt');
264
265     if ($info['type'] == 'boolean') {
266       $fields[] = $field;
267       $values[] = $_POST[$field] == 'on'?1:0;
268     } elseif ($info['type'] == 'hidden') {
269       $fields[] = $field;
270       if (empty($_POST[$field]) && $info['null'] === true)
271         $values[] = 'NULL';
272       else {
273         if ($info['subtype'] == 'string')
274           $values[] = $db->quote($_POST[$field]);
275         else
276           $values[] = intval($_POST[$field]);
277       }
278     } elseif ($info['type'] == 'number' || ($info['type'] == 'select' && $info['options_string'] !== true)) {
279       $fields[] = $field;
280       if (empty($_POST[$field]) && $info['null'] === true)
281         $values[] = 'NULL';
282       else
283         $values[] = intval($_POST[$field]);
284     } elseif ($info['type'] == 'decimal') {
285       $fields[] = $field;
286       if (empty($_POST[$field]) && $info['null'] === true)
287         $values[] = 'NULL';
288       else
289         $values[] = format_decimal($_POST[$field]);
290     } elseif ($info['type'] == 'date') {
291       $fields[] = $field;
292       if (empty($_POST[$field]) && $info['null'] === true)
293         $values[] = 'NULL';
294       else
295         $values[] = "'" . format_date($_POST[$field]) . "'";
296     } elseif ($info['type'] == 'passwd') {
297       if (!empty($_POST[$field])) {
298         $fields[] = $field;
299         $values[] = $db->quote(passwd(empty($_POST['login'])?$_SESSION['sys']['login']:$_POST['login'],
300                                       $_POST[$field]));
301       }
302     } elseif ($info['type'] == 'file') {
303       $fields[] = $field;
304       if (empty($_FILES[$field]) && $info['null'] === true)
305         $values[] = 'NULL';
306       elseif (empty($_FILES[$field]))
307         $values[] = "''";
308       else {
309         $fname = store_file($field, $info);
310         if (is_array($fname))
311           return $fname;
312         $values[] = $db->quote($fname);
313       }
314
315     } else {
316       $fields[] = $field;
317       if (empty($_POST[$field]) && isset($info['null']) && $info['null'] === true)
318         $values[] = 'NULL';
319       else
320         $values[] = $db->quote(utf8_encode($_POST[$field]));
321     }
322   }
323
324   $sql = sprintf('INSERT INTO %s (%s) VALUES (%s)',
325                  empty($mask['edit_table']) ? $mask['table'] : $mask['edit_table'],
326                  implode(',', $fields),
327                  implode(',', $values));
328
329   $sth = $db->query($sql);
330
331   if ($sth === false) {
332     error_log($sql . ': ' . db_error());
333     return array('error' => db_error(),
334                  'sql' => $sql);
335   }
336
337   $id = db_lastid(empty($mask['edit_table']) ? $mask['table'] : $mask['edit_table']);
338
339   if (array_key_exists('postinsert',$mask))
340     $mask['postinsert']($id);
341
342   return array('status' => true, 'id' => $id);
343 }
344
345 function delete_or_copy_row($table,$id,$mask)
346 {
347   global $db;
348
349   if (array_key_exists('predelete',$mask))
350     $mask['predelete']($id);
351
352   if (DELETE_COPY === true) {
353     $sql = sprintf("INSERT INTO %s_deleted SELECT * FROM %s WHERE id = %d",
354                    $table, $table, $id);
355
356     $sth = $db->query($sql);
357
358     if ($sth === false) {
359       error_log($sql . ': ' . db_error());
360       return array('error' => db_error(),
361                    'sql' => $sql);
362     }
363
364     $sql = sprintf("UPDATE %s_deleted SET sys_user='%s',sys_edit=now() WHERE id = %d",
365                    $table, $_SESSION['sys']['login'], $id);
366
367     $sth = $db->query($sql);
368
369     if ($sth === false) {
370       error_log($sql . ': ' . db_error());
371       return array('error' => db_error(),
372                    'sql' => $sql);
373     }
374   } else {
375     $fields = array();
376     foreach ($mask['edit'] as $field => $info)
377       if ($info['type'] === 'file')
378         $fields[] = array('name' => $field, 'path' => $info['path']);
379
380     if (count($fields)) {
381       $f = array();
382       foreach ($fields as $i)
383         $f[] = $i['name'];
384
385       $sql = sprintf("SELECT %s FROM %s WHERE id = %d", implode(',',$f), $table, $id);
386       $sth = $db->query($sql);
387
388       if ($sth === false) {
389         error_log($sql . ': ' . db_error());
390         return array('error' => db_error(),
391                      'sql' => $sql);
392       }
393
394       $row = $sth->fetch();
395       foreach ($fields as $f) {
396         $base = $_SESSION['sys']['basedir'] . 'archive/' . $f['path'];
397         $fname = $base . '/' . $row[$f['name']];
398         if (is_file($fname))
399           unlink($fname);
400       }
401     }
402   }
403
404   $sql = sprintf("DELETE FROM %s WHERE id = %d", $table, $_POST['id']);
405
406   $sth = $db->query($sql);
407
408   if ($sth === false) {
409     error_log($sql . ': ' . db_error());
410     return array('error' => db_error(),
411                  'sql' => $sql);
412   }
413
414   return array('status' => true);
415 }
416
417 function delete_or_copy($mask)
418 {
419   if (empty($_POST['id']))
420     return array('error' => 'Missing ID');
421
422   if (array_key_exists('delete', $mask))
423     return $mask['delete']($mask);
424
425   if (!empty($mask['edit_table']))
426     return array('error' => 'Cannot handle deletion for secondary table');
427
428   return delete_or_copy_row($mask['table'],$_POST['id'],$mask);
429 }
430
431 function set_variable($name,$mask)
432 {
433   if (!array_key_exists('variables',$mask))
434     return array('error' => 'Unknown variable ' . htmlspecialchars($_POST['name']));
435
436   if (!array_key_exists($_POST['name'],$mask['variables']))
437     return array('error' => 'Unknown variable ' . htmlspecialchars($_POST['name']));
438
439   $_SESSION[$name . '.' . $_POST['name']] = $_POST['value'];
440
441   if (array_key_exists('postcall',$mask['variables'][$_POST['name']]))
442     $mask['variables'][$_POST['name']]['postcall']();
443
444   return array('status' => true);
445 }
446
447 function get_infos($mask)
448 {
449   if (!array_key_exists('info',$mask))
450     return array('error' => 'Unknown callback ' . htmlspecialchars($_POST['name']));
451
452   if (!array_key_exists($_POST['name'],$mask['info']))
453     return array('error' => 'Unknown callback ' . htmlspecialchars($_POST['name']));
454
455   if (!array_key_exists('sql',$mask['info'][$_POST['name']]))
456     return array('error' => 'Unknown callback ' . htmlspecialchars($_POST['name']));
457
458   $sql = $mask['info'][$_POST['name']]['sql'];
459
460   while (preg_match('/\{([^\}]*)\}/', $sql, $matches))
461     $sql = str_replace('{'.$matches[1].'}', $_POST[$matches[1]], $sql);
462
463   return array('info' => query_db($sql),
464                'parameter' => $_POST);
465 }
466
467 function custom_function($mask)
468 {
469   if (!array_key_exists('callbacks',$mask))
470     return array('error' => 'Unknown callback ' . htmlspecialchars($_POST['callback']));
471
472   if (!array_key_exists($_POST['callback'],$mask['callbacks']))
473     return array('error' => 'Unknown callback ' . htmlspecialchars($_POST['callback']));
474
475   return $mask['callbacks'][$_POST['callback']]();
476 }
477
478 function send_file($fname)
479 {
480   if (($f = fopen($fname,'r')) === false)
481     return sprintf("Cannot open file %s", $fname);
482
483   $basename = basename($fname);
484   $filesize = filesize($fname);
485   $content_type = mime_content_type($fname);
486
487   if ($content_type == 'text/plain' || $content_type == 'text/html')
488     $content_type .= '; charset=UTF-8';
489
490   header(sprintf('Content-disposition: inline; filename="%s"', $basename));
491   header(sprintf('Content-Length: %d', $filesize));
492   header(sprintf('Content-Type: %s', $content_type));
493   header("Cache-Control: ");
494   header("Pragma: ");
495   usleep(5000);
496   fpassthru($f);
497   fclose($f);
498 }
499
500 function download_file($table,$column,$path,$id)
501 {
502   global $db;
503   global $mask;
504
505   $sql = sprintf("SELECT %s FROM %s WHERE id = %d", $column, $table, $id);
506   $sth = $db->query($sql);
507   if ($sth === false) return "Database error, Query " . $sql;
508
509   $row = $sth->fetch();
510
511   $fname = $_SESSION['sys']['basedir'] . 'archive/' . $path . '/' . $row[$column];
512
513   if (!file_exists($fname))
514     return sprintf("File not found\n%s", $fname);
515
516   return send_file($fname);
517 }
518
519 function process_file($mask)
520 {
521   if (!array_key_exists('files',$mask))
522     return array('error' => 'Unknown function ' . htmlspecialchars($_GET['name']));
523
524   if (!array_key_exists($_GET['name'],$mask['files']))
525     return array('error' => 'Unknown callback ' . htmlspecialchars($_GET['name']));
526
527   $mask['files'][$_GET['name']]();
528   exit;
529 }
530
531 if (empty($_REQUEST['func']))
532   exit;
533
534 if (empty($_REQUEST['source']))
535   exit;
536
537 db_connect();
538 if (load_mask($_REQUEST['source']) === false) exit;
539
540 $data = array('error' => 'Unknown function');
541
542 if (isset($_GET['func']) && $_GET['func'] == 'file' && !empty($_GET['name']))
543   $data = process_file($mask);
544
545 if ($_POST['func'] == 'fetch') {
546   $data = fetch($mask);
547 } elseif ($_POST['func'] == 'details') {
548   $data = details($mask);
549 } elseif ($_POST['func'] == 'save') {
550   $data = save($mask);
551 } elseif ($_POST['func'] == 'insert') {
552   $data = insert($mask);
553 } elseif ($_POST['func'] == 'delete') {
554   $data = delete_or_copy($mask);
555 } elseif ($_POST['func'] == 'setvar') {
556   $data = set_variable($_POST['source'],$mask);
557 } elseif ($_POST['func'] == 'info') {
558   $data = get_infos($mask);
559 } elseif ($_POST['func'] == 'function') {
560   $data = custom_function($mask);
561 }
562
563 format_ajax($data);
564
565 ?>