"success", "warning" => "warning-msg", "error" => "error", "message" => "message", "static" => "static-msg"); # Auth check public static function check($permissions) { global $core; if ($core->blog && $core->auth->check($permissions,$core->blog->id)) { return; } if (session_id()) { $core->session->destroy(); } http::redirect(DC_AUTH_PAGE); } # Check super admin public static function checkSuper() { global $core; if (!$core->auth->isSuperAdmin()) { if (session_id()) { $core->session->destroy(); } http::redirect(DC_AUTH_PAGE); } } # Top of admin page public static function open($title='',$head='',$breadcrumb='',$options=array()) { global $core; # List of user's blogs if ($core->auth->getBlogCount() == 1 || $core->auth->getBlogCount() > 20) { $blog_box = '

'.__('Blog:').' '. html::escapeHTML($core->blog->name).''; if ($core->auth->getBlogCount() > 20) { $blog_box .= ' - '.__('Change blog').''; } $blog_box .= '

'; } else { $rs_blogs = $core->getBlogs(array('order'=>'LOWER(blog_name)','limit'=>20)); $blogs = array(); while ($rs_blogs->fetch()) { $blogs[html::escapeHTML($rs_blogs->blog_name.' - '.$rs_blogs->blog_url)] = $rs_blogs->blog_id; } $blog_box = '

'. $core->formNonce(). form::combo('switchblog',$blogs,$core->blog->id). '

'; } $safe_mode = isset($_SESSION['sess_safe_mode']) && $_SESSION['sess_safe_mode']; # Display $headers = new ArrayObject(array()); # Content-Type $headers['content-type'] = 'Content-Type: text/html; charset=UTF-8'; # Prevents Clickjacking as far as possible if (isset($options['x-frame-allow'])) { self::setXFrameOptions($headers,$options['x-frame-allow']); } else { self::setXFrameOptions($headers); } # Content-Security-Policy (only if safe mode if not active, it may help) if (!$safe_mode && $core->blog->settings->system->csp_admin_on) { // Get directives from settings if exist, else set defaults $csp = new ArrayObject(array()); // SQlite Clearbricks driver does not allow using single quote at beginning or end of a field value // so we have to use neutral values (localhost and 127.0.0.1) for some CSP directives $csp_prefix = $core->con->driver() == 'sqlite' ? 'localhost ' : ''; // Hack for SQlite Clearbricks driver $csp_suffix = $core->con->driver() == 'sqlite' ? ' 127.0.0.1' : ''; // Hack for SQlite Clearbricks driver $csp['default-src'] = $core->blog->settings->system->csp_admin_default ?: $csp_prefix."'self'".$csp_suffix; $csp['script-src'] = $core->blog->settings->system->csp_admin_script ?: $csp_prefix."'self' 'unsafe-inline' 'unsafe-eval'".$csp_suffix; $csp['style-src'] = $core->blog->settings->system->csp_admin_style ?: $csp_prefix."'self' 'unsafe-inline'".$csp_suffix; $csp['img-src'] = $core->blog->settings->system->csp_admin_img ?: $csp_prefix."'self' data: media.dotaddict.org blob:"; # Cope with blog post preview (via public URL in iframe) if (!is_null($core->blog->host)) { $csp['default-src'] .= ' '.parse_url($core->blog->host,PHP_URL_HOST); $csp['script-src'] .= ' '.parse_url($core->blog->host,PHP_URL_HOST); $csp['style-src'] .= ' '.parse_url($core->blog->host,PHP_URL_HOST); } # Cope with media display in media manager (via public URL) if (!is_null($core->media)) { $csp['img-src'] .= ' '.parse_url($core->media->root_url,PHP_URL_HOST); } # Allow everything in iframe (used by editors to preview public content) $csp['child-src'] = "*"; # --BEHAVIOR-- adminPageHTTPHeaderCSP $core->callBehavior('adminPageHTTPHeaderCSP',$csp); // Construct CSP header $directives = array(); foreach ($csp as $key => $value) { if ($value) { $directives[] = $key.' '.$value; } } if (count($directives)) { if (version_compare(phpversion(),'5.4','>=')) { // csp_report.php needs PHP ≥ 5.4 $directives[] = "report-uri ".DC_ADMIN_URL."csp_report.php"; } $report_only = ($core->blog->settings->system->csp_admin_report_only) ? '-Report-Only' : ''; $headers['csp'] = "Content-Security-Policy".$report_only.": ".implode(" ; ",$directives); } } # --BEHAVIOR-- adminPageHTTPHeaders $core->callBehavior('adminPageHTTPHeaders',$headers); foreach ($headers as $key => $value) { header($value); } echo ''. ''."\n". "\n". ' '."\n". ' '."\n". ' '."\n". ' '."\n". ' '.$title.' - '.html::escapeHTML($core->blog->name).' - '.html::escapeHTML(DC_VENDOR_NAME).' - '.DC_VERSION.''."\n". self::cssLoad('style/default.css'); if (l10n::getTextDirection($GLOBALS['_lang']) == 'rtl') { echo self::cssLoad('style/default-rtl.css'); } $core->auth->user_prefs->addWorkspace('interface'); $user_ui_hide_std_favicon = $core->auth->user_prefs->interface->hide_std_favicon; if (!$user_ui_hide_std_favicon) { echo ''."\n". ''."\n"; } if ($core->auth->user_prefs->interface->htmlfontsize) { echo '\n"; } echo self::jsCommon(). self::jsToggles(). $head; if ($core->auth->user_prefs->interface->hidemoreinfo) { echo '\n"; } # --BEHAVIOR-- adminPageHTMLHead $core->callBehavior('adminPageHTMLHead'); echo "\n". ''."\n". ''."\n". ''; // end header echo '
'."\n". '
'. '
'."\n". '
'."\n"; # Safe mode if ($safe_mode) { echo ''; } // Display breadcrumb (if given) before any error messages echo $breadcrumb; // Display notices and errors echo self::notices(); } public static function notices() { global $core; static $error_displayed = false; $res = ''; // return error messages if any if ($core->error->flag() && !$error_displayed) { # --BEHAVIOR-- adminPageNotificationError $notice_error = $core->callBehavior('adminPageNotificationError',$core,$core->error); if (isset($notice_error) && !empty($notice_error)) { $res .= $notice_error; } else { $res .= '

'. ''.(count($core->error->getErrors()) > 1 ? __('Errors:') : __('Error:')).''. '

'.$core->error->toHTML().'
'; } $error_displayed = true; } // return notices if any if (isset($_SESSION['notifications'])) { foreach ($_SESSION['notifications'] as $notification) { # --BEHAVIOR-- adminPageNotification $notice = $core->callBehavior('adminPageNotification',$core,$notification); $res .= (isset($notice) && !empty($notice) ? $notice : self::getNotification($notification)); } unset($_SESSION['notifications']); } return $res; } public static function addNotice($type,$message,$options=array()) { if (isset(self::$N_TYPES[$type])){ $class = self::$N_TYPES[$type]; } else { $class=$type; } if (isset($_SESSION['notifications']) && is_array($_SESSION['notifications'])) { $notifications = $_SESSION['notifications']; } else { $notifications = array(); } $n = array_merge($options,array('class' => $class,'ts' => time(), 'text' => $message)); if ($type != "static") { $notifications[] = $n; } else { array_unshift($notifications, $n); } $_SESSION['notifications'] = $notifications; } public static function addSuccessNotice($message,$options=array()) { self::addNotice("success",$message,$options); } public static function addWarningNotice($message,$options=array()) { self::addNotice("warning",$message,$options); } public static function addErrorNotice($message,$options=array()) { self::addNotice("error",$message,$options); } protected static function getNotification($n) { global $core; $tag = (isset($n['divtag']) && $n['divtag']) ? 'div' : 'p'; $ts = ''; if (!isset($n['with_ts']) || ($n['with_ts'] == true)) { $ts = dt::str(__('[%H:%M:%S]'),$n['ts'],$core->auth->getInfo('user_tz')).' '; } $res = '<'.$tag.' class="'.$n['class'].'" role="alert">'.$ts.$n['text'].''; return $res; } public static function close() { global $core; if (!$GLOBALS['__resources']['ctxhelp']) { if (!$core->auth->user_prefs->interface->hidehelpbutton) { echo '

'.__('Global help').'

'; } } $menu =& $GLOBALS['_menu']; echo "
\n". // End of #content "
\n". // End of #main ''."\n". // End of #main-menu "
\n"; // End of #wrapper echo '

'.__('Page top').'

'."\n"; $figure = " /\_/\ (='.'=) (\")-(\")"; echo ''."\n". ""."\n"; if (defined('DC_DEV') && DC_DEV === true) { echo self::debugInfo(); } echo ''; } public static function openPopup($title='',$head='',$breadcrumb='') { global $core; # Display header('Content-Type: text/html; charset=UTF-8'); // Prevents Clickjacking as far as possible header('X-Frame-Options: SAMEORIGIN'); // FF 3.6.9+ Chrome 4.1+ IE 8+ Safari 4+ Opera 10.5+ echo ''. ''."\n". "\n". ' '."\n". ' '."\n". ' '.$title.' - '.html::escapeHTML($core->blog->name).' - '.html::escapeHTML(DC_VENDOR_NAME).' - '.DC_VERSION.''."\n". ' '."\n". ' '."\n". self::cssLoad('style/default.css'); if (l10n::getTextDirection($GLOBALS['_lang']) == 'rtl') { echo self::cssLoad('style/default-rtl.css'); } $core->auth->user_prefs->addWorkspace('interface'); if ($core->auth->user_prefs->interface->htmlfontsize) { echo '\n"; } echo self::jsCommon(). self::jsToggles(). $head; if ($core->auth->user_prefs->interface->hidemoreinfo) { echo '\n"; } # --BEHAVIOR-- adminPageHTMLHead $core->callBehavior('adminPageHTMLHead'); echo "\n". ''."\n". '

'.DC_VENDOR_NAME.'

'."\n"; echo '
'."\n". '
'."\n". '
'."\n"; // display breadcrumb if given echo $breadcrumb; // Display notices and errors echo self::notices(); } public static function closePopup() { echo "
\n". // End of #content "
\n". // End of #main "
\n". // End of #wrapper '

'.__('Page top').'

'."\n". ''."\n". ''; } public static function breadcrumb($elements=null,$options=array()) { global $core; $with_home_link = isset($options['home_link']) ? $options['home_link'] : true; $hl = isset($options['hl']) ? $options['hl'] : true; $hl_pos = isset($options['hl_pos']) ? $options['hl_pos'] : -1; // First item of array elements should be blog's name, System or Plugins $res = '

'.($with_home_link ? ''.__('Go to dashboard').'' : ''); $index = 0; if ($hl_pos < 0) { $hl_pos = count($elements)+$hl_pos; } foreach ($elements as $element => $url) { if ($hl && $index == $hl_pos) { $element = sprintf('%s',$element); } $res .= ($with_home_link ? ($index == 1 ? ' : ' : ' › ') : ($index == 0 ? ' ' : ' › ')). ($url ? '' : '').$element.($url ? '' : ''); $index++; } $res .= '

'; return $res; } public static function message($msg,$timestamp=true,$div=false,$echo=true,$class='message') { global $core; $res = ''; if ($msg != '') { $res = ($div ? '
' : '').''. ($timestamp ? dt::str(__('[%H:%M:%S]'),null,$core->auth->getInfo('user_tz')).' ' : '').$msg. '

'.($div ? '
' : ''); if ($echo) { echo $res; } } return $res; } public static function success($msg,$timestamp=true,$div=false,$echo=true) { return self::message($msg,$timestamp,$div,$echo,"success"); } public static function warning($msg,$timestamp=true,$div=false,$echo=true) { return self::message($msg,$timestamp,$div,$echo,"warning-msg"); } private static function debugInfo() { $global_vars = implode(', ',array_keys($GLOBALS)); $res = '
'. '

memory usage: '.memory_get_usage().' ('.files::size(memory_get_usage()).')

'; if (function_exists('xdebug_get_profiler_filename')) { $res .= '

Elapsed time: '.xdebug_time_index().' seconds

'; $prof_file = xdebug_get_profiler_filename(); if ($prof_file) { $res .= '

Profiler file : '.xdebug_get_profiler_filename().'

'; } else { $prof_url = http::getSelfURI(); $prof_url .= (strpos($prof_url,'?') === false) ? '?' : '&'; $prof_url .= 'XDEBUG_PROFILE'; $res .= '

Trigger profiler

'; } /* xdebug configuration: zend_extension = /.../xdebug.so xdebug.auto_trace = On xdebug.trace_format = 0 xdebug.trace_options = 1 xdebug.show_mem_delta = On xdebug.profiler_enable = 0 xdebug.profiler_enable_trigger = 1 xdebug.profiler_output_dir = /tmp xdebug.profiler_append = 0 xdebug.profiler_output_name = timestamp */ } $res .= '

Global vars: '.$global_vars.'

'. '
'; return $res; } public static function help($page,$index='') { # Deprecated but we keep this for plugins. } public static function helpBlock() { global $core; if ($core->auth->user_prefs->interface->hidehelpbutton) { return; } $args = func_get_args(); $args = new ArrayObject($args); # --BEHAVIOR-- adminPageHelpBlock $GLOBALS['core']->callBehavior('adminPageHelpBlock',$args); if (empty($args)) { return; }; global $__resources; if (empty($__resources['help'])) { return; } $content = ''; foreach ($args as $v) { if (is_object($v) && isset($v->content)) { $content .= $v->content; continue; } if (!isset($__resources['help'][$v])) { continue; } $f = $__resources['help'][$v]; if (!file_exists($f) || !is_readable($f)) { continue; } $fc = file_get_contents($f); if (preg_match('|]*?>(.*?)|ms',$fc,$matches)) { $content .= $matches[1]; } else { $content .= $fc; } } if (trim($content) == '') { return; } // Set contextual help global flag $GLOBALS['__resources']['ctxhelp'] = true; echo '

'.__('Help about this page').'

