Changeset 3703:53c8bef8608a for admin/index.php
- Timestamp:
- 02/15/18 16:39:52 (7 years ago)
- Branch:
- default
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
admin/index.php
r3639 r3703 12 12 13 13 if (!empty($_GET['pf'])) { 14 require dirname(__FILE__).'/../inc/load_plugin_file.php';15 14 require dirname(__FILE__) . '/../inc/load_plugin_file.php'; 15 exit; 16 16 } 17 17 18 18 if (!empty($_GET['vf'])) { 19 require dirname(__FILE__).'/../inc/load_var_file.php';20 21 } 22 23 require dirname(__FILE__) .'/../inc/admin/prepend.php';19 require dirname(__FILE__) . '/../inc/load_var_file.php'; 20 exit; 21 } 22 23 require dirname(__FILE__) . '/../inc/admin/prepend.php'; 24 24 25 25 if (!empty($_GET['default_blog'])) { 26 27 $core->setUserDefaultBlog($core->auth->userID(),$core->blog->id);28 29 30 31 26 try { 27 $core->setUserDefaultBlog($core->auth->userID(), $core->blog->id); 28 $core->adminurl->redirect("admin.home"); 29 } catch (Exception $e) { 30 $core->error->add($e->getMessage()); 31 } 32 32 } 33 33 34 34 dcPage::check('usage,contentadmin'); 35 35 36 if ($core->plugins->disableDepModules($core->adminurl->get('admin.home', array()))) {37 36 if ($core->plugins->disableDepModules($core->adminurl->get('admin.home', array()))) { 37 exit; 38 38 } 39 39 40 40 # Logout 41 41 if (!empty($_GET['logout'])) { 42 43 44 45 setcookie('dc_admin',false,-600,'','',DC_ADMIN_SSL);46 47 48 42 $core->session->destroy(); 43 if (isset($_COOKIE['dc_admin'])) { 44 unset($_COOKIE['dc_admin']); 45 setcookie('dc_admin', false, -600, '', '', DC_ADMIN_SSL); 46 } 47 $core->adminurl->redirect("admin.auth"); 48 exit; 49 49 } 50 50 … … 55 55 $ws = $core->auth->user_prefs->addWorkspace('dashboard'); 56 56 if (!$core->auth->user_prefs->dashboard->prefExists('doclinks')) { 57 if (!$core->auth->user_prefs->dashboard->prefExists('doclinks',true)) {58 $core->auth->user_prefs->dashboard->put('doclinks',true,'boolean','',null,true);59 60 $core->auth->user_prefs->dashboard->put('doclinks',true,'boolean');57 if (!$core->auth->user_prefs->dashboard->prefExists('doclinks', true)) { 58 $core->auth->user_prefs->dashboard->put('doclinks', true, 'boolean', '', null, true); 59 } 60 $core->auth->user_prefs->dashboard->put('doclinks', true, 'boolean'); 61 61 } 62 62 if (!$core->auth->user_prefs->dashboard->prefExists('dcnews')) { 63 if (!$core->auth->user_prefs->dashboard->prefExists('dcnews',true)) {64 $core->auth->user_prefs->dashboard->put('dcnews',true,'boolean','',null,true);65 66 $core->auth->user_prefs->dashboard->put('dcnews',true,'boolean');63 if (!$core->auth->user_prefs->dashboard->prefExists('dcnews', true)) { 64 $core->auth->user_prefs->dashboard->put('dcnews', true, 'boolean', '', null, true); 65 } 66 $core->auth->user_prefs->dashboard->put('dcnews', true, 'boolean'); 67 67 } 68 68 if (!$core->auth->user_prefs->dashboard->prefExists('quickentry')) { 69 if (!$core->auth->user_prefs->dashboard->prefExists('quickentry',true)) {70 $core->auth->user_prefs->dashboard->put('quickentry',false,'boolean','',null,true);71 72 $core->auth->user_prefs->dashboard->put('quickentry',false,'boolean');69 if (!$core->auth->user_prefs->dashboard->prefExists('quickentry', true)) { 70 $core->auth->user_prefs->dashboard->put('quickentry', false, 'boolean', '', null, true); 71 } 72 $core->auth->user_prefs->dashboard->put('quickentry', false, 'boolean'); 73 73 } 74 74 if (!$core->auth->user_prefs->dashboard->prefExists('nodcupdate')) { 75 if (!$core->auth->user_prefs->dashboard->prefExists('nodcupdate',true)) {76 $core->auth->user_prefs->dashboard->put('nodcupdate',false,'boolean','',null,true);77 78 $core->auth->user_prefs->dashboard->put('nodcupdate',false,'boolean');75 if (!$core->auth->user_prefs->dashboard->prefExists('nodcupdate', true)) { 76 $core->auth->user_prefs->dashboard->put('nodcupdate', false, 'boolean', '', null, true); 77 } 78 $core->auth->user_prefs->dashboard->put('nodcupdate', false, 'boolean'); 79 79 } 80 80 … … 82 82 $ws = $core->auth->user_prefs->addWorkspace('toggles'); 83 83 if (!$core->auth->user_prefs->toggles->prefExists('unfolded_sections')) { 84 $core->auth->user_prefs->toggles->put('unfolded_sections','','string','Folded sections in admin',null,true); 85 } 86 84 $core->auth->user_prefs->toggles->put('unfolded_sections', '', 'string', 'Folded sections in admin', null, true); 85 } 87 86 88 87 # Dashboard icons … … 93 92 94 93 # Check plugins and themes update from repository 95 $checkStoreUpdate = function($mod, $url, $img, $icon) 96 { 97 $repo = new dcStore($mod, $url); 98 $upd = $repo->get(true); 99 if (!empty($upd)) { 100 $icon[0] .= '<br />'.sprintf(__('An update is available', '%s updates are available.', count($upd)),count($upd)); 101 $icon[1] .= '#update'; 102 $icon[2] = 'images/menu/'.$img.'-b-update.png'; 103 } 94 $checkStoreUpdate = function ($mod, $url, $img, $icon) { 95 $repo = new dcStore($mod, $url); 96 $upd = $repo->get(true); 97 if (!empty($upd)) { 98 $icon[0] .= '<br />' . sprintf(__('An update is available', '%s updates are available.', count($upd)), count($upd)); 99 $icon[1] .= '#update'; 100 $icon[2] = 'images/menu/' . $img . '-b-update.png'; 101 } 104 102 }; 105 103 if (isset($__dashboard_icons['plugins'])) { 106 104 $checkStoreUpdate($core->plugins, $core->blog->settings->system->store_plugin_url, 'plugins', $__dashboard_icons['plugins']); 107 105 } 108 106 if (isset($__dashboard_icons['blog_theme'])) { 109 110 111 107 $themes = new dcThemes($core); 108 $themes->loadModules($core->blog->themes_path, null); 109 $checkStoreUpdate($themes, $core->blog->settings->system->store_theme_url, 'blog-theme', $__dashboard_icons['blog_theme']); 112 110 } 113 111 114 112 # Latest news for dashboard 115 $__dashboard_items = new ArrayObject(array(new ArrayObject(), new ArrayObject()));113 $__dashboard_items = new ArrayObject(array(new ArrayObject(), new ArrayObject())); 116 114 117 115 $dashboardItem = 0; … … 119 117 # Documentation links 120 118 if ($core->auth->user_prefs->dashboard->doclinks) { 121 if (!empty($__resources['doc'])) 122 { 123 $doc_links = '<div class="box small dc-box"><h3>'.__('Documentation and support').'</h3><ul>'; 124 125 foreach ($__resources['doc'] as $k => $v) { 126 $doc_links .= '<li><a class="outgoing" href="'.$v.'" title="'.$k.'">'.$k. 127 ' <img src="images/outgoing-blue.png" alt="" /></a></li>'; 128 } 129 130 $doc_links .= '</ul></div>'; 131 $__dashboard_items[$dashboardItem][] = $doc_links; 132 $dashboardItem++; 133 } 119 if (!empty($__resources['doc'])) { 120 $doc_links = '<div class="box small dc-box"><h3>' . __('Documentation and support') . '</h3><ul>'; 121 122 foreach ($__resources['doc'] as $k => $v) { 123 $doc_links .= '<li><a class="outgoing" href="' . $v . '" title="' . $k . '">' . $k . 124 ' <img src="images/outgoing-blue.png" alt="" /></a></li>'; 125 } 126 127 $doc_links .= '</ul></div>'; 128 $__dashboard_items[$dashboardItem][] = $doc_links; 129 $dashboardItem++; 130 } 134 131 } 135 132 … … 137 134 138 135 # Dashboard content 139 $__dashboard_contents = new ArrayObject(array(new ArrayObject, new ArrayObject));136 $__dashboard_contents = new ArrayObject(array(new ArrayObject, new ArrayObject)); 140 137 $core->callBehavior('adminDashboardContents', $core, $__dashboard_contents); 141 138 … … 143 140 $admin_post_behavior = ''; 144 141 if ($core->auth->user_prefs->dashboard->quickentry) { 145 if ($core->auth->check('usage,contentadmin',$core->blog->id)) 146 { 147 $post_format = $core->auth->getOption('post_format'); 148 $post_editor = $core->auth->getOption('editor'); 149 if ($post_editor && !empty($post_editor[$post_format])) { 150 // context is not post because of tags not available 151 $admin_post_behavior = $core->callBehavior('adminPostEditor', $post_editor[$post_format], 'quickentry', array('#post_content'),$post_format); 152 } 153 } 142 if ($core->auth->check('usage,contentadmin', $core->blog->id)) { 143 $post_format = $core->auth->getOption('post_format'); 144 $post_editor = $core->auth->getOption('editor'); 145 if ($post_editor && !empty($post_editor[$post_format])) { 146 // context is not post because of tags not available 147 $admin_post_behavior = $core->callBehavior('adminPostEditor', $post_editor[$post_format], 'quickentry', array('#post_content'), $post_format); 148 } 149 } 154 150 } 155 151 … … 157 153 -------------------------------------------------------- */ 158 154 dcPage::open(__('Dashboard'), 159 dcPage::jsLoad('js/_index.js').160 $admin_post_behavior.161 162 163 164 165 __('Dashboard').' : '.html::escapeHTML($core->blog->name) => ''166 167 array('home_link' =>false)168 155 dcPage::jsLoad('js/_index.js') . 156 $admin_post_behavior . 157 # --BEHAVIOR-- adminDashboardHeaders 158 $core->callBehavior('adminDashboardHeaders'), 159 dcPage::breadcrumb( 160 array( 161 __('Dashboard') . ' : ' . html::escapeHTML($core->blog->name) => '' 162 ), 163 array('home_link' => false) 164 ) 169 165 ); 170 166 171 167 if ($core->auth->getInfo('user_default_blog') != $core->blog->id && $core->auth->getBlogCount() > 1) { 172 173 '<p><a href="'.$core->adminurl->get("admin.home",array('default_blog' => 1)).'" class="button">'.__('Make this blog my default blog').'</a></p>';168 echo 169 '<p><a href="' . $core->adminurl->get("admin.home", array('default_blog' => 1)) . '" class="button">' . __('Make this blog my default blog') . '</a></p>'; 174 170 } 175 171 176 172 if ($core->blog->status == 0) { 177 echo '<p class="static-msg">'.__('This blog is offline').'.</p>';173 echo '<p class="static-msg">' . __('This blog is offline') . '.</p>'; 178 174 } elseif ($core->blog->status == -1) { 179 echo '<p class="static-msg">'.__('This blog is removed').'.</p>';175 echo '<p class="static-msg">' . __('This blog is removed') . '.</p>'; 180 176 } 181 177 182 178 if (!defined('DC_ADMIN_URL') || !DC_ADMIN_URL) { 183 184 '<p class="static-msg">'.185 sprintf(__('%s is not defined, you should edit your configuration file.'),'DC_ADMIN_URL').186 ' '.__('See <a href="http://dotclear.org/documentation/2.0/admin/config">documentation</a> for more information.').187 179 echo 180 '<p class="static-msg">' . 181 sprintf(__('%s is not defined, you should edit your configuration file.'), 'DC_ADMIN_URL') . 182 ' ' . __('See <a href="http://dotclear.org/documentation/2.0/admin/config">documentation</a> for more information.') . 183 '</p>'; 188 184 } 189 185 190 186 if (!defined('DC_ADMIN_MAILFROM') || !DC_ADMIN_MAILFROM) { 191 192 '<p class="static-msg">'.193 sprintf(__('%s is not defined, you should edit your configuration file.'),'DC_ADMIN_MAILFROM').194 ' '.__('See <a href="http://dotclear.org/documentation/2.0/admin/config">documentation</a> for more information.').195 187 echo 188 '<p class="static-msg">' . 189 sprintf(__('%s is not defined, you should edit your configuration file.'), 'DC_ADMIN_MAILFROM') . 190 ' ' . __('See <a href="http://dotclear.org/documentation/2.0/admin/config">documentation</a> for more information.') . 191 '</p>'; 196 192 } 197 193 … … 199 195 200 196 # Check cache directory 201 if ( $core->auth->isSuperAdmin()) {202 203 $err[] = '<p>'.__("The cache directory does not exist or is not writable. You must create this directory with sufficient rights and affect this location to \"DC_TPL_CACHE\" in inc/config.php file.").'</p>';204 197 if ($core->auth->isSuperAdmin()) { 198 if (!is_dir(DC_TPL_CACHE) || !is_writable(DC_TPL_CACHE)) { 199 $err[] = '<p>' . __("The cache directory does not exist or is not writable. You must create this directory with sufficient rights and affect this location to \"DC_TPL_CACHE\" in inc/config.php file.") . '</p>'; 200 } 205 201 } else { 206 207 $err[] = '<p>'.__("The cache directory does not exist or is not writable. You should contact your administrator.").'</p>';208 202 if (!is_dir(DC_TPL_CACHE) || !is_writable(DC_TPL_CACHE)) { 203 $err[] = '<p>' . __("The cache directory does not exist or is not writable. You should contact your administrator.") . '</p>'; 204 } 209 205 } 210 206 211 207 # Check public directory 212 if ( $core->auth->isSuperAdmin()) {213 214 $err[] = '<p>'.__("There is no writable directory /public/ at the location set in about:config \"public_path\". You must create this directory with sufficient rights (or change this setting).").'</p>';215 208 if ($core->auth->isSuperAdmin()) { 209 if (!is_dir($core->blog->public_path) || !is_writable($core->blog->public_path)) { 210 $err[] = '<p>' . __("There is no writable directory /public/ at the location set in about:config \"public_path\". You must create this directory with sufficient rights (or change this setting).") . '</p>'; 211 } 216 212 } else { 217 218 $err[] = '<p>'.__("There is no writable root directory for the media manager. You should contact your administrator.").'</p>';219 213 if (!is_dir($core->blog->public_path) || !is_writable($core->blog->public_path)) { 214 $err[] = '<p>' . __("There is no writable root directory for the media manager. You should contact your administrator.") . '</p>'; 215 } 220 216 } 221 217 222 218 # Error list 223 219 if (count($err) > 0) { 224 echo '<div class="error"><p><strong>'.__('Error:').'</strong></p>'.225 '<ul><li>'.implode("</li><li>",$err).'</li></ul></div>';220 echo '<div class="error"><p><strong>' . __('Error:') . '</strong></p>' . 221 '<ul><li>' . implode("</li><li>", $err) . '</li></ul></div>'; 226 222 } 227 223 228 224 # Plugins install messages 229 if (!empty($plugins_install['success'])) 230 { 231 echo '<div class="success">'.__('Following plugins have been installed:').'<ul>'; 232 foreach ($plugins_install['success'] as $k => $v) { 233 echo '<li>'.$k.'</li>'; 234 } 235 echo '</ul></div>'; 236 } 237 if (!empty($plugins_install['failure'])) 238 { 239 echo '<div class="error">'.__('Following plugins have not been installed:').'<ul>'; 240 foreach ($plugins_install['failure'] as $k => $v) { 241 echo '<li>'.$k.' ('.$v.')</li>'; 242 } 243 echo '</ul></div>'; 225 if (!empty($plugins_install['success'])) { 226 echo '<div class="success">' . __('Following plugins have been installed:') . '<ul>'; 227 foreach ($plugins_install['success'] as $k => $v) { 228 echo '<li>' . $k . '</li>'; 229 } 230 echo '</ul></div>'; 231 } 232 if (!empty($plugins_install['failure'])) { 233 echo '<div class="error">' . __('Following plugins have not been installed:') . '<ul>'; 234 foreach ($plugins_install['failure'] as $k => $v) { 235 echo '<li>' . $k . ' (' . $v . ')</li>'; 236 } 237 echo '</ul></div>'; 244 238 } 245 239 # Errors modules notifications 246 if ($core->auth->isSuperAdmin()) 247 { 248 $list = $core->plugins->getErrors(); 249 if (!empty($list)) { 250 echo 251 '<div class="error" id="module-errors" class="error"><p>'.__('Errors have occured with following plugins:').'</p> '. 252 '<ul><li>'.implode("</li>\n<li>", $list).'</li></ul></div>'; 253 } 240 if ($core->auth->isSuperAdmin()) { 241 $list = $core->plugins->getErrors(); 242 if (!empty($list)) { 243 echo 244 '<div class="error" id="module-errors" class="error"><p>' . __('Errors have occured with following plugins:') . '</p> ' . 245 '<ul><li>' . implode("</li>\n<li>", $list) . '</li></ul></div>'; 246 } 254 247 } 255 248 256 249 # Dashboard items and contents (processed first, as we need to know the result before displaying the icons.) 257 250 $dashboardItems = ''; 258 foreach ($__dashboard_items as $i) 259 { 260 foreach ($i as $v) { 261 $dashboardItems .= $v; 262 } 251 foreach ($__dashboard_items as $i) { 252 foreach ($i as $v) { 253 $dashboardItems .= $v; 254 } 263 255 } 264 256 $dashboardContents = ''; 265 foreach ($__dashboard_contents as $i) 266 { 267 foreach ($i as $v) { 268 $dashboardContents .= $v; 269 } 257 foreach ($__dashboard_contents as $i) { 258 foreach ($i as $v) { 259 $dashboardContents .= $v; 260 } 270 261 } 271 262 … … 274 265 275 266 if (!$core->auth->user_prefs->dashboard->nofavicons) { 276 # Dashboard icons 277 echo '<div id="icons">'; 278 foreach ($__dashboard_icons as $i) 279 { 280 echo 281 '<p><a href="'.$i[1].'"><img src="'.dc_admin_icon_url($i[2]).'" alt="" />'. 282 '<br /><span>'.$i[0].'</span></a></p>'; 283 } 284 echo '</div>'; 267 # Dashboard icons 268 echo '<div id="icons">'; 269 foreach ($__dashboard_icons as $i) { 270 echo 271 '<p><a href="' . $i[1] . '"><img src="' . dc_admin_icon_url($i[2]) . '" alt="" />' . 272 '<br /><span>' . $i[0] . '</span></a></p>'; 273 } 274 echo '</div>'; 285 275 } 286 276 287 277 if ($core->auth->user_prefs->dashboard->quickentry) { 288 if ($core->auth->check('usage,contentadmin',$core->blog->id)) 289 { 290 # Getting categories 291 $categories_combo = dcAdminCombos::getCategoriesCombo( 292 $core->blog->getCategories(array()) 293 ); 294 295 echo 296 '<div id="quick">'. 297 '<h3>'.__('Quick entry').sprintf(' › %s',$core->auth->getOption('post_format')).'</h3>'. 298 '<form id="quick-entry" action="'.$core->adminurl->get('admin.post').'" method="post" class="fieldset">'. 299 '<h4>'.__('New entry').'</h4>'. 300 '<p class="col"><label for="post_title" class="required"><abbr title="'.__('Required field').'">*</abbr> '.__('Title:').'</label>'. 301 form::field('post_title',20,255,'','maximal','',false,'required placeholder="'.__('Title').'"'). 302 '</p>'. 303 '<p class="area"><label class="required" '. 304 'for="post_content"><abbr title="'.__('Required field').'">*</abbr> '.__('Content:').'</label> '. 305 form::textarea('post_content',50,10,'','','',false,'required placeholder="'.__('Content').'"'). 306 '</p>'. 307 '<p><label for="cat_id" class="classic">'.__('Category:').'</label> '. 308 form::combo('cat_id',$categories_combo).'</p>'. 309 ($core->auth->check('categories', $core->blog->id) 310 ? '<div>'. 311 '<p id="new_cat" class="q-cat">'.__('Add a new category').'</p>'. 312 '<p class="q-cat"><label for="new_cat_title">'.__('Title:').'</label> '. 313 form::field('new_cat_title',30,255,'','').'</p>'. 314 '<p class="q-cat"><label for="new_cat_parent">'.__('Parent:').'</label> '. 315 form::combo('new_cat_parent',$categories_combo,'',''). 316 '</p>'. 317 '<p class="form-note info clear">'.__('This category will be created when you will save your post.').'</p>'. 318 '</div>' 319 : ''). 320 '<p><input type="submit" value="'.__('Save').'" name="save" /> '. 321 ($core->auth->check('publish',$core->blog->id) 322 ? '<input type="hidden" value="'.__('Save and publish').'" name="save-publish" />' 323 : ''). 324 $core->formNonce(). 325 form::hidden('post_status',-2). 326 form::hidden('post_format',$core->auth->getOption('post_format')). 327 form::hidden('post_excerpt',''). 328 form::hidden('post_lang',$core->auth->getInfo('user_lang')). 329 form::hidden('post_notes',''). 330 '</p>'. 331 '</form>'. 332 '</div>'; 333 } 278 if ($core->auth->check('usage,contentadmin', $core->blog->id)) { 279 # Getting categories 280 $categories_combo = dcAdminCombos::getCategoriesCombo( 281 $core->blog->getCategories(array()) 282 ); 283 284 echo 285 '<div id="quick">' . 286 '<h3>' . __('Quick entry') . sprintf(' › %s', $core->auth->getOption('post_format')) . '</h3>' . 287 '<form id="quick-entry" action="' . $core->adminurl->get('admin.post') . '" method="post" class="fieldset">' . 288 '<h4>' . __('New entry') . '</h4>' . 289 '<p class="col"><label for="post_title" class="required"><abbr title="' . __('Required field') . '">*</abbr> ' . __('Title:') . '</label>' . 290 form::field('post_title', 20, 255, '', 'maximal', '', false, 'required placeholder="' . __('Title') . '"') . 291 '</p>' . 292 '<p class="area"><label class="required" ' . 293 'for="post_content"><abbr title="' . __('Required field') . '">*</abbr> ' . __('Content:') . '</label> ' . 294 form::textarea('post_content', 50, 10, '', '', '', false, 'required placeholder="' . __('Content') . '"') . 295 '</p>' . 296 '<p><label for="cat_id" class="classic">' . __('Category:') . '</label> ' . 297 form::combo('cat_id', $categories_combo) . '</p>' . 298 ($core->auth->check('categories', $core->blog->id) 299 ? '<div>' . 300 '<p id="new_cat" class="q-cat">' . __('Add a new category') . '</p>' . 301 '<p class="q-cat"><label for="new_cat_title">' . __('Title:') . '</label> ' . 302 form::field('new_cat_title', 30, 255, '', '') . '</p>' . 303 '<p class="q-cat"><label for="new_cat_parent">' . __('Parent:') . '</label> ' . 304 form::combo('new_cat_parent', $categories_combo) . 305 '</p>' . 306 '<p class="form-note info clear">' . __('This category will be created when you will save your post.') . '</p>' . 307 '</div>' 308 : '') . 309 '<p><input type="submit" value="' . __('Save') . '" name="save" /> ' . 310 ($core->auth->check('publish', $core->blog->id) 311 ? '<input type="hidden" value="' . __('Save and publish') . '" name="save-publish" />' 312 : '') . 313 $core->formNonce() . 314 form::hidden('post_status', -2) . 315 form::hidden('post_format', $core->auth->getOption('post_format')) . 316 form::hidden('post_excerpt', '') . 317 form::hidden('post_lang', $core->auth->getInfo('user_lang')) . 318 form::hidden('post_notes', '') . 319 '</p>' . 320 '</form>' . 321 '</div>'; 322 } 334 323 } 335 324 336 325 if ($dashboardContents != '' || $dashboardItems != '') { 337 338 '<div id="dashboard-boxes">'.339 ($dashboardItems != '' ? '<div class="db-items">'.$dashboardItems.'</div>' : '').340 ($dashboardContents != '' ? '<div class="db-contents">'.$dashboardContents.'</div>' : '').341 326 echo 327 '<div id="dashboard-boxes">' . 328 ($dashboardItems != '' ? '<div class="db-items">' . $dashboardItems . '</div>' : '') . 329 ($dashboardContents != '' ? '<div class="db-contents">' . $dashboardContents . '</div>' : '') . 330 '</div>'; 342 331 } 343 332
Note: See TracChangeset
for help on using the changeset viewer.