1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
16: class Horde
17: {
18: 19: 20: 21: 22:
23: static protected $_compressStart = false;
24:
25: 26: 27: 28: 29:
30: static protected $_used = array();
31:
32: 33: 34: 35: 36:
37: static protected $_labels = array();
38:
39: 40: 41: 42: 43:
44: static protected $_noAccessKey;
45:
46: 47: 48: 49: 50:
51: static protected $_hooksLoaded = array();
52:
53: 54: 55: 56: 57:
58: static protected $_inlineScript = array();
59:
60: 61: 62: 63: 64:
65: static protected $_bufferLevel = 0;
66:
67: 68: 69: 70: 71:
72: static protected $_contentSent = false;
73:
74: 75: 76: 77: 78:
79: static protected $_metaTags = array();
80:
81: 82: 83: 84: 85:
86: static public function logMessage($event, $priority = null,
87: array $options = array())
88: {
89: 90:
91: if (isset($GLOBALS['conf']) && isset($GLOBALS['injector'])) {
92: $options['trace'] = 2;
93: $GLOBALS['injector']->getInstance('Horde_Log_Logger')->log($event, $priority, $options);
94: }
95: }
96:
97: 98: 99: 100: 101: 102: 103: 104:
105: static public function debug($event = null, $fname = null)
106: {
107: if (is_null($fname)) {
108: $fname = self::getTempDir() . '/horde_debug.txt';
109: }
110:
111: try {
112: $logger = new Horde_Log_Logger(new Horde_Log_Handler_Stream($fname));
113: } catch (Exception $e) {
114: return;
115: }
116:
117: $html_ini = ini_set('html_errors', 'Off');
118: self::startBuffer();
119: if (!is_null($event)) {
120: echo "Variable information:\n";
121: var_dump($event);
122: echo "\n";
123: }
124:
125: if (is_resource($event)) {
126: echo "Stream contents:\n";
127: rewind($event);
128: fpassthru($event);
129: echo "\n";
130: }
131:
132: echo "Backtrace:\n";
133: echo strval(new Horde_Support_Backtrace());
134:
135: $logger->log(self::endBuffer(), Horde_Log::DEBUG);
136: ini_set('html_errors', $html_ini);
137: }
138:
139: 140: 141: 142: 143: 144: 145: 146: 147:
148: static public function fatal($error, $file = null, $line = null,
149: $log = true)
150: {
151:
152: if ($log) {
153: try {
154: self::logMessage($error, 'EMERG');
155: } catch (Exception $e) {}
156: }
157:
158: header('Content-type: text/html; charset=UTF-8');
159: try {
160: $admin = $GLOBALS['registry']->isAdmin();
161: $cli = Horde_Cli::runningFromCLI();
162:
163: $errortext = '<h1>' . Horde_Core_Translation::t("A fatal error has occurred") . '</h1>';
164:
165: if (($error instanceof PEAR_Error) ||
166: (is_object($error) && method_exists($error, 'getMessage'))) {
167: $errortext .= '<h3>' . htmlspecialchars($error->getMessage()) . '</h3>';
168: } elseif (is_string($error)) {
169: $errortext .= '<h3>' . htmlspecialchars($error) . '</h3>';
170: }
171:
172: if ($admin || $cli) {
173: $trace = ($error instanceof Exception)
174: ? $error
175: : debug_backtrace();
176: $errortext .= '<div id="backtrace"><pre>' .
177: strval(new Horde_Support_Backtrace($trace)) .
178: '</pre></div>';
179: if (is_object($error)) {
180: $errortext .= '<h3>' . Horde_Core_Translation::t("Details") . '</h3>';
181: $errortext .= '<h4>' . Horde_Core_Translation::t("The full error message is logged in Horde's log file, and is shown below only to administrators. Non-administrative users will not see error details.") . '</h4>';
182: $errortext .= '<div id="details"><pre>' . htmlspecialchars(print_r($error, true)) . '</pre></div>';
183: }
184: } elseif ($log) {
185: $errortext .= '<h3>' . Horde_Core_Translation::t("Details have been logged for the administrator.") . '</h3>';
186: }
187: } catch (Exception $e) {
188: die($e);
189: }
190:
191: if ($cli) {
192: echo html_entity_decode(strip_tags(str_replace(array('<br />', '<p>', '</p>', '<h1>', '</h1>', '<h3>', '</h3>'), "\n", $errortext)));
193: } else {
194: echo <<< HTML
195: <html>
196: <head><title>Horde :: Fatal Error</title></head>
197: <body style="background:#fff; color:#000">$errortext</body>
198: </html>
199: HTML;
200: }
201: exit(1);
202: }
203:
204: 205: 206: 207: 208: 209: 210: 211: 212:
213: static public function errorHandler($errno, $errstr, $errfile, $errline,
214: $errcontext)
215: {
216:
217: if (error_reporting() == 0) {
218:
219: return false;
220: }
221:
222: if (class_exists('Horde_Log')) {
223: try {
224: switch ($errno) {
225: case E_WARNING:
226: $priority = Horde_Log::WARN;
227: break;
228:
229: case E_NOTICE:
230: $priority = Horde_Log::NOTICE;
231: break;
232:
233: default:
234: $priority = Horde_Log::DEBUG;
235: break;
236: }
237:
238: self::logMessage(new ErrorException('PHP ERROR: ' . $errstr, 0, $errno, $errfile, $errline), $priority);
239: if (class_exists('Horde_Support_Backtrace')) {
240: self::logMessage(new Horde_Support_Backtrace(), Horde_Log::DEBUG);
241: }
242: } catch (Exception $e) {}
243: }
244: }
245:
246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266:
267: static public function addScriptFile($file, $app = null,
268: $options = array())
269: {
270: $hsf = $GLOBALS['injector']->getInstance('Horde_Script_Files');
271: if (empty($options['external'])) {
272: $hsf->add($file, $app, !empty($options['full']));
273: } else {
274: $hsf->addExternal($file, $app);
275: }
276: }
277:
278: 279: 280: 281: 282: 283:
284: static public function includeScriptFiles()
285: {
286: global $conf;
287:
288: $driver = empty($conf['cachejs'])
289: ? 'none'
290: : $conf['cachejsparams']['driver'];
291: $hsf = $GLOBALS['injector']->getInstance('Horde_Script_Files');
292:
293: if ($driver == 'none') {
294: $hsf->includeFiles();
295: return;
296: }
297:
298: $js = array(
299: 'force' => array(),
300: 'external' => array(),
301: 'tocache' => array()
302: );
303: $mtime = array(
304: 'force' => array(),
305: 'tocache' => array()
306: );
307:
308: $s_list = $hsf->listFiles();
309: if (empty($s_list)) {
310: return;
311: }
312:
313: if ($driver == 'horde_cache') {
314: $cache = $GLOBALS['injector']->getInstance('Horde_Cache');
315: $cache_lifetime = empty($conf['cachejsparams']['lifetime'])
316: ? 0
317: : $conf['cachejsparams']['lifetime'];
318: }
319:
320:
321: if ($s_list['horde'][0]['f'] == 'prototype.js') {
322: $js['force'][] = $s_list['horde'][0]['p'] . $s_list['horde'][0]['f'];
323: $mtime['force'][] = filemtime($s_list['horde'][0]['p'] . $s_list['horde'][0]['f']);
324: unset($s_list['horde'][0]);
325: }
326:
327: foreach ($s_list as $files) {
328: foreach ($files as $file) {
329: if ($file['d'] && ($file['f'][0] != '/') && empty($file['e'])) {
330: $js['tocache'][] = $file['p'] . $file['f'];
331: $mtime['tocache'][] = filemtime($file['p'] . $file['f']);
332: } elseif (!empty($file['e'])) {
333: $js['external'][] = $file['u'];
334: } else {
335: $js['force'][] = $file['p'] . $file['f'];
336: $mtime['force'][] = filemtime($file['p'] . $file['f']);
337: }
338: }
339: }
340:
341: $jsmin_params = null;
342: foreach ($js as $key => $files) {
343: if (!count($files)) {
344: continue;
345: }
346:
347: if ($key == 'external') {
348: foreach ($files as $val) {
349: $hsf->outputTag($val);
350: }
351: continue;
352: }
353:
354: $sig_files = $files;
355: sort($sig_files);
356: $sig = hash('md5', serialize($sig_files) . max($mtime[$key]));
357:
358: switch ($driver) {
359: case 'filesystem':
360: $js_filename = '/static/' . $sig . '.js';
361: $js_path = $GLOBALS['registry']->get('fileroot', 'horde') . $js_filename;
362: $js_url = $GLOBALS['registry']->get('webroot', 'horde') . $js_filename;
363: $exists = file_exists($js_path);
364: break;
365:
366: case 'horde_cache':
367:
368: $exists = $cache->exists($sig, $cache_lifetime);
369: $js_url = self::getCacheUrl('js', array('cid' => $sig));
370: break;
371: }
372:
373: if (!$exists) {
374: $out = '';
375: foreach ($files as $val) {
376: $js_text = file_get_contents($val);
377:
378: if ($conf['cachejsparams']['compress'] == 'none') {
379: $out .= $js_text . "\n";
380: } else {
381: if (is_null($jsmin_params)) {
382: switch ($conf['cachejsparams']['compress']) {
383: case 'closure':
384: $jsmin_params = array(
385: 'closure' => $conf['cachejsparams']['closurepath'],
386: 'java' => $conf['cachejsparams']['javapath']
387: );
388: break;
389:
390: case 'yui':
391: $jsmin_params = array(
392: 'java' => $conf['cachejsparams']['javapath'],
393: 'yui' => $conf['cachejsparams']['yuipath']
394: );
395: break;
396: }
397: }
398:
399: 400:
401: try {
402: $out .= $GLOBALS['injector']->getInstance('Horde_Core_Factory_TextFilter')->filter($js_text, 'JavascriptMinify', $jsmin_params) . "\n";
403: } catch (Horde_Exception $e) {
404: $out .= $js_text . "\n";
405: }
406: }
407: }
408:
409: switch ($driver) {
410: case 'filesystem':
411: if (!file_put_contents($js_path, $out)) {
412: throw new Horde_Exception('Could not write cached JS file to disk.');
413: }
414: break;
415:
416: case 'horde_cache':
417: $cache->set($sig, $out);
418: break;
419: }
420: }
421:
422: $hsf->outputTag($js_url);
423: }
424:
425: $hsf->clear();
426: }
427:
428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438:
439: static public function signQueryString($queryString, $now = null)
440: {
441: if (!isset($GLOBALS['conf']['secret_key'])) {
442: return $queryString;
443: }
444:
445: if (is_null($now)) {
446: $now = time();
447: }
448:
449: $queryString .= '&_t=' . $now . '&_h=';
450:
451: return $queryString . Horde_Url::uriB64Encode(hash_hmac('sha1', $queryString, $GLOBALS['conf']['secret_key'], true));
452: }
453:
454: 455: 456: 457: 458: 459: 460: 461:
462: static public function verifySignedQueryString($data, $now = null)
463: {
464: if (is_null($now)) {
465: $now = time();
466: }
467:
468: $pos = strrpos($data, '&_h=');
469: if ($pos === false) {
470: return false;
471: }
472: $pos += 4;
473:
474: $queryString = substr($data, 0, $pos);
475: $hmac = substr($data, $pos);
476:
477: if ($hmac != Horde_Url::uriB64Encode(hash_hmac('sha1', $queryString, $GLOBALS['conf']['secret_key'], true))) {
478: return false;
479: }
480:
481:
482: parse_str($queryString, $values);
483:
484: return !($values['_t'] + $GLOBALS['conf']['urls']['hmac_lifetime'] * 60 < $now);
485: }
486:
487: 488: 489: 490: 491: 492: 493: 494: 495: 496: 497: 498: 499: 500: 501: 502: 503: 504: 505: 506: 507: 508: 509: 510: 511:
512: static public function getServiceLink($type, $app = null)
513: {
514: $opts = array('app' => 'horde');
515:
516: switch ($type) {
517: case 'ajax':
518: $opts['noajax'] = true;
519: return self::url('services/ajax.php/' . $app . '/', false, $opts);
520:
521: case 'cache':
522: $opts['append_session'] = -1;
523: return self::url('services/cache.php', false, $opts);
524:
525: case 'download':
526: return self::url('services/download/', false, $opts)
527: ->add('module', $app);
528:
529: case 'emailconfirm':
530: $opts['noajax'] = true;
531: return self::url('services/confirm.php', false, $opts);
532:
533: case 'go':
534: $opts['noajax'] = true;
535: return self::url('services/go.php', false, $opts);
536:
537: case 'help':
538: return self::url('services/help/', false, $opts)
539: ->add('module', $app);
540:
541: case 'imple':
542: $opts['noajax'] = true;
543: return self::url('services/imple.php', false, $opts);
544:
545: case 'login':
546: $opts['noajax'] = true;
547: return self::url('login.php', false, $opts);
548:
549: case 'logintasks':
550: return self::url('services/logintasks.php', false, $opts)
551: ->add('app', $app);
552:
553: case 'logout':
554: return $GLOBALS['registry']->getLogoutUrl(array('reason' => Horde_Auth::REASON_LOGOUT));
555:
556: case 'pixel':
557: return self::url('services/images/pixel.php', false, $opts);
558:
559: case 'prefs':
560: if (!in_array($GLOBALS['conf']['prefs']['driver'], array('', 'none'))) {
561: $url = self::url('services/prefs.php', false, $opts);
562: if (!is_null($app)) {
563: $url->add('app', $app);
564: }
565: return $url;
566: }
567: break;
568:
569: case 'portal':
570: if ($GLOBALS['session']->get('horde', 'mode') == 'smartmobile' && self::ajaxAvailable()) {
571: return self::url('services/portal/mobile.php', false, $opts);
572: } else {
573: return self::url('services/portal/', false, $opts);
574: }
575: break;
576:
577: case 'problem':
578: return self::url('services/problem.php', false, $opts)
579: ->add('return_url', self::selfUrl(true, true, true));
580:
581: case 'sidebar':
582: return self::url('services/sidebar.php', false, $opts);
583:
584: case 'twitter':
585: return self::url('services/twitter/', true, $opts);
586: }
587:
588: return false;
589: }
590:
591: 592: 593: 594: 595: 596: 597: 598: 599: 600: 601:
602: static public function prepareResponse($data = null, $notify = false)
603: {
604: $response = new stdClass();
605: $response->response = $data;
606:
607: if ($notify) {
608: $stack = $GLOBALS['notification']->notify(array('listeners' => 'status', 'raw' => true));
609: if (!empty($stack)) {
610: $response->msgs = $stack;
611: }
612: }
613:
614: return $response;
615: }
616:
617: 618: 619: 620: 621: 622: 623:
624: static public function sendHTTPResponse($data, $ct)
625: {
626:
627: switch ($ct) {
628: case 'json':
629: case 'js-json':
630: 631: 632: 633: 634: 635: 636: 637: 638: 639: 640: 641: 642:
643: $s_data = str_replace("\00", '', self::escapeJson($data));
644:
645: if ($ct == 'json') {
646: header('Content-Type: application/json');
647: echo $s_data;
648: } else {
649: header('Content-Type: text/html; charset=UTF-8');
650: echo htmlspecialchars($s_data);
651: }
652: break;
653:
654: case 'html':
655: case 'plain':
656: case 'xml':
657: $s_data = is_string($data) ? $data : $data->response;
658: header('Content-Type: text/' . $ct . '; charset=UTF-8');
659: echo $s_data;
660: break;
661:
662: default:
663: echo $data;
664: }
665:
666: exit;
667: }
668:
669: 670: 671: 672: 673: 674: 675: 676: 677: 678: 679: 680: 681: 682:
683: static public function escapeJson($data, array $options = array())
684: {
685: $json = Horde_Serialize::serialize($data, Horde_Serialize::JSON);
686: if (empty($options['nodelimit'])) {
687: $json = '/*-secure-' . $json . '*/';
688: }
689:
690: return empty($options['urlencode'])
691: ? $json
692: : '\'' . rawurlencode($json) . '\'';
693: }
694:
695: 696: 697: 698: 699: 700:
701: static public function isConnectionSecure()
702: {
703: if ($GLOBALS['browser']->usingSSLConnection()) {
704: return true;
705: }
706:
707: if (!empty($GLOBALS['conf']['safe_ips'])) {
708: if (reset($GLOBALS['conf']['safe_ips']) == '*') {
709: return true;
710: }
711:
712: 713: 714: 715: 716:
717: if (!isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
718: $remote_addr = $_SERVER['REMOTE_ADDR'];
719: foreach ($GLOBALS['conf']['safe_ips'] as $safe_ip) {
720: $safe_ip = preg_replace('/(\.0)*$/', '', $safe_ip);
721: if (strpos($remote_addr, $safe_ip) === 0) {
722: return true;
723: }
724: }
725: }
726: }
727:
728: return false;
729: }
730:
731: 732: 733: 734: 735:
736: static public function requireSecureConnection()
737: {
738: if (!self::isConnectionSecure()) {
739: throw new Horde_Exception(Horde_Core_Translation::t("The encryption features require a secure web connection."));
740: }
741: }
742:
743: 744: 745: 746: 747: 748: 749: 750: 751: 752: 753: 754: 755: 756: 757: 758: 759:
760: static public function loadConfiguration($config_file, $var_names = null,
761: $app = null, $show_output = false)
762: {
763: global $registry;
764:
765: if (is_null($app)) {
766: $app = $registry->getApp();
767: }
768:
769:
770:
771: $filelist = array();
772: $was_included = false;
773:
774:
775: $config_dir = (($app == 'horde') && defined('HORDE_BASE'))
776: ? HORDE_BASE . '/config/'
777: : $registry->get('fileroot', $app) . '/config/';
778: $base_path = $file = $config_dir . $config_file;
779: if (file_exists($file)) {
780: $filelist[$file] = 1;
781: }
782:
783:
784: $directory = preg_replace('/\.php$/', '.d', $base_path);
785: if (file_exists($directory) &&
786: is_dir($directory) &&
787: ($sub_files = glob("$directory/*.php"))) {
788: foreach ($sub_files as $val) {
789: $filelist[$val] = 0;
790: }
791: }
792:
793:
794: $file = substr($file, 0, strrpos($file, '.')) . '.local'
795: . substr($file, strrpos($file, '.'));
796: if (file_exists($file)) {
797: $filelist[$file] = 0;
798: }
799:
800:
801:
802:
803: $vhost_added = false;
804: if (!empty($GLOBALS['conf']['vhosts'])) {
805: $file = $config_dir . substr($config_file, 0, -4) . '-' . $GLOBALS['conf']['server']['name'] . '.php';
806:
807: if (file_exists($file)) {
808: $filelist[$file] = 0;
809: }
810: $vhost_added = true;
811: }
812:
813: 814:
815: while (list($file, $log_check) = each($filelist)) {
816: 817: 818:
819: self::startBuffer();
820: $success = (is_null($var_names) && !$show_output)
821: ? include_once $file
822: : include $file;
823: $output = self::endBuffer();
824:
825: if (!$success) {
826: throw new Horde_Exception(sprintf('Failed to import configuration file "%s".', $file));
827: }
828:
829: if (!empty($output) && !$show_output) {
830: 831:
832: if ($log_check &&
833: isset($conf['log']['priority']) &&
834: (strpos($conf['log']['priority'], 'PEAR_LOG_') !== false)) {
835: $conf['log']['priority'] = 'INFO';
836: self::logMessage('Logging priority is using the old PEAR_LOG constant', 'INFO');
837: } else {
838: throw new Horde_Exception(sprintf('Failed to import configuration file "%s": ', $file) . strip_tags($output));
839: }
840: }
841:
842:
843: if (!$vhost_added &&
844: $app == 'horde' &&
845: $config_file == 'conf.php') {
846: if (!empty($conf['vhosts'])) {
847: $file = $config_dir . 'conf-' . $conf['server']['name'] . '.php';
848: if (file_exists($file)) {
849: $filelist[$file] = 0;
850: }
851: }
852: $vhost_added = true;
853: }
854:
855: $was_included = true;
856: }
857:
858:
859:
860: if (!$was_included) {
861: throw new Horde_Exception(sprintf('Failed to import configuration file "%s".', $base_path));
862: }
863:
864: if (isset($output) && $show_output) {
865: echo $output;
866: }
867:
868: Horde::logMessage('Load config file (' . $config_file . '; app: ' . $app . ')', 'DEBUG');
869:
870: if (is_null($var_names)) {
871: return;
872: } elseif (is_array($var_names)) {
873: return compact($var_names);
874: } elseif (isset($$var_names)) {
875: return $$var_names;
876: }
877:
878: return array();
879: }
880:
881: 882: 883: 884: 885: 886: 887: 888: 889: 890: 891: 892: 893:
894: static public function getDriverConfig($backend, $type = 'sql')
895: {
896: global $conf;
897:
898: if (!is_null($type)) {
899: $type = Horde_String::lower($type);
900: }
901:
902: if (is_array($backend)) {
903: $c = Horde_Array::getElement($conf, $backend);
904: } elseif (isset($conf[$backend])) {
905: $c = $conf[$backend];
906: } else {
907: $c = null;
908: }
909:
910: if (!is_null($c) && isset($c['params'])) {
911: $c['params']['umask'] = $conf['umask'];
912: return (!is_null($type) && isset($conf[$type]))
913: ? array_merge($conf[$type], $c['params'])
914: : $c['params'];
915: }
916:
917: return (!is_null($type) && isset($conf[$type]))
918: ? $conf[$type]
919: : array();
920: }
921:
922: 923: 924: 925: 926: 927: 928: 929: 930: 931: 932: 933: 934: 935: 936: 937: 938: 939:
940: static public function assertDriverConfig($params, $driver, $fields,
941: $name = null,
942: $file = 'conf.php',
943: $variable = '$conf')
944: {
945: global $registry;
946:
947:
948:
949: if (is_null($name)) {
950: $name = isset($registry) ? $registry->getApp() : '[unknown]';
951: }
952: $fileroot = isset($registry) ? $registry->get('fileroot') : '';
953:
954: if (!is_array($params) || !count($params)) {
955: throw new Horde_Exception(
956: sprintf(Horde_Core_Translation::t("No configuration information specified for %s."), $name) . "\n\n" .
957: sprintf(Horde_Core_Translation::t("The file %s should contain some %s settings."),
958: $fileroot . '/config/' . $file,
959: sprintf("%s['%s']['params']", $variable, $driver)));
960: }
961:
962: foreach ($fields as $field) {
963: if (!isset($params[$field])) {
964: throw new Horde_Exception(
965: sprintf(Horde_Core_Translation::t("Required \"%s\" not specified in %s configuration."), $field, $name) . "\n\n" .
966: sprintf(Horde_Core_Translation::t("The file %s should contain a %s setting."),
967: $fileroot . '/config/' . $file,
968: sprintf("%s['%s']['params']['%s']", $variable, $driver, $field)));
969: }
970: }
971: }
972:
973: 974: 975: 976: 977: 978: 979: 980: 981: 982: 983: 984: 985: 986: 987: 988: 989: 990: 991: 992: 993: 994: 995: 996: 997:
998: static public function url($uri, $full = false, $opts = array())
999: {
1000: if (is_array($opts)) {
1001: $append_session = isset($opts['append_session'])
1002: ? $opts['append_session']
1003: : 0;
1004: if (!empty($opts['force_ssl'])) {
1005: $full = true;
1006: }
1007: } else {
1008: $append_session = $opts;
1009: $opts = array();
1010: }
1011:
1012: $puri = parse_url($uri);
1013: $url = '';
1014: $schemeRegexp = '|^([a-zA-Z][a-zA-Z0-9+.-]{0,19})://|';
1015: $webroot = ltrim($GLOBALS['registry']->get('webroot', empty($opts['app']) ? null : $opts['app']), '/');
1016:
1017: if ($full &&
1018: !isset($puri['scheme']) &&
1019: !preg_match($schemeRegexp, $webroot) ) {
1020:
1021: $server_name = $GLOBALS['conf']['server']['name'];
1022: $server_port = isset($GLOBALS['conf']['server']['port']) ? $GLOBALS['conf']['server']['port'] : '';
1023:
1024: $protocol = 'http';
1025: switch ($GLOBALS['conf']['use_ssl']) {
1026: case 1:
1027: $protocol = 'https';
1028: break;
1029:
1030: case 2:
1031: if ($GLOBALS['browser']->usingSSLConnection()) {
1032: $protocol = 'https';
1033: }
1034: break;
1035:
1036: case 3:
1037: $server_port = '';
1038: if (!empty($opts['force_ssl'])) {
1039: $protocol = 'https';
1040: }
1041: break;
1042: }
1043:
1044:
1045: if (!empty($server_port) &&
1046: ((($protocol == 'http') && ($server_port != 80)) ||
1047: (($protocol == 'https') && ($server_port != 443)))) {
1048: $server_name .= ':' . $server_port;
1049: }
1050:
1051: $url = $protocol . '://' . $server_name;
1052: } elseif (isset($puri['scheme'])) {
1053: $url = $puri['scheme'] . '://' . $puri['host'];
1054:
1055:
1056: if (isset($puri['port']) &&
1057: ((($puri['scheme'] == 'http') && ($puri['port'] != 80)) ||
1058: (($puri['scheme'] == 'https') && ($puri['port'] != 443)))) {
1059: $url .= ':' . $puri['port'];
1060: }
1061: }
1062:
1063: if (isset($puri['path']) &&
1064: (substr($puri['path'], 0, 1) == '/') &&
1065: (!preg_match($schemeRegexp, $webroot) ||
1066: (preg_match($schemeRegexp, $webroot) && isset($puri['scheme'])))) {
1067: $url .= $puri['path'];
1068: } elseif (isset($puri['path']) && preg_match($schemeRegexp, $webroot)) {
1069: if (substr($puri['path'], 0, 1) == '/') {
1070: $pwebroot = parse_url($webroot);
1071: $url = $pwebroot['scheme'] . '://' . $pwebroot['host']
1072: . $puri['path'];
1073: } else {
1074: $url = $webroot . '/' . $puri['path'];
1075: }
1076: } else {
1077: $url .= '/' . ($webroot ? $webroot . '/' : '') . (isset($puri['path']) ? $puri['path'] : '');
1078: }
1079:
1080: if (isset($puri['query'])) {
1081: $url .= '?' . $puri['query'];
1082: }
1083:
1084: $ob = new Horde_Url($url, $full);
1085:
1086: if (empty($GLOBALS['conf']['session']['use_only_cookies']) &&
1087: (($append_session == 1) ||
1088: (($append_session == 0) && !isset($_COOKIE[session_name()])))) {
1089: $ob->add(session_name(), session_id());
1090: }
1091:
1092: if (empty($opts['noajax']) &&
1093: ($append_session >= 0) &&
1094: Horde_Util::getFormData('ajaxui')) {
1095: $ob->add('ajaxui', 1);
1096: }
1097:
1098: return $ob;
1099: }
1100:
1101: 1102: 1103: 1104: 1105: 1106: 1107: 1108: 1109: 1110:
1111: static public function externalUrl($url, $tag = false)
1112: {
1113: if (!isset($_GET[session_name()]) ||
1114: Horde_String::substr($url, 0, 1) == '#' ||
1115: Horde_String::substr($url, 0, 7) == 'mailto:') {
1116: $ext = $url;
1117: } else {
1118: $ext = self::getServiceLink('go', 'horde');
1119:
1120:
1121: $url = preg_replace(array('/(=?.*?)&(.*?=)/', '/(=?.*?)&(.*?=)/'), '$1&$2', $url);
1122: $ext .= '?' . self::signQueryString('url=' . urlencode($url));
1123: }
1124:
1125: if ($tag) {
1126: $ext = self::link($ext, $url, '', '_blank');
1127: }
1128:
1129: return $ext;
1130: }
1131:
1132: 1133: 1134: 1135: 1136: 1137: 1138: 1139: 1140: 1141: 1142: 1143:
1144: static public function downloadUrl($filename, $params = array(),
1145: $url = null)
1146: {
1147: global $browser, $registry;
1148:
1149: $horde_url = false;
1150:
1151: if (is_null($url)) {
1152: $url = self::getServiceLink('download', $registry->getApp());
1153: $horde_url = true;
1154: }
1155:
1156:
1157: if (!is_null($params)) {
1158: $url->add($params);
1159: }
1160:
1161: 1162: 1163: 1164:
1165: if ($horde_url) {
1166: $url->add('fn', '/' . rawurlencode($filename));
1167: } elseif ($browser->hasQuirk('break_disposition_filename')) {
1168: 1169: 1170: 1171:
1172: $url = (string)$url;
1173: $filename = rawurlencode($filename);
1174:
1175:
1176: $server = self::webServerID();
1177:
1178: 1179: 1180: 1181:
1182: if (($server != 'apache2')) {
1183: if (($pos = strrpos($filename, '.'))) {
1184: $name = '/' . preg_replace('/\./', '%2E', substr($filename, 0, $pos));
1185: $ext = substr($filename, $pos);
1186: } else {
1187: $name = '/' . $filename;
1188: $ext = '';
1189: }
1190:
1191:
1192: if (($pos = strpos($url, '?'))) {
1193: $url = substr($url, 0, $pos) . $name . substr($url, $pos);
1194: } else {
1195: $url .= $name;
1196: }
1197: }
1198: $url = new Horde_Url($url);
1199:
1200:
1201: if (($server == 'apache2') || !empty($ext)) {
1202: $url->add('fn_ext', '/' . $filename);
1203: }
1204: }
1205:
1206: return $url;
1207: }
1208:
1209: 1210: 1211: 1212: 1213: 1214: 1215: 1216: 1217: 1218: 1219: 1220: 1221: 1222: 1223: 1224: 1225: 1226:
1227: static public function link($url = '', $title = '', $class = '',
1228: $target = '', $onclick = '', $title2 = '',
1229: $accesskey = '', $attributes = array(),
1230: $escape = true)
1231: {
1232: if (!($url instanceof Horde_Url)) {
1233: $url = new Horde_Url($url);
1234: }
1235:
1236: if (!empty($title2)) {
1237: $title = $title2;
1238: }
1239: if (!empty($onclick)) {
1240: $attributes['onclick'] = $onclick;
1241: }
1242: if (!empty($class)) {
1243: $attributes['class'] = $class;
1244: }
1245: if (!empty($target)) {
1246: $attributes['target'] = $target;
1247: }
1248: if (!empty($accesskey)) {
1249: $attributes['accesskey'] = $accesskey;
1250: }
1251: if (!empty($title)) {
1252: if ($escape) {
1253: $title = str_replace(
1254: array("\r", "\n"), '',
1255: htmlspecialchars(nl2br(htmlspecialchars($title))));
1256:
1257: $title = preg_replace('/&([a-z]+|(#\d+));/i', '&\\1;', $title);
1258: }
1259: $attributes['title.raw'] = $title;
1260: }
1261:
1262: return $url->link($attributes);
1263: }
1264:
1265: 1266: 1267: 1268: 1269: 1270: 1271: 1272: 1273: 1274: 1275: 1276: 1277: 1278: 1279: 1280: 1281:
1282: static public function linkTooltip($url, $status = '', $class = '',
1283: $target = '', $onclick = '',
1284: $title = '', $accesskey = '',
1285: $attributes = array())
1286: {
1287: if (strlen($title)) {
1288: $attributes['nicetitle'] = Horde_Serialize::serialize(explode("\n", preg_replace('/<br\s*\/?\s*>/', "\n", $title)), Horde_Serialize::JSON);
1289: $title = null;
1290: self::addScriptFile('tooltips.js', 'horde');
1291: }
1292:
1293: return self::link($url, $title, $class, $target, $onclick, null, $accesskey, $attributes, false);
1294: }
1295:
1296: 1297: 1298: 1299: 1300: 1301: 1302: 1303: 1304: 1305: 1306: 1307: 1308: 1309: 1310: 1311:
1312: static public function widget($url, $title = '', $class = 'widget',
1313: $target = '', $onclick = '', $title2 = '',
1314: $nocheck = false)
1315: {
1316: if (!empty($title2)) {
1317: $title = $title2;
1318: }
1319:
1320: $ak = self::getAccessKey($title, $nocheck);
1321:
1322: return self::link($url, '', $class, $target, $onclick, '', $ak) . self::highlightAccessKey($title, $ak) . '</a>';
1323: }
1324:
1325: 1326: 1327: 1328: 1329: 1330: 1331: 1332: 1333: 1334: 1335: 1336: 1337:
1338: static public function selfUrl($script_params = false, $nocache = true,
1339: $full = false, $force_ssl = false)
1340: {
1341: if (!strncmp(PHP_SAPI, 'cgi', 3)) {
1342:
1343:
1344:
1345: $url = $_SERVER['PHP_SELF'];
1346: } else {
1347: $url = isset($_SERVER['SCRIPT_NAME']) ?
1348: $_SERVER['SCRIPT_NAME'] :
1349: $_SERVER['PHP_SELF'];
1350: }
1351: if (isset($_SERVER['REQUEST_URI'])) {
1352: $url = Horde_String::common($_SERVER['REQUEST_URI'], $url);
1353: }
1354: if (substr($url, -9) == 'index.php') {
1355: $url = substr($url, 0, -9);
1356: }
1357:
1358: if ($script_params) {
1359: if ($pathInfo = Horde_Util::getPathInfo()) {
1360: if (substr($url, -1) == '/') {
1361: $pathInfo = substr($pathInfo, 1);
1362: }
1363: $url .= $pathInfo;
1364: }
1365: if (!empty($_SERVER['QUERY_STRING'])) {
1366: $url .= '?' . $_SERVER['QUERY_STRING'];
1367: }
1368: }
1369:
1370: $url = self::url($url, $full, array('force_ssl' => $force_ssl));
1371:
1372: return ($nocache && $GLOBALS['browser']->hasQuirk('cache_same_url'))
1373: ? $url->unique()
1374: : $url;
1375: }
1376:
1377: 1378: 1379: 1380: 1381: 1382: 1383: 1384: 1385: 1386: 1387: 1388:
1389: static public function img($src, $alt = '', $attr = '')
1390: {
1391:
1392: if (!$GLOBALS['browser']->hasFeature('images')) {
1393: return htmlspecialchars($alt);
1394: }
1395:
1396:
1397: if (!($src instanceof Horde_Themes_Image) && (substr($src, 0, 1) != '/')) {
1398: $src = Horde_Themes::img($src);
1399: }
1400:
1401:
1402: $attributes = array('alt' => $alt);
1403: if (is_array($attr)) {
1404: $attributes = array_merge($attributes, $attr);
1405: }
1406:
1407: $img = '<img';
1408: foreach ($attributes as $attribute => $value) {
1409: $img .= ' ' . $attribute . '="' . @htmlspecialchars($value) . '"';
1410: }
1411:
1412:
1413: if (is_string($attr) && !empty($attr)) {
1414: $img .= ' ' . $attr;
1415: }
1416:
1417:
1418: return $img . ' src="' . (empty($GLOBALS['conf']['nobase64_img']) ? self::base64ImgData($src) : $src) . '" />';
1419: }
1420:
1421: 1422: 1423: 1424: 1425: 1426: 1427:
1428: static public function fullSrcImg($src, $options = array())
1429: {
1430:
1431: if (!$GLOBALS['browser']->hasFeature('images')) {
1432: return '';
1433: }
1434:
1435:
1436: if (!($src instanceof Horde_Themes_Image) && (substr($src, 0, 1) != '/')) {
1437: $src = Horde_Themes::img($src, $options);
1438: }
1439:
1440:
1441: if (!empty($GLOBALS['conf']['nobase64_img'])) {
1442: $src = self::base64ImgData($src);
1443: }
1444: if (substr($src, 0, 10) != 'data:image') {
1445: $src = self::url($src, true, array('append_session' => -1));
1446: }
1447:
1448: $img = '<img';
1449: if (!empty($options['attr'])) {
1450:
1451: if (is_array($options['attr'])) {
1452: foreach ($options['attr'] as $attribute => $value) {
1453: $img .= ' ' . $attribute . '="' . htmlspecialchars($value) . '"';
1454: }
1455: }
1456:
1457: 1458:
1459: if (is_string($options['attr'])) {
1460: $img .= ' ' . $options['attr'];
1461: }
1462: }
1463:
1464:
1465: return $img . ' src="' . $src . '" />';
1466: }
1467:
1468: 1469: 1470: 1471: 1472: 1473: 1474: 1475: 1476: 1477: 1478: 1479:
1480: static public function base64ImgData($in, $limit = null)
1481: {
1482: $dataurl = $GLOBALS['browser']->hasFeature('dataurl');
1483: if (!$dataurl) {
1484: return $in;
1485: }
1486:
1487: if (!is_null($limit) &&
1488: (is_bool($dataurl) || ($limit < $dataurl))) {
1489: $dataurl = $limit;
1490: }
1491:
1492:
1493: if (!($in instanceof Horde_Themes_Image)) {
1494: $in = Horde_Themes_Image::fromUri($in);
1495: }
1496: if (!file_exists($in->fs)) {
1497: return $in->uri;
1498: }
1499:
1500: 1501: 1502:
1503: return (($dataurl === true) ||
1504: (filesize($in->fs) <= (($dataurl * 0.75) - 50)))
1505: ? 'data:' . Horde_Mime_Magic::extToMime(substr($in->uri, strrpos($in->uri, '.') + 1)) . ';base64,' . base64_encode(file_get_contents($in->fs))
1506: : $in->uri;
1507: }
1508:
1509: 1510: 1511:
1512: static public function includeFavicon()
1513: {
1514: $img = strval(Horde_Themes::img('favicon.ico', array(
1515: 'nohorde' => true
1516: )));
1517: if (!$img) {
1518: $img = strval(Horde_Themes::img('favicon.ico', array(
1519: 'app' => 'horde'
1520: )));
1521: }
1522:
1523: echo '<link href="' . $img . '" rel="SHORTCUT ICON" />';
1524: }
1525:
1526: 1527: 1528: 1529: 1530: 1531: 1532:
1533: static public function includeStylesheetFiles(array $opts = array(),
1534: $full = false)
1535: {
1536: foreach ($GLOBALS['injector']->getInstance('Horde_Themes_Css')->getStylesheetUrls($opts) as $val) {
1537: echo '<link href="' . $val->toString(false, $full) . '" rel="stylesheet" type="text/css" />';
1538: }
1539: }
1540:
1541: 1542: 1543: 1544: 1545: 1546: 1547:
1548: static public function getTempDir()
1549: {
1550: global $conf;
1551:
1552:
1553: if (!empty($conf['tmpdir'])) {
1554: $tmp = $conf['tmpdir'];
1555: }
1556:
1557:
1558: if (empty($tmp)) {
1559: $tmp = Horde_Util::getTempDir();
1560: }
1561:
1562: 1563:
1564: return empty($tmp)
1565: ? false
1566: : $tmp;
1567: }
1568:
1569: 1570: 1571: 1572: 1573: 1574: 1575: 1576: 1577: 1578: 1579: 1580: 1581: 1582: 1583: 1584: 1585: 1586:
1587: static public function getTempFile($prefix = 'Horde', $delete = true,
1588: $dir = '', $secure = false,
1589: $session_remove = false)
1590: {
1591: if (empty($dir) || !is_dir($dir)) {
1592: $dir = self::getTempDir();
1593: }
1594: $tmpfile = Horde_Util::getTempFile($prefix, $delete, $dir, $secure);
1595: if ($session_remove) {
1596: $gcfiles = $GLOBALS['session']->get('horde', 'gc_tempfiles', Horde_Session::TYPE_ARRAY);
1597: $gcfiles[] = $tmpfile;
1598: $GLOBALS['session']->set('horde', 'gc_tempfiles', $gcfiles);
1599: }
1600:
1601: return $tmpfile;
1602: }
1603:
1604: 1605: 1606:
1607: static public function compressOutput()
1608: {
1609: if (self::$_compressStart) {
1610: return;
1611: }
1612:
1613:
1614: if ($GLOBALS['conf']['compress_pages'] &&
1615: !$GLOBALS['browser']->hasQuirk('buggy_compression') &&
1616: !(bool)ini_get('zlib.output_compression') &&
1617: !(bool)ini_get('zend_accelerator.compress_all') &&
1618: ini_get('output_handler') != 'ob_gzhandler') {
1619: if (ob_get_level()) {
1620: ob_end_clean();
1621: }
1622: ob_start('ob_gzhandler');
1623: }
1624:
1625: self::$_compressStart = true;
1626: }
1627:
1628: 1629: 1630: 1631: 1632:
1633: static public function allowOutputCompression()
1634: {
1635: return !$GLOBALS['browser']->hasQuirk('buggy_compression') &&
1636: (ini_get('zlib.output_compression') == '') &&
1637: (ini_get('zend_accelerator.compress_all') == '') &&
1638: (ini_get('output_handler') != 'ob_gzhandler');
1639: }
1640:
1641: 1642: 1643: 1644: 1645: 1646: 1647:
1648: static public function webServerID()
1649: {
1650: switch (PHP_SAPI) {
1651: case 'apache':
1652: return 'apache1';
1653:
1654: case 'apache2filter':
1655: case 'apache2handler':
1656: return 'apache2';
1657:
1658: default:
1659: return PHP_SAPI;
1660: }
1661: }
1662:
1663: 1664: 1665: 1666: 1667: 1668: 1669: 1670: 1671: 1672:
1673: static public function getAccessKey($label, $nocheck = false,
1674: $shutdown = false)
1675: {
1676:
1677: if ($shutdown) {
1678: if (!count(self::$_labels)) {
1679: return;
1680: }
1681: $script = basename($_SERVER['PHP_SELF']);
1682: $labels = array_keys(self::$_labels);
1683: sort($labels);
1684: $used = array_keys(self::$_used);
1685: sort($used);
1686: $remaining = str_replace($used, array(), 'abcdefghijklmnopqrstuvwxyz');
1687: self::logMessage('Access key information for ' . $script);
1688: self::logMessage('Used labels: ' . implode(',', $labels));
1689: self::logMessage('Used keys: ' . implode('', $used));
1690: self::logMessage('Free keys: ' . $remaining);
1691: return;
1692: }
1693:
1694:
1695: if (!isset(self::$_noAccessKey)) {
1696: self::$_noAccessKey = !$GLOBALS['browser']->hasFeature('accesskey') || !$GLOBALS['prefs']->getValue('widget_accesskey');
1697: }
1698:
1699: if (self::$_noAccessKey || !preg_match('/_([A-Za-z])/', $label, $match)) {
1700: return '';
1701: }
1702: $key = $match[1];
1703:
1704:
1705: if (isset(self::$_used[strtolower($key)]) &&
1706: !($nocheck && isset(self::$_labels[$label]))) {
1707: return '';
1708: }
1709:
1710:
1711: self::$_used[strtolower($key)] = true;
1712: self::$_labels[$label] = true;
1713:
1714: return $key;
1715: }
1716:
1717: 1718: 1719: 1720: 1721: 1722: 1723: 1724: 1725:
1726: static public function stripAccessKey($label)
1727: {
1728: return preg_replace('/_([A-Za-z])/', $GLOBALS['registry']->nlsconfig->curr_multibyte && preg_match('/[\x80-\xff]/', $label) ? '' : '\1', $label);
1729: }
1730:
1731: 1732: 1733: 1734: 1735: 1736: 1737: 1738: 1739:
1740: static public function highlightAccessKey($label, $accessKey)
1741: {
1742: $stripped_label = self::stripAccessKey($label);
1743:
1744: if (empty($accessKey)) {
1745: return $stripped_label;
1746: }
1747:
1748: if ($GLOBALS['registry']->nlsconfig->curr_multibyte) {
1749: 1750:
1751: return $stripped_label . "\xe2\x80\xad" .
1752: '(<span class="accessKey">' . strtoupper($accessKey) .
1753: '</span>' . ')';
1754: }
1755:
1756: return str_replace('_' . $accessKey, '<span class="accessKey">' . $accessKey . '</span>', $label);
1757: }
1758:
1759: 1760: 1761: 1762: 1763: 1764: 1765: 1766: 1767: 1768: 1769:
1770: static public function getAccessKeyAndTitle($label, $nocheck = false)
1771: {
1772: $ak = self::getAccessKey($label, $nocheck);
1773: $attributes = 'title="' . self::stripAccessKey($label);
1774: if (!empty($ak)) {
1775: $attributes .= sprintf(Horde_Core_Translation::t(" (Accesskey %s)"), strtoupper($ak))
1776: . '" accesskey="' . $ak;
1777: }
1778:
1779: return $attributes . '"';
1780: }
1781:
1782: 1783: 1784: 1785: 1786: 1787: 1788: 1789: 1790: 1791: 1792:
1793: static public function label($for, $label, $ak = null)
1794: {
1795: if (is_null($ak)) {
1796: $ak = self::getAccessKey($label, 1);
1797: }
1798: $label = self::highlightAccessKey($label, $ak);
1799:
1800: return sprintf('<label for="%s"%s>%s</label>',
1801: $for,
1802: !empty($ak) ? ' accesskey="' . $ak . '"' : '',
1803: $label);
1804: }
1805:
1806: 1807: 1808: 1809: 1810: 1811: 1812: 1813: 1814: 1815: 1816: 1817: 1818: 1819: 1820: 1821:
1822: static public function callHook($hook, $args = array(), $app = 'horde')
1823: {
1824: if (!self::hookExists($hook, $app)) {
1825: throw new Horde_Exception_HookNotSet();
1826: }
1827:
1828: $hook_class = $app . '_Hooks';
1829: $hook_ob = new $hook_class;
1830: try {
1831: self::logMessage(sprintf('Hook %s in application %s called.', $hook, $app), 'DEBUG');
1832: return call_user_func_array(array($hook_ob, $hook), $args);
1833: } catch (Horde_Exception $e) {
1834: self::logMessage($e, 'ERR');
1835: throw $e;
1836: }
1837: }
1838:
1839: 1840: 1841: 1842: 1843: 1844: 1845: 1846: 1847: 1848: 1849:
1850: static public function hookExists($hook, $app = 'horde')
1851: {
1852: $hook_class = $app . '_Hooks';
1853:
1854: if (!isset(self::$_hooksLoaded[$app])) {
1855: self::$_hooksLoaded[$app] = false;
1856: if (!class_exists($hook_class, false)) {
1857: try {
1858: self::loadConfiguration('hooks.php', null, $app);
1859: self::$_hooksLoaded[$app] = array();
1860: } catch (Horde_Exception $e) {}
1861: }
1862: }
1863:
1864: if (self::$_hooksLoaded[$app] === false) {
1865: return false;
1866: }
1867:
1868: if (!isset(self::$_hooksLoaded[$app][$hook])) {
1869: self::$_hooksLoaded[$app][$hook] =
1870: class_exists($hook_class, false) &&
1871: ($hook_ob = new $hook_class) &&
1872: method_exists($hook_ob, $hook);
1873: }
1874:
1875: return self::$_hooksLoaded[$app][$hook];
1876: }
1877:
1878: 1879: 1880: 1881: 1882: 1883:
1884: static public function redirect($url)
1885: {
1886: if ($GLOBALS['browser']->isBrowser('msie') &&
1887: ($GLOBALS['conf']['use_ssl'] == 3) &&
1888: (strlen($url) < 160)) {
1889: header('Refresh: 0; URL=' . $url);
1890: } else {
1891: header('Location: ' . $url);
1892: }
1893: exit;
1894: }
1895:
1896: 1897: 1898: 1899: 1900: 1901: 1902: 1903: 1904:
1905: static public function addInlineScript($script, $onload = null,
1906: $top = false)
1907: {
1908: if (is_array($script)) {
1909: $script = implode(';', $script);
1910: }
1911:
1912: $script = trim($script);
1913: if (empty($script)) {
1914: return;
1915: }
1916:
1917: if (is_null($onload)) {
1918: $onload = 'none';
1919: }
1920:
1921: $script = trim($script, ';') . ';';
1922:
1923: if ($top && isset(self::$_inlineScript[$onload])) {
1924: array_unshift(self::$_inlineScript[$onload], $script);
1925: } else {
1926: self::$_inlineScript[$onload][] = $script;
1927: }
1928:
1929:
1930:
1931: if (self::contentSent()) {
1932: self::outputInlineScript();
1933: }
1934: }
1935:
1936: 1937: 1938: 1939: 1940: 1941: 1942: 1943: 1944: 1945: 1946: 1947: 1948: 1949: 1950: 1951: 1952: 1953: 1954: 1955:
1956: static public function addInlineJsVars($data, array $opts = array())
1957: {
1958: $out = array();
1959: $opts = array_merge(array(
1960: 'onload' => null,
1961: 'ret_vars' => false,
1962: 'top' => false
1963: ), $opts);
1964:
1965: foreach ($data as $key => $val) {
1966: if ($key[0] == '-') {
1967: $key = substr($key, 1);
1968: } else {
1969: $val = Horde_Serialize::serialize($val, Horde_Serialize::JSON);
1970: }
1971:
1972: $out[] = $key . '=' . $val;
1973: }
1974:
1975: if ($opts['ret_vars']) {
1976: return $out;
1977: }
1978:
1979: self::addInlineScript($out, $opts['onload'], $opts['top']);
1980: }
1981:
1982: 1983: 1984: 1985: 1986: 1987:
1988: static public function outputInlineScript($raw = false)
1989: {
1990: if (empty(self::$_inlineScript)) {
1991: return;
1992: }
1993:
1994: $script = array();
1995:
1996: foreach (self::$_inlineScript as $key => $val) {
1997: $val = implode('', $val);
1998:
1999: if (!$raw) {
2000: switch ($key) {
2001: case 'dom':
2002: $val = 'document.observe("dom:loaded", function() {' . $val . '});';
2003: break;
2004:
2005: case 'load':
2006: $val = 'Event.observe(window, "load", function() {' . $val . '});';
2007: break;
2008: }
2009: }
2010:
2011: $script[] = $val;
2012: }
2013:
2014: echo $raw
2015: ? implode('', $script)
2016: : self::wrapInlineScript($script);
2017:
2018: self::$_inlineScript = array();
2019: }
2020:
2021: 2022: 2023: 2024: 2025: 2026: 2027: 2028: 2029:
2030: static public function wrapInlineScript($script)
2031: {
2032: return '<script type="text/javascript">//<![CDATA[' . "\n" . implode('', $script) . "\n//]]></script>\n";
2033: }
2034:
2035: 2036: 2037: 2038: 2039: 2040: 2041: 2042: 2043: 2044: 2045: 2046: 2047: 2048: 2049: 2050: 2051: 2052: 2053: 2054: 2055:
2056: static public function getCacheUrl($type, $params = array())
2057: {
2058: $url = self::getserviceLink('cache', 'horde')->add('cache', $type);
2059: foreach ($params as $key => $val) {
2060: $url .= '/' . $key . '=' . rawurlencode(strval($val));
2061: }
2062:
2063: return self::url($url, true, array('append_session' => -1));
2064: }
2065:
2066: 2067: 2068: 2069: 2070: 2071: 2072: 2073: 2074: 2075: 2076: 2077: 2078: 2079: 2080: 2081: 2082: 2083: 2084: 2085: 2086: 2087: 2088:
2089: static public function ($url, $options = array())
2090: {
2091: self::addScriptFile('popup.js', 'horde');
2092:
2093: $params = new stdClass;
2094:
2095: if (!$url instanceof Horde_Url) {
2096: $url = new Horde_Url($url);
2097: }
2098: $params->url = $url->url;
2099:
2100: if (!empty($url->parameters)) {
2101: if (!isset($options['params'])) {
2102: $options['params'] = array();
2103: }
2104: $options['params'] = array_merge($url->parameters, $options['params']);
2105: }
2106:
2107: if (!empty($options['height'])) {
2108: $params->height = $options['height'];
2109: }
2110: if (!empty($options['menu'])) {
2111: $params->menu = 1;
2112: }
2113: if (!empty($options['onload'])) {
2114: $params->onload = $options['onload'];
2115: }
2116: if (!empty($options['params'])) {
2117:
2118: $params->params = http_build_query(array_map('rawurlencode', $options['params']), '', '&');
2119: }
2120: if (!empty($options['width'])) {
2121: $params->width = $options['width'];
2122: }
2123:
2124: return 'void(Horde.popup(' . self::escapeJson($params, array('nodelimit' => true, 'urlencode' => !empty($options['urlencode']))) . '));';
2125: }
2126:
2127: 2128: 2129:
2130: static public function startBuffer()
2131: {
2132: if (!self::$_bufferLevel) {
2133: self::$_contentSent = self::contentSent();
2134: }
2135:
2136: ++self::$_bufferLevel;
2137: ob_start();
2138: }
2139:
2140: 2141: 2142: 2143: 2144:
2145: static public function endBuffer()
2146: {
2147: if (self::$_bufferLevel) {
2148: --self::$_bufferLevel;
2149: return ob_get_clean();
2150: }
2151:
2152: return '';
2153: }
2154:
2155: 2156: 2157: 2158: 2159:
2160: static public function contentSent()
2161: {
2162: return ((self::$_bufferLevel && self::$_contentSent) ||
2163: (!self::$_bufferLevel && (ob_get_length() || headers_sent())));
2164: }
2165:
2166: 2167: 2168: 2169: 2170: 2171:
2172: static public function addMetaTag($type, $content)
2173: {
2174: self::$_metaTags[$type] = $content;
2175: }
2176:
2177: 2178: 2179: 2180: 2181: 2182:
2183: static public function metaRefresh($time, $url)
2184: {
2185: if (!empty($time) && !empty($url)) {
2186: self::addMetaTag('refresh', $time . ';url=' . $url);
2187: }
2188: }
2189:
2190: 2191: 2192: 2193:
2194: static public function noDnsPrefetch()
2195: {
2196: self::addMetaTag('x-dns-prefetch-control', 'off');
2197: }
2198:
2199: 2200: 2201:
2202: static public function outputMetaTags()
2203: {
2204: foreach (self::$_metaTags as $key => $val) {
2205: echo '<meta http-equiv="' . $key . '" content="' . $val . "\" />\n";
2206: }
2207:
2208: self::$_metaTags = array();
2209: }
2210:
2211: 2212: 2213: 2214: 2215:
2216: static public function ajaxAvailable()
2217: {
2218: global $browser;
2219:
2220: return $browser->hasFeature('xmlhttpreq') &&
2221: (!$browser->isBrowser('msie') || $browser->getMajor() >= 7) &&
2222: (!$browser->hasFeature('issafari') || $browser->getMajor() >= 2);
2223: }
2224:
2225: 2226: 2227: 2228: 2229: 2230: 2231: 2232: 2233: 2234: 2235: 2236: 2237: 2238: 2239: 2240: 2241: 2242:
2243: static public function (array $opts = array())
2244: {
2245: global $injector, $registry;
2246:
2247: if (empty($opts['app'])) {
2248: $opts['app'] = $registry->getApp();
2249: }
2250: if (!isset($opts['mask'])) {
2251: $opts['mask'] = Horde_Menu::MASK_ALL;
2252: }
2253:
2254: $menu = new Horde_Menu(isset($opts['mask']) ? $opts['mask'] : Horde_Menu::MASK_ALL);
2255:
2256: $registry->callAppMethod($opts['app'], 'menu', array(
2257: 'args' => array($menu)
2258: ));
2259:
2260: if (!empty($opts['menu_ob'])) {
2261: return $menu;
2262: }
2263:
2264: self::startBuffer();
2265: require $registry->get('templates', 'horde') . '/menu/menu.inc';
2266: return self::endBuffer();
2267: }
2268:
2269: 2270: 2271: 2272: 2273: 2274: 2275: 2276: 2277:
2278: static public function permissionDeniedError($app, $perm, $error = null)
2279: {
2280: try {
2281: self::callHook('perms_denied', array($app, $perm));
2282: } catch (Horde_Exception_HookNotSet $e) {}
2283:
2284: if (!is_null($error)) {
2285: $GLOBALS['notification']->push($error, 'horde.warning');
2286: }
2287: }
2288: }
2289: