Overview

Packages

  • awl
    • caldav-client-v2
    • RRule
  • davical
    • authentication
      • drivers
    • caldav
    • DAViCalSession
    • DAVTicket
    • external-bind
    • feed
    • HTTPAuthSession
    • iSchedule
    • iSchedule-POST
    • logging
    • metrics
    • Principal
    • propfind
    • PublicSession
    • Request
    • Resource
    • tzservice
  • None
  • PHP

Classes

  • CalDAVClient
  • CheckResult
  • setupFakeSession
  • VCard
  • VTimezone

Functions

  • access_ticket_browser
  • binding_row_editor
  • bindings_to_other_browser
  • bindings_to_us_browser
  • build_dependencies_table
  • build_privileges_html
  • build_site_statistics
  • BuildSqlFilter
  • calquery_apply_filter
  • cardquery_apply_filter
  • catch_setup_errors
  • check_awl_version
  • check_calendar
  • check_curl
  • check_database_connection
  • check_datetime
  • check_davical_version
  • check_gettext
  • check_iconv
  • check_ldap
  • check_magic_quotes_gpc
  • check_magic_quotes_runtime
  • check_pdo
  • check_pdo_pgsql
  • check_pgsql
  • check_real_php
  • check_schema_version
  • check_string
  • check_suhosin_server_strip
  • check_xml
  • collection_privilege_format_function
  • confirm_delete_bind_in
  • confirm_delete_binding
  • confirm_delete_collection
  • confirm_delete_principal
  • confirm_delete_ticket
  • do_error
  • edit_binding_row
  • edit_grant_row_collection
  • edit_grant_row_principal
  • edit_group_row
  • edit_ticket_row
  • errorResponse
  • expand_properties
  • fetch_external
  • get_address_properties
  • get_freebusy
  • get_href_containers
  • get_phpinfo
  • grant_row_editor
  • group_members_browser
  • group_memberships_browser
  • group_row_editor
  • handle_subaction
  • i18n
  • ischedule_get
  • log_setup_error
  • make_help_link
  • principal_collection_browser
  • principal_editor
  • principal_grants_browser
  • principal_privilege_format_function
  • send_page_header
  • SqlFilterCardDAV
  • SqlFilterFragment
  • ticket_row_editor
  • unicodeToUtf8
  • update_external
  • utf8ToUnicode
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: /** todo work out something more than true/false returns for dependency checks */
  3: 
  4: 
  5: function i18n($value) {
  6:   return $value;  /* Just pass the value through */
  7: }
  8: 
  9: $skip_errors = false; // We need to hide a couple of unsightly errors even here...
 10: function log_setup_error($errno , $errstr , $errfile , $errline) {
 11:   global $skip_errors;
 12:   if ( $skip_errors ) return;
 13:   error_log('DAViCal setup.php: Informational: '.$errfile.'('.$errline.'): ['.$errno.'] '.$errstr);
 14: }
 15: 
 16: function catch_setup_errors($errno , $errstr , $errfile , $errline , $errcontext ) {
 17:   if ( $errno == 2 ) {
 18:     // A working installation will regularly fail to include_once() for several files as it searches for the location
 19:     log_setup_error($errno , $errstr , $errfile , $errline);
 20:     return true;
 21:   }
 22:   if ( $errno == 8 ) {
 23:     // Yeah, OK, so we redundantly call ob_flash() without needing to...
 24:     log_setup_error($errno , $errstr , $errfile , $errline);
 25:     return true;
 26:   }
 27:   else if ( $errno == 256 ) {
 28:     // This will (probably) be a database connection error, which will throw an exception if we return.
 29:     log_setup_error($errno , $errstr , $errfile , $errline);
 30:     return true;
 31:   }
 32:   if ( !headers_sent() ) header("Content-type: text/plain"); else echo "<pre>\n";
 33:   try {
 34:     @ob_flush(); // Seems like it should be better to do the following but is problematic on PHP5.3 at least: while ( ob_get_level() > 0 ) ob_end_flush();
 35:   }
 36:   catch( Exception $ignored ) {}
 37:   echo "Error [".$errno."] ".$errstr."\n";
 38:   echo "At line ", $errline, " of ", $errfile, "\n";
 39: 
 40:   $e = new Exception();
 41:   $trace = array_reverse($e->getTrace());
 42:   echo "================= Stack Trace ===================\n";
 43:   foreach( $trace AS $k => $v ) {
 44:     printf( "%s[%d] %s%s%s()\n", $v['file'], $v['line'], (isset($v['class'])?$v['class']:''), (isset($v['type'])?$v['type']:''), (isset($v['function'])?$v['function']:'') );
 45:   }
 46: }
 47: 
 48: set_error_handler('catch_setup_errors', E_ALL);
 49: 
 50: class CheckResult {
 51:   private $ok;
 52:   private $use_class;
 53:   private $description;
 54: 
 55:   function __construct( $success, $description=null, $use_class=null ) {
 56:     $this->ok = (boolean) $success;
 57:     $this->description = (isset($description)?$description : ($success===true? i18n('Passed') : i18n('Fail')));
 58:     $this->use_class = (isset($use_class)?$use_class:($success===true?'dep_ok' : 'dep_fail'));
 59:   }
 60: 
 61:   public function getClass() {
 62:     return $this->use_class;
 63:   }
 64: 
 65:   public function setClass( $new_class ) {
 66:     $this->use_class = $new_class;
 67:   }
 68: 
 69:   public function getOK() {
 70:     return $this->ok;
 71:   }
 72: 
 73:   public function getDescription() {
 74:     return translate($this->description);
 75:   }
 76: 
 77:   public function setDescription( $new_desc ) {
 78:     $this->description = $new_desc;
 79:   }
 80: 
 81: }
 82: 
 83: /**
 84:  * We put many of these checks before we even try to load always.php so that we
 85:  * can try and do some diagnostic work to ensure it will load OK.
 86:  */
 87: function check_pgsql() {
 88:   return new CheckResult(function_exists('pg_connect'));
 89: }
 90: 
 91: function check_pdo() {
 92:   return new CheckResult(class_exists('PDO'));
 93: }
 94: 
 95: function check_pdo_pgsql() {
 96:   global $loaded_extensions;
 97: 
 98:   if ( !check_pdo() ) return new CheckResult(false);
 99:   return new CheckResult(isset($loaded_extensions['pdo_pgsql']));
100: }
101: 
102: function check_database_connection() {
103:   global $c;
104: 
105:   if ( !check_pdo_pgsql() ) return new CheckResult(false);
106:   return new CheckResult( !( empty($c->schema_major) || $c->schema_major == 0 || empty($c->schema_minor) || $c->schema_minor == 0) );
107: }
108: 
109: function check_gettext() {
110:   global $phpinfo, $loaded_extensions;
111: 
112:   if ( !function_exists('gettext') ) return new CheckResult(false);
113:   return new CheckResult(isset($loaded_extensions['gettext']));
114: }
115: 
116: function check_iconv() {
117:   global $phpinfo, $loaded_extensions;
118: 
119:   if ( !function_exists('iconv') ) return new CheckResult(false);
120:   return new CheckResult(isset($loaded_extensions['iconv']));
121: }
122: 
123: function check_ldap() {
124:   global $phpinfo, $loaded_extensions;
125: 
126:   if (!function_exists('ldap_connect')) return new CheckResult(false);
127:   return new CheckResult(isset($loaded_extensions['ldap']));
128: }
129: 
130: function check_real_php() {
131:   global $phpinfo, $loaded_extensions;
132:   // Looking for "Server API </td><td class="v">Apache 2.0 Filter" in the phpinfo
133:   if ( preg_match('{Server API.*Apache 2\.. Filter}', $phpinfo) ) return new CheckResult(false);
134:   return new CheckResult(true);
135: }
136: 
137: function check_calendar() {
138:   global $phpinfo, $loaded_extensions;
139: 
140:   if (!function_exists('cal_days_in_month')) return new CheckResult(false);
141:   return new CheckResult(isset($loaded_extensions['calendar']));
142: }
143: 
144: function check_suhosin_server_strip() {
145:   global $loaded_extensions;
146: 
147:   if ( !isset($loaded_extensions['suhosin']) ) return new CheckResult(true);
148:   return new CheckResult( ini_get('suhosin.server.strip') == "0"
149:        || strtolower(ini_get('suhosin.server.strip')) == "off"
150:        || ini_get('suhosin.server.strip') == "" );
151: }
152: 
153: function check_magic_quotes_gpc() {
154:   return new CheckResult( (get_magic_quotes_gpc() == 0) );
155: }
156: 
157: function check_magic_quotes_runtime() {
158:   return new CheckResult( (get_magic_quotes_runtime() == 0) );
159: }
160: 
161: function check_curl() {
162:   global $phpinfo, $loaded_extensions;
163: 
164:   if (!function_exists('curl_init')) return new CheckResult(false);
165:   return new CheckResult(isset($loaded_extensions['curl']));
166: }
167: 
168: $loaded_extensions = array_flip(get_loaded_extensions());
169: 
170: 
171: function do_error( $errormessage ) {
172:   // We can't translate this because we're testing these things even before
173:   // the translation interface is available...
174:   printf("<p class='error'><br/>%s</p>", $errormessage );
175: }
176: 
177: if ( !check_gettext()->getOK() )   do_error("The GNU 'gettext' extension for PHP is not available.");
178: if ( !check_pgsql()->getOK() )     do_error("PHP 'pgsql' functions are not available");
179: if ( !check_pdo()->getOK() )       do_error("PHP 'PDO' module is not available");
180: if ( !check_pdo_pgsql()->getOK() ) do_error("The PDO drivers for PostgreSQL are not available");
181: if ( !check_iconv()->getOK() )     do_error("The 'iconv' extension for PHP is not available");
182: 
183: function get_phpinfo() {
184:   ob_start( );
185:   phpinfo();
186:   $phpinfo = ob_get_contents( );
187:   ob_end_clean( );
188: 
189:   $phpinfo = preg_replace( '{^.*?<body>}s', '', $phpinfo);
190:   $phpinfo = preg_replace( '{</body>.*?$}s', '', $phpinfo);
191:   return $phpinfo;
192: }
193: $phpinfo = get_phpinfo();
194: 
195: try {
196:   include("./always.php");
197:   set_error_handler('log_setup_error', E_ALL);
198:   include("DAViCalSession.php");
199:   if ( check_pgsql()->GetOK() ) {
200:     $session->LoginRequired( (isset($c->restrict_setup_to_admin) && $c->restrict_setup_to_admin ? 'Admin' : null ) );
201:   }
202: }
203: catch( Exception $e ) {
204:   class setupFakeSession {
205:     function AllowedTo() {
206:       return true;
207:     }
208:   }
209:   $session = new setupFakeSession(1);
210: }
211: 
212: 
213: include("interactive-page.php");
214: include("page-header.php");
215: 
216: require_once("AwlQuery.php");
217: 
218: 
219: function check_datetime() {
220:   if ( class_exists('DateTime') ) return new CheckResult(true);
221:   $result = new CheckResult(false);
222:   $result->setClass('dep_warning');
223:   $result->setDescription(i18n('Most of DAViCal will work but upgrading to PHP 5.2 or later is strongly recommended.'));
224:   return $result;
225: }
226: 
227: function check_xml() {
228:   return new CheckResult(function_exists('xml_parser_create_ns'));
229: }
230: 
231: function check_schema_version() {
232:   global $c;
233:   if ( $c->want_dbversion[0] == $c->schema_major
234:     && $c->want_dbversion[1] == $c->schema_minor
235:     && $c->want_dbversion[2] == $c->schema_patch ) {
236:     return new CheckResult( true );
237:   }
238:   $result = new CheckResult(false);
239:   if ( $c->want_dbversion[0] < $c->schema_major
240:        || ($c->want_dbversion[0] == $c->schema_major && $c->want_dbversion[1] < $c->schema_minor)
241:        || ($c->want_dbversion[0] == $c->schema_major
242:               && $c->want_dbversion[1] == $c->schema_minor
243:               && $c->want_dbversion[2] < $c->schema_patch)
244:       )
245:     {
246:       $result->setClass('dep_warning');
247:     }
248:     $result->setDescription( sprintf(i18n('Want: %s, Currently: %s'), implode('.',$c->want_dbversion),
249:             $c->schema_major.'.'.$c->schema_minor.'.'.$c->schema_patch));
250:     return $result;
251: }
252: 
253: function check_davical_version() {
254:   global $c;
255:   if ( ! ini_get('allow_url_fopen') )
256:     return new CheckResult( false, translate("Cannot determine upstream version, because PHP has set “<a href=\"https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen\"><code>allow_url_fopen</code></a>” to “<code>FALSE</code>”."), 'dep_warning' );
257:   $url = 'https://www.davical.org/current_davical_version?v='.$c->version_string;
258:   $version_file = @fopen($url, 'r');
259:   if ( ! $version_file ) return new CheckResult( false, translate("Could not retrieve") . " '$url'", 'dep_warning' );
260:   $current_version = htmlentities( trim(fread( $version_file,12)) );
261:   fclose($version_file);
262:   $result = new CheckResult($c->version_string == $current_version);
263:   if ( ! $result->getOK() ) {
264:     if ( $c->version_string > $current_version ) {
265:       $result->setClass('dep_ok');
266:       $result->setDescription( sprintf(i18n('Stable: %s, We have: %s !'), $current_version, $c->version_string) );
267:     }
268:     else {
269:       $result->setDescription( sprintf(i18n('Want: %s, Currently: %s'), $current_version, $c->version_string) );
270:     }
271:   }
272:   return $result;
273: }
274: 
275: 
276: function check_awl_version() {
277:   global $c;
278: 
279:   if ( !function_exists('awl_version') ) return new CheckResult(false);
280: 
281:   $result = new CheckResult($c->want_awl_version == awl_version());
282:   if ( ! $result->getOK() ) {
283:     $result->setDescription( sprintf(i18n('Want: %s, Currently: %s'), $c->want_awl_version, awl_version()) );
284:     if ( $c->want_awl_version < awl_version() ) $result->setClass('dep_warning');
285:   }
286:   return $result;
287: 
288: }
289: 
290: 
291: function build_site_statistics() {
292:   $principals  = translate('No. of Principals');
293:   $collections = translate('No. of Collections');
294:   $resources   = translate('No. of Resources');
295:   $table = <<<EOTABLE
296: <table class="statistics">
297: <tr><th>$principals</th><th>$collections</th><th>$resources</th></tr>
298: <tr>%s</tr>
299: </table>
300: EOTABLE;
301: 
302:   if ( !check_database_connection() ) {
303:     return sprintf( $table, '<td colspan="3">'.translate('Site Statistics require the database to be available!').'</td>');
304:   }
305:   $sql = 'SELECT
306: (SELECT count(1) FROM principal) AS principals,
307: (SELECT count(1) FROM collection) AS collections,
308: (SELECT count(1) FROM caldav_data) AS resources';
309:   $qry = new AwlQuery($sql);
310:   if ( $qry->Exec('setup',__LINE__,__FILE__) && $s = $qry->Fetch() ) {
311:     $row = sprintf('<td align="center">%s</td><td align="center">%s</td><td align="center">%s</td>',
312:                                        $s->principals, $s->collections, $s->resources );
313:     return sprintf( $table, $row );
314:   }
315:   return sprintf( $table, '<td colspan="3">'.translate('Site Statistics require the database to be available!').'</td>');
316: }
317: 
318: 
319: function build_dependencies_table( ) {
320:   global $c;
321: 
322:   $dependencies = array(
323:     translate('Current DAViCal version ')         => 'check_davical_version',
324:     translate('AWL Library version ')             => 'check_awl_version',
325:     translate('PHP not using Apache Filter mode') => 'check_real_php',
326:     translate('PHP PDO module available')         => 'check_pdo',
327:     translate('PDO PostgreSQL drivers')           => 'check_pdo_pgsql',
328:     translate('Database is Connected')            => 'check_database_connection',
329:     translate('DAViCal DB Schema version ')       => 'check_schema_version',
330:     translate('GNU gettext support')              => 'check_gettext',
331:     translate('PHP iconv support')                => 'check_iconv',
332:     translate('PHP DateTime class')               => 'check_datetime',
333:     translate('PHP XML support')                  => 'check_xml',
334:     translate('Suhosin "server.strip" disabled')  => 'check_suhosin_server_strip',
335:     translate('PHP Magic Quotes GPC off')         => 'check_magic_quotes_gpc',
336:     translate('PHP Magic Quotes runtime off')     => 'check_magic_quotes_runtime',
337:     translate('PHP calendar extension available') => 'check_calendar',
338:     translate('PHP curl support')                 => 'check_curl'
339:     );
340: 
341:   if ( isset($c->authenticate_hook) && isset($c->authenticate_hook['call']) && $c->authenticate_hook['call'] == 'LDAP_check') {
342:     $dependencies[translate('PHP LDAP module available')] = 'check_ldap';
343:   }
344: 
345:   $translated_failure_code = translate('<a href="https://wiki.davical.org/w/Setup_Failure_Codes/%s">Explanation on DAViCal Wiki</a>');
346: 
347:   $dependencies_table = '';
348:   $dep_tpl = '<tr class="%s">
349:   <td>%s</td>
350:   <td>%s</td>
351:   <td>'.$translated_failure_code.'</td>
352: </tr>
353: ';
354:   foreach( $dependencies AS $k => $v ) {
355:     $check_result = $v();
356:     $dependencies_table .= sprintf( $dep_tpl, $check_result->getClass(),
357:                              $k,
358:                              $check_result->getDescription(),
359:                              rawurlencode($k)
360:                            );
361:   }
362: 
363:   return $dependencies_table;
364: }
365: 
366: 
367: $heading_setup = translate('Setup');
368: $paragraph_setup = translate('This page primarily checks the environment needed for DAViCal to work correctly.  Suggestions or patches to make it do more useful stuff will be gratefully received.');
369: 
370: /*
371: $want_dbversion = implode('.',$c->want_dbversion);
372: $heading_versions = translate('Current Versions');
373: if ( check_schema_version() != true )
374: {
375:   $paragraph_versions = translate('You are currently running DAViCal version %s. The database schema should be at version %s and it is at version %d.%d.%d.');
376:   $paragraph_versions = sprintf( $paragraph_versions, $c->version_string, $want_dbversion, $c->schema_major, $c->schema_minor, $c->schema_patch);
377: } else {
378:   $paragraph_versions = translate('You are currently running DAViCal version %s. The database schema is at version %d.%d.%d.');
379:   $paragraph_versions = sprintf( $paragraph_versions, $c->version_string, $c->schema_major, $c->schema_minor, $c->schema_patch);
380: }
381: */
382: 
383: $heading_dependencies = translate('Dependencies');
384: $th_dependency = translate('Dependency');
385: $th_status     = translate('Status');
386: $dependencies_table = build_dependencies_table();
387: 
388: $heading_site_statistics = translate('Site Statistics');
389: if ( check_database_connection()->GetOK() ) {
390:   try {
391:     $site_statistics_table = build_site_statistics();
392:   }
393:   catch( Exception $e ) {
394:     $site_statistics_table = translate('Statistics unavailable');
395:   }
396: }
397: else {
398:   $site_statistics_table = translate('Statistics unavailable');
399: }
400: 
401: $heading_php_info = translate('PHP Information');
402: 
403: // Translations shared with index.php
404: $heading_clients = translate('Configuring Calendar Clients for DAViCal');
405: $content_cli1 = translate('The <a href="https://www.davical.org/clients.php">client setup page on the DAViCal website</a> has information on how to configure Evolution, Sunbird, Lightning and Mulberry to use remotely hosted calendars.');
406: $content_cli2 = translate('The administrative interface has no facility for viewing or modifying calendar data.');
407: 
408: // Translations shared with index.php
409: $heading_configure = translate('Configuring DAViCal');
410: $content_config1 = translate('If you can read this then things must be mostly working already.');
411: $content_config2 = ( $config_warnings == '' ? '' : '<div class="error"><h3 class="error">'
412:              . translate('Your configuration produced PHP errors which should be corrected') . '</h3><pre>'
413:              . $config_warnings.'</pre></div>'
414:           );
415: $content_config3 = translate('The <a href="https://www.davical.org/installation.php">DAViCal installation page</a> on the DAViCal website has some further information on how to install and configure this application.');
416: 
417: 
418:   echo <<<EOBODY
419: <style>
420: tr.dep_ok {
421:   background-color:#80ff80;
422: }
423: tr.dep_fail {
424:   background-color:#ff8080;
425: }
426: tr.dep_warning {
427:   background-color:#ffb040;
428: }
429: table, table.dependencies {
430:   border: 1px grey solid;
431:   border-collapse: collapse;
432:   padding: 0.1em;
433:   margin: 0 1em 1.5em;
434: }
435: table tr td, table tr th, table.dependencies tr td, table.dependencies tr th {
436:   border: 1px grey solid;
437:   padding: 0.1em 0.2em;
438: }
439: p {
440:   padding: 0.3em 0.2em 0.7em;
441: }
442: </style>
443: 
444: <h1>$heading_setup</h1>
445: <p>$paragraph_setup
446: 
447: <h2>$heading_dependencies</h2>
448: <p>
449: <table class="dependencies">
450: <tr>
451: <th>$th_dependency</th>
452: <th>$th_status</th>
453: </tr>
454: $dependencies_table
455: </table>
456: </p>
457: <h2>$heading_configure</h2>
458: <p>$content_config1</p>
459: $content_config2
460: <p>$content_config3</p>
461: 
462: <h2>$heading_clients</h2>
463: <p>$content_cli1</p>
464: <p>$content_cli2</p>
465: 
466: <h2>$heading_site_statistics</h2>
467: <p>$site_statistics_table</p>
468: 
469: <h2>$heading_php_info</h2>
470: <script language="javascript">
471: function toggle_visible() {
472:   var argv = toggle_visible.arguments;
473:   var argc = argv.length;
474: 
475:   var fld_checkbox =  document.getElementById(argv[0]);
476: 
477:   if ( argc < 2 ) {
478:     return;
479:   }
480: 
481:   for (var i = 1; i < argc; i++) {
482:     var block_id = argv[i].substr(1);
483:     var block_logical = argv[i].substr(0,1);
484:     var b = document.getElementById(block_id);
485:     if ( block_logical == '!' )
486:       b.style.display = (fld_checkbox.checked ? 'none' : '');
487:     else
488:       b.style.display = (!fld_checkbox.checked ? 'none' : '');
489:   }
490: }
491: </script><p><label>Show phpinfo() output:<input type="checkbox" value="1" id="fld_show_phpinfo" onclick="toggle_visible('fld_show_phpinfo','=phpinfo')"></label></p>
492: <div style="display:none" id="phpinfo">$phpinfo</div>
493: 
494: EOBODY;
495: 
496: include("page-footer.php");
497: 
DAViCal API documentation generated by ApiGen 2.8.0