Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
 
3
require_once('../config.inc.php');
4
 
5
require_once(HTML2PS_DIR.'stubs.common.inc.php');
6
require_once(HTML2PS_DIR.'error.php');
7
require_once(HTML2PS_DIR.'config.parse.php');
8
 
9
parse_config_file('../html2ps.config');
10
 
11
define('CHECK_STATUS_FAILED',  0);
12
define('CHECK_STATUS_WARNING', 1);
13
define('CHECK_STATUS_SUCCESS', 2);
14
 
15
error_reporting(E_ALL);
16
ini_set("display_errors","1");
17
 
18
$__g_registered_checks = array();
19
 
20
function out_header() {
21
  readfile('systemcheck.header.tpl');
22
}
23
 
24
function out_footer() {
25
  readfile('systemcheck.footer.tpl');
26
}
27
 
28
function status2class($status) {
29
  $mapping = array(CHECK_STATUS_FAILED  => "failed",
30
                   CHECK_STATUS_WARNING => "warning",
31
                   CHECK_STATUS_SUCCESS => "success");
32
  if (isset($mapping[$status])) {
33
    return $mapping[$status];
34
  };
35
 
36
  error_log(sprintf("Unknown status code passed to 'status2class': %s", $status));
37
  return "unknown";
38
}
39
 
40
function out_check_list() {
41
  $checks = ManagerChecks::getChecks();
42
  foreach ($checks as $check) {
43
    $title   = htmlspecialchars($check->title());
44
    $message = nl2br($check->getMessage());
45
    $status_class = status2class($check->getStatus());
46
 
47
    print <<<EOF
48
<div class="check">
49
<div class="title ${status_class}">${title}</div>
50
<div class="message">${message}</div>
51
</div>
52
EOF;
53
  };
54
}
55
 
56
class ManagerChecks {
57
  function register($check) {
58
    global $__g_registered_checks;
59
    $__g_registered_checks[] = $check;
60
  }
61
 
62
  function run() {
63
    global $__g_registered_checks;
64
    $size = count($__g_registered_checks);
65
    for ($i=0; $i<$size; $i++) {
66
      $__g_registered_checks[$i]->run();
67
    };
68
  }
69
 
70
  function getChecks() {
71
    global $__g_registered_checks;
72
    return $__g_registered_checks;
73
  }
74
}
75
 
76
class CheckSimple {
77
  var $_message;
78
 
79
  /**
80
   * Invariants
81
   */
82
  function title() {
83
    error_no_method('title', get_class($this));
84
  }
85
 
86
  function description() {
87
    error_no_method('description', get_class($this));
88
  }
89
 
90
  /**
91
   * Start checking
92
   */
93
  function run() {
94
    error_no_method('run', get_class($this));
95
  }
96
 
97
  /**
98
   * Get check status code; status code should be one of the following
99
   * predefined constants:
100
   * CHECK_STATUS_FAILED  - check failed, script will not work unless this issue is fixed
101
   * CHECK_STATUS_WARNING - check succeeded, script may encounter minor issues
102
   * CHECK_STATUS_SUCCESS - check succeeded without any problems
103
   *
104
   * @return Integer Status code
105
   */
106
  function getStatus() {
107
    error_no_method('status', get_class($this));
108
  }
109
 
110
  /**
111
   * Returns a short human-readable  message describing results of the
112
   * check run. By default, this message is generated in 'run' method
113
   * (overridden in CheckSimple children) and stored via 'setMessage'
114
   *
115
   * @return String description of the test results
116
   */
117
  function getMessage() {
118
    return $this->_message;
119
  }
120
 
121
  function setMessage($message) {
122
    $this->_message = $message;
123
  }
124
}
125
 
126
/**
127
 */
128
class CheckBinary extends CheckSimple {
129
  var $_success;
130
 
131
  function setSuccess($success) {
132
    $this->_success = $success;
133
  }
134
 
135
  function getSuccess() {
136
    return $this->_success;
137
  }
138
}
139
 
140
/**
141
 */
142
class CheckBinaryRequired extends CheckBinary {
143
  function getStatus() {
144
    if ($this->getSuccess()) {
145
      return CHECK_STATUS_SUCCESS;
146
    } else {
147
      return CHECK_STATUS_FAILED;
148
    };
149
  }
150
}
151
 
152
/**
153
 */
154
class CheckBinaryRecommended extends CheckBinary {
155
  function getStatus() {
156
    if ($this->getSuccess()) {
157
      return CHECK_STATUS_SUCCESS;
158
    } else {
159
      return CHECK_STATUS_WARNING;
160
    };
161
  }
162
}
163
 
164
/**
165
 */
166
class CheckTriState extends CheckSimple {
167
  var $_status;
168
 
169
  function getStatus() {
170
    return $this->_status;
171
  }
172
 
173
  function setStatus($status) {
174
    $this->_status = $status;
175
  }
176
}
177
 
178
/**
179
 * Actual checks
180
 */
181
 
182
/**
183
 * PHP version
184
 */
185
class CheckPHPVersion extends CheckTriState {
186
  function title() {
187
    return "PHP Version";
188
  }
189
 
190
  function description() {
191
    return "";
192
  }
193
 
194
  function run() {
195
    //    > "4.3.0";
196
  }
197
}
198
// ManagerChecks::register(new CheckPHPVersion());
199
 
200
/**
201
 * Required / recommended extensions
202
 */
203
 
204
/**
205
 * Presense of DOM/XML extensions
206
 */
207
class CheckDOM extends CheckTriState {
208
  function title() {
209
    return "XML DOM extension";
210
  }
211
 
212
  function description() {
213
    return "HTML files are parsed using XML DOM extensions";
214
  }
215
 
216
  function run() {
217
    if (function_exists('domxml_open_mem') ||
218
        class_exists('DOMDocument')) {
219
      $this->setStatus(CHECK_STATUS_SUCCESS);
220
      $this->setMessage('Native XML DOM extension found');
221
      return;
222
    };
223
 
224
    if (file_exists(HTML2PS_DIR.'classes/include.php')) {
225
      $this->setStatus(CHECK_STATUS_WARNING);
226
      $this->setMessage('No native XML DOM extension found, falling back to Active-State DOM XML. Note that it is <b>highly recommended to use native PHP XML DOM extension</b>.');
227
      return;
228
    };
229
 
230
    $this->setStatus(CHECK_STATUS_FAILED);
231
    $this->setMessage('No XML DOM extension found');
232
  }
233
}
234
 
235
/**
236
 * Presense of PDFLIB extension
237
 */
238
class CheckPDFLIB extends CheckBinaryRecommended {
239
}
240
 
241
/**
242
 * Presense of Curl extension
243
 */
244
class CheckCurl extends CheckBinaryRecommended {
245
  function title() {
246
    return "Curl PHP Extension";
247
  }
248
 
249
  function description() {
250
    return "Curl PHP extension is recommended for fetching files via HTTP protocol";
251
  }
252
 
253
  function run() {
254
    $this->setSuccess(false);
255
 
256
    if (!extension_loaded('curl')) {
257
      $this->setMessage('Missing Curl extension. Script will use pure-PHP fallback (allow_url_fopen=On is required!). <b>Proxy support is not available</b>');
258
      return;
259
    };
260
 
261
    $version = curl_version();
262
    // PHP 5.0.1 and greater return array instead of string
263
    if (is_array($version)) {
264
      $version = $version['version'];
265
    };
266
    $this->setMessage(sprintf('Found Curl extension version %s.', $version['version']));
267
    $this->setSuccess(true);
268
  }
269
}
270
 
271
/**
272
 * Presense of GD extension
273
 */
274
class CheckGD extends CheckBinaryRequired {
275
  function title() {
276
    return "GD PHP Extension";
277
  }
278
 
279
  function description() {
280
    return "GD PHP extension is required for graphic file processing";
281
  }
282
 
283
  function run() {
284
    $this->setSuccess(false);
285
 
286
    if (!extension_loaded('gd')) {
287
      $this->setMessage('Missing GD extension. Please refer to <a href="http://php.net/gd">PHP.net instructions</a> on installing/enabling this extension.');
288
      return;
289
    };
290
 
291
    $gd_info = gd_info();
292
    $gd_version_string = $gd_info['GD Version'];
293
 
294
    /**
295
     * Extract version number if it is a bundled version; otherwise we assume that
296
     * version string should contain verions number only
297
     */
298
    if (preg_match("/bundled \(([\d\.]+) compatible\)/", $gd_version_string, $matches)) {
299
      $gd_version = $matches[1];
300
    } else {
301
      $gd_version = $gd_version_string;
302
    };
303
 
304
    if (!function_exists('imagecreatetruecolor')) {
305
      $this->setMessage("GD version 2.0.1+ required for 'imagecreatetruecolor' function to work");
306
      return;
307
    };
308
 
309
    $this->setMessage("Found GD version $gd_version.");
310
    $this->setSuccess(true);
311
  }
312
}
313
 
314
/**
315
 * Presense of ZLIB extension (compressed files)
316
 */
317
class CheckZLIB extends CheckBinaryRecommended {
318
}
319
 
320
/**
321
 * System limits & settings
322
 */
323
 
324
/**
325
 * Execution time limit
326
 */
327
class CheckMaxExecutionTime extends CheckTriState {
328
}
329
 
330
/**
331
 * Memory limit
332
 */
333
class CheckMemoryLimit extends CheckTriState {
334
}
335
 
336
/**
337
 * Allow_url_fopen setting
338
 */
339
class CheckAllowURLFopen extends CheckBinaryRecommended {
340
  function title() {
341
    return "allow_url_fopen ini setting";
342
  }
343
 
344
  function description() {
345
    return "allow_url_fopen should be enabled when CURL extension is not available";
346
  }
347
 
348
  function run() {
349
    $this->setSuccess(false);
350
 
351
    $setting = ini_get('allow_url_fopen');
352
    if (!$setting) {
353
      $this->setMessage('<a href="http://php.net/filesystem">allow_url_fopen</a> is disabled. You will not be able to fetch files via HTTP without CURL extension.');
354
      return;
355
    }
356
 
357
    $this->setMessage('allow_url_fopen is enabled');
358
    $this->setSuccess(true);
359
  }
360
}
361
 
362
 
363
/**
364
 * pcre.backtrack_limit setting (PHP 5.2)
365
 */
366
class CheckPCREBacktrack extends CheckBinaryRecommended {
367
  function title() {
368
    return "pcre.backtrack_limit ini setting";
369
  }
370
 
371
  function description() {
372
    return "It is recommended to increase pcre.backtrack_limit value to 1,000,000";
373
  }
374
 
375
  function run() {
376
    $this->setSuccess(false);
377
 
378
    $version = explode('.', PHP_VERSION);
379
    if ($version[0] < 5 ||
380
        ($version[0] == 5 && $version[1] < 2)) {
381
      $this->setMessage('pcre.backtrack_limit is not available in PHP prior to 5.2.0');
382
      $this->setSuccess(true);
383
      return;
384
    };
385
 
386
    $setting = ini_get('pcre.backtrack_limit');
387
    if ($setting < 1000000) {
388
      $this->setMessage(sprintf('<a href="http://php.net/filesystem">pcre.backtrack_limit</a> is set to %s (less than 1,000,000). You could experience issues converting large pages.',
389
                                $setting));
390
      return;
391
    }
392
 
393
    $this->setMessage('pcre.backtrack_limit is greater than 1,000,000');
394
    $this->setSuccess(true);
395
  }
396
}
397
 
398
 
399
/**
400
 * Access/permissions
401
 */
402
 
403
/**
404
 * permissions on cache directory
405
 */
406
class CheckPermissionsCache extends CheckBinaryRequired {
407
  function title() {
408
    return "Permissions on 'cache' subdirectory";
409
  }
410
 
411
  function description() {
412
    return "Script should have full access to 'cache' subdirectory to keep cached files there";
413
  }
414
 
415
  function run() {
416
    if (!file_exists(HTML2PS_DIR.'/cache/')) {
417
      $this->setMessage("'cache' subdirectory is missing");
418
      $this->setSuccess(false);
419
      return;
420
    };
421
 
422
    if (!is_readable(HTML2PS_DIR.'/cache/')) {
423
      $this->setMessage("'cache' subdirectory is not readable");
424
      $this->setSuccess(false);
425
      return;
426
    };
427
 
428
    if (!is_writable(HTML2PS_DIR.'/cache/')) {
429
      $this->setMessage("'cache' subdirectory is not writable");
430
      $this->setSuccess(false);
431
      return;
432
    };
433
 
434
    if (!is_executable(HTML2PS_DIR.'/cache/') && PHP_OS != "WINNT") {
435
      $this->setMessage("'cache' subdirectory is not executable");
436
      $this->setSuccess(false);
437
      return;
438
    };
439
 
440
    $this->setMessage("'cache' subdirectory is fully accessible to the script");
441
    $this->setSuccess(true);
442
  }
443
}
444
 
445
/**
446
 * Permissions on 'out' directory
447
 */
448
class CheckPermissionsOut extends CheckBinaryRecommended {
449
  function title() {
450
    return "Permissions on 'out' subdirectory";
451
  }
452
 
453
  function description() {
454
    return "Script should have full access to 'out' subdirectory to put generated files there";
455
  }
456
 
457
  function run() {
458
    if (!file_exists(HTML2PS_DIR.'/out/')) {
459
      $this->setMessage("'out' subdirectory is missing");
460
      $this->setSuccess(false);
461
      return;
462
    };
463
 
464
    if (!is_readable(HTML2PS_DIR.'/out/')) {
465
      $this->setMessage("'out' subdirectory is not readable");
466
      $this->setSuccess(false);
467
      return;
468
    };
469
 
470
    if (!is_writable(HTML2PS_DIR.'/out/')) {
471
      $this->setMessage("'out' subdirectory is not writable");
472
      $this->setSuccess(false);
473
      return;
474
    };
475
 
476
    if (!is_executable(HTML2PS_DIR.'/out/') && PHP_OS != "WINNT") {
477
      $this->setMessage("'out' subdirectory is not executable");
478
      $this->setSuccess(false);
479
      return;
480
    };
481
 
482
    $this->setMessage("'out' subdirectory is fully accessible to the script");
483
    $this->setSuccess(true);
484
  }
485
}
486
 
487
/**
488
 * Permissions on 'temp' directory (system-dependent)
489
 */
490
class CheckPermissionsTemp extends CheckBinaryRequired {
491
  function title() {
492
    return "Permissions on 'temp' subdirectory";
493
  }
494
 
495
  function description() {
496
    return "Script should have full access to 'temp' subdirectory to keep temporary files there";
497
  }
498
 
499
  function run() {
500
    if (!file_exists(HTML2PS_DIR.'/temp/')) {
501
      $this->setMessage("'temp' subdirectory is missing");
502
      $this->setSuccess(false);
503
      return;
504
    };
505
 
506
    if (!is_readable(HTML2PS_DIR.'/temp/')) {
507
      $this->setMessage("'temp' subdirectory is not readable");
508
      $this->setSuccess(false);
509
      return;
510
    };
511
 
512
    if (!is_writable(HTML2PS_DIR.'/temp/')) {
513
      $this->setMessage("'temp' subdirectory is not writable");
514
      $this->setSuccess(false);
515
      return;
516
    };
517
 
518
    if (!is_executable(HTML2PS_DIR.'/temp/') && PHP_OS != "WINNT") {
519
      $this->setMessage("'temp' subdirectory is not executable");
520
      $this->setSuccess(false);
521
      return;
522
    };
523
 
524
    $this->setMessage("'temp' subdirectory is fully accessible to the script");
525
    $this->setSuccess(true);
526
  }
527
}
528
 
529
/**
530
 * Permissions/availability of GS executable
531
 */
532
 
533
/**
534
 * Permissions of fonts directory
535
 */
536
class CheckPermissionsFonts extends CheckBinaryRequired {
537
  function title() {
538
    return "Permissions on 'fonts' subdirectory";
539
  }
540
 
541
  function description() {
542
    return "Script should be able to read 'fonts' subdirectory to access installed fonts";
543
  }
544
 
545
  function run() {
546
    if (!file_exists(HTML2PS_DIR.'/fonts/')) {
547
      $this->setMessage("'fonts' subdirectory is missing");
548
      $this->setSuccess(false);
549
      return;
550
    };
551
 
552
    if (!is_readable(HTML2PS_DIR.'/fonts/')) {
553
      $this->setMessage("'fonts' subdirectory is not readable");
554
      $this->setSuccess(false);
555
      return;
556
    };
557
 
558
    if (!is_executable(HTML2PS_DIR.'/fonts/') && PHP_OS != "WINNT") {
559
      $this->setMessage("'fonts' subdirectory is not executable");
560
      $this->setSuccess(false);
561
      return;
562
    };
563
 
564
    $this->setMessage("'fonts' subdirectory is readable and executable by the script");
565
    $this->setSuccess(true);
566
  }
567
}
568
 
569
/**
570
 * Permissions/presence of Type1 fonts repository
571
 */
572
class CheckPermissionsType1 extends CheckBinaryRecommended {
573
  function title() {
574
    return "Permissions on Type1 fonts directory";
575
  }
576
 
577
  function description() {
578
    return "Script should be able to access Type1 fonts directory containing font metrics in order to generate Postscript files";
579
  }
580
 
581
  function run() {
582
    if (!file_exists(TYPE1_FONTS_REPOSITORY)) {
583
      $this->setMessage("Type1 fonts directory (".TYPE1_FONTS_REPOSITORY.") is missing. You will not be able to generate postscript files.");
584
      $this->setSuccess(false);
585
      return;
586
    };
587
 
588
    if (!is_readable(TYPE1_FONTS_REPOSITORY)) {
589
      $this->setMessage("Type1 fonts directory (".TYPE1_FONTS_REPOSITORY.") is not readable. You will not be able to generate postscript files.");
590
      $this->setSuccess(false);
591
      return;
592
    };
593
 
594
    if (!is_executable(HTML2PS_DIR.'/fonts/') && PHP_OS != "WINNT") {
595
      $this->setMessage("Type1 fonts directory (".TYPE1_FONTS_REPOSITORY.") is not executable. You will not be able to generate postscript files.");
596
      $this->setSuccess(false);
597
      return;
598
    };
599
 
600
    $this->setMessage("Type1 fonts directory is readable and executable by the script");
601
    $this->setSuccess(true);
602
  }
603
}
604
 
605
/**
606
 * Fonts
607
 */
608
 
609
/**
610
 * Permissions/presense of TTF files
611
 */
612
class CheckPresenceTTF extends CheckBinaryRecommended {
613
  function title() {
614
    return "Presense of registered TTF files";
615
  }
616
 
617
  function description() {
618
    return "TrueType fonts registered in html2ps.config should be present in order to generate PDF files with these fonts.";
619
  }
620
 
621
  function run() {
622
    $message = "";
623
    $this->setSuccess(true);
624
 
625
    global $g_font_resolver_pdf;
626
    foreach ($g_font_resolver_pdf->ttf_mappings as $file) {
627
      $fullname = HTML2PS_DIR.'/fonts/'.$file;
628
 
629
      if (!file_exists($fullname)) {
630
        $message .= "Font ".$fullname." is missing. You will not be able to generate PDF files with this font.\n";
631
        $this->setSuccess(false);
632
      } elseif (!file_exists($fullname)) {
633
        $message .= "Font ".$fullname." is not readable. You will not be able to generate PDF files with this font.\n";
634
        $this->setSuccess(false);
635
      } else {
636
        $message .= "Font ".$fullname." is present and readable.\n";
637
      };
638
    };
639
 
640
    $this->setMessage($message);
641
  }
642
}
643
 
644
/**
645
 * Permissions/presense of Type1 fonts
646
 */
647
 
648
/**
649
 * Permissions/presense of AFM files for Type1 fonts
650
 */
651
class CheckPresenceType1AFM extends CheckBinaryRecommended {
652
  function title() {
653
    return "Presense of registered TTF files";
654
  }
655
 
656
  function description() {
657
    return "TrueType fonts registered in html2ps.config should be present in order to generate PDF files with these fonts.";
658
  }
659
 
660
  function run() {
661
    $message = "";
662
    $this->setSuccess(true);
663
 
664
    global $g_font_resolver;
665
    foreach ($g_font_resolver->afm_mappings as $file) {
666
      $fullname = TYPE1_FONTS_REPOSITORY.$file.'.afm';
667
 
668
      if (!file_exists($fullname)) {
669
        $message .= "Font ".$fullname." is missing. You will not be able to generate PDF files with this font.\n";
670
        $this->setSuccess(false);
671
      } elseif (!file_exists($fullname)) {
672
        $message .= "Font ".$fullname." is not readable. You will not be able to generate PDF files with this font.\n";
673
        $this->setSuccess(false);
674
      } else {
675
        $message .= "Font ".$fullname." is present and readable.\n";
676
      };
677
    };
678
 
679
    $this->setMessage($message);
680
  }
681
}
682
 
683
/**
684
 * Graphics
685
 */
686
 
687
/**
688
 * Generic
689
 */
690
class CheckGDFormat extends CheckBinaryRequired {
691
  function title() {
692
    return "GD ".$this->_getFormatName()." Support";
693
  }
694
 
695
  function description() {
696
    return "GD ".$this->_getFormatName()." Support is required for reading images in ".$this->_getFormatName()." format";
697
  }
698
 
699
  function run() {
700
    $this->setSuccess(false);
701
 
702
    if (!extension_loaded('gd')) {
703
      $this->setMessage('Missing GD extension. Please refer to <a href="http://php.net/gd">PHP.net instructions</a> on installing/enabling this extension.');
704
      return;
705
    };
706
 
707
    $gd_info = gd_info();
708
    if (!$gd_info[$this->_getInfoKey()]) {
709
      $this->setMessage("No ".$this->_getFormatName()." support, some images will not be displayed");
710
      return;
711
    };
712
 
713
    $this->setMessage($this->_getFormatName()." support enabled");
714
    $this->setSuccess(true);
715
  }
716
}
717
 
718
/**
719
 * JPEG support
720
 */
721
class CheckGDJPEG extends CheckGDFormat {
722
  function _getFormatName() {
723
    return "JPEG";
724
  }
725
 
726
  function _getInfoKey() {
727
    return "JPG Support";
728
  }
729
}
730
 
731
/**
732
 * GIF support
733
 */
734
class CheckGDGIF extends CheckGDFormat {
735
  function _getFormatName() {
736
    return "GIF";
737
  }
738
 
739
  function _getInfoKey() {
740
    return "GIF Read Support";
741
  }
742
}
743
 
744
/**
745
 * PNG support
746
 */
747
class CheckGDPNG extends CheckGDFormat {
748
  function _getFormatName() {
749
    return "PNG";
750
  }
751
 
752
  function _getInfoKey() {
753
    return "PNG Support";
754
  }
755
}
756
 
757
/**
758
 * Freetype support
759
 */
760
 
761
/**
762
 * Miscellanous
763
 */
764
 
765
/**
766
 * Check if outgoing connections are allowed
767
 */
768
class CheckOutgoingConnections extends CheckBinary {
769
}
770
 
771
ManagerChecks::register(new CheckDOM());
772
ManagerChecks::register(new CheckCurl());
773
ManagerChecks::register(new CheckAllowURLFopen());
774
ManagerChecks::register(new CheckPCREBacktrack());
775
ManagerChecks::register(new CheckGD());
776
ManagerChecks::register(new CheckGDJPEG());
777
ManagerChecks::register(new CheckGDGIF());
778
ManagerChecks::register(new CheckGDPNG());
779
ManagerChecks::register(new CheckPermissionsTemp());
780
ManagerChecks::register(new CheckPermissionsFonts());
781
ManagerChecks::register(new CheckPermissionsType1());
782
ManagerChecks::register(new CheckPresenceTTF());
783
ManagerChecks::register(new CheckPresenceType1AFM());
784
 
785
ManagerChecks::run();
786
out_header();
787
out_check_list();
788
out_footer();
789
 
790
?>