'. $content. '
'. '
'; } public static function cssLoad($src,$media='screen',$v='') { $escaped_src = html::escapeHTML($src); if (!isset(self::$loaded_css[$escaped_src])) { self::$loaded_css[$escaped_src] = true; $escaped_src = self::appendVersion($escaped_src,$v); return ''."\n"; } } public static function jsLoad($src,$v='') { $escaped_src = html::escapeHTML($src); if (!isset(self::$loaded_js[$escaped_src])) { self::$loaded_js[$escaped_src] = true; $escaped_src = self::appendVersion($escaped_src,$v); return ''."\n"; } } private static function appendVersion($src,$v='') { $src .= (strpos($src,'?') === false ? '?' : '&').'v='; if (defined('DC_DEV') && DC_DEV === true) { $src .= md5(uniqid()); } else { $src .= ($v === '' ? DC_VERSION : $v); } return $src; } public static function jsVar($n,$v) { return $n." = '".html::escapeJS($v)."';\n"; } public static function jsToggles() { if($GLOBALS['core']->auth->user_prefs->toggles) { $unfolded_sections = explode(',',$GLOBALS['core']->auth->user_prefs->toggles->unfolded_sections); foreach ($unfolded_sections as $k=>&$v) { if ($v == '') { unset($unfolded_sections[$k]); } else { $v = "'".html::escapeJS($v)."':true"; } } } else { $unfolded_sections=array(); } return '\n"; } public static function jsCommon() { $mute_or_no = ''; if (empty($GLOBALS['core']->blog) || $GLOBALS['core']->blog->settings->system->jquery_migrate_mute) { $mute_or_no .= '\n"; } return self::jsLoad('js/jquery/jquery.js'). $mute_or_no. self::jsLoad('js/jquery/jquery-migrate.js'). self::jsLoad('js/jquery/jquery.biscuit.js'). self::jsLoad('js/jquery/jquery.bgFade.js'). self::jsLoad('js/common.js'). self::jsLoad('js/prelude.js'). '\n"; } /** @deprecated since version 2.11 */ public static function jsLoadIE7() { return ''; } public static function jsConfirmClose() { $args = func_get_args(); if (count($args) > 0) { foreach ($args as $k => $v) { $args[$k] = "'".html::escapeJS($v)."'"; } $args = implode(',',$args); } else { $args = ''; } return self::jsLoad('js/confirm-close.js'). '\n"; } public static function jsPageTabs($default=null) { if ($default) { $default = "'".html::escapeJS($default)."'"; } return self::jsLoad('js/jquery/jquery.pageTabs.js'). '\n"; } public static function jsModal() { return self::jsLoad('js/jquery/jquery.magnific-popup.js'); } public static function jsColorPicker() { return self::cssLoad('style/farbtastic/farbtastic.css'). self::jsLoad('js/jquery/jquery.farbtastic.js'). self::jsLoad('js/color-picker.js'); } public static function jsDatePicker() { return self::cssLoad('style/date-picker.css'). self::jsLoad('js/date-picker.js'). '\n"; } public static function jsToolBar() { # Deprecated but we keep this for plugins. } public static function jsUpload($params=array(),$base_url=null) { if (!$base_url) { $base_url = path::clean(dirname(preg_replace('/(\?.*$)?/','',$_SERVER['REQUEST_URI']))).'/'; } $params = array_merge($params,array( 'sess_id='.session_id(), 'sess_uid='.$_SESSION['sess_browser_uid'], 'xd_check='.$GLOBALS['core']->getNonce() )); return '\n". self::jsLoad('js/jquery/jquery-ui.custom.js'). self::jsLoad('js/jsUpload/tmpl.js'). self::jsLoad('js/jsUpload/template-upload.js'). self::jsLoad('js/jsUpload/template-download.js'). self::jsLoad('js/jsUpload/load-image.js'). self::jsLoad('js/jsUpload/jquery.iframe-transport.js'). self::jsLoad('js/jsUpload/jquery.fileupload.js'). self::jsLoad('js/jsUpload/jquery.fileupload-process.js'). self::jsLoad('js/jsUpload/jquery.fileupload-resize.js'). self::jsLoad('js/jsUpload/jquery.fileupload-ui.js'); } public static function jsMetaEditor() { return self::jsLoad('js/meta-editor.js'); } public static function jsFilterControl($show=true) { return self::jsLoad('js/filter-controls.js'). '"; } public static function jsLoadCodeMirror($theme = '',$multi = true,$modes = array('css','htmlmixed','javascript','php','xml')) { $ret = self::cssLoad('js/codemirror/lib/codemirror.css'). self::jsLoad('js/codemirror/lib/codemirror.js'); if ($multi) { $ret .= self::jsLoad('js/codemirror/addon/mode/multiplex.js'); } foreach ($modes as $mode) { $ret .= self::jsLoad('js/codemirror/mode/'.$mode.'/'.$mode.'.js'); } $ret .= self::jsLoad('js/codemirror/addon/edit/closebrackets.js'). self::jsLoad('js/codemirror/addon/edit/matchbrackets.js'). self::cssLoad('js/codemirror/addon/display/fullscreen.css'). self::jsLoad('js/codemirror/addon/display/fullscreen.js'); if ($theme != '') { $ret .= self::cssLoad('js/codemirror/theme/'.$theme.'.css'); } return $ret; } public static function jsRunCodeMirror($name,$id,$mode,$theme = '') { $ret = ''; return $ret; } public static function getCodeMirrorThemes() { $themes = array(); $themes_root = dirname(__FILE__).'/../../admin'.'/js/codemirror/theme/'; if (is_dir($themes_root) && is_readable($themes_root)) { if (($d = @dir($themes_root)) !== false) { while (($entry = $d->read()) !== false) { if ($entry != '.' && $entry != '..' && substr($entry, 0, 1) != '.' && is_readable($themes_root.'/'.$entry)) { $themes[] = substr($entry,0,-4); // remove .css extension } } sort($themes); } } return $themes; } public static function getPF($file) { return $GLOBALS['core']->adminurl->get('load.plugin.file',array('pf' => $file)); } public static function getVF($file) { return $GLOBALS['core']->adminurl->get('load.var.file',array('vf' => $file)); } public static function setXFrameOptions($headers,$origin = null) { if (self::$xframe_loaded) { return; } if ($origin !== null) { $url = parse_url($origin); $headers['x-frame-options'] = sprintf('X-Frame-Options: %s',is_array($url) && isset($url['host']) ? ("ALLOW-FROM ".(isset($url['scheme']) ? $url['scheme'].':' : '' ).'//'.$url['host']) : 'SAMEORIGIN'); } else { $headers['x-frame-options'] = 'X-Frame-Options: SAMEORIGIN'; // FF 3.6.9+ Chrome 4.1+ IE 8+ Safari 4+ Opera 10.5+ } self::$xframe_loaded = true; } }