Merge branch 'MDL-32639-23' of git://github.com/FMCorz/moodle into MOODLE_23_STABLE
authorDan Poltawski <dan@moodle.com>
Tue, 8 Jan 2013 06:46:34 +0000 (14:46 +0800)
committerDan Poltawski <dan@moodle.com>
Tue, 8 Jan 2013 06:46:34 +0000 (14:46 +0800)
242 files changed:
.gitignore
admin/tool/phpunit/cli/util.php
admin/tool/uploaduser/index.php
admin/user/user_bulk_download.php
auth/ldap/auth.php
auth/shibboleth/index_form.html
auth/shibboleth/lang/en/auth_shibboleth.php
backup/backup.php
backup/backupfilesedit.php
backup/converter/moodle1/handlerlib.php
backup/converter/moodle1/lib.php
backup/converter/moodle1/tests/lib_test.php
backup/import.php
backup/moodle2/restore_stepslib.php
backup/restore.php
backup/util/loggers/file_logger.class.php
backup/util/loggers/output_indented_logger.class.php
backup/util/loggers/output_text_logger.class.php
backup/util/ui/base_moodleform.class.php
blocks/community/block_community.php
blocks/community/communitycourse.php
blocks/community/styles.css
blocks/community/yui/comments/comments.js
blocks/community/yui/imagegallery/imagegallery.js
blocks/dock.js
blocks/glossary_random/block_glossary_random.php
blocks/html/backup/moodle1/lib.php [new file with mode: 0644]
blocks/online_users/block_online_users.php
blocks/rss_client/backup/moodle1/lib.php [new file with mode: 0644]
blocks/rss_client/backup/moodle2/restore_rss_client_stepslib.php
blocks/tags/edit_form.php
blocks/tags/lang/en/block_tags.php
blog/rsslib.php
comment/comment.js
comment/comment_post.php
composer.json [new file with mode: 0644]
course/category.php
course/dnduploadlib.php
course/externallib.php
course/lib.php
course/publish/backup.php
course/recent_form.php
course/renderer.php
course/rest.php
course/search.php
course/switchrole.php
course/yui/toolboxes/toolboxes.js
enrol/README.txt
enrol/cohort/yui/quickenrolment/quickenrolment.js
enrol/locallib.php
enrol/manual/yui/quickenrolment/quickenrolment.js
enrol/meta/addinstance_form.php
enrol/otherusers.php
enrol/paypal/ipn.php
enrol/paypal/lib.php
enrol/yui/notification/assets/skins/sam/notification.css
enrol/yui/notification/notification.js
files/renderer.php
filter/glossary/yui/autolinker/autolinker.js
grade/edit/outcome/edit_form.php
grade/edit/tree/lib.php
grade/export/ods/grade_export_ods.php
grade/export/xls/grade_export_xls.php
grade/report/grader/styles.css
grade/report/lib.php
grade/tests/reportlib_test.php [new file with mode: 0644]
group/externallib.php
install/lang/zh_tw/langconfig.php
lang/en/block.php
lang/en/error.php
lang/en/moodle.php
lang/en/question.php
lang/en/repository.php
lib/accesslib.php
lib/adminlib.php
lib/ajax/blocks.php
lib/blocklib.php
lib/completion/completion_criteria_grade.php
lib/conditionlib.php
lib/datalib.php
lib/db/upgrade.php
lib/db/upgradelib.php
lib/ddl/oracle_sql_generator.php
lib/dml/pdo_moodle_database.php
lib/dml/tests/dml_test.php
lib/editor/tinymce/lang/en/editor_tinymce.php
lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/changelog.txt
lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/classes/GoogleSpell.php
lib/excellib.class.php
lib/filebrowser/file_info_context_course.php
lib/filebrowser/file_info_context_coursecat.php
lib/filelib.php
lib/filestorage/tests/file_storage_test.php
lib/formslib.php
lib/grade/grade_category.php
lib/grade/grade_item.php
lib/javascript-static.js
lib/moodlelib.php
lib/navigationlib.php
lib/odslib.class.php
lib/outputrenderers.php
lib/outputrequirementslib.php
lib/phpunit/classes/hint_resultprinter.php
lib/phpunit/readme.md
lib/rsslib.php
lib/sessionlib.php
lib/setuplib.php
lib/tablelib.php
lib/tests/moodlelib_test.php
lib/tests/pagelib_test.php
lib/tests/textlib_test.php
lib/textlib.class.php
lib/timezone.txt
lib/webdavlib.php
lib/weblib.php
lib/yui/blocks/blocks.js
lib/yui/chooserdialogue/chooserdialogue.js
lib/yui/formautosubmit/formautosubmit.js [new file with mode: 0644]
login/token.php
message/edit.php
message/lib.php
mnet/lib.php
mod/assign/gradingbatchoperationsform.php
mod/assign/gradingoptionsform.php
mod/assign/index.php
mod/assign/lang/en/assign.php
mod/assign/locallib.php
mod/assign/renderer.php
mod/assign/submission/comments/lib.php
mod/assign/submission/comments/locallib.php
mod/assign/submission/file/locallib.php
mod/assign/submission/onlinetext/locallib.php
mod/assign/upgradelib.php
mod/assignment/lib.php
mod/choice/lib.php
mod/choice/report.php
mod/data/db/upgrade.php
mod/data/field/latlong/kml.php
mod/data/lib.php
mod/data/version.php
mod/data/view.php
mod/feedback/analysis_course.php
mod/feedback/analysis_to_excel.php
mod/feedback/item/captcha/captcha_form.php
mod/feedback/item/multichoice/multichoice_form.php
mod/feedback/item/multichoicerated/multichoicerated_form.php
mod/feedback/item/numeric/numeric_form.php
mod/feedback/item/textarea/textarea_form.php
mod/feedback/item/textfield/textfield_form.php
mod/forum/lib.php
mod/forum/rsslib.php
mod/forum/subscribe.php
mod/lesson/essay.php
mod/lesson/essay_form.php
mod/lesson/format.php
mod/lesson/report.php
mod/lesson/view.php
mod/lti/backup/moodle2/backup_lti_stepslib.php
mod/lti/locallib.php
mod/quiz/accessmanager.php
mod/quiz/accessrule/accessrulebase.php
mod/quiz/accessrule/delaybetweenattempts/tests/rule_test.php
mod/quiz/accessrule/ipaddress/tests/rule_test.php
mod/quiz/accessrule/numattempts/tests/rule_test.php
mod/quiz/accessrule/openclosedate/rule.php
mod/quiz/accessrule/openclosedate/tests/rule_test.php
mod/quiz/accessrule/password/tests/rule_test.php
mod/quiz/accessrule/safebrowser/tests/rule_test.php
mod/quiz/accessrule/securewindow/tests/rule_test.php
mod/quiz/accessrule/timelimit/rule.php
mod/quiz/accessrule/timelimit/tests/rule_test.php
mod/quiz/accessrule/upgrade.txt
mod/quiz/attemptlib.php
mod/quiz/backup/moodle2/backup_quiz_stepslib.php
mod/quiz/backup/moodle2/restore_quiz_stepslib.php
mod/quiz/cronlib.php
mod/quiz/db/events.php
mod/quiz/db/install.xml
mod/quiz/db/upgrade.php
mod/quiz/lang/en/quiz.php
mod/quiz/lib.php
mod/quiz/locallib.php
mod/quiz/mod_form.php
mod/quiz/module.js
mod/quiz/overrideedit.php
mod/quiz/processattempt.php
mod/quiz/renderer.php
mod/quiz/settings.php
mod/quiz/startattempt.php
mod/quiz/summary.php
mod/quiz/tests/attempts_test.php [new file with mode: 0644]
mod/quiz/tests/generator_test.php [new file with mode: 0644]
mod/quiz/version.php
mod/scorm/lib.php
mod/scorm/locallib.php
mod/scorm/report/basic/report.php
mod/scorm/report/interactions/report.php
mod/scorm/report/reportlib.php
mod/survey/download.php
mod/wiki/create.php
mod/wiki/filesedit.php
mod/wiki/pagelib.php
mod/wiki/parser/utils.php
mod/workshop/lib.php
question/behaviour/upgrade.txt
question/category.php
question/category_class.php
question/export.php
question/format.php
question/format/blackboard_six/formatbase.php
question/format/blackboard_six/formatpool.php
question/format/blackboard_six/formatqti.php
question/format/blackboard_six/tests/blackboardformatpool_test.php
question/format/blackboard_six/tests/blackboardsixformatqti_test.php
question/format/learnwise/format.php
question/format/learnwise/lang/en/qformat_learnwise.php
question/format/upgrade.txt
question/format/xml/format.php
question/preview.php
question/previewlib.php
question/type/calculated/questiontype.php
question/type/multianswer/renderer.php
question/type/shortanswer/question.php
question/type/shortanswer/tests/question_test.php
report/log/locallib.php
report/outline/index.php
repository/s3/lib.php
repository/webdav/lib.php
tag/coursetags_add.php
theme/arialist/style/core.css
theme/base/style/core.css
theme/base/style/filemanager.css
theme/base/style/question.css
theme/magazine/style/core.css
theme/mymobile/renderers.php
theme/sky_high/style/admin.css
theme/standardold/layout/frontpage.php
user/files.php
user/profile.php
user/view.php
version.php
webservice/externallib.php

index e95a47a..e27bed2 100644 (file)
@@ -25,4 +25,8 @@ CVS
 /.project
 /.buildpath
 /.cache
-phpunit.xml
\ No newline at end of file
+phpunit.xml
+# Composer support - only composer.json is to be in git, the rest is installed in each checkout.
+composer.phar
+composer.lock
+/vendor/
index 5afd3ba..5cfd128 100644 (file)
@@ -39,7 +39,6 @@ list($options, $unrecognized) = cli_get_params(
         'buildconfig'           => false,
         'buildcomponentconfigs' => false,
         'diag'                  => false,
-        'phpunitdir'            => false,
         'run'                   => false,
         'help'                  => false,
     ),
@@ -48,24 +47,12 @@ list($options, $unrecognized) = cli_get_params(
     )
 );
 
-if ($options['phpunitdir']) {
-    // nasty skodak's hack for testing of future PHPUnit versions - intentionally not documented
-    if (!file_exists($options['phpunitdir'])) {
-        cli_error('Invalid custom PHPUnit lib location');
-    }
-    $files = scandir($options['phpunitdir']);
-    foreach ($files as $file) {
-        $path = $options['phpunitdir'].'/'.$file;
-        if (!is_dir($path) or strpos($file, '.') === 0) {
-            continue;
-        }
-        ini_set('include_path', $path . PATH_SEPARATOR . ini_get('include_path'));
-    }
-    unset($files);
-    unset($file);
+if (file_exists(__DIR__.'/../../../../vendor/autoload.php')) {
+    // Composer packages present.
+    require_once(__DIR__.'/../../../../vendor/autoload.php');
 }
 
-// verify PHPUnit libs are loaded
+// Verify PHPUnit libs can be loaded.
 if (!include_once('PHPUnit/Autoload.php')) {
     phpunit_bootstrap_error(PHPUNIT_EXITCODE_PHPUNITMISSING);
 }
@@ -75,7 +62,7 @@ if ($options['run']) {
     unset($unrecognized);
 
     foreach ($_SERVER['argv'] as $k=>$v) {
-        if (strpos($v, '--run') === 0 or strpos($v, '--phpunitdir') === 0) {
+        if (strpos($v, '--run') === 0) {
             unset($_SERVER['argv'][$k]);
             $_SERVER['argc'] = $_SERVER['argc'] - 1;
         }
index 380db45..911d26a 100644 (file)
@@ -285,7 +285,11 @@ if ($formdata = $mform2->is_cancelled()) {
             $userserrors++;
             continue;
         }
-
+        if ($user->username !== clean_param($user->username, PARAM_USERNAME)) {
+            $upt->track('status', get_string('invalidusername', 'error', 'username'), 'error');
+            $upt->track('username', $errorstr, 'error');
+            $userserrors++;
+        }
         if ($existinguser = $DB->get_record('user', array('username'=>$user->username, 'mnethostid'=>$CFG->mnet_localhost_id))) {
             $upt->track('id', $existinguser->id, 'normal', false);
         }
@@ -900,7 +904,11 @@ if ($formdata = $mform2->is_cancelled()) {
                     $newgroupdata = new stdClass();
                     $newgroupdata->name = $addgroup;
                     $newgroupdata->courseid = $ccache[$shortname]->id;
-                    if ($ccache[$shortname]->groups[$addgroup]->id = groups_create_group($newgroupdata)){
+                    $newgroupdata->description = '';
+                    $gid = groups_create_group($newgroupdata);
+                    if ($gid){
+                        $ccache[$shortname]->groups[$addgroup] = new stdClass();
+                        $ccache[$shortname]->groups[$addgroup]->id   = $gid;
                         $ccache[$shortname]->groups[$addgroup]->name = $newgroupdata->name;
                     } else {
                         $upt->track('enrolments', get_string('unknowngroup', 'error', s($addgroup)), 'error');
index 27fc9b9..b7a1d3f 100644 (file)
@@ -81,7 +81,7 @@ function user_download_ods($fields) {
 
     $worksheet = array();
 
-    $worksheet[0] =& $workbook->add_worksheet('');
+    $worksheet[0] = $workbook->add_worksheet('');
     $col = 0;
     foreach ($fields as $fieldname) {
         $worksheet[0]->write(0, $col, $fieldname);
@@ -119,7 +119,7 @@ function user_download_xls($fields) {
 
     $worksheet = array();
 
-    $worksheet[0] =& $workbook->add_worksheet('');
+    $worksheet[0] = $workbook->add_worksheet('');
     $col = 0;
     foreach ($fields as $fieldname) {
         $worksheet[0]->write(0, $col, $fieldname);
index 88bb10d..1a6bac8 100644 (file)
@@ -685,7 +685,7 @@ class auth_plugin_ldap extends auth_plugin_base {
 /// User removal
         // Find users in DB that aren't in ldap -- to be removed!
         // this is still not as scalable (but how often do we mass delete?)
-        if ($this->config->removeuser !== AUTH_REMOVEUSER_KEEP) {
+        if ($this->config->removeuser != AUTH_REMOVEUSER_KEEP) {
             $sql = 'SELECT u.*
                       FROM {user} u
                       LEFT JOIN {tmp_extuser} e ON (u.username = e.username AND u.mnethostid = e.mnethostid)
index 1e93cf2..29943d6 100644 (file)
@@ -40,8 +40,7 @@ if ($show_instructions) {
             </form>
             <p>
             <?php
-                print_string("auth_shibboleth_contact_administrator", "auth_shibboleth");
-                echo '<a href="mailto:'.get_admin()->email.'"> Moodle Administrator</a>.';
+                print_string("auth_shib_contact_administrator", "auth_shibboleth", get_admin()->email);
             ?>
             </p>
           </div>
index aace9a1..a043403 100644 (file)
@@ -25,6 +25,7 @@
 
 $string['auth_shib_auth_method'] = 'Authentication method name';
 $string['auth_shib_auth_method_description'] = 'Provide a name for the Shibboleth authentication method that is familiar to your users. This could be the name of your Shibboleth federation, e.g. <tt>SWITCHaai Login</tt> or <tt>InCommon Login</tt> or similar.';
+$string['auth_shib_contact_administrator'] = 'In case you are not associated with the given organizations and you need access to a course on this server, please contact the <a href="mailto:{$a}">Moodle Administrator</a>.';
 $string['auth_shibboleth_contact_administrator'] = 'In case you are not associated with the given organizations and you need access to a course on this server, please contact the';
 $string['auth_shibbolethdescription'] = 'Using this method users are created and authenticated using <a href="http://shibboleth.internet2.edu/">Shibboleth</a>.<br />Be sure to read the <a href="../auth/shibboleth/README.txt">README</a> for Shibboleth on how to set up your Moodle with Shibboleth';
 $string['auth_shibboleth_errormsg'] = 'Please select the organization you are member of!';
index ef0a897..5cc4bff 100644 (file)
@@ -98,7 +98,7 @@ $PAGE->navbar->add($backup->get_stage_name());
 $renderer = $PAGE->get_renderer('core','backup');
 echo $OUTPUT->header();
 if ($backup->enforce_changed_dependencies()) {
-    echo $renderer->dependency_notification(get_string('dependenciesenforced','backup'));
+    debugging('Your settings have been altered due to unmet dependencies', DEBUG_DEVELOPER);
 }
 echo $renderer->progress_bar($backup->get_progress_bar());
 echo $backup->display($renderer);
index 0059bbc..67e72a0 100644 (file)
@@ -33,7 +33,7 @@ $currentcontext = required_param('currentcontext', PARAM_INT);
 // file parameters
 $component  = optional_param('component', null, PARAM_COMPONENT);
 $filearea   = optional_param('filearea', null, PARAM_AREA);
-$returnurl  = optional_param('returnurl', null, PARAM_URL);
+$returnurl  = optional_param('returnurl', null, PARAM_LOCALURL);
 
 list($context, $course, $cm) = get_context_info_array($currentcontext);
 $filecontext = get_context_instance_by_id($contextid);
index 51cad64..a2744c2 100644 (file)
@@ -88,10 +88,13 @@ abstract class moodle1_handlers_factory {
         foreach ($plugins as $name => $dir) {
             $handlerfile  = $dir . '/backup/moodle1/lib.php';
             $handlerclass = "moodle1_{$type}_{$name}_handler";
-            if (!file_exists($handlerfile)) {
+            if (file_exists($handlerfile)) {
+                require_once($handlerfile);
+            } elseif ($type == 'block') {
+                $handlerclass = "moodle1_block_generic_handler";
+            } else {
                 continue;
             }
-            require_once($handlerfile);
 
             if (!class_exists($handlerclass)) {
                 throw new moodle1_convert_exception('missing_handler_class', $handlerclass);
@@ -1989,9 +1992,93 @@ abstract class moodle1_resource_successor_handler extends moodle1_mod_handler {
  */
 abstract class moodle1_block_handler extends moodle1_plugin_handler {
 
+    public function get_paths() {
+        $blockname = strtoupper($this->pluginname);
+        return array(
+            new convert_path('block', "/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/{$blockname}"),
+        );
+    }
+
+    public function process_block(array $data) {
+        $newdata = $this->convert_common_block_data($data);
+
+        $this->write_block_xml($newdata, $data);
+        $this->write_inforef_xml($newdata, $data);
+        $this->write_roles_xml($newdata, $data);
+
+        return $data;
+    }
+
+    protected function convert_common_block_data(array $olddata) {
+        $newdata = array();
+
+        $newdata['blockname'] = $olddata['name'];
+        $newdata['parentcontextid'] = $this->converter->get_contextid(CONTEXT_COURSE, 0);
+        $newdata['showinsubcontexts'] = 0;
+        $newdata['pagetypepattern'] = $olddata['pagetype'].='-*';
+        $newdata['subpagepattern'] = null;
+        $newdata['defaultregion'] = ($olddata['position']=='l')?'side-pre':'side-post';
+        $newdata['defaultweight'] = $olddata['weight'];
+        $newdata['configdata'] = $this->convert_configdata($olddata);
+
+        return $newdata;
+    }
+
+    protected function convert_configdata(array $olddata) {
+        return $olddata['configdata'];
+    }
+
+    protected function write_block_xml($newdata, $data) {
+        $contextid = $this->converter->get_contextid(CONTEXT_BLOCK, $data['id']);
+
+        $this->open_xml_writer("course/blocks/{$data['name']}_{$data['id']}/block.xml");
+        $this->xmlwriter->begin_tag('block', array('id' => $data['id'], 'contextid' => $contextid));
+
+        foreach ($newdata as $field => $value) {
+            $this->xmlwriter->full_tag($field, $value);
+        }
+
+        $this->xmlwriter->begin_tag('block_positions');
+        $this->xmlwriter->begin_tag('block_position', array('id' => 1));
+        $this->xmlwriter->full_tag('contextid', $newdata['parentcontextid']);
+        $this->xmlwriter->full_tag('pagetype', $data['pagetype']);
+        $this->xmlwriter->full_tag('subpage', '');
+        $this->xmlwriter->full_tag('visible', $data['visible']);
+        $this->xmlwriter->full_tag('region', $newdata['defaultregion']);
+        $this->xmlwriter->full_tag('weight', $newdata['defaultweight']);
+        $this->xmlwriter->end_tag('block_position');
+        $this->xmlwriter->end_tag('block_positions');
+        $this->xmlwriter->end_tag('block');
+        $this->close_xml_writer();
+    }
+
+    protected function write_inforef_xml($newdata, $data) {
+        $this->open_xml_writer("course/blocks/{$data['name']}_{$data['id']}/inforef.xml");
+        $this->xmlwriter->begin_tag('inforef');
+        // Subclasses may provide inforef contents if needed
+        $this->xmlwriter->end_tag('inforef');
+        $this->close_xml_writer();
+    }
+
+    protected function write_roles_xml($newdata, $data) {
+        // This is an empty shell, as the moodle1 converter doesn't handle user data.
+        $this->open_xml_writer("course/blocks/{$data['name']}_{$data['id']}/roles.xml");
+        $this->xmlwriter->begin_tag('roles');
+        $this->xmlwriter->full_tag('role_overrides', '');
+        $this->xmlwriter->full_tag('role_assignments', '');
+        $this->xmlwriter->end_tag('roles');
+        $this->close_xml_writer();
+    }
 }
 
 
+/**
+ * Base class for block generic handler
+ */
+class moodle1_block_generic_handler extends moodle1_block_handler {
+
+}
+
 /**
  * Base class for the activity modules' subplugins
  */
index bdfb47c..3b3fd4a 100644 (file)
@@ -254,7 +254,7 @@ class moodle1_converter extends base_converter {
             $path = '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/' . $this->currentblock;
 
         } else if (strpos($path, '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK') === 0) {
-            $path = str_replace('/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK', '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/' . $this->currentmod, $path);
+            $path = str_replace('/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK', '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/' . $this->currentblock, $path);
         }
 
         if ($path !== $data['path']) {
@@ -350,12 +350,12 @@ class moodle1_converter extends base_converter {
         }
 
         if ($path === '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK') {
-            $this->currentmod = null;
+            $this->currentblock = null;
             $forbidden = true;
 
         } else if (strpos($path, '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK') === 0) {
             // expand the BLOCK paths so that they contain the module name
-            $path = str_replace('/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK', '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/' . $this->currentmod, $path);
+            $path = str_replace('/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK', '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/' . $this->currentblock, $path);
         }
 
         if (empty($this->pathelements[$path])) {
@@ -397,7 +397,7 @@ class moodle1_converter extends base_converter {
             $path = '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/' . $this->currentblock;
 
         } else if (strpos($path, '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK') === 0) {
-            $path = str_replace('/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK', '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/' . $this->currentmod, $path);
+            $path = str_replace('/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK', '/MOODLE_BACKUP/COURSE/BLOCKS/BLOCK/' . $this->currentblock, $path);
         }
 
         if (empty($this->pathelements[$path])) {
@@ -641,7 +641,9 @@ class moodle1_converter extends base_converter {
         }
         foreach ($matches[2] as $match) {
             $file = str_replace(array('$@FILEPHP@$', '$@SLASH@$', '$@FORCEDOWNLOAD@$'), array('', '/', ''), $match);
-            $files[] = rawurldecode($file);
+            if ($file === clean_param($file, PARAM_PATH)) {
+                $files[] = rawurldecode($file);
+            }
         }
 
         return array_unique($files);
@@ -1209,6 +1211,10 @@ class moodle1_file_manager implements loggable {
 
         $sourcefullpath = $this->basepath.'/'.$sourcepath;
 
+        if ($sourcefullpath !== clean_param($sourcefullpath, PARAM_PATH)) {
+            throw new moodle1_convert_exception('file_invalid_path', $sourcefullpath);
+        }
+
         if (!is_readable($sourcefullpath)) {
             throw new moodle1_convert_exception('file_not_readable', $sourcefullpath);
         }
index bf4935c..154b6c8 100644 (file)
@@ -273,6 +273,15 @@ class moodle1_converter_testcase extends advanced_testcase {
         $fileids = $fileman->get_fileids();
         $this->assertEquals(gettype($fileids), 'array');
         $this->assertEquals(0, count($fileids));
+        // try to migrate an invalid file
+        $fileman->itemid = 1;
+        $thrown = false;
+        try {
+            $fileman->migrate_file('/../../../../../../../../../../../../../../etc/passwd');
+        } catch (moodle1_convert_exception $e) {
+            $thrown = true;
+        }
+        $this->assertTrue($thrown);
         // migrate a single file
         $fileman->itemid = 4;
         $fileman->migrate_file('moddata/unittest/4/icon.gif');
@@ -435,6 +444,8 @@ class moodle1_converter_testcase extends advanced_testcase {
 
         $text = 'This is a text containing links to file.php
 as it is parsed from the backup file. <br /><br /><img border="0" width="110" vspace="0" hspace="0" height="92" title="News" alt="News" src="$@FILEPHP@$$@SLASH@$pics$@SLASH@$news.gif" /><a href="$@FILEPHP@$$@SLASH@$pics$@SLASH@$news.gif$@FORCEDOWNLOAD@$">download image</a><br />
+    <div><a href=\'$@FILEPHP@$/../../../../../../../../../../../../../../../etc/passwd\'>download passwords</a></div>
+    <div><a href=\'$@FILEPHP@$$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$etc$@SLASH@$shadow\'>download shadows</a></div>
     <br /><a href=\'$@FILEPHP@$$@SLASH@$MANUAL.DOC$@FORCEDOWNLOAD@$\'>download manual</a><br />';
 
         $files = moodle1_converter::find_referenced_files($text);
@@ -446,6 +457,8 @@ as it is parsed from the backup file. <br /><br /><img border="0" width="110" vs
         $text = moodle1_converter::rewrite_filephp_usage($text, array('/pics/news.gif', '/another/file/notused.txt'));
         $this->assertEquals($text, 'This is a text containing links to file.php
 as it is parsed from the backup file. <br /><br /><img border="0" width="110" vspace="0" hspace="0" height="92" title="News" alt="News" src="@@PLUGINFILE@@/pics/news.gif" /><a href="@@PLUGINFILE@@/pics/news.gif?forcedownload=1">download image</a><br />
+    <div><a href=\'$@FILEPHP@$/../../../../../../../../../../../../../../../etc/passwd\'>download passwords</a></div>
+    <div><a href=\'$@FILEPHP@$$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$..$@SLASH@$etc$@SLASH@$shadow\'>download shadows</a></div>
     <br /><a href=\'$@FILEPHP@$$@SLASH@$MANUAL.DOC$@FORCEDOWNLOAD@$\'>download manual</a><br />');
     }
 
index d205a64..0f00baf 100644 (file)
@@ -154,7 +154,7 @@ $PAGE->navbar->add($backup->get_stage_name());
 // Display the current stage
 echo $OUTPUT->header();
 if ($backup->enforce_changed_dependencies()) {
-    echo $renderer->dependency_notification(get_string('dependenciesenforced','backup'));
+    debugging('Your settings have been altered due to unmet dependencies', DEBUG_DEVELOPER);
 }
 echo $renderer->progress_bar($backup->get_progress_bar());
 echo $backup->display($renderer);
index 103fb3d..740c202 100644 (file)
@@ -190,6 +190,15 @@ class restore_gradebook_structure_step extends restore_structure_step {
                 $data->id = $newitemid = $existinggradeitem->id;
                 $DB->update_record('grade_items', $data);
             }
+        } else if ($data->itemtype == 'manual') {
+            // Manual items aren't assigned to a cm, so don't go duplicating them in the target if one exists.
+            $gi = array(
+                'itemtype' => $data->itemtype,
+                'courseid' => $data->courseid,
+                'itemname' => $data->itemname,
+                'categoryid' => $data->categoryid,
+            );
+            $newitemid = $DB->get_field('grade_items', 'id', $gi);
         }
 
         if (empty($newitemid)) {
@@ -288,8 +297,13 @@ class restore_gradebook_structure_step extends restore_structure_step {
 
         $data->courseid = $this->get_courseid();
 
-        $newitemid = $DB->insert_record('grade_settings', $data);
-        //$this->set_mapping('grade_setting', $oldid, $newitemid);
+        if (!$DB->record_exists('grade_settings', array('courseid' => $data->courseid, 'name' => $data->name))) {
+            $newitemid = $DB->insert_record('grade_settings', $data);
+        } else {
+            $newitemid = $data->id;
+        }
+
+        $this->set_mapping('grade_setting', $oldid, $newitemid);
     }
 
     /**
@@ -1151,11 +1165,11 @@ class restore_section_structure_step extends restore_structure_step {
         $sectionid = $this->get_task()->get_sectionid();
 
         // Get data object for current section availability (if any).
-        $data = $DB->get_record('course_sections_availability',
-                array('coursesectionid' => $sectionid), 'id, sourcecmid, gradeitemid', IGNORE_MISSING);
+        $records = $DB->get_records('course_sections_availability',
+                array('coursesectionid' => $sectionid), 'id, sourcecmid, gradeitemid');
 
         // If it exists, update mappings.
-        if ($data) {
+        foreach ($records as $data) {
             // Only update mappings for entries which are created by this restore.
             // Otherwise, when you restore to an existing course, it will mess up
             // existing section availability entries.
@@ -2904,9 +2918,6 @@ class restore_create_categories_and_questions extends restore_structure_step {
             $data->penalty = 1;
         }
 
-        $data->timecreated  = $this->apply_date_offset($data->timecreated);
-        $data->timemodified = $this->apply_date_offset($data->timemodified);
-
         $userid = $this->get_mappingid('user', $data->createdby);
         $data->createdby = $userid ? $userid : $this->task->get_userid();
 
index 2ac6b78..6091c09 100644 (file)
@@ -61,7 +61,7 @@ $PAGE->navbar->add($restore->get_stage_name());
 $renderer = $PAGE->get_renderer('core','backup');
 echo $OUTPUT->header();
 if (!$restore->is_independent() && $restore->enforce_changed_dependencies()) {
-    echo $renderer->dependency_notification(get_string('dependenciesenforced','backup'));
+    debugging('Your settings have been altered due to unmet dependencies', DEBUG_DEVELOPER);
 }
 echo $renderer->progress_bar($restore->get_progress_bar());
 echo $restore->display($renderer);
index e4ab4b1..5c05380 100644 (file)
@@ -75,7 +75,7 @@ class file_logger extends base_logger {
         if (substr($this->fullpath, -5) !== '.html') {
             $content = $prefix . str_repeat('  ', $depth) . $message . PHP_EOL;
         } else {
-            $content = $prefix . str_repeat('&nbsp;&nbsp;', $depth) . htmlentities($message, ENT_QUOTES) . '<br/>' . PHP_EOL;
+            $content = $prefix . str_repeat('&nbsp;&nbsp;', $depth) . htmlentities($message, ENT_QUOTES, 'UTF-8') . '<br/>' . PHP_EOL;
         }
         if (false === fwrite($this->fhandle, $content)) {
             throw new base_logger_exception('error_writing_file', $this->fullpath);
index 8bb6811..2eaea5b 100644 (file)
@@ -38,7 +38,7 @@ class output_indented_logger extends base_logger {
         if (defined('STDOUT')) {
             echo $prefix . str_repeat('  ', $depth) . $message . PHP_EOL;
         } else {
-            echo $prefix . str_repeat('&nbsp;&nbsp;', $depth) . htmlentities($message, ENT_QUOTES) . '<br/>' . PHP_EOL;
+            echo $prefix . str_repeat('&nbsp;&nbsp;', $depth) . htmlentities($message, ENT_QUOTES, 'UTF-8') . '<br/>' . PHP_EOL;
         }
         flush();
         return true;
index fe61536..9d13dfd 100644 (file)
@@ -37,7 +37,7 @@ class output_text_logger extends base_logger {
         if (defined('STDOUT')) {
             echo $prefix . $message . PHP_EOL;
         } else {
-            echo $prefix . htmlentities($message, ENT_QUOTES) . '<br/>' . PHP_EOL;
+            echo $prefix . htmlentities($message, ENT_QUOTES, 'UTF-8') . '<br/>' . PHP_EOL;
         }
         flush();
         return true;
index ce95e7a..fb0e975 100644 (file)
@@ -322,6 +322,7 @@ abstract class base_moodleform extends moodleform {
         $config->question = get_string('confirmcancelquestion', 'backup');
         $config->yesLabel = get_string('confirmcancelyes', 'backup');
         $config->noLabel = get_string('confirmcancelno', 'backup');
+        $config->closeButtonTitle = get_string('close', 'editor');
         $PAGE->requires->yui_module('moodle-backup-confirmcancel', 'M.core_backup.watch_cancel_buttons', array($config));
 
         $PAGE->requires->yui_module('moodle-backup-backupselectall', 'M.core_backup.select_all_init',
index 35e3f2e..bef1b69 100644 (file)
@@ -69,7 +69,7 @@ class block_community extends block_list {
         }
 
         $icon = html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('i/group'),
-                    'class' => 'icon', 'alt' => get_string('addcourse', 'block_community')));
+                    'class' => 'icon', 'alt' => ""));
         $addcourseurl = new moodle_url('/blocks/community/communitycourse.php',
                         array('add' => true, 'courseid' => $this->page->course->id));
         $searchlink = html_writer::tag('a', $icon . '&nbsp;' . get_string('addcourse', 'block_community'),
index dbd9e07..5cef966 100644 (file)
@@ -228,10 +228,10 @@ if (!empty($courses)) {
     }
 }
 $PAGE->requires->yui_module('moodle-block_community-comments', 'M.blocks_community.init_comments',
-        array(array('commentids' => $commentedcourseids)));
+        array(array('commentids' => $commentedcourseids, 'closeButtonTitle' => get_string('close', 'editor'))));
 $PAGE->requires->yui_module('moodle-block_community-imagegallery', 'M.blocks_community.init_imagegallery',
         array(array('imageids' => $courseids, 'imagenumbers' => $courseimagenumbers,
-                'huburl' => $huburl)));
+                'huburl' => $huburl, 'closeButtonTitle' => get_string('close', 'editor'))));
 
 echo highlight($search, $renderer->course_list($courses, $huburl, $courseid));
 
index 97e6e1d..28d6162 100644 (file)
     background-color:#F6F6F6;
     border:1px solid #CCCCCC;
     overflow: auto;
+    padding: 7px 6px;
 }
 
 #page-blocks-community-communitycourse .moodle-dialogue-base .moodle-dialogue-bd {
 
 #page-blocks-community-communitycourse .moodle-dialogue-base .closebutton {
     margin-top:4px;
-    width:30px;
-}
\ No newline at end of file
+    margin-right: 4px;
+}
index 7355b80..300fcdf 100644 (file)
@@ -9,8 +9,8 @@ YUI.add('moodle-block_community-comments', function(Y) {
     Y.extend(COMMENTS, Y.Base, {
 
         event:null,
-        overlayevent:null,
-        overlays: [], //all the comment boxes
+        panelevent: null,
+        panels: [], //all the comment boxes
 
         initializer : function(params) {
 
@@ -18,17 +18,19 @@ YUI.add('moodle-block_community-comments', function(Y) {
             for (var i=0;i<this.get('commentids').length;i++)
             {
                 var commentid = this.get('commentids')[i];
-                this.overlays[commentid] = new M.core.dialogue({
-                    headerContent:Y.one('#commentoverlay-'+commentid+' .commenttitle').get('innerHTML'),
+                this.panels[commentid] = new M.core.dialogue({
+                    headerContent:Y.Node.create('<h1>')
+                        .append(Y.one('#commentoverlay-'+commentid+' .commenttitle').get('innerHTML')),
                     bodyContent:Y.one('#commentoverlay-'+commentid).get('innerHTML'),
                     visible: false, //by default it is not displayed
                     lightbox : false,
-                    zIndex:100
+                    zIndex:100,
+                    closeButtonTitle: this.get('closeButtonTitle')
                 });
 
-                this.overlays[commentid].get('contentBox').one('.commenttitle').remove();
-                this.overlays[commentid].render();
-                this.overlays[commentid].hide();
+                this.panels[commentid].get('contentBox').one('.commenttitle').remove();
+                this.panels[commentid].render();
+                this.panels[commentid].hide();
 
                 Y.one('#comments-'+commentid).on('click', this.show, this, commentid);
             }
@@ -37,34 +39,37 @@ YUI.add('moodle-block_community-comments', function(Y) {
 
         show : function (e, commentid) {
 
-            //hide all overlays
+            // Hide all panels.
             for (var i=0;i<this.get('commentids').length;i++)
             {
                 this.hide(e, this.get('commentids')[i]);
             }
 
-            this.overlays[commentid].show(); //show the overlay
+            this.panels[commentid].show(); //show the panel
 
-            e.halt(); // we are going to attach a new 'hide overlay' event to the body,
+            e.halt(); // we are going to attach a new 'hide panel' event to the body,
             // because javascript always propagate event to parent tag,
             // we need to tell Yahoo to stop to call the event on parent tag
             // otherwise the hide event will be call right away.
 
-            //we add a new event on the body in order to hide the overlay for the next click
+            // We add a new event on the body in order to hide the panel for the next click.
             this.event = Y.one(document.body).on('click', this.hide, this, commentid);
-            //we add a new event on the overlay in order to hide the overlay for the next click (touch device)
-            this.overlayevent = Y.one("#commentoverlay-"+commentid).on('click', this.hide, this, commentid);
+            // We add a new event on the panel in order to hide the panel for the next click (touch device).
+            this.panelevent = Y.one("#commentoverlay-"+commentid).on('click', this.hide, this, commentid);
+
+            // Focus on the close button
+            this.panels[commentid].get('buttons').header[0].focus();
         },
 
         hide : function (e, commentid) {
-            this.overlays[commentid].hide(); //hide the overlay
+            this.panels[commentid].hide(); //hide the panel
             if (this.event != null) {
                 this.event.detach(); //we need to detach the body hide event
             //Note: it would work without but create js warning everytime
             //we click on the body
             }
-            if (this.overlayevent != null) {
-                this.overlayevent.detach(); //we need to detach the overlay hide event
+            if (this.panelevent != null) {
+                this.panelevent.detach(); //we need to detach the panel hide event
             //Note: it would work without but create js warning everytime
             //we click on the body
             }
@@ -74,7 +79,11 @@ YUI.add('moodle-block_community-comments', function(Y) {
     }, {
         NAME : COMMENTSNAME,
         ATTRS : {
-            commentids: {}
+            commentids: {},
+            closeButtonTitle : {
+                validator : Y.Lang.isString,
+                value : 'Close'
+            }
         }
     });
 
@@ -84,5 +93,5 @@ YUI.add('moodle-block_community-comments', function(Y) {
     }
 
 }, '@VERSION@', {
-    requires:['base','overlay', 'moodle-enrol-notification']
+    requires:['base', 'moodle-enrol-notification']
 });
index f91abb0..5407234 100644 (file)
@@ -11,8 +11,8 @@ YUI.add('moodle-block_community-imagegallery', function(Y) {
         event:null,
         previousevent:null,
         nextevent:null,
-        overlayevent:null,
-        overlay:null, //all the comment boxes
+        panelevent: null,
+        panel: null, //all the images boxes
         imageidnumbers: [],
         imageloadingevent: null,
         loadingimage: null,
@@ -26,15 +26,15 @@ YUI.add('moodle-block_community-imagegallery', function(Y) {
                 +'</div>');
             objBody.append(this.loadingimage);
 
-            /// create the div for overlay
+            // Create the div for panel.
             var objBody = Y.one(document.body);
-            var overlaytitle = Y.Node.create('<div id="imagetitleoverlay" class="hiddenoverlay"></div>');
-            objBody.append(overlaytitle);
-            var overlay = Y.Node.create('<div id="imageoverlay" class="hiddenoverlay"></div>');
-            objBody.append(overlay);
+            var paneltitle = Y.Node.create('<div id="imagetitleoverlay" class="hiddenoverlay"></div>');
+            objBody.append(paneltitle);
+            var panel = Y.Node.create('<div id="imageoverlay" class="hiddenoverlay"></div>');
+            objBody.append(panel);
 
-            /// create the overlay
-            this.overlay = new M.core.dialogue({
+            /// Create the panel.
+            this.panel = new M.core.dialogue({
                 headerContent:Y.one('#imagetitleoverlay').get('innerHTML'),
                 bodyContent:Y.one('#imageoverlay').get('innerHTML'),
                 visible: false, //by default it is not displayed
@@ -42,8 +42,8 @@ YUI.add('moodle-block_community-imagegallery', function(Y) {
                 zIndex:100
             });
 
-            this.overlay.render();
-            this.overlay.hide();
+            this.panel.render();
+            this.panel.hide();
 
             //attach a show event on the image divs (<tag id='image-X'>)
             for (var i=0;i<this.get('imageids').length;i++)
@@ -85,31 +85,31 @@ YUI.add('moodle-block_community-imagegallery', function(Y) {
             var maxheight = windowheight - 150;
 
             //load the title + link to next image
-            var overlaytitle = Y.one('#imagetitleoverlay');
+            var paneltitle = Y.one('#imagetitleoverlay');
             var previousimagelink = "<div id=\"previousarrow\" class=\"imagearrow\">←</div>";
             var nextimagelink = "<div id=\"nextarrow\" class=\"imagearrow\">→</div>";
 
-            /// need to load the images in the overlay
-            var overlay = Y.one('#imageoverlay');
-            overlay.setContent('');
+            // Need to load the images in the panel.
+            var panel = Y.one('#imageoverlay');
+            panel.setContent('');
 
-
-            overlay.append(Y.Node.create('<div style="text-align:center"><img id=\"imagetodisplay\" src="' + url
+            panel.append(Y.Node.create('<div style="text-align:center"><img id=\"imagetodisplay\" src="' + url
                 + '" style="max-height:' + maxheight + 'px;"></div>'));
-            this.overlay.destroy();
-            this.overlay = new M.core.dialogue({
-                headerContent:previousimagelink + '<div id=\"imagenumber\" class=\"imagetitle\"> Image '
-                + screennumber + ' / ' + this.imageidnumbers[imageid] + ' </div>' + nextimagelink,
+            this.panel.destroy();
+            this.panel = new M.core.dialogue({
+                headerContent:previousimagelink + '<div id=\"imagenumber\" class=\"imagetitle\"><h1> Image '
+                + screennumber + ' / ' + this.imageidnumbers[imageid] + ' </h1></div>' + nextimagelink,
                 bodyContent:Y.one('#imageoverlay').get('innerHTML'),
                 visible: false, //by default it is not displayed
                 lightbox : false,
-                zIndex:100
+                zIndex:100,
+                closeButtonTitle: this.get('closeButtonTitle')
             });
-            this.overlay.render();
-            this.overlay.hide(); //show the overlay
-            this.overlay.set("centered", true);
+            this.panel.render();
+            this.panel.hide(); //show the panel
+            this.panel.set("centered", true);
 
-            e.halt(); // we are going to attach a new 'hide overlay' event to the body,
+            e.halt(); // we are going to attach a new 'hide panel' event to the body,
             // because javascript always propagate event to parent tag,
             // we need to tell Yahoo to stop to call the event on parent tag
             // otherwise the hide event will be call right away.
@@ -123,14 +123,17 @@ YUI.add('moodle-block_community-imagegallery', function(Y) {
                 var screenshot = new Image();
                 screenshot.src = url;
 
-                var overlaywidth = windowwidth - 100;
-                if(overlaywidth > screenshot.width) {
-                    overlaywidth = screenshot.width;
+                var panelwidth = windowwidth - 100;
+                if(panelwidth > screenshot.width) {
+                    panelwidth = screenshot.width;
                 }
 
-                this.overlay.set('width', overlaywidth);
-                this.overlay.set("centered", true);
-                this.overlay.show();
+                this.panel.set('width', panelwidth);
+                this.panel.set("centered", true);
+                this.panel.show();
+
+                // Focus on the close button
+                this.panel.get('buttons').header[0].focus();
 
             }, this, url);
 
@@ -147,12 +150,12 @@ YUI.add('moodle-block_community-imagegallery', function(Y) {
             Y.one('#nextarrow').on('click', this.show, this, imageid, nextnumber);
             Y.one('#imagenumber').on('click', this.show, this, imageid, nextnumber);
 
-            //we add a new event on the body in order to hide the overlay for the next click
+            //we add a new event on the body in order to hide the panel for the next click
             this.event = Y.one(document.body).on('click', this.hide, this);
-            //we add a new event on the overlay in order to hide the overlay for the next click (touch device)
-            this.overlayevent = Y.one("#imageoverlay").on('click', this.hide, this);
+            //we add a new event on the panel in order to hide the panel for the next click (touch device)
+            this.panelevent = Y.one("#imageoverlay").on('click', this.hide, this);
 
-            this.overlay.on('visibleChange',function(e){
+            this.panel.on('visibleChange',function(e){
                 if(e.newVal == 0){
                     this.get('maskNode').remove()
                 }
@@ -167,14 +170,14 @@ YUI.add('moodle-block_community-imagegallery', function(Y) {
             //hide the loading image
             Y.one('#hubloadingimage').setStyle('display', 'none');
 
-            this.overlay.hide(); //hide the overlay
+            this.panel.hide(); //hide the panel
             if (this.event != null) {
                 this.event.detach(); //we need to detach the body hide event
             //Note: it would work without but create js warning everytime
             //we click on the body
             }
-            if (this.overlayevent != null) {
-                this.overlayevent.detach(); //we need to detach the overlay hide event
+            if (this.panelevent != null) {
+                this.panelevent.detach(); //we need to detach the panel hide event
             //Note: it would work without but create js warning everytime
             //we click on the body
             }
@@ -185,7 +188,11 @@ YUI.add('moodle-block_community-imagegallery', function(Y) {
         ATTRS : {
             imageids: {},
             imagenumbers: {},
-            huburl: {}
+            huburl: {},
+            closeButtonTitle : {
+                validator : Y.Lang.isString,
+                value : 'Close'
+            }
         }
     });
 
@@ -195,5 +202,5 @@ YUI.add('moodle-block_community-imagegallery', function(Y) {
     }
 
 }, '@VERSION@', {
-    requires:['base','node','overlay', 'moodle-enrol-notification']
+    requires:['base','node', 'moodle-enrol-notification']
 });
index a759913..6f63816 100644 (file)
@@ -916,7 +916,7 @@ M.core_dock.genericblock.prototype = {
             }, this);
             // Add a close icon
             // Must set the image src seperatly of we get an error with XML strict headers
-            var closeicon = Y.Node.create('<span class="hidepanelicon" tabindex="0"><img alt="" style="width:11px;height:11px;cursor:pointer;" /></span>');
+            var closeicon = Y.Node.create('<span class="hidepanelicon" tabindex="0"><img alt="'+M.str.block.hidepanel+'" title="'+M.str.block.hidedockpanel+'" style="width:11px;height:11px;cursor:pointer;"/></span>');
             closeicon.one('img').setAttribute('src', M.util.image_url('t/dockclose', 'moodle'));
             closeicon.on('forceclose|click', this.hide, this);
             closeicon.on('dock:actionkey',this.hide, this, {actions:{enter:true,toggle:true}});
index 102a167..c06d078 100644 (file)
@@ -137,6 +137,7 @@ class block_glossary_random extends block_base {
             $this->config->cache = '';
             $this->instance_config_commit();
 
+            $this->content = new stdClass();
             $this->content->text   = get_string('notyetconfigured','block_glossary_random');
             $this->content->footer = '';
             return $this->content;
diff --git a/blocks/html/backup/moodle1/lib.php b/blocks/html/backup/moodle1/lib.php
new file mode 100644 (file)
index 0000000..d4a491f
--- /dev/null
@@ -0,0 +1,46 @@
+<?php\r
+\r
+/**\r
+ * Provides support for the conversion of moodle1 backup to the moodle2 format\r
+ *\r
+ * @package    block_html\r
+ * @copyright  2012 Paul Nicholls\r
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r
+ */\r
+\r
+defined('MOODLE_INTERNAL') || die();\r
+\r
+/**\r
+ * Block conversion handler for html\r
+ */\r
+class moodle1_block_html_handler extends moodle1_block_handler {\r
+    private $fileman = null;\r
+    protected function convert_configdata(array $olddata) {\r
+        $instanceid = $olddata['id'];\r
+        $contextid  = $this->converter->get_contextid(CONTEXT_BLOCK, $olddata['id']);\r
+        $configdata = unserialize(base64_decode($olddata['configdata']));\r
+\r
+        // get a fresh new file manager for this instance\r
+        $this->fileman = $this->converter->get_file_manager($contextid, 'block_html');\r
+\r
+        // convert course files embedded in the block content\r
+        $this->fileman->filearea = 'content';\r
+        $this->fileman->itemid   = 0;\r
+        $configdata->text = moodle1_converter::migrate_referenced_files($configdata->text, $this->fileman);\r
+        $configdata->format = FORMAT_HTML;\r
+\r
+        return base64_encode(serialize($configdata));\r
+    }\r
+\r
+    protected function write_inforef_xml($newdata, $data) {\r
+        $this->open_xml_writer("course/blocks/{$data['name']}_{$data['id']}/inforef.xml");\r
+        $this->xmlwriter->begin_tag('inforef');\r
+        $this->xmlwriter->begin_tag('fileref');\r
+        foreach ($this->fileman->get_fileids() as $fileid) {\r
+            $this->write_xml('file', array('id' => $fileid));\r
+        }\r
+        $this->xmlwriter->end_tag('fileref');\r
+        $this->xmlwriter->end_tag('inforef');\r
+        $this->close_xml_writer();\r
+    }\r
+}
\ No newline at end of file
index 2efe9a2..77f8a69 100644 (file)
@@ -151,12 +151,13 @@ class block_online_users extends block_base {
                 $timeago = format_time($now - $user->lastaccess); //bruno to calculate correctly on frontpage
 
                 if (isguestuser($user)) {
-                    $this->content->text .= '<div class="user">'.$OUTPUT->user_picture($user, array('size'=>16));
+                    $this->content->text .= '<div class="user">'.$OUTPUT->user_picture($user, array('size'=>16, 'alttext'=>false));
                     $this->content->text .= get_string('guestuser').'</div>';
 
                 } else {
-                    $this->content->text .= '<div class="user">'.$OUTPUT->user_picture($user, array('size'=>16));
-                    $this->content->text .= '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$user->id.'&amp;course='.$this->page->course->id.'" title="'.$timeago.'">'.$user->fullname.'</a></div>';
+                    $this->content->text .= '<div class="user">';
+                    $this->content->text .= '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$user->id.'&amp;course='.$this->page->course->id.'" title="'.$timeago.'">';
+                    $this->content->text .= $OUTPUT->user_picture($user, array('size'=>16, 'alttext'=>false, 'link'=>false)) .$user->fullname.'</a></div>';
                 }
                 if ($canshowicon and ($USER->id != $user->id) and !isguestuser($user)) {  // Only when logged in and messaging active etc
                     $anchortagcontents = '<img class="iconsmall" src="'.$OUTPUT->pix_url('t/message') . '" alt="'. get_string('messageselectadd') .'" />';
diff --git a/blocks/rss_client/backup/moodle1/lib.php b/blocks/rss_client/backup/moodle1/lib.php
new file mode 100644 (file)
index 0000000..95da634
--- /dev/null
@@ -0,0 +1,34 @@
+<?php\r
+\r
+/**\r
+ * Provides support for the conversion of moodle1 backup to the moodle2 format\r
+ *\r
+ * @package    block_rss_client\r
+ * @copyright  2012 Paul Nicholls\r
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r
+ */\r
+\r
+defined('MOODLE_INTERNAL') || die();\r
+\r
+/**\r
+ * Block conversion handler for rss_client\r
+ */\r
+class moodle1_block_rss_client_handler extends moodle1_block_handler {\r
+    public function process_block(array $data) {\r
+        parent::process_block($data);\r
+        $instanceid = $data['id'];\r
+        $contextid = $this->converter->get_contextid(CONTEXT_BLOCK, $data['id']);\r
+\r
+        // Moodle 1.9 backups do not include sufficient data to restore feeds, so we need an empty shell rss_client.xml\r
+        // for the restore process to find\r
+        $this->open_xml_writer("course/blocks/{$data['name']}_{$instanceid}/rss_client.xml");\r
+        $this->xmlwriter->begin_tag('block', array('id' => $instanceid, 'contextid' => $contextid, 'blockname' => 'rss_client'));\r
+        $this->xmlwriter->begin_tag('rss_client', array('id' => $instanceid));\r
+        $this->xmlwriter->full_tag('feeds', '');\r
+        $this->xmlwriter->end_tag('rss_client');\r
+        $this->xmlwriter->end_tag('block');\r
+        $this->close_xml_writer();\r
+\r
+        return $data;\r
+    }\r
+}
\ No newline at end of file
index 8e28ac2..c23d7b9 100644 (file)
@@ -78,6 +78,9 @@ class restore_rss_client_block_structure_step extends restore_structure_step {
         $configdata = $DB->get_field('block_instances', 'configdata', array('id' => $this->task->get_blockid()));
         // Extract configdata
         $config = unserialize(base64_decode($configdata));
+        if (empty($config)) {
+            $config = new stdClass();
+        }
         // Set array of used rss feeds
         $config->rssid = $feedsarr;
         // Serialize back the configdata
index eec3202..c1b4d5d 100644 (file)
@@ -34,7 +34,7 @@ class block_tags_edit_form extends block_edit_form {
         // Fields for editing HTML block title and contents.
         $mform->addElement('header', 'configheader', get_string('blocksettings', 'block'));
 
-        $mform->addElement('text', 'config_title', get_string('pluginname', 'block_tags'));
+        $mform->addElement('text', 'config_title', get_string('configtitle', 'block_tags'));
         $mform->setType('config_title', PARAM_MULTILANG);
         $mform->setDefault('config_title', get_string('pluginname', 'block_tags'));
 
index 265cd5a..4998f68 100644 (file)
@@ -31,6 +31,7 @@ $string['arrowtitle'] = 'Click here to enter the suggested text (grey letters).'
 $string['communitytags'] = 'Community tags:';
 $string['communitytags1'] = 'community tags';
 $string['communitytags2'] = 'Show all user created course tags';
+$string['configtitle'] = 'Block title';
 $string['coursetags'] = 'Course tags:';
 $string['coursetags1'] = 'course tags';
 $string['coursetags2'] = 'Show tags for this course';
index 770fb06..37e3532 100644 (file)
@@ -163,6 +163,13 @@ function blog_rss_get_feed($context, $args) {
         return '';
     }
 
+    if ($CFG->bloglevel == BLOG_SITE_LEVEL) {
+        if (isguestuser()) {
+            debugging(get_string('nopermissiontoshow','error'));
+            return '';
+        }
+    }
+
     $sitecontext = get_context_instance(CONTEXT_SYSTEM);
     if (!has_capability('moodle/blog:view', $sitecontext)) {
         return null;
index 37c44d4..76efcf3 100644 (file)
@@ -184,7 +184,7 @@ bodyContent: '<div class="comment-delete-confirm"><a href="#" id="confirmdelete-
                         val = val.replace('___name___', list[i].fullname);
                     }
                     if (list[i]['delete']||newcmt) {
-                        list[i].content = '<div class="comment-delete"><a href="#" id ="comment-delete-'+this.client_id+'-'+list[i].id+'" title="'+M.str.moodle.deletecomment+'"><img src="'+M.util.image_url('t/delete', 'core')+'" /></a></div>' + list[i].content;
+                        list[i].content = '<div class="comment-delete"><a href="#" id ="comment-delete-'+this.client_id+'-'+list[i].id+'" title="'+M.str.moodle.deletecomment+'"><img alt="" src="'+M.util.image_url('t/delete', 'core')+'" /></a></div>' + list[i].content;
                     }
                     val = val.replace('___time___', list[i].time);
                     val = val.replace('___picture___', list[i].avatar);
index b7a39a8..a960293 100644 (file)
@@ -38,7 +38,7 @@ $action    = optional_param('action',    '',  PARAM_ALPHA);
 $area      = optional_param('area',      '',  PARAM_AREA);
 $content   = optional_param('content',   '',  PARAM_RAW);
 $itemid    = optional_param('itemid',    '',  PARAM_INT);
-$returnurl = optional_param('returnurl', '/', PARAM_URL);
+$returnurl = optional_param('returnurl', '/', PARAM_LOCALURL);
 $component = optional_param('component', '',  PARAM_COMPONENT);
 
 // Currently this script can only add comments
diff --git a/composer.json b/composer.json
new file mode 100644 (file)
index 0000000..5f618de
--- /dev/null
@@ -0,0 +1,6 @@
+{
+    "require-dev": {
+        "phpunit/phpunit": "3.7.*",
+        "phpunit/dbUnit": "1.2.*"
+    }
+}
\ No newline at end of file
index cb1d0c7..7751058 100644 (file)
@@ -191,6 +191,7 @@ if ($editingon && can_edit_in_category()) {
     // Integrate into the admin tree only if the user can edit categories at the top level,
     // otherwise the admin block does not appear to this user, and you get an error.
     require_once($CFG->libdir . '/adminlib.php');
+    navigation_node::override_active_url(new moodle_url('/course/category.php', array('id' => $id)));
     admin_externalpage_setup('coursemgmt', '', $urlparams, $CFG->wwwroot . '/course/category.php');
     $PAGE->set_context($context);   // Ensure that we are actually showing blocks etc for the cat context
 
@@ -434,8 +435,11 @@ if (!$courses) {
         $movetocategories[$category->id] = get_string('moveselectedcoursesto');
         echo '<tr><td colspan="3" align="right">';
         echo html_writer::label(get_string('moveselectedcoursesto'), 'movetoid', false, array('class' => 'accesshide'));
-        echo html_writer::select($movetocategories, 'moveto', $category->id, null, array('id'=>'movetoid'));
-        $PAGE->requires->js_init_call('M.util.init_select_autosubmit', array('movecourses', 'movetoid', false));
+        echo html_writer::select($movetocategories, 'moveto', $category->id, null, array('id'=>'movetoid', 'class' => 'autosubmit'));
+        $PAGE->requires->yui_module('moodle-core-formautosubmit',
+            'M.core.init_formautosubmit',
+            array(array('selectid' => 'movetoid', 'nothing' => $category->id))
+        );
         echo '<input type="hidden" name="id" value="'.$category->id.'" />';
         echo '</td></tr>';
     }
index 038c09b..2aa6b02 100644 (file)
@@ -555,6 +555,15 @@ class dndupload_ajax_processor {
         $this->cm->groupmode = $this->course->groupmode;
         $this->cm->groupingid = $this->course->defaultgroupingid;
 
+        // Set the correct default for completion tracking.
+        $this->cm->completion = COMPLETION_TRACKING_NONE;
+        $completion = new completion_info($this->course);
+        if ($completion->is_enabled()) {
+            if (plugin_supports('mod', $this->cm->modulename, FEATURE_MODEDIT_DEFAULT_COMPLETION, true)) {
+                $this->cm->completion = COMPLETION_TRACKING_MANUAL;
+            }
+        }
+
         if (!$this->cm->id = add_course_module($this->cm)) {
             throw new coding_exception("Unable to create the course module");
         }
index 88fd0fa..1d91b94 100644 (file)
@@ -212,7 +212,7 @@ class core_course_external extends external_api {
                                 array(
                                     'id' => new external_value(PARAM_INT, 'activity id'),
                                     'url' => new external_value(PARAM_URL, 'activity url', VALUE_OPTIONAL),
-                                    'name' => new external_value(PARAM_TEXT, 'activity module name'),
+                                    'name' => new external_value(PARAM_RAW, 'activity module name'),
                                     'description' => new external_value(PARAM_RAW, 'activity description', VALUE_OPTIONAL),
                                     'visible' => new external_value(PARAM_INT, 'is the module visible', VALUE_OPTIONAL),
                                     'modicon' => new external_value(PARAM_URL, 'activity icon url'),
index 21fcfcd..54dfc74 100644 (file)
@@ -583,7 +583,7 @@ function print_log_csv($course, $user, $date, $order='l.time DESC', $modname,
             $ld = $DB->get_record('log_display', array('module'=>$log->module, 'action'=>$log->action));
             $ldcache[$log->module][$log->action] = $ld;
         }
-        if ($ld && !empty($log->info)) {
+        if ($ld && is_numeric($log->info)) {
             // ugly hack to make sure fullname is shown correctly
             if (($ld->mtable == 'user') and ($ld->field ==  $DB->sql_concat('firstname', "' '" , 'lastname'))) {
                 $log->info = fullname($DB->get_record($ld->mtable, array('id'=>$log->info)), true);
@@ -600,7 +600,7 @@ function print_log_csv($course, $user, $date, $order='l.time DESC', $modname,
         $firstField = format_string($courses[$log->course], true, array('context' => $coursecontext));
         $fullname = fullname($log, has_capability('moodle/site:viewfullnames', $coursecontext));
         $row = array($firstField, userdate($log->time, $strftimedatetime), $log->ip, $fullname, $log->module.' '.$log->action, $log->info);
-        $actionurl = $CFG->wwwroot. make_log_url($log->module,$log->url);\r
+        $actionurl = $CFG->wwwroot. make_log_url($log->module,$log->url);
         $row = array($firstField, userdate($log->time, $strftimedatetime), $log->ip, $fullname, $log->module.' '.$log->action.' ('.$actionurl.')', $log->info);
         $text = implode("\t", $row);
         echo $text." \n";
@@ -655,7 +655,7 @@ function print_log_xls($course, $user, $date, $order='l.time DESC', $modname,
     // Creating worksheets
     for ($wsnumber = 1; $wsnumber <= $nroPages; $wsnumber++) {
         $sheettitle = get_string('logs').' '.$wsnumber.'-'.$nroPages;
-        $worksheet[$wsnumber] =& $workbook->add_worksheet($sheettitle);
+        $worksheet[$wsnumber] = $workbook->add_worksheet($sheettitle);
         $worksheet[$wsnumber]->set_column(1, 1, 30);
         $worksheet[$wsnumber]->write_string(0, 0, get_string('savedat').
                                     userdate(time(), $strftimedatetime));
@@ -684,7 +684,7 @@ function print_log_xls($course, $user, $date, $order='l.time DESC', $modname,
             $ld = $DB->get_record('log_display', array('module'=>$log->module, 'action'=>$log->action));
             $ldcache[$log->module][$log->action] = $ld;
         }
-        if ($ld && !empty($log->info)) {
+        if ($ld && is_numeric($log->info)) {
             // ugly hack to make sure fullname is shown correctly
             if (($ld->mtable == 'user') and ($ld->field == $DB->sql_concat('firstname', "' '" , 'lastname'))) {
                 $log->info = fullname($DB->get_record($ld->mtable, array('id'=>$log->info)), true);
@@ -769,7 +769,7 @@ function print_log_ods($course, $user, $date, $order='l.time DESC', $modname,
     // Creating worksheets
     for ($wsnumber = 1; $wsnumber <= $nroPages; $wsnumber++) {
         $sheettitle = get_string('logs').' '.$wsnumber.'-'.$nroPages;
-        $worksheet[$wsnumber] =& $workbook->add_worksheet($sheettitle);
+        $worksheet[$wsnumber] = $workbook->add_worksheet($sheettitle);
         $worksheet[$wsnumber]->set_column(1, 1, 30);
         $worksheet[$wsnumber]->write_string(0, 0, get_string('savedat').
                                     userdate(time(), $strftimedatetime));
@@ -798,7 +798,7 @@ function print_log_ods($course, $user, $date, $order='l.time DESC', $modname,
             $ld = $DB->get_record('log_display', array('module'=>$log->module, 'action'=>$log->action));
             $ldcache[$log->module][$log->action] = $ld;
         }
-        if ($ld && !empty($log->info)) {
+        if ($ld && is_numeric($log->info)) {
             // ugly hack to make sure fullname is shown correctly
             if (($ld->mtable == 'user') and ($ld->field == $DB->sql_concat('firstname', "' '" , 'lastname'))) {
                 $log->info = fullname($DB->get_record($ld->mtable, array('id'=>$log->info)), true);
@@ -1710,14 +1710,25 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false,
                         } else {
                             $extraclass = '';
                         }
-                        echo "
-<form class='togglecompletion$extraclass' method='post' action='".$CFG->wwwroot."/course/togglecompletion.php'><div>
-<input type='hidden' name='id' value='{$mod->id}' />
-<input type='hidden' name='modulename' value='".s($mod->name)."' />
-<input type='hidden' name='sesskey' value='".sesskey()."' />
-<input type='hidden' name='completionstate' value='$newstate' />
-<input type='image' src='$imgsrc' alt='$imgalt' title='$imgtitle' />
-</div></form>";
+                        echo html_writer::start_tag('form', array(
+                                'class' => 'togglecompletion' . $extraclass,
+                                'method' => 'post',
+                                'action' => $CFG->wwwroot . '/course/togglecompletion.php'));
+                        echo html_writer::start_tag('div');
+                        echo html_writer::empty_tag('input', array(
+                                'type' => 'hidden', 'name' => 'id', 'value' => $mod->id));
+                        echo html_writer::empty_tag('input', array(
+                                'type' => 'hidden', 'name' => 'modulename',
+                                'value' => $mod->name));
+                        echo html_writer::empty_tag('input', array(
+                                'type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
+                        echo html_writer::empty_tag('input', array(
+                                'type' => 'hidden', 'name' => 'completionstate',
+                                'value' => $newstate));
+                        echo html_writer::empty_tag('input', array(
+                                'type' => 'image', 'src' => $imgsrc, 'alt' => $imgalt, 'title' => $imgtitle));
+                        echo html_writer::end_tag('div');
+                        echo html_writer::end_tag('form');
                     } else {
                         // In auto mode, or when editing, the icon is just an image
                         echo "<span class='autocompletion'>";
@@ -1737,17 +1748,20 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false,
             if (!$mod->uservisible) {
                 echo '<div class="availabilityinfo">'.$mod->availableinfo.'</div>';
             } else if ($canviewhidden && !empty($CFG->enableavailability)) {
-                $visibilityclass = '';
-                if (!$mod->visible) {
-                    $visibilityclass = 'accesshide';
-                }
-                $ci = new condition_info($mod);
-                $fullinfo = $ci->get_full_information();
-                if($fullinfo) {
-                    echo '<div class="availabilityinfo '.$visibilityclass.'">'.get_string($mod->showavailability
-                        ? 'userrestriction_visible'
-                        : 'userrestriction_hidden','condition',
-                        $fullinfo).'</div>';
+                // Don't add availability information if user is not editing and activity is hidden.
+                if ($mod->visible || $PAGE->user_is_editing()) {
+                    $hidinfoclass = '';
+                    if (!$mod->visible) {
+                        $hidinfoclass = 'hide';
+                    }
+                    $ci = new condition_info($mod);
+                    $fullinfo = $ci->get_full_information();
+                    if($fullinfo) {
+                        echo '<div class="availabilityinfo '.$hidinfoclass.'">'.get_string($mod->showavailability
+                            ? 'userrestriction_visible'
+                            : 'userrestriction_hidden','condition',
+                            $fullinfo).'</div>';
+                    }
                 }
             }
 
@@ -1869,7 +1883,7 @@ function print_section_add_menus($course, $section, $modnames, $vertical=false,
         // The module chooser link
         $modchooser = html_writer::start_tag('div', array('class' => 'mdl-right'));
         $modchooser.= html_writer::start_tag('div', array('class' => 'section-modchooser'));
-        $icon = $OUTPUT->pix_icon('t/add', $straddeither);
+        $icon = $OUTPUT->pix_icon('t/add', '');
         $span = html_writer::tag('span', $straddeither, array('class' => 'section-modchooser-text'));
         $modchooser .= html_writer::tag('span', $icon . $span, array('class' => 'section-modchooser-link'));
         $modchooser.= html_writer::end_tag('div');
@@ -4542,6 +4556,7 @@ function include_course_ajax($course, $usedmodules = array(), $enabledmodules =
         'courseid' => $course->id,
         'pagetype' => $PAGE->pagetype,
         'pagelayout' => $PAGE->pagelayout,
+        'subpage' => $PAGE->subpage,
         'regions' => $PAGE->blocks->get_regions(),
     );
     $PAGE->requires->yui_module('moodle-core-blocks', 'M.core_blocks.init_dragdrop', array($params), null, true);
@@ -4584,7 +4599,7 @@ function include_course_ajax($course, $usedmodules = array(), $enabledmodules =
     // Add the module chooser
     $PAGE->requires->yui_module('moodle-course-modchooser',
         'M.course.init_chooser',
-        array(array('courseid' => $course->id))
+        array(array('courseid' => $course->id, 'closeButtonTitle' => get_string('close', 'editor')))
     );
     $PAGE->requires->strings_for_js(array(
             'addresourceoractivity',
index ef59eb8..ca375da 100644 (file)
@@ -78,7 +78,7 @@ if ($backup->get_stage() !== backup_ui::STAGE_COMPLETE) {
     echo $OUTPUT->header();
     echo $OUTPUT->heading(get_string('publishcourseon', 'hub', !empty($hubname)?$hubname:$huburl), 3, 'main');
     if ($backup->enforce_changed_dependencies()) {
-        echo $renderer->dependency_notification(get_string('dependenciesenforced', 'backup'));
+        debugging('Your settings have been altered due to unmet dependencies', DEBUG_DEVELOPER);
     }
     echo $renderer->progress_bar($backup->get_progress_bar());
     echo $backup->display($renderer);
index dc7fa19..5f35a57 100644 (file)
@@ -99,6 +99,9 @@ class recent_form extends moodleform {
 
             $mform->addElement('select', 'user', get_string('participants'), $options);
             $mform->setAdvanced('user');
+        } else {
+            // Default to no user.
+            $mform->addElement('hidden', 'user', 0);
         }
 
         $options = array(''=>get_string('allactivities'));
index a980841..e6ed2b5 100644 (file)
@@ -123,6 +123,7 @@ class core_course_renderer extends plugin_renderer_base {
         if ($hascourses) {
             $content .= html_writer::start_tag('div', array('class'=>'courses'));
             $coursecount = 0;
+            $strinfo = new lang_string('info');
             foreach ($category->courses as $course) {
                 $classes = array('course');
                 $linkclass = 'course_link';
@@ -143,8 +144,9 @@ class core_course_renderer extends plugin_renderer_base {
                 }
 
                 if ($course->summary) {
+                    $url = new moodle_url('/course/info.php', array('id' => $course->id));
                     $image = html_writer::empty_tag('img', array('src'=>$this->output->pix_url('i/info'), 'alt'=>$this->strings->summary));
-                    $content .= html_writer::link(new moodle_url('/course/info.php', array('id'=>$course->id)), $image, array('title'=>$this->strings->summary));
+                    $content .= $this->action_link($url, $image, new popup_action('click', $url, 'courseinfo'), array('title' => $this->strings->summary));
                 }
                 $content .= html_writer::end_tag('div');
                 $content .= html_writer::end_tag('div');
index 61392ea..a7b55c9 100644 (file)
@@ -150,6 +150,7 @@ switch($requestmethod) {
                         break;
                     case 'updatetitle':
                         require_capability('moodle/course:manageactivities', $modcontext);
+                        require_once($CFG->libdir . '/gradelib.php');
                         $cm = get_coursemodule_from_id('', $id, 0, false, MUST_EXIST);
                         $module = new stdClass();
                         $module->id = $cm->instance;
@@ -167,10 +168,16 @@ switch($requestmethod) {
                             $module->name = $cm->name;
                         }
 
+                        // Attempt to update the grade item if relevant
+                        $grademodule = $DB->get_record($cm->modname, array('id' => $cm->instance));
+                        $grademodule->cmidnumber = $cm->idnumber;
+                        $grademodule->modname = $cm->modname;
+                        grade_update_mod_grades($grademodule);
+
                         // We need to return strings after they've been through filters for multilang
                         $stringoptions = new stdClass;
                         $stringoptions->context = $coursecontext;
-                        echo json_encode(array('instancename' => format_string($module->name, true,  $stringoptions)));
+                        echo json_encode(array('instancename' => html_entity_decode(format_string($module->name, true,  $stringoptions))));
                         break;
                 }
                 rebuild_course_cache($course->id);
index 8c9f85c..0022d5a 100644 (file)
@@ -175,13 +175,11 @@ if (!empty($moveto) and $data = data_submitted() and confirm_sesskey()) {   // S
 if (!empty($blocklist) and confirm_sesskey()) {
     $blockname = $DB->get_field('block', 'name', array('id' => $blocklist));
     $courses = array();
-    $courses = $DB->get_records_sql("
-            SELECT * FROM {course} WHERE id IN (
-                SELECT DISTINCT ctx.instanceid
-                FROM {context} ctx
-                JOIN {block_instances} bi ON bi.parentcontextid = ctx.id
-                WHERE ctx.contextlevel = " . CONTEXT_COURSE . " AND bi.blockname = ?)",
-            array($blockname));
+    list($select, $join) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx');
+    $sql = "SELECT c.* $select FROM {course} c
+            $join JOIN {block_instances} bi ON bi.parentcontextid = ctx.id
+            WHERE bi.blockname = ?";
+    $courses = $DB->get_records_sql($sql, array($blockname));
     $totalcount = count($courses);
     // Keep only chunk of array which you want to display
     if ($totalcount > $perpage) {
@@ -193,26 +191,24 @@ if (!empty($blocklist) and confirm_sesskey()) {
     }
 } elseif (!empty($modulelist) and confirm_sesskey()) { // get list of courses containing modules
     $modulename = $modulelist;
-    $sql =  "SELECT DISTINCT c.id FROM {".$modulelist."} module, {course} c"
-        ." WHERE module.course=c.id";
-
-    $courseids = $DB->get_records_sql($sql);
+    list($select, $join) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx');
+    $sql = "SELECT c.* $select FROM {course} c $join
+            WHERE c.id IN (SELECT DISTINCT cc.id FROM {".$modulelist."} module, {course} cc
+                           WHERE module.course = cc.id)";
+    $courselist = $DB->get_records_sql($sql);
     $courses = array();
-    if (!empty($courseids)) {
+    if (!empty($courselist)) {
         $firstcourse = $page*$perpage;
         $lastcourse = $page*$perpage + $perpage -1;
         $i = 0;
-        foreach ($courseids as $courseid) {
+        foreach ($courselist as $course) {
             if ($i >= $firstcourse && $i <= $lastcourse) {
-                $courses[$courseid->id] = $DB->get_record('course', array('id'=> $courseid->id));
+                $courses[$course->id] = $course;
             }
             $i++;
         }
-        $totalcount = count($courseids);
-    }
-    else {
-        $totalcount = 0;
     }
+    $totalcount = count($courselist);
 } else if (!empty($searchterm)) {
     // Donot do search for empty search request.
     $courses = get_courses_search($searchterms, "fullname ASC", $page, $perpage, $totalcount);
@@ -294,6 +290,7 @@ if ($courses) {
 
         foreach ($courses as $course) {
 
+            context_helper::preload_from_record($course);
             $coursecontext = context_course::instance($course->id);
 
             $linkcss = $course->visible ? "" : " class=\"dimmed\" ";
@@ -313,7 +310,7 @@ if ($courses) {
 
             echo "<tr>\n";
             echo "<td><a $linkcss href=\"view.php?id=$course->id\">"
-                . highlight($search, format_string($course->fullname)) . "</a></td>\n";
+                . highlight($search, $coursecontext->get_context_name(false)) . "</a></td>\n";
             echo "<td>".$displaylist[$course->category]."</td>\n";
             echo "<td>\n";
 
@@ -378,8 +375,11 @@ if ($courses) {
         echo "<input type=\"button\" onclick=\"checknone()\" value=\"$strdeselectall\" />\n";
         // Select box should only show categories in which user has min capability to move course.
         echo html_writer::label(get_string('moveselectedcoursesto'), 'movetoid', false, array('class' => 'accesshide'));
-        echo html_writer::select($usercatlist, 'moveto', '', array(''=>get_string('moveselectedcoursesto')), array('id'=>'movetoid'));
-        $PAGE->requires->js_init_call('M.util.init_select_autosubmit', array('movecourses', 'movetoid', false));
+        echo html_writer::select($usercatlist, 'moveto', '', array(''=>get_string('moveselectedcoursesto')), array('id'=>'movetoid', 'class' => 'autosubmit'));
+        $PAGE->requires->yui_module('moodle-core-formautosubmit',
+            'M.core.init_formautosubmit',
+            array(array('selectid' => 'movetoid', 'nothing' => false))
+        );
         echo "</td>\n</tr>\n";
         echo "</table>\n</form>";
 
@@ -432,4 +432,4 @@ function print_navigation_bar($totalcount, $page, $perpage, $encodedsearch, $mod
         echo "<a href=\"search.php?search=$encodedsearch".$modulelink."&amp;perpage=".$defaultperpage."\">".get_string("showperpage", "", $defaultperpage)."</a>";
         echo "</p></center>";
     }
-}
\ No newline at end of file
+}
index 12cba20..dc387fb 100644 (file)
@@ -35,7 +35,7 @@ require_once($CFG->dirroot.'/course/lib.php');
 
 $id         = required_param('id', PARAM_INT);
 $switchrole = optional_param('switchrole',-1, PARAM_INT);
-$returnurl  = optional_param('returnurl', false, PARAM_URL);
+$returnurl  = optional_param('returnurl', false, PARAM_LOCALURL);
 
 $PAGE->set_url('/course/switchrole.php', array('id'=>$id));
 
@@ -86,4 +86,4 @@ if ($returnurl === false) {
     $returnurl = new moodle_url('/course/view.php', array('id' => $course->id));
 }
 
-redirect($returnurl);
\ No newline at end of file
+redirect($returnurl);
index d7d031b..2486fba 100644 (file)
@@ -37,7 +37,7 @@ YUI.add('moodle-course-toolboxes', function(Y) {
         CONDITIONALHIDDEN : 'conditionalhidden',
         AVAILABILITYINFODIV : 'div.availabilityinfo',
         SHOWCLASS : 'editing_show',
-        ACCESSHIDECLASS : 'accesshide'
+        HIDECLASS : 'hide'
     };
 
     /**
@@ -99,7 +99,7 @@ YUI.add('moodle-course-toolboxes', function(Y) {
             var availabilityinfo = element.one(CSS.AVAILABILITYINFODIV);
 
             if (availabilityinfo) {
-                availabilityinfo.toggleClass(CSS.ACCESSHIDECLASS);
+                availabilityinfo.toggleClass(CSS.HIDECLASS);
             }
             return value;
         },
index 70ce970..d6a1887 100644 (file)
@@ -3,102 +3,7 @@ ENROLMENT MODULES
 
 (Yes, that's the correct English spelling  ;-) )
 
-enrol.class.php contains a simple 'factory' method that
-will instantiate your class when called. For an example
-of a complete class, take a look at the 'manual' class.
-
-Each plugin is in a subfolder here.
-
-Except for the configuration methods, most methods
-defined in the API are optional -- callers will use
-method_exists() to determine whether your plugin offers
-the functionality they are after.
-
-
-Mandatory methods
-=================
-
-  config_form()
-  process_config()
-
-
-Login-time methods
-==================
-
-  Before Moodle 1.7
-  -----------------
-
-      get_student_courses()
-      get_teacher_courses()
-
-  You probably will want to offer at least get_student_courses().
-
-  These methods are triggered when a user logs in successfully,
-  and they are expected to populate $USER->student and
-  $USER->teacher arrays and maintain (add/delete) entries from
-  user_students and user_teachers.
-
-  These methods are relevant for most plugins, and are the main
-  interest for plugins that work with a read-only backend such
-  as LDAP or a database.
-
-  Note that with the multi-enrol infrastructure two things have
-  changed. We now have an 'enrol' field in those tables, and
-  each plugin must maintain only its own enrolment records.
-  Conversely, the $USER->student and ->teacher arrays have the
-  enrolment type as value, like
-
-     $USER->student = array ( $courseid => $plugintype );
-
-
-  Moodle 1.7 and later
-  --------------------
-
-      setup_enrolments()
-
-  With the advent of roles, there could well not be students and
-  teachers any more, so enrolment plugins have to be more flexible
-  about how they map outside data to the internal roles.
-
-  This one method should do everything, calling functions from
-  lib/accesslib.php as necessary to set up relationships.
-
-
-Interactive enrolment methods
-=============================
-
-  print_entry()
-  check_entry()
-  check_group_entry()
-  get_access_icons()
-
-These methods are for enrolment plugins that allow for user
-driven enrolment. These methods are relevant for plugins
-that implement payment gateways (credit card, paypal),
-as well as "magic password" schemes.
-
-Only one interactive enrolment method can be active for
-a given course. The site default can be set from
-Admin->Enrolment, and then individual courses can be
-set to specific interactive enrolment methods.
-
-
-Cron
-====
-
-If your class offers a cron() method, it will be invoked by
-the standard Moodle cron every time it is called. Note that if the
-tasks are not lightweight you must control how frequently they
-execute, perhaps offering a config option.
-
-For really heavy cron processing, an alternative is to have
-a separate script to be called separately. Currently the LDAP
-and DB plugins have external scripts.
-
-
-Guilty Parties
---------------
-
-Martin Dougiamas and Shane Elliott, Moodle.com
-Martin Langhoff and Patrick Li, Catalyst IT
+All enrolment modules must extend base class enrol_plugin
+which is defined in lib/enrollib.php. You can find documentation
+of each method in the base class.
 
index 7f5437e..341a439 100644 (file)
@@ -20,6 +20,7 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
         AJAXURL = 'ajaxurl',
         MANUALENROLMENT = 'manualEnrolment',
         CSS = {
+            CLOSEBTN : 'close-button',
             COHORT : 'qce-cohort',
             COHORTS : 'qce-cohorts',
             COHORTBUTTON : 'qce-cohort-button',
@@ -52,13 +53,16 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
             this.publish('cohortsloaded');
             this.publish('defaultcohortroleloaded', {fireOnce:true});
 
+            var finishbutton = Y.Node.create('<div class="'+CSS.CLOSEBTN+'"></div>')
+                                   .append(Y.Node.create('<input type="button" value="'+M.str.enrol.finishenrollingusers+'" />'));
             var base = Y.Node.create('<div class="'+CSS.PANELCONTENT+'"></div>')
                 .append(Y.Node.create('<div class="'+CSS.PANELROLES+'"></div>'))
                 .append(Y.Node.create('<div class="'+CSS.PANELCOHORTS+'"></div>'))
                 .append(Y.Node.create('<div class="'+CSS.FOOTER+'"></div>')
-                    .append(Y.Node.create('<div class="'+CSS.SEARCH+'"><label>'+M.str.enrol_cohort.cohortsearch+':</label></div>')
+                    .append(Y.Node.create('<div class="'+CSS.SEARCH+'"><label for="enrolcohortsearch">'+M.str.enrol_cohort.cohortsearch+':</label></div>')
                         .append(Y.Node.create('<input type="text" id="enrolcohortsearch" value="" />'))
                     )
+                    .append(finishbutton)
                 )
                 .append(Y.Node.create('<div class="'+CSS.LIGHTBOX+' '+CSS.HIDDEN+'"></div>')
                     .append(Y.Node.create('<img alt="loading" class="'+CSS.LOADINGICON+'" />')
@@ -99,6 +103,7 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
             this.on('defaultcohortroleloaded', this.updateContent, this, panel);
             Y.on('key', this.hide, document.body, 'down:27', this);
             close.on('click', this.hide, this);
+            finishbutton.on('click', this.hide, this);
 
             Y.all('.enrol_cohort_plugin input').each(function(node){
                 if (node.getAttribute('type', 'submit')) {
@@ -117,6 +122,11 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
             this.getCohorts(e, false);
             this.getAssignableRoles();
             this.fire('show');
+
+            var rolesselect = Y.one('#id_enrol_cohort_assignable_roles');
+            if (rolesselect) {
+                rolesselect.focus();
+            }
         },
         updateContent : function(e, panel) {
             var content, i, roles, cohorts, count=0, supportmanual = this.get(MANUALENROLMENT), defaultrole;
@@ -154,13 +164,14 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
                     break;
                 case 'assignablerolesloaded':
                     roles = this.get(ASSIGNABLEROLES);
-                    content = Y.Node.create('<select></select>');
+                    content = Y.Node.create('<select id="id_enrol_cohort_assignable_roles"></select>');
                     for (i in roles) {
                         content.append(Y.Node.create('<option value="'+i+'">'+roles[i]+'</option>'));
                     }
-                    panel.get('contentBox').one('.'+CSS.PANELROLES).setContent(Y.Node.create('<div><label>'+M.str.role.assignroles+':</label></div>').append(content));
+                    panel.get('contentBox').one('.'+CSS.PANELROLES).setContent(Y.Node.create('<div><label for="id_enrol_cohort_assignable_roles">'+M.str.role.assignroles+':</label></div>').append(content));
 
                     this.getDefaultCohortRole();
+                    Y.one('#id_enrol_cohort_assignable_roles').focus();
                     break;
                 case 'defaultcohortroleloaded':
                     defaultrole = this.get(DEFAULTCOHORTROLE);
@@ -280,7 +291,8 @@ YUI.add('moodle-enrol_cohort-quickenrolment', function(Y) {
                                 new M.core.ajaxException(result);
                             } else {
                                 if (result.response && result.response.message) {
-                                    new M.core.alert(result.response);
+                                    var alertpanel = new M.core.alert(result.response);
+                                    Y.Node.one('#id_yuialertconfirm-' + alertpanel.COUNT).focus();
                                 }
                                 var enrolled = Y.Node.create('<div class="'+CSS.COHORTBUTTON+' alreadyenrolled">'+M.str.enrol.synced+'</div>');
                                 node.one('.'+CSS.COHORT+' #cohortid_'+cohort.get(COHORTID)).replace(enrolled);
index e923c2e..2b4e0fc 100644 (file)
@@ -867,7 +867,7 @@ class course_enrolment_manager {
                 $details['enrolments'][$ue->id] = array(
                     'text' => $ue->enrolmentinstancename,
                     'period' => $period,
-                    'dimmed' =>  ($periodoutside || $ue->status != ENROL_USER_ACTIVE),
+                    'dimmed' =>  ($periodoutside or $ue->status != ENROL_USER_ACTIVE or $ue->enrolmentinstance->status != ENROL_INSTANCE_ENABLED),
                     'actions' => $ue->enrolmentplugin->get_user_enrolment_actions($manager, $ue)
                 );
             }
index c1963aa..3236a75 100644 (file)
@@ -89,8 +89,8 @@ YUI.add('moodle-enrol_manual-quickenrolment', function(Y) {
                         .append(create('<h2>'+M.str.enrol.enrolusers+'</h2>')))
                     .append(create('<div class="'+CSS.CONTENT+'"></div>')
                         .append(create('<div class="'+CSS.SEARCHCONTROLS+'"></div>')
-                            .append(create('<div class="'+CSS.ENROLMENTOPTION+' '+CSS.ROLE+'">'+M.str.role.assignroles+'</div>')
-                                    .append(create('<select><option value="">'+M.str.enrol.none+'</option></select>'))
+                            .append(create('<div class="'+CSS.ENROLMENTOPTION+' '+CSS.ROLE+'"><label for="id_enrol_manual_assignable_roles">'+M.str.role.assignroles+'</label></div>')
+                                    .append(create('<select id="id_enrol_manual_assignable_roles"><option value="">'+M.str.enrol.none+'</option></select>'))
                             )
                             .append(create('<div class="'+CSS.SEARCHOPTIONS+'"></div>')
                                 .append(create('<div class="'+CSS.COLLAPSIBLEHEADING+'"><img alt="" />'+M.str.enrol.enrolmentoptions+'</div>'))
@@ -149,6 +149,11 @@ YUI.add('moodle-enrol_manual-quickenrolment', function(Y) {
             }
 
             this.get(UEP.BASE).one('.'+CSS.SEARCHOPTIONS+' .'+CSS.COLLAPSIBLEHEADING).one('img').setAttribute('src', M.util.image_url(collapsedimage, 'moodle'));
+            this.get(UEP.BASE).one('.'+CSS.SEARCHOPTIONS+' .'+CSS.COLLAPSIBLEHEADING).once('click', function() {
+                // We want to do this just once, the first time the controls are shown.
+                this.populateStartDates();
+                this.populateDuration();
+            }, this);
             this.get(UEP.BASE).one('.'+CSS.SEARCHOPTIONS+' .'+CSS.COLLAPSIBLEHEADING).on('click', function(){
                 this.get(UEP.BASE).one('.'+CSS.SEARCHOPTIONS+' .'+CSS.COLLAPSIBLEHEADING).toggleClass(CSS.ACTIVE);
                 this.get(UEP.BASE).one('.'+CSS.SEARCHOPTIONS+' .'+CSS.COLLAPSIBLEAREA).toggleClass(CSS.HIDDEN);
@@ -158,10 +163,7 @@ YUI.add('moodle-enrol_manual-quickenrolment', function(Y) {
                     this.get(UEP.BASE).one('.'+CSS.SEARCHOPTIONS+' .'+CSS.COLLAPSIBLEHEADING).one('img').setAttribute('src', M.util.image_url('t/expanded', 'moodle'));
                 }
             }, this);
-
             this.populateAssignableRoles();
-            this.populateStartDates();
-            this.populateDuration();
         },
         populateAssignableRoles : function() {
             this.on('assignablerolesloaded', function(){
@@ -178,6 +180,7 @@ YUI.add('moodle-enrol_manual-quickenrolment', function(Y) {
                     s.append(option);
                 }
                 s.set('selectedIndex', index);
+                Y.one('#id_enrol_manual_assignable_roles').focus();
             }, this);
             this.getAssignableRoles();
         },
@@ -200,9 +203,10 @@ YUI.add('moodle-enrol_manual-quickenrolment', function(Y) {
             var select = this.get(UEP.BASE).one('.'+CSS.ENROLMENTOPTION+'.'+CSS.DURATION+' select');
             var defaultvalue = this.get(UEP.DEFAULTDURATION);
             var index = 0, count = 0;
+            var durationdays = M.util.get_string('durationdays', 'enrol', '{a}');
             for (var i = 1; i <= 365; i++) {
                 count++;
-                var option = create('<option value="'+i+'">'+M.util.get_string('durationdays', 'enrol', i)+'</option>');
+                var option = create('<option value="'+i+'">'+durationdays.replace('{a}', i)+'</option>');
                 if (i == defaultvalue) {
                     index = count;
                 }
@@ -268,6 +272,10 @@ YUI.add('moodle-enrol_manual-quickenrolment', function(Y) {
             }
 
             this._escCloseEvent = Y.on('key', this.hide, document.body, 'down:27', this);
+            var rolesselect = Y.one('#id_enrol_manual_assignable_roles');
+            if (rolesselect) {
+                rolesselect.focus();
+            }
         },
         hide : function(e) {
             if (this._escCloseEvent) {
index ee95387..7d69a8c 100644 (file)
@@ -41,19 +41,22 @@ class enrol_meta_addinstance_form extends moodleform {
 
         // TODO: this has to be done via ajax or else it will fail very badly on large sites!
         $courses = array('' => get_string('choosedots'));
-        $rs = $DB->get_recordset('course', array(), 'sortorder ASC', 'id, fullname, shortname, visible');
+        list ($select, $join) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx');
+        $sql = "SELECT c.id, c.fullname, c.shortname, c.visible $select FROM {course} c $join ORDER BY c.sortorder ASC";
+        $rs = $DB->get_recordset_sql($sql);
         foreach ($rs as $c) {
             if ($c->id == SITEID or $c->id == $course->id or isset($existing[$c->id])) {
                 continue;
             }
-            $coursecontext = get_context_instance(CONTEXT_COURSE, $c->id);
+            context_helper::preload_from_record($c);
+            $coursecontext = context_course::instance($c->id);
             if (!$c->visible and !has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
                 continue;
             }
             if (!has_capability('enrol/meta:selectaslinked', $coursecontext)) {
                 continue;
             }
-            $courses[$c->id] = format_string($c->fullname). ' ['.format_string($c->shortname, true, array('context' => $coursecontext)).']';
+            $courses[$c->id] = $coursecontext->get_context_name(false);
         }
         $rs->close();
 
index 52b34bf..2665b2f 100644 (file)
@@ -47,6 +47,7 @@ $PAGE->set_pagelayout('admin');
 $manager = new course_enrolment_manager($PAGE, $course, $filter);
 $table = new course_enrolment_other_users_table($manager, $PAGE);
 $PAGE->set_url('/enrol/otherusers.php', $manager->get_url_params()+$table->get_url_params());
+navigation_node::override_active_url(new moodle_url('/enrol/otherusers.php', array('id' => $id)));
 
 $userdetails = array (
     'picture' => false,
index e5ec7dd..86951db 100644 (file)
@@ -90,13 +90,14 @@ if (! $plugin_instance = $DB->get_record("enrol", array("id"=>$data->instanceid,
 $plugin = enrol_get_plugin('paypal');
 
 /// Open a connection back to PayPal to validate the data
+$paypaladdr = empty($CFG->usepaypalsandbox) ? 'www.paypal.com' : 'www.sandbox.paypal.com';
 $c = new curl();
 $options = array(
     'returntransfer' => true,
-    'httpheader' => array('application/x-www-form-urlencoded'),
+    'httpheader' => array('application/x-www-form-urlencoded', "Host: $paypaladdr"),
     'timeout' => 30,
+    'CURLOPT_HTTP_VERSION' => CURL_HTTP_VERSION_1_1,
 );
-$paypaladdr = empty($CFG->usepaypalsandbox) ? 'www.paypal.com' : 'www.sandbox.paypal.com';
 $location = "https://$paypaladdr/cgi-bin/webscr";
 $result = $c->post($location, $req, $options);
 
@@ -171,7 +172,7 @@ if (strlen($result) > 0) {
 
         }
 
-        if ($data->business != $plugin->get_config('paypalbusiness')) {   // Check that the email is the one we want it to be
+        if (textlib::strtolower($data->business) !== textlib::strtolower($plugin->get_config('paypalbusiness'))) {   // Check that the email is the one we want it to be
             message_paypal_error_to_admin("Business email is {$data->business} (not ".
                     $plugin->get_config('paypalbusiness').")", $data);
             die;
index d9f9d49..f23e91b 100644 (file)
@@ -207,4 +207,23 @@ class enrol_paypal_plugin extends enrol_plugin {
         return $OUTPUT->box(ob_get_clean());
     }
 
+    /**
+     * Gets an array of the user enrolment actions
+     *
+     * @param course_enrolment_manager $manager
+     * @param stdClass $ue A user enrolment object
+     * @return array An array of user_enrolment_actions
+     */
+    public function get_user_enrolment_actions(course_enrolment_manager $manager, $ue) {
+        $actions = array();
+        $context = $manager->get_context();
+        $instance = $ue->enrolmentinstance;
+        $params = $manager->get_moodlepage()->url->params();
+        $params['ue'] = $ue->id;
+        if ($this->allow_unenrol($instance) && has_capability("enrol/paypal:unenrol", $context)) {
+            $url = new moodle_url('/enrol/unenroluser.php', $params);
+            $actions[] = new user_enrolment_action(new pix_icon('t/delete', ''), get_string('unenrol', 'enrol'), $url, array('class'=>'unenrollink', 'rel'=>$ue->id));
+        }
+        return $actions;
+    }
 }
index 66cddda..91fd8d2 100644 (file)
@@ -1,12 +1,15 @@
 .moodle-dialogue-base .hidden,
 .moodle-dialogue-base .moodle-dialogue-hidden {display:none;}
-.moodle-dialogue-base .moodle-dialogue-lightbox {background-color:#AAA;position:absolute;top:0;left:0;width:100%;height:100%;}
+.moodle-dialogue-base .moodle-dialogue-lightbox {background-color:#AAA;}
 .moodle-dialogue-base .moodle-dialogue {background-color:#666;border:0 solid #666;border-right-width:3px;border-bottom-width:3px;}
 .moodle-dialogue-base .moodle-dialogue-wrap {background-color:#FFF;margin-top:-3px;margin-left:-3px;border:1px solid #555;height:auto;}
-.moodle-dialogue-base .moodle-dialogue-hd {font-size:110%;color:inherit;font-weight:bold;text-align:left;padding:5px 6px;margin:0;border-bottom:1px solid #ccc;background-color:#f6f6f6;}
-.moodle-dialogue-base .closebutton {background-image:url(sprite.png);width:25px;height:15px;background-repeat:no-repeat;float:right;vertical-align:middle;display:inline-block;cursor:pointer;}
+.moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-hd {font-size:110%;color:inherit;font-weight:bold;text-align:left;padding:5px 6px;margin:0;border-bottom:1px solid #ccc;background:#f6f6f6;}
+.moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-hd h1{font-size:100%;font-weight:bold;margin:0;padding:0;display:inline;}
+.moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-hd .yui3-widget-buttons {padding: 5px;}
+.moodle-dialogue-base .closebutton {background-image:url(sprite.png);width:25px;height:15px;background-repeat:no-repeat;float:right;vertical-align:middle;display:inline-block;cursor:pointer;padding:0px;border-style:none;}
 .moodle-dialogue-base .moodle-dialogue-bd {padding:5px; overflow: auto;}
-.moodle-dialogue-base .moodle-dialogue-ft {}
+.moodle-dialogue-base .moodle-dialogue-wrap .moodle-dialogue-content {background:#FFF;padding:0px;}
+.moodle-dialogue-base .moodle-dialogue .moodle-dialogue-content .moodle-dialogue-ft {padding:0px;}
 
 .moodle-dialogue-confirm .confirmation-dialogue {text-align:center;}
 .moodle-dialogue-confirm .confirmation-message {margin:0.5em 1em;}
index 2ed9af0..b2b4d45 100644 (file)
@@ -8,8 +8,6 @@ var DIALOGUE_NAME = 'Moodle dialogue',
     ALERT_NAME = 'Moodle alert',
     C = Y.Node.create,
     BASE = 'notificationBase',
-    LIGHTBOX = 'lightbox',
-    NODELIGHTBOX = 'nodeLightbox',
     COUNT = 0,
     CONFIRMYES = 'yesLabel',
     CONFIRMNO = 'noLabel',
@@ -31,7 +29,6 @@ var DIALOGUE = function(config) {
     var id = 'moodle-dialogue-'+COUNT;
     config.notificationBase =
         C('<div class="'+CSS.BASE+'">')
-            .append(C('<div class="'+CSS.LIGHTBOX+' '+CSS.HIDDEN+'"></div>'))
             .append(C('<div id="'+id+'" class="'+CSS.WRAP+'"></div>')
                 .append(C('<div class="'+CSS.HEADER+' yui3-widget-hd"></div>'))
                 .append(C('<div class="'+CSS.BODY+' yui3-widget-bd"></div>'))
@@ -42,41 +39,50 @@ var DIALOGUE = function(config) {
     config.visible =    config.visible || false;
     config.center =     config.centered || true;
     config.centered =   false;
+
+    // lightbox param to keep the stable versions API.
+    if (config.lightbox !== false) {
+        config.modal = true;
+    }
+    delete config.lightbox;
+
+    // closeButton param to keep the stable versions API.
+    if (config.closeButton === false) {
+        config.buttons = null;
+    } else {
+        config.buttons = [
+            {
+                section: Y.WidgetStdMod.HEADER,
+                classNames: 'closebutton',
+                action: function (e) {
+                    this.hide();
+                }
+            }
+        ];
+    }
     DIALOGUE.superclass.constructor.apply(this, [config]);
+
+    if (config.closeButton !== false) {
+        // The buttons constructor does not allow custom attributes
+        this.get('buttons').header[0].setAttribute('title', this.get('closeButtonTitle'));
+    }
 };
-Y.extend(DIALOGUE, Y.Overlay, {
+Y.extend(DIALOGUE, Y.Panel, {
     initializer : function(config) {
-        this.set(NODELIGHTBOX, this.get(BASE).one('.'+CSS.LIGHTBOX).setStyle('opacity', 0.5));
         this.after('visibleChange', this.visibilityChanged, this);
-        this.after('headerContentChange', function(e){
-            var h = (this.get('closeButton'))?this.get(BASE).one('.'+CSS.HEADER):false;
-            if (h && !h.one('.closebutton')) {
-                var c = C('<div class="closebutton"></div>');
-                c.on('click', this.hide, this);
-                h.append(c);
-            }
-        }, this);
         this.render();
         this.show();
     },
     visibilityChanged : function(e) {
         switch (e.attrName) {
             case 'visible':
-                if (this.get(LIGHTBOX)) {
-                    var l = this.get(NODELIGHTBOX);
-                    if (!e.prevVal && e.newVal) {
-                        l.setStyle('height',l.get('docHeight')+'px').removeClass(CSS.HIDDEN);
-                    } else if (e.prevVal && !e.newVal) {
-                        l.addClass(CSS.HIDDEN);
-                    }
-                }
+                this.get('maskNode').addClass(CSS.LIGHTBOX);
                 if (this.get('center') && !e.prevVal && e.newVal) {
                     this.centerDialogue();
                 }
                 if (this.get('draggable')) {
                     var titlebar = '#' + this.get('id') + ' .' + CSS.HEADER;
                     this.plug(Y.Plugin.Drag, {handles : [titlebar]});
-                    this.dd.addInvalid('div.closebutton');
                     Y.one(titlebar).setStyle('cursor', 'move');
                 }
                 break;
@@ -101,9 +107,6 @@ Y.extend(DIALOGUE, Y.Overlay, {
     ATTRS : {
         notificationBase : {
 
-        },
-        nodeLightbox : {
-            value : null
         },
         lightbox : {
             validator : Y.Lang.isBoolean,
@@ -113,6 +116,10 @@ Y.extend(DIALOGUE, Y.Overlay, {
             validator : Y.Lang.isBoolean,
             value : true
         },
+        closeButtonTitle : {
+            validator : Y.Lang.isString,
+            value : 'Close'
+        },
         center : {
             validator : Y.Lang.isBoolean,
             value : true
@@ -132,14 +139,14 @@ Y.extend(ALERT, DIALOGUE, {
     _enterKeypress : null,
     initializer : function(config) {
         this.publish('complete');
-        var yes = C('<input type="button" value="'+this.get(CONFIRMYES)+'" />'),
+        var yes = C('<input type="button" id="id_yuialertconfirm-' + this.COUNT + '" value="'+this.get(CONFIRMYES)+'" />'),
             content = C('<div class="confirmation-dialogue"></div>')
                     .append(C('<div class="confirmation-message">'+this.get('message')+'</div>'))
                     .append(C('<div class="confirmation-buttons"></div>')
                             .append(yes));
         this.get(BASE).addClass('moodle-dialogue-confirm');
         this.setStdModContent(Y.WidgetStdMod.BODY, content, Y.WidgetStdMod.REPLACE);
-        this.setStdModContent(Y.WidgetStdMod.HEADER, this.get(TITLE), Y.WidgetStdMod.REPLACE);
+        this.setStdModContent(Y.WidgetStdMod.HEADER, '<h1>' + this.get(TITLE) + '</h1>', Y.WidgetStdMod.REPLACE);
         this.after('destroyedChange', function(){this.get(BASE).remove();}, this);
         this._enterKeypress = Y.on('key', this.submit, window, 'down:13', this);
         yes.on('click', this.submit, this);
@@ -185,8 +192,8 @@ Y.extend(CONFIRM, DIALOGUE, {
         this.publish('complete');
         this.publish('complete-yes');
         this.publish('complete-no');
-        var yes = C('<input type="button" value="'+this.get(CONFIRMYES)+'" />'),
-            no = C('<input type="button" value="'+this.get(CONFIRMNO)+'" />'),
+        var yes = C('<input type="button" id="id_yuiconfirmyes-' + this.COUNT + '" value="'+this.get(CONFIRMYES)+'" />'),
+            no = C('<input type="button" id="id_yuiconfirmno-' + this.COUNT + '" value="'+this.get(CONFIRMNO)+'" />'),
             content = C('<div class="confirmation-dialogue"></div>')
                         .append(C('<div class="confirmation-message">'+this.get(QUESTION)+'</div>'))
                         .append(C('<div class="confirmation-buttons"></div>')
@@ -194,7 +201,7 @@ Y.extend(CONFIRM, DIALOGUE, {
                             .append(no));
         this.get(BASE).addClass('moodle-dialogue-confirm');
         this.setStdModContent(Y.WidgetStdMod.BODY, content, Y.WidgetStdMod.REPLACE);
-        this.setStdModContent(Y.WidgetStdMod.HEADER, this.get(TITLE), Y.WidgetStdMod.REPLACE);
+        this.setStdModContent(Y.WidgetStdMod.HEADER, '<h1>' + this.get(TITLE) + '</h1>', Y.WidgetStdMod.REPLACE);
         this.after('destroyedChange', function(){this.get(BASE).remove();}, this);
         this._enterKeypress = Y.on('key', this.submit, window, 'down:13', this, true);
         this._escKeypress = Y.on('key', this.submit, window, 'down:27', this, false);
@@ -247,7 +254,7 @@ Y.extend(EXCEPTION, DIALOGUE, {
     _keypress : null,
     initializer : function(config) {
         this.get(BASE).addClass('moodle-dialogue-exception');
-        this.setStdModContent(Y.WidgetStdMod.HEADER, config.name, Y.WidgetStdMod.REPLACE);
+        this.setStdModContent(Y.WidgetStdMod.HEADER, '<h1>' + config.name + '</h1>', Y.WidgetStdMod.REPLACE);
         var content = C('<div class="moodle-exception"></div>')
                     .append(C('<div class="moodle-exception-message">'+this.get('message')+'</div>'))
                     .append(C('<div class="moodle-exception-param hidden param-filename"><label>File:</label> '+this.get('fileName')+'</div>'))
@@ -318,7 +325,7 @@ Y.extend(AJAXEXCEPTION, DIALOGUE, {
     _keypress : null,
     initializer : function(config) {
         this.get(BASE).addClass('moodle-dialogue-exception');
-        this.setStdModContent(Y.WidgetStdMod.HEADER, config.name, Y.WidgetStdMod.REPLACE);
+        this.setStdModContent(Y.WidgetStdMod.HEADER, '<h1>' + config.name + '</h1>', Y.WidgetStdMod.REPLACE);
         var content = C('<div class="moodle-ajaxexception"></div>')
                     .append(C('<div class="moodle-exception-message">'+this.get('error')+'</div>'))
                     .append(C('<div class="moodle-exception-param hidden param-debuginfo"><label>URL:</label> '+this.get('reproductionlink')+'</div>'))
@@ -382,4 +389,4 @@ M.core.confirm = CONFIRM;
 M.core.exception = EXCEPTION;
 M.core.ajaxException = AJAXEXCEPTION;
 
-}, '@VERSION@', {requires:['base','node','overlay','event-key', 'moodle-enrol-notification-skin', 'dd-plugin']});
+}, '@VERSION@', {requires:['base','node','panel','event-key', 'moodle-enrol-notification-skin', 'dd-plugin']});
index 3c5d013..4c6dc8b 100644 (file)
@@ -188,7 +188,7 @@ class core_files_renderer extends plugin_renderer_base {
         $strdroptoupload = get_string('droptoupload', 'moodle');
         $icon_progress = $OUTPUT->pix_icon('i/loading_small', $strloading).'';
         $restrictions = $this->fm_print_restrictions($fm);
-        $strdndenabled = get_string('dndenabled_insentence', 'moodle').$OUTPUT->help_icon('dndenabled');
+        $strdndnotsupported = get_string('dndnotsupported_insentence', 'moodle').$OUTPUT->help_icon('dndnotsupported');
         $strdndenabledinbox = get_string('dndenabled_inbox', 'moodle');
         $loading = get_string('loading', 'repository');
 
@@ -196,7 +196,7 @@ class core_files_renderer extends plugin_renderer_base {
 <div id="filemanager-'.$client_id.'" class="filemanager fm-loading">
     <div class="fp-restrictions">
         '.$restrictions.'
-        <span class="dndupload-message"> - '.$strdndenabled.' </span>
+        <span class="dnduploadnotsupported-message"> - '.$strdndnotsupported.' </span>
     </div>
     <div class="fp-navbar">
         <div class="filemanager-toolbar">
index 484c42e..743159a 100644 (file)
@@ -70,7 +70,8 @@ YUI.add('moodle-filter_glossary-autolinker', function(Y) {
 
                     for (key in data.entries) {
                         definition = data.entries[key].definition + data.entries[key].attachments
-                        new M.core.alert({title:data.entries[key].concept, message:definition, lightbox:false});
+                        var alertpanel = new M.core.alert({title:data.entries[key].concept, message:definition, lightbox:false});
+                        Y.Node.one('#id_yuialertconfirm-' + alertpanel.COUNT).focus();
                     }
 
                     return true;
index fe2c682..2cd24c5 100644 (file)
@@ -121,7 +121,7 @@ class edit_outcome_form extends moodleform {
             if (empty($courseid)) {
                 $mform->hardFreeze('standard');
 
-            } else if (empty($outcome->courseid) and !has_capability('moodle/grade:manage', get_context_instance(CONTEXT_SYSTEM))) {
+            } else if (!has_capability('moodle/grade:manage', get_context_instance(CONTEXT_SYSTEM))) {
                 $mform->hardFreeze('standard');
 
             } else if ($coursecount and empty($outcome->courseid)) {
index 2bc2dc7..df0638c 100644 (file)
@@ -273,12 +273,6 @@ class grade_edit_tree {
                 $root = true;
             }
 
-            $row_count_offset = 0;
-
-            if (empty($category_total_item) && !$this->moving) {
-                $row_count_offset = -1;
-            }
-
             $levelclass = "level$level";
 
             $courseclass = '';
@@ -297,7 +291,7 @@ class grade_edit_tree {
             $headercell->scope = 'row';
             $headercell->attributes['title'] = $object->stripped_name;
             $headercell->attributes['class'] = 'cell rowspan ' . $levelclass;
-            $headercell->rowspan = $row_count+1+$row_count_offset;
+            $headercell->rowspan = $row_count + 1;
             $row->cells[] = $headercell;
 
             foreach ($this->columns as $column) {
index e366131..48ae321 100644 (file)
@@ -41,7 +41,7 @@ class grade_export_ods extends grade_export {
     /// Sending HTTP headers
         $workbook->send($downloadfilename);
     /// Adding the worksheet
-        $myxls =& $workbook->add_worksheet($strgrades);
+        $myxls = $workbook->add_worksheet($strgrades);
 
     /// Print names of all the fields
         $myxls->write_string(0,0,get_string("firstname"));
index a89c910..8b04bf4 100644 (file)
@@ -40,7 +40,7 @@ class grade_export_xls extends grade_export {
     /// Sending HTTP headers
         $workbook->send($downloadfilename);
     /// Adding the worksheet
-        $myxls =& $workbook->add_worksheet($strgrades);
+        $myxls = $workbook->add_worksheet($strgrades);
 
     /// Print names of all the fields
         $myxls->write_string(0,0,get_string("firstname"));
index c562c82..2babb4e 100644 (file)
@@ -214,7 +214,7 @@ border-color:#cecece;
 }
 
 .path-grade-report-grader th {
-padding:2px 10px 0;
+padding:1px 10px;
 }
 
 .path-grade-report-grader span.inclusion-links {
@@ -377,6 +377,8 @@ float:left;
 clear:none;
 padding-top:20px;
 }
+.path-grade-report-grader.dir-rtl .left_scroller {float:right;}
+
 
 .path-grade-report-grader .right_scroller {
 width:auto;
index 2475550..6e6db0b 100644 (file)
@@ -351,17 +351,21 @@ abstract class grade_report {
         global $CFG, $DB;
         static $hiding_affected = null;//array of items in this course affected by hiding
 
-        //if we're dealing with multiple users we need to know when we've moved on to a new user
+        // If we're dealing with multiple users we need to know when we've moved on to a new user.
         static $previous_userid = null;
 
+        // If we're dealing with multiple courses we need to know when we've moved on to a new course.
+        static $previous_courseid = null;
+
         if( $this->showtotalsifcontainhidden==GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN ) {
             return $finalgrade;
         }
 
-        //if we've moved on to another user don't return the previous user's affected grades
-        if ($previous_userid!=$this->user->id) {
+        // If we've moved on to another course or user, reload the grades.
+        if ($previous_userid != $this->user->id || $previous_courseid != $courseid) {
             $hiding_affected = null;
             $previous_userid = $this->user->id;
+            $previous_courseid = $courseid;
         }
 
         if( !$hiding_affected ) {
diff --git a/grade/tests/reportlib_test.php b/grade/tests/reportlib_test.php
new file mode 100644 (file)
index 0000000..48b0eaa
--- /dev/null
@@ -0,0 +1,197 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Unit tests for grade/report/lib.php.
+ *
+ * @pacakge  core_grade
+ * @category phpunit
+ * @author   Andrew Davis
+ * @license  http://www.gnu.org/copyleft/gpl.html GNU Public License
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->dirroot.'/grade/lib.php');
+require_once($CFG->dirroot.'/grade/report/lib.php');
+
+/**
+ * A test class used to test grade_report, the abstract grade report parent class
+ */
+class grade_report_test extends grade_report {
+    public function __construct($courseid, $gpr, $context, $user) {
+        parent::__construct($courseid, $gpr, $context);
+        $this->user = $user;
+    }
+
+    /**
+     * A wrapper around blank_hidden_total() to allow test code to call it directly
+     */
+    public function blank_hidden_total($courseid, $courseitem, $finalgrade) {
+        return parent::blank_hidden_total($courseid, $courseitem, $finalgrade);
+    }
+
+    /**
+     * Implementation of the abstract method process_data()
+     */
+    public function process_data($data) {
+    }
+
+    /**
+     * Implementation of the abstract method process_action()
+     */
+    public function process_action($target, $action) {
+    }
+}
+
+/**
+ * Tests grade_report, the parent class for all grade reports.
+ */
+class gradereportlib_testcase extends advanced_testcase {
+
+    /**
+     * Tests grade_report::blank_hidden_total()
+     */
+    public function test_blank_hidden_total() {
+        global $DB;
+
+        $this->resetAfterTest(true);
+
+        $student = $this->getDataGenerator()->create_user();
+        $this->setUser($student);
+
+        // Create a course and two activities.
+        // One activity will be hidden.
+        $course = $this->getDataGenerator()->create_course();
+        $coursegradeitem = grade_item::fetch_course_item($course->id);
+        $coursecontext = context_course::instance($course->id);
+
+        $data = $this->getDataGenerator()->create_module('data', array('assessed' => 1, 'scale' => 100, 'course' => $course->id));
+        $datacm = get_coursemodule_from_id('data', $data->cmid);
+
+        $forum = $this->getDataGenerator()->create_module('forum', array('assessed' => 1, 'scale' => 100, 'course' => $course->id));
+        $forumcm = get_coursemodule_from_id('forum', $forum->cmid);
+
+        // Insert student grades for the two activities.
+        $gi = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'data', 'iteminstance' => $data->id, 'courseid' => $course->id));
+        $datagrade = 50;
+        $grade_grade = new grade_grade();
+        $grade_grade->itemid = $gi->id;
+        $grade_grade->userid = $student->id;
+        $grade_grade->rawgrade = $datagrade;
+        $grade_grade->finalgrade = $datagrade;
+        $grade_grade->rawgrademax = 100;
+        $grade_grade->rawgrademin = 0;
+        $grade_grade->timecreated = time();
+        $grade_grade->timemodified = time();
+        $grade_grade->insert();
+
+        $gi = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'forum', 'iteminstance' => $forum->id, 'courseid' => $course->id));
+        $forumgrade = 70;
+        $grade_grade = new grade_grade();
+        $grade_grade->itemid = $gi->id;
+        $grade_grade->userid = $student->id;
+        $grade_grade->rawgrade = $forumgrade;
+        $grade_grade->finalgrade = $forumgrade;
+        $grade_grade->rawgrademax = 100;
+        $grade_grade->rawgrademin = 0;
+        $grade_grade->timecreated = time();
+        $grade_grade->timemodified = time();
+        $grade_grade->insert();
+
+        // Hide the database activity.
+        set_coursemodule_visible($datacm->id, 0);
+
+        $gpr = new grade_plugin_return(array('type' => 'report', 'courseid' => $course->id));
+        $report = new grade_report_test($course->id, $gpr, $coursecontext, $student);
+
+        // Should return the supplied student total grade regardless of hiding.
+        $report->showtotalsifcontainhidden = GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN;
+        $this->assertEquals($datagrade + $forumgrade, $report->blank_hidden_total($course->id, $coursegradeitem, $datagrade + $forumgrade));
+
+        // Should blank the student total as course grade depends on a hidden item.
+        $report->showtotalsifcontainhidden = GRADE_REPORT_HIDE_TOTAL_IF_CONTAINS_HIDDEN;
+        $this->assertEquals(null, $report->blank_hidden_total($course->id, $coursegradeitem, $datagrade + $forumgrade));
+
+        // Should return the course total minus the hidden database activity grade.
+        $report->showtotalsifcontainhidden = GRADE_REPORT_SHOW_TOTAL_IF_CONTAINS_HIDDEN;
+        $this->assertEquals($forumgrade, $report->blank_hidden_total($course->id, $coursegradeitem, $datagrade + $forumgrade));
+
+        // Note: we cannot simply hide modules and call $report->blank_hidden_total() again.
+        // It stores grades in a static variable so $report->blank_hidden_total() will return incorrect totals
+        // In practice this isn't a problem. Grade visibility isn't altered mid-request outside of the unit tests.
+
+        // Add a second course to test:
+        // 1) How a course with no visible activities behaves.
+        // 2) That $report->blank_hidden_total() correctly moves on to the new course.
+        $course = $this->getDataGenerator()->create_course();
+        $coursegradeitem = grade_item::fetch_course_item($course->id);
+        $coursecontext = context_course::instance($course->id);
+
+        $data = $this->getDataGenerator()->create_module('data', array('assessed' => 1, 'scale' => 100, 'course' => $course->id));
+        $datacm = get_coursemodule_from_id('data', $data->cmid);
+
+        $forum = $this->getDataGenerator()->create_module('forum', array('assessed' => 1, 'scale' => 100, 'course' => $course->id));
+        $forumcm = get_coursemodule_from_id('forum', $forum->cmid);
+
+        $gi = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'data', 'iteminstance' => $data->id, 'courseid' => $course->id));
+        $datagrade = 50;
+        $grade_grade = new grade_grade();
+        $grade_grade->itemid = $gi->id;
+        $grade_grade->userid = $student->id;
+        $grade_grade->rawgrade = $datagrade;
+        $grade_grade->finalgrade = $datagrade;
+        $grade_grade->rawgrademax = 100;
+        $grade_grade->rawgrademin = 0;
+        $grade_grade->timecreated = time();
+        $grade_grade->timemodified = time();
+        $grade_grade->insert();
+
+        $gi = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'forum', 'iteminstance' => $forum->id, 'courseid' => $course->id));
+        $forumgrade = 70;
+        $grade_grade = new grade_grade();
+        $grade_grade->itemid = $gi->id;
+        $grade_grade->userid = $student->id;
+        $grade_grade->rawgrade = $forumgrade;
+        $grade_grade->finalgrade = $forumgrade;
+        $grade_grade->rawgrademax = 100;
+        $grade_grade->rawgrademin = 0;
+        $grade_grade->timecreated = time();
+        $grade_grade->timemodified = time();
+        $grade_grade->insert();
+
+        // Hide both activities.
+        set_coursemodule_visible($datacm->id, 0);
+        set_coursemodule_visible($forumcm->id, 0);
+
+        $gpr = new grade_plugin_return(array('type' => 'report', 'courseid' => $course->id));
+        $report = new grade_report_test($course->id, $gpr, $coursecontext, $student);
+
+        // Should return the supplied student total grade regardless of hiding.
+        $report->showtotalsifcontainhidden = GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN;
+        $this->assertEquals($datagrade + $forumgrade, $report->blank_hidden_total($course->id, $coursegradeitem, $datagrade + $forumgrade));
+
+        // Should blank the student total as course grade depends on a hidden item.
+        $report->showtotalsifcontainhidden = GRADE_REPORT_HIDE_TOTAL_IF_CONTAINS_HIDDEN;
+        $this->assertEquals(null, $report->blank_hidden_total($course->id, $coursegradeitem, $datagrade + $forumgrade));
+
+        // Should return the course total minus the hidden activity grades.
+        // They are both hidden so should return null.
+        $report->showtotalsifcontainhidden = GRADE_REPORT_SHOW_TOTAL_IF_CONTAINS_HIDDEN;
+        $this->assertEquals(null, $report->blank_hidden_total($course->id, $coursegradeitem, $datagrade + $forumgrade));
+    }
+}
index 39db087..c12d5a5 100644 (file)
@@ -576,7 +576,7 @@ class core_group_external extends external_api {
                             'courseid' => new external_value(PARAM_INT, 'id of course'),
                             'name' => new external_value(PARAM_TEXT, 'multilang compatible name, course unique'),
                             'description' => new external_value(PARAM_RAW, 'grouping description text'),
-                            'descriptionformat' => new external_format_value('descripiton', VALUE_DEFAULT)
+                            'descriptionformat' => new external_format_value('description', VALUE_DEFAULT)
                         )
                     ), 'List of grouping object. A grouping has a courseid, a name and a description.'
                 )
index 4771cc5..dc44dd2 100644 (file)
@@ -30,5 +30,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
+$string['parentlanguage'] = '';
 $string['thisdirection'] = 'ltr';
 $string['thislanguage'] = '正體中文';
index a685f0e..d662beb 100644 (file)
@@ -39,6 +39,8 @@ $string['defaultweight'] = 'Default weight';
 $string['defaultweight_help'] = 'The default weight allows you to choose roughly where you want the block to appear in the chosen region, either at the top or the bottom. The final location is calculated from all the blocks in that region (for example, only one block can actually be at the top). This value can be overridden on specific pages if required.';
 $string['deletecheck'] = 'Delete {$a} block?';
 $string['deleteblockcheck'] = 'Are you sure that you want to delete this block titled {$a}?';
+$string['hidedockpanel'] = 'Hide the dock panel';
+$string['hidepanel'] = 'Hide panel';
 $string['moveblockhere'] = 'Move block here';
 $string['movingthisblockcancel'] = 'Moving this block ({$a})';
 $string['onthispage'] = 'On this page';
index 7ad032c..06fe926 100644 (file)
@@ -329,6 +329,7 @@ $string['invalidurl'] = 'Invalid URL';
 $string['invaliduser'] = 'Invalid user';
 $string['invaliduserid'] = 'Invalid user id';
 $string['invaliduserfield'] = 'Invalid user field: {$a}';
+$string['invalidusername'] = 'The given username contains invalid characters';
 $string['invalidxmlfile'] = '"{$a}" is not a valid XML file';
 $string['iplookupfailed'] = 'Cannot find geo information about this IP address {$a}';
 $string['iplookupprivate'] = 'Cannot display lookup of private IP address';
@@ -432,6 +433,7 @@ $string['refoundtoorigi'] = 'Refunded to original amount: {$a}';
 $string['remotedownloaderror'] = 'Download of component to your server failed, please verify proxy settings, PHP cURL extension is highly recommended.<br /><br />You must download the <a href="{$a->url}">{$a->url}</a> file manually, copy it to "{$a->dest}" in your server and unzip it there.';
 $string['remotedownloadnotallowed'] = 'Download of components to your server isn\'t allowed (allow_url_fopen is disabled).<br /><br />You must download the <a href="{$a->url}">{$a->url}</a> file manually, copy it to "{$a->dest}" in your server and unzip it there.';
 $string['reportnotavailable'] = 'This type of report is only available for the site course';
+$string['requirecorrectaccess'] = 'Invalid url or port.';
 $string['requireloginerror'] = 'Course or activity not accessible.';
 $string['restorechecksumfailed'] = 'Some problem happened with the restore information stored in your session. Please check your PHP memory/DB package size limits. Restore stopped.';
 $string['restore_path_element_missingmethod'] = 'Restore method {$a} is missing. It must be defined by a developer.';
index c594038..b556ece 100644 (file)
@@ -467,6 +467,9 @@ $string['dndenabled'] = 'Drag and drop available';
 $string['dndenabled_help'] = 'You can drag one or more files from your desktop and drop them onto the box below to upload them.<br />Note: this may not work with other web browsers';
 $string['dndenabled_insentence'] = 'drag and drop available';
 $string['dndenabled_inbox'] = 'You can drag and drop files here to add them.';
+$string['dndnotsupported'] = 'Drag and drop upload not supported';
+$string['dndnotsupported_help'] = 'Your browser does not support drag and drop upload.<br />This feature is available in all recent versions of Chrome, Firefox and Safari, as well as Internet Explorer v10 and above.';
+$string['dndnotsupported_insentence'] = 'drag and drop not supported';
 $string['dnduploadwithoutcontent'] = 'This upload does not have any content';
 $string['dndworkingfiletextlink'] = 'Drag and drop files, text or links onto course sections to upload them';
 $string['dndworkingfilelink'] = 'Drag and drop files or links onto course sections to upload them';
index dfa1aeb..56d1a07 100644 (file)
@@ -306,6 +306,8 @@ $string['cannotloadquestion'] = 'Could not load question';
 $string['cannotpreview'] = 'You can\'t preview these questions!';
 $string['category'] = 'Category';
 $string['changeoptions'] = 'Change options';
+$string['attemptoptions'] = 'Attempt options';
+$string['displayoptions'] = 'Display options';
 $string['check'] = 'Check';
 $string['clearwrongparts'] = 'Clear incorrect responses';
 $string['closepreview'] = 'Close preview';
@@ -384,6 +386,7 @@ $string['requiresgrading'] = 'Requires grading';
 $string['responsehistory'] = 'Response history';
 $string['restart'] = 'Start again';
 $string['restartwiththeseoptions'] = 'Start again with these options';
+$string['updatedisplayoptions'] = 'Update display options';
 $string['rightanswer'] = 'Right answer';
 $string['rightanswer_help'] = 'an automatically generated summary of the correct response. This can be limited, so you may wish to consider explaining the correct solution in the general feedback for the question, and turning this option off.';
 $string['saved'] = 'Saved: {$a}';
index 8682378..5a4a965 100644 (file)
@@ -100,6 +100,7 @@ $string['error'] = 'An unknown error occurred!';
 $string['errornotyourfile'] = 'You cannot pick file which is not added by your';
 $string['erroruniquename'] = 'Repository instance name should be unique';
 $string['errorpostmaxsize'] = 'The uploaded file may exceed max_post_size directive in php.ini.';
+$string['errorwhilecommunicatingwith'] = 'Error while communicating with the repository \'{$a}\'.';
 $string['errorwhiledownload'] = 'An error occured while downloading the file: {$a}';
 $string['existingrepository'] = 'This repository already exists';
 $string['federatedsearch'] = 'Federated search';
index 50a9ee4..48f24df 100644 (file)
@@ -2937,8 +2937,13 @@ function get_user_roles_in_course($userid, $courseid) {
 function user_can_assign(context $context, $targetroleid) {
     global $DB;
 
-    // first check if user has override capability
-    // if not return false;
+    // First check to see if the user is a site administrator.
+    if (is_siteadmin()) {
+        return true;
+    }
+
+    // Check if user has override capability.
+    // If not return false.
     if (!has_capability('moodle/role:assign', $context)) {
         return false;
     }
index 2812fef..d638e50 100644 (file)
@@ -123,6 +123,9 @@ define('INSECURE_DATAROOT_ERROR', 2);
 function uninstall_plugin($type, $name) {
     global $CFG, $DB, $OUTPUT;
 
+    // This may take a long time.
+    @set_time_limit(0);
+
     // recursively uninstall all module subplugins first
     if ($type === 'mod') {
         if (file_exists("$CFG->dirroot/mod/$name/db/subplugins.php")) {
index 041190a..470106d 100644 (file)
@@ -30,6 +30,7 @@ require_once(dirname(__FILE__) . '/../../config.php');
 $courseid = required_param('courseid', PARAM_INT);
 $pagelayout = required_param('pagelayout', PARAM_ALPHAEXT);
 $pagetype = required_param('pagetype', PARAM_ALPHAEXT);
+$subpage = optional_param('subpage', '', PARAM_ALPHANUMEXT);
 $cmid = optional_param('cmid', null, PARAM_INT);
 $action = optional_param('action', '', PARAM_ALPHA);
 // Params for blocks-move actions
@@ -51,6 +52,7 @@ require_sesskey();
 
 // Setting layout to replicate blocks configuration for the page we edit
 $PAGE->set_pagelayout($pagelayout);
+$PAGE->set_subpage($subpage);
 echo $OUTPUT->header(); // send headers
 
 switch ($action) {
index 9413201..841a000 100644 (file)
@@ -1834,6 +1834,7 @@ function block_add_block_ui($page, $output) {
 
     $actionurl = new moodle_url($page->url, array('sesskey'=>sesskey()));
     $select = new single_select($actionurl, 'bui_addblock', $menu, null, array(''=>get_string('adddots')), 'add_block');
+    $select->set_label(get_string('addblock'), array('class'=>'accesshide'));
     $bc->content = $OUTPUT->render($select);
     return $bc;
 }
index 56a4d0f..d0f976b 100644 (file)
@@ -45,7 +45,7 @@ class completion_criteria_grade extends completion_criteria {
     /**
      * Finds and returns a data_object instance based on params.
      *
-     * @param array $params associative array varname => value of various 
+     * @param array $params associative array varname => value of various
      * parameters used to fetch data_object
      * @return data_object data_object instance or false if none found.
      */
index 550d49a..c1a0851 100644 (file)
@@ -760,7 +760,7 @@ abstract class condition_info_base {
                 if (empty($modinfo->cms[$cmid])) {
                     global $PAGE, $UNITTEST;
                     if (!empty($UNITTEST) || (isset($PAGE) && strpos($PAGE->pagetype, 'course-view-')===0)) {
-                        debugging("Warning: activity {$this->cm->id} '{$this->cm->name}' has condition " .
+                        debugging("Warning: activity {$this->item->id} '{$this->item->name}' has condition " .
                                 "on deleted activity $cmid (to get rid of this message, edit the named activity)");
                     }
                     continue;
index dde0f20..d17e3e1 100644 (file)
@@ -1694,7 +1694,7 @@ function add_to_log($courseid, $module, $action, $url='', $info='', $cm=0, $user
     $timenow = time();
     $info = $info;
     if (!empty($url)) { // could break doing html_entity_decode on an empty var.
-        $url = html_entity_decode($url);
+        $url = html_entity_decode($url, ENT_QUOTES, 'UTF-8');
     } else {
         $url = '';
     }
index 91263db..1ffa88a 100644 (file)
@@ -227,17 +227,10 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2012030100.01);
     }
 
-    if ($oldversion < 2012030100.02) {
-        // migrate all numbers to signed - it should be safe to interrupt this and continue later
-        upgrade_mysql_fix_unsigned_columns();
-
-        // Main savepoint reached
-        upgrade_main_savepoint(true, 2012030100.02);
-    }
-
     if ($oldversion < 2012030900.01) {
-        // migrate all texts and binaries to big size - it should be safe to interrupt this and continue later
-        upgrade_mysql_fix_lob_columns();
+        // Migrate all numbers to signed & all texts and binaries to big size.
+        // It should be safe to interrupt this and continue later.
+        upgrade_mysql_fix_unsigned_and_lob_columns();
 
         // Main savepoint reached
         upgrade_main_savepoint(true, 2012030900.01);
@@ -985,5 +978,19 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2012062502.07);
     }
 
+    if ($oldversion < 2012062503.07) {
+        // Remove "_utf8" suffix from all langs in course table.
+        $langs = $DB->get_records_sql("SELECT DISTINCT lang FROM {course} WHERE lang LIKE ?", array('%_utf8'));
+
+        foreach ($langs as $lang=>$unused) {
+            $newlang = str_replace('_utf8', '', $lang);
+            $sql = "UPDATE {course} SET lang = :newlang WHERE lang = :lang";
+            $DB->execute($sql, array('newlang'=>$newlang, 'lang'=>$lang));
+        }
+
+        // Main savepoint reached.
+        upgrade_main_savepoint(true, 2012062503.07);
+    }
+
     return true;
 }
index 5247e49..6edc5d8 100644 (file)
@@ -77,14 +77,15 @@ function upgrade_mysql_get_supported_tables() {
 }
 
 /**
- * Remove all signed numbers from current database - mysql only.
+ * Remove all signed numbers from current database and change
+ * text fields to long texts - mysql only.
  */
-function upgrade_mysql_fix_unsigned_columns() {
-    // we are not using standard API for changes of column
-    // because everything 'signed'-related will be removed soon
+function upgrade_mysql_fix_unsigned_and_lob_columns() {
+    // We are not using standard API for changes of column
+    // because everything 'signed'-related will be removed soon.
 
-    // if anybody already has numbers higher than signed limit the execution stops
-    // and tables must be fixed manually before continuing upgrade
+    // If anybody already has numbers higher than signed limit the execution stops
+    // and tables must be fixed manually before continuing upgrade.
 
     global $DB;
 
@@ -92,7 +93,7 @@ function upgrade_mysql_fix_unsigned_columns() {
         return;
     }
 
-    $pbar = new progress_bar('mysqlconvertunsigned', 500, true);
+    $pbar = new progress_bar('mysqlconvertunsignedlobs', 500, true);
 
     $prefix = $DB->get_prefix();
     $tables = upgrade_mysql_get_supported_tables();
@@ -101,16 +102,12 @@ function upgrade_mysql_fix_unsigned_columns() {
     $i = 0;
     foreach ($tables as $table) {
         $i++;
-        // set appropriate timeout - 5 minutes per milion of records should be enough, min 60 minutes just in case
-        $count = $DB->count_records($table, array());
-        $timeout = ($count/1000000)*5*60;
-        $timeout = ($timeout < 60*60) ? 60*60 : (int)$timeout;
+
+        $changes = array();
 
         $sql = "SHOW COLUMNS FROM `{{$table}}`";
         $rs = $DB->get_recordset_sql($sql);
         foreach ($rs as $column) {
-            upgrade_set_timeout($timeout);
-
             $column = (object)array_change_key_case((array)$column, CASE_LOWER);
             if (stripos($column->type, 'unsigned') !== false) {
                 $maxvalue = 0;
@@ -134,67 +131,36 @@ function upgrade_mysql_fix_unsigned_columns() {
                 $notnull = ($column->null === 'NO') ? 'NOT NULL' : 'NULL';
                 $default = (!is_null($column->default) and $column->default !== '') ? "DEFAULT '$column->default'" : '';
                 $autoinc = (stripos($column->extra, 'auto_increment') !== false) ? 'AUTO_INCREMENT' : '';
-                // primary and unique not necessary here, change_database_structure does not add prefix
-                $sql = "ALTER TABLE `{$prefix}$table` MODIFY COLUMN `$column->field` $type $notnull $default $autoinc";
-                $DB->change_database_structure($sql);
-            }
-        }
-        $rs->close();
-
-        $pbar->update($i, $tablecount, "Converted unsigned columns in MySQL database - $i/$tablecount.");
-    }
-}
-
-/**
- * Migrate all text and binary columns to big size - mysql only.
- */
-function upgrade_mysql_fix_lob_columns() {
-    // we are not using standard API for changes of column intentionally
-
-    global $DB;
-
-    if ($DB->get_dbfamily() !== 'mysql') {
-        return;
-    }
-
-    $pbar = new progress_bar('mysqlconvertlobs', 500, true);
-
-    $prefix = $DB->get_prefix();
-    $tables = upgrade_mysql_get_supported_tables();
-    asort($tables);
-
-    $tablecount = count($tables);
-    $i = 0;
-    foreach ($tables as $table) {
-        $i++;
-        // set appropriate timeout - 1 minute per thousand of records should be enough, min 60 minutes just in case
-        $count = $DB->count_records($table, array());
-        $timeout = ($count/1000)*60;
-        $timeout = ($timeout < 60*60) ? 60*60 : (int)$timeout;
-
-        $sql = "SHOW COLUMNS FROM `{{$table}}`";
-        $rs = $DB->get_recordset_sql($sql);
-        foreach ($rs as $column) {
-            upgrade_set_timeout($timeout);
+                // Primary and unique not necessary here, change_database_structure does not add prefix.
+                $changes[] = "MODIFY COLUMN `$column->field` $type $notnull $default $autoinc";
 
-            $column = (object)array_change_key_case((array)$column, CASE_LOWER);
-            if ($column->type === 'tinytext' or $column->type === 'mediumtext' or $column->type === 'text') {
+            } else if ($column->type === 'tinytext' or $column->type === 'mediumtext' or $column->type === 'text') {
                 $notnull = ($column->null === 'NO') ? 'NOT NULL' : 'NULL';
                 $default = (!is_null($column->default) and $column->default !== '') ? "DEFAULT '$column->default'" : '';
-                // primary, unique and inc are not supported for texts
-                $sql = "ALTER TABLE `{$prefix}$table` MODIFY COLUMN `$column->field` LONGTEXT $notnull $default";
-                $DB->change_database_structure($sql);
-            }
-            if ($column->type === 'tinyblob' or $column->type === 'mediumblob' or $column->type === 'blob') {
+                // Primary, unique and inc are not supported for texts.
+                $changes[] = "MODIFY COLUMN `$column->field` LONGTEXT $notnull $default";
+
+            } else if ($column->type === 'tinyblob' or $column->type === 'mediumblob' or $column->type === 'blob') {
                 $notnull = ($column->null === 'NO') ? 'NOT NULL' : 'NULL';
                 $default = (!is_null($column->default) and $column->default !== '') ? "DEFAULT '$column->default'" : '';
-                // primary, unique and inc are not supported for blobs
-                $sql = "ALTER TABLE `{$prefix}$table` MODIFY COLUMN `$column->field` LONGBLOB $notnull $default";
-                $DB->change_database_structure($sql);
+                // Primary, unique and inc are not supported for blobs.
+                $changes[] = "MODIFY COLUMN `$column->field` LONGBLOB $notnull $default";
             }
+
         }
         $rs->close();
 
-        $pbar->update($i, $tablecount, "Converted LOB columns in MySQL database - $i/$tablecount.");
+        if ($changes) {
+            // Set appropriate timeout - 1 minute per thousand of records should be enough, min 60 minutes just in case.
+            $count = $DB->count_records($table, array());
+            $timeout = ($count/1000)*60;
+            $timeout = ($timeout < 60*60) ? 60*60 : (int)$timeout;
+            upgrade_set_timeout($timeout);
+
+            $sql = "ALTER TABLE `{$prefix}$table` ".implode(', ', $changes);
+            $DB->change_database_structure($sql);
+        }
+
+        $pbar->update($i, $tablecount, "Converted unsigned/lob columns in MySQL database - $i/$tablecount.");
     }
 }
index e096c87..8deccf9 100644 (file)
@@ -172,7 +172,7 @@ class oracle_sql_generator extends sql_generator {
     public function getTypeSQL($xmldb_type, $xmldb_length=null, $xmldb_decimals=null) {
 
         switch ($xmldb_type) {
-            case XMLDB_TYPE_INTEGER:    // From http://www.postgresql.org/docs/7.4/interactive/datatype.html
+            case XMLDB_TYPE_INTEGER:    // See http://www.acs.ilstu.edu/docs/oracle/server.101/b10759/sql_elements001.htm#sthref86.
                 if (empty($xmldb_length)) {
                     $xmldb_length = 10;
                 }
index 4aae9ce..61b161c 100644 (file)
@@ -172,7 +172,7 @@ abstract class pdo_moodle_database extends moodle_database {
      * Function to print/save/ignore debugging messages related to SQL queries.
      */
     protected function debug_query($sql, $params = null) {
-        echo '<hr /> (', $this->get_dbtype(), '): ',  htmlentities($sql);
+        echo '<hr /> (', $this->get_dbtype(), '): ',  htmlentities($sql, ENT_QUOTES, 'UTF-8');
         if($params) {
             echo ' (parameters ';
             print_r($params);
index e056b53..39481ad 100644 (file)
@@ -3813,7 +3813,7 @@ class dml_testcase extends database_driver_testcase {
         $this->assertEquals("Firstname Surname", $DB->get_field_sql($sql, $params));
     }
 
-    function sql_sql_order_by_text() {
+    function test_sql_order_by_text() {
         $DB = $this->tdb;
         $dbman = $DB->get_manager();
 
index 2209291..0b72fa9 100644 (file)
@@ -687,6 +687,7 @@ $string['table_dlg:bordercolor'] = 'Border color';
 $string['table_dlg:caption'] = 'Table caption';
 $string['table_dlg:cell_all'] = 'Update all cells in table';
 $string['table_dlg:cell_cell'] = 'Update current cell';
+$string['table_dlg:cell_col'] = 'Update all cells in column';
 $string['table_dlg:cell_limit'] = 'You\'ve exceeded the maximum number of cells of {$cells}.';
 $string['table_dlg:cell_row'] = 'Update all cells in row';
 $string['table_dlg:cell_title'] = 'Table cell properties';
index ed606cf..afe04fb 100644 (file)
@@ -1,3 +1,5 @@
+Version 2.0.6.1 (2012-11-16)\r
+       Fixed security issue with google spellchecker.\r
 Version 2.0.6 (2011-09-29)\r
        Fixed incorrect position of suggestion menu.\r
        Fixed handling of mispelled words with no suggestions in PSpellShell engine.\r
index e3acf2d..5edf76a 100644 (file)
@@ -51,6 +51,8 @@ class GoogleSpell extends SpellChecker {
        }\r
 \r
        function &_getMatches($lang, $str) {\r
+               $lang = preg_replace('/[^a-z\-]/i', '', $lang); // Sanitize, remove everything but a-z or -\r
+               $str = preg_replace('/[\x00-\x1F\x7F]/', '', $str); // Sanitize, remove all control characters\r
                $server = "www.google.com";\r
                $port = 443;\r
                $path = "/tbproxy/spell?lang=" . $lang . "&hl=en";\r
@@ -126,6 +128,7 @@ class GoogleSpell extends SpellChecker {
        }\r
 \r
        function _unhtmlentities($string) {\r
+        return textlib::entities_to_utf8($string); // Moodle hack\r
                $string = preg_replace('~&#x([0-9a-f]+);~ei', 'chr(hexdec("\\1"))', $string);\r
                $string = preg_replace('~&#([0-9]+);~e', 'chr(\\1)', $string);\r
 \r
index 44315ca..69205d9 100644 (file)
@@ -74,8 +74,8 @@ class MoodleExcelWorkbook {
      * @param string $name Name of the sheet
      * @return object MoodleExcelWorksheet
      */
-    function &add_worksheet($name = '') {
-    /// Create the Moodle Worksheet. Returns one pointer to it
+    function add_worksheet($name = '') {
+        // Create the Moodle Worksheet. Returns one pointer to it
         $ws = new MoodleExcelWorksheet ($name, $this->pear_excel_workbook, $this->latin_output);
         return $ws;
     }
@@ -138,6 +138,9 @@ class MoodleExcelWorksheet {
      */
     function MoodleExcelWorksheet($name, &$workbook, $latin_output=false) {
 
+        // Replace any characters in the name that Excel cannot cope with.
+        $name = strtr($name, '[]*/\?:', '       ');
+
         if (strlen($name) > 31) {
             // Excel does not seem able to cope with sheet names > 31 chars.
             // With $latin_output = false, it does not cope at all.
index 5e61f56..dae2d8b 100644 (file)
@@ -813,7 +813,7 @@ class file_info_area_backup_section extends file_info {
             'component' => 'backup',
             'filearea' => 'section',
             'emptyfilename' => '.');
-        $sql1 = "SELECT DISTINCT cs.id sectionid FROM {files} f, {course_sections} cs
+        $sql1 = "SELECT DISTINCT cs.id AS sectionid FROM {files} f, {course_sections} cs
             WHERE cs.course = :courseid
             AND f.contextid = :contextid
             AND f.component = :component
index e8d542c..d3e55fb 100644 (file)
@@ -204,7 +204,7 @@ class file_info_context_coursecat extends file_info {
             return $cnt;
         }
 
-        $rs = $DB->get_recordset_sql('SELECT ctx.id contextid, c.visible
+        $rs = $DB->get_recordset_sql('SELECT ctx.id AS contextid, c.visible
                 FROM {context} ctx, {course} c
                 WHERE ctx.instanceid = c.id
                 AND ctx.contextlevel = :courselevel
@@ -226,7 +226,7 @@ class file_info_context_coursecat extends file_info {
             return $cnt;
         }
 
-        $rs = $DB->get_recordset_sql('SELECT ctx.id contextid, cat.visible
+        $rs = $DB->get_recordset_sql('SELECT ctx.id AS contextid, cat.visible
                 FROM {context} ctx, {course_categories} cat
                 WHERE ctx.instanceid = cat.id
                 AND ctx.contextlevel = :catlevel
index fd3c612..ce5c160 100644 (file)
@@ -2250,7 +2250,7 @@ function send_file($path, $filename, $lifetime = 'default' , $filter=0, $pathiss
             $options = new stdClass();
             $options->newlines = false;
             $options->noclean = true;
-            $text = htmlentities($pathisstring ? $path : implode('', file($path)));
+            $text = htmlentities($pathisstring ? $path : implode('', file($path)), ENT_QUOTES, 'UTF-8');
             $output = '<pre>'. format_text($text, FORMAT_MOODLE, $options, $COURSE->id) .'</pre>';
 
             readstring_accel($output, $mimetype, false);
index dfc4fa0..049acfe 100644 (file)
@@ -67,6 +67,10 @@ class filestoragelib_testcase extends advanced_testcase {
     public function test_get_file_preview(stored_file $file) {
         global $CFG;
 
+        if (empty($CFG->gdversion)) {
+            $this->markTestSkipped('GD extension is disabled');
+        }
+
         $this->resetAfterTest(true);
         $fs = get_file_storage();
 
index f5ba088..83b06c9 100644 (file)
@@ -1964,7 +1964,7 @@ function qf_errorHandler(element, _qfMsg) {
             list($jsArr,$element)=$jsandelement;
             //end of fix
             $escapedElementName = preg_replace_callback(
-                '/[_\[\]]/',
+                '/[_\[\]-]/',
                 create_function('$matches', 'return sprintf("_%2x",ord($matches[0]));'),
                 $elementName);
             $js .= '
index 3fa19ec..6f3deff 100644 (file)
@@ -886,7 +886,9 @@ class grade_category extends grade_object {
                 $droppedsomething = false;
 
                 $grade_keys = array_keys($grade_values);
-                if (count($grade_keys) === 0) {
+                $gradekeycount = count($grade_keys);
+
+                if ($gradekeycount === 0) {
                     //We've dropped all grade items
                     break;
                 }
@@ -910,7 +912,7 @@ class grade_category extends grade_object {
                 }
 
                 $i = 1;
-                while ($originalindex+$i < count($grade_keys)) {
+                while ($originalindex + $i < $gradekeycount) {
 
                     $possibleitemid = $grade_keys[$originalindex+$i];
                     $i++;
index 8378b78..4610192 100644 (file)
@@ -1730,16 +1730,27 @@ class grade_item extends grade_object {
             return true; // no need to recalculate locked items
         }
 
-        // precreate grades - we need them to exist
-        $params = array($this->courseid, $this->id, $this->id);
-        $sql = "SELECT DISTINCT go.userid
-                  FROM {grade_grades} go
-                       JOIN {grade_items} gi
-                       ON (gi.id = go.itemid AND gi.courseid = ?)
-                       LEFT OUTER JOIN {grade_grades} g
-                       ON (g.userid = go.userid AND g.itemid = ?)
-                 WHERE gi.id <> ? AND g.id IS NULL";
-        if ($missing = $DB->get_records_sql($sql, $params)) {
+        // Precreate grades - we need them to exist
+        if ($userid) {
+            $missing = array();
+            if (!$DB->record_exists('grade_grades', array('itemid'=>$this->id, 'userid'=>$userid))) {
+                $m = new stdClass();
+                $m->userid = $userid;
+                $missing[] = $m;
+            }
+        } else {
+            // Find any users who have grades for some but not all grade items in this course
+            $params = array('gicourseid' => $this->courseid, 'ggitemid' => $this->id);
+            $sql = "SELECT gg.userid
+                      FROM {grade_grades} gg
+                           JOIN {grade_items} gi
+                           ON (gi.id = gg.itemid AND gi.courseid = :gicourseid)
+                     GROUP BY gg.userid
+                     HAVING SUM(CASE WHEN gg.itemid = :ggitemid THEN 1 ELSE 0 END) = 0";
+            $missing = $DB->get_records_sql($sql, $params);
+        }
+
+        if ($missing) {
             foreach ($missing as $m) {
                 $grade = new grade_grade(array('itemid'=>$this->id, 'userid'=>$m->userid), false);
                 $grade->grade_item =& $this;
index 1233a28..858fe24 100644 (file)
@@ -1855,7 +1855,7 @@ M.util.load_flowplayer = function() {
                                 object.width = width;
                                 object.height = height;
                             }
-                               }
+                        }
                     }
                 });
             }
index 32697fa..bf3bdc1 100644 (file)
@@ -1128,7 +1128,7 @@ function clean_param($param, $type) {
 
         case PARAM_TIMEZONE:    //can be int, float(with .5 or .0) or string seperated by '/' and can have '-_'
             $param = fix_utf8($param);
-            $timezonepattern = '/^(([+-]?(0?[0-9](\.[5|0])?|1[0-3]|1[0-2]\.5))|(99)|[[:alnum:]]+(\/?[[:alpha:]_-])+)$/';
+            $timezonepattern = '/^(([+-]?(0?[0-9](\.[5|0])?|1[0-3](\.0)?|1[0-2]\.5))|(99)|[[:alnum:]]+(\/?[[:alpha:]_-])+)$/';
             if (preg_match($timezonepattern, $param)) {
                 return $param;
             } else {
index b95aae6..d0b2d5f 100644 (file)
@@ -3515,9 +3515,9 @@ class settings_navigation extends navigation_node {
                         continue;
                     }
                     if ($type->modclass == MOD_CLASS_RESOURCE) {
-                        $resources[html_entity_decode($type->type)] = $type->typestr;
+                        $resources[html_entity_decode($type->type, ENT_QUOTES, 'UTF-8')] = $type->typestr;
                     } else {
-                        $activities[html_entity_decode($type->type)] = $type->typestr;
+                        $activities[html_entity_decode($type->type, ENT_QUOTES, 'UTF-8')] = $type->typestr;
                     }
                 }
             } else {
@@ -4194,7 +4194,7 @@ class settings_navigation extends navigation_node {
 
         // Messaging
         if (($currentuser && has_capability('moodle/user:editownmessageprofile', $systemcontext)) || (!isguestuser($user) && has_capability('moodle/user:editmessageprofile', $usercontext) && !is_primary_admin($user->id))) {
-            $url = new moodle_url('/message/edit.php', array('id'=>$user->id, 'course'=>$course->id));
+            $url = new moodle_url('/message/edit.php', array('id'=>$user->id));
             $usersetting->add(get_string('editmymessage', 'message'), $url, self::TYPE_SETTING);
         }
 
@@ -4254,7 +4254,7 @@ class settings_navigation extends navigation_node {
     protected function load_category_settings() {
         global $CFG;
 
-        $categorynode = $this->add(print_context_name($this->context));
+        $categorynode = $this->add(print_context_name($this->context), null, null, null, 'categorysettings');
         $categorynode->force_open();
 
         if (has_any_capability(array('moodle/category:manage', 'moodle/course:create'), $this->context)) {
@@ -4491,7 +4491,7 @@ class navigation_json {
         }
 
         if ($child->forcetitle || $child->title !== $child->text) {
-            $attributes['title'] = htmlentities($child->title);
+            $attributes['title'] = htmlentities($child->title, ENT_QUOTES, 'UTF-8');
         }
         if (array_key_exists($child->key.':'.$child->type, $this->expandable)) {
             $attributes['expandable'] = $child->key;
index be1a5d9..8192a37 100644 (file)
@@ -50,7 +50,7 @@ class MoodleODSWorkbook {
     /* Create one Moodle Worksheet
      * @param string $name Name of the sheet
      */
-    function &add_worksheet($name = '') {
+    function add_worksheet($name = '') {
     /// Create the Moodle Worksheet. Returns one pointer to it
         $ws = new MoodleODSWorksheet($name);
         $this->worksheets[] =& $ws;
index 85816b1..bc89a75 100644 (file)
@@ -1336,6 +1336,11 @@ class core_renderer extends renderer_base {
             $select->attributes['title'] = $select->tooltip;
         }
 
+        $select->attributes['class'] = 'autosubmit';
+        if ($select->class) {
+            $select->attributes['class'] .= ' ' . $select->class;
+        }
+
         if ($select->label) {
             $output .= html_writer::label($select->label, $select->attributes['id'], false, $select->labelattributes);
         }
@@ -1351,7 +1356,10 @@ class core_renderer extends renderer_base {
         $output .= html_writer::tag('noscript', html_writer::tag('div', $go), array('style'=>'inline'));
 
         $nothing = empty($select->nothing) ? false : key($select->nothing);
-        $this->page->requires->js_init_call('M.util.init_select_autosubmit', array($select->formid, $select->attributes['id'], $nothing));
+        $this->page->requires->yui_module('moodle-core-formautosubmit',
+            'M.core.init_formautosubmit',
+            array(array('selectid' => $select->attributes['id'], 'nothing' => $nothing))
+        );
 
         // then div wrapper for xhtml strictness
         $output = html_writer::tag('div', $output);
@@ -1417,6 +1425,17 @@ class core_renderer extends renderer_base {
             $output .= html_writer::label($select->label, $select->attributes['id'], false, $select->labelattributes);
         }
 
+        $classes = array();
+        if (!$select->showbutton) {
+            $classes[] = 'autosubmit';
+        }
+        if ($select->class) {
+            $classes[] = $select->class;
+        }
+        if (count($classes)) {
+            $select->attributes['class'] = implode(' ', $classes);
+        }
+
         if ($select->helpicon instanceof help_icon) {
             $output .= $this->render($select->helpicon);
         } else if ($select->helpicon instanceof old_help_icon) {
@@ -1474,7 +1493,10 @@ class core_renderer extends renderer_base {
             $go = html_writer::empty_tag('input', array('type'=>'submit', 'value'=>get_string('go')));
             $output .= html_writer::tag('noscript', html_writer::tag('div', $go), array('style'=>'inline'));
             $nothing = empty($select->nothing) ? false : key($select->nothing);
-            $output .= $this->page->requires->js_init_call('M.util.init_url_select', array($select->formid, $select->attributes['id'], $nothing));
+            $this->page->requires->yui_module('moodle-core-formautosubmit',
+                'M.core.init_formautosubmit',
+                array(array('selectid' => $select->attributes['id'], 'nothing' => $nothing))
+            );
         } else {
             $output .= html_writer::empty_tag('input', array('type'=>'submit', 'value'=>$select->showbutton));
         }
index e438abf..dda9f6b 100644 (file)
@@ -480,7 +480,7 @@ class page_requirements_manager {
                     $module = array('name'     => 'core_dock',
                                     'fullpath' => '/blocks/dock.js',
                                     'requires' => array('base', 'node', 'event-custom', 'event-mouseenter', 'event-resize'),
-                                    'strings' => array(array('addtodock', 'block'),array('undockitem', 'block'),array('undockall', 'block'),array('thisdirectionvertical', 'langconfig')));
+                                    'strings' => array(array('addtodock', 'block'),array('undockitem', 'block'),array('undockall', 'block'),array('thisdirectionvertical', 'langconfig'),array('hidedockpanel', 'block'),array('hidepanel', 'block')));
                     break;
                 case 'core_message':
                     $module = array('name'     => 'core_message',
index 33ec793..4f68206 100644 (file)
@@ -88,10 +88,28 @@ class Hint_ResultPrinter extends PHPUnit_TextUI_ResultPrinter {
             $file = substr($file, strlen($cwd)+1);
         }
 
-        $executable = 'phpunit';
-        if (phpunit_bootstrap_is_cygwin()) {
-            $file = str_replace('\\', '/', $file);
-            $executable = 'phpunit.bat';
+        $executable = null;
+
+        if (isset($_SERVER['argv'][0])) {
+            if (preg_match('/phpunit(\.bat|\.cmd)?$/', $_SERVER['argv'][0])) {
+                $executable = $_SERVER['argv'][0];
+                for($i=1;$i<count($_SERVER['argv']);$i++) {
+                    if (!isset($_SERVER['argv'][$i])) {
+                        break;
+                    }
+                    if (in_array($_SERVER['argv'][$i], array('--colors', '--verbose', '-v', '--debug', '--strict'))) {
+                        $executable .= ' '.$_SERVER['argv'][$i];
+                    }
+                }
+            }
+        }
+
+        if (!$executable) {
+            $executable = 'phpunit';
+            if (phpunit_bootstrap_is_cygwin()) {
+                $file = str_replace('\\', '/', $file);
+                $executable = 'phpunit.bat';
+            }
         }
 
         $this->write("\nTo re-run:\n $executable $testName $file\n");
index 5af9c06..0bf70c4 100644 (file)
@@ -5,22 +5,35 @@ PHPUnit testing support in Moodle
 Documentation
 -------------
 * [Moodle Dev wiki](http://docs.moodle.org/dev/PHPUnit)
-* [PHPUnit online documentaion](http://www.phpunit.de/manual/current/en/)
+* [PHPUnit online documentation](http://www.phpunit.de/manual/current/en/)
+* [Composer dependency manager](http://getcomposer.org/)
 
 
-Installation
-------------
+Composer installation
+---------------------
+Composer is a new dependency manager for PHP projects.
+It installs PHP libraries into /vendor/ subdirectory inside your moodle dirroot.
+
+1. install Composer - http://getcomposer.org/doc/00-intro.md
+2. go to your moodle dirroot and execute `php composer.phar install --dev`
+
+
+PEAR installation (not recommended)
+-----------------------------------
+PEAR is a framework and distribution system for reusable PHP components.
+The packages installed via PEAR are available in all PHP projects.
+
 1. install PEAR package manager - see [PEAR Manual](http://pear.php.net/manual/en/installation.php)
 2. install PHPUnit package and phpunit/DbUnit extension - see [PHPUnit installation documentation](http://www.phpunit.de/manual/current/en/installation.html)
 3. edit main config.php - add `$CFG->phpunit_prefix` and `$CFG->phpunit_dataroot` - see config-dist.php
-4. execute `php admin/tool/phpunit/cli/init.php` to initialise the test environemnt, repeat it after every upgrade or installation of plugins
+4. execute `php admin/tool/phpunit/cli/init.php` to initialise the test environment, repeat it after every upgrade or installation of plugins
 
 
 Test execution
 --------------
-* execute `phpunit` from dirroot directory
-* you can execute a single test case class using class name followed by path to test file `phpunit core_phpunit_basic_testcase lib/tests/phpunit_test.php`
-* it is also possible to create custom configuration files in xml format and use `phpunit -c mytestsuites.xml`
+* execute `vendor/bin/phpunit` (or `phpunit` if you use PEAR) from dirroot directory
+* you can execute a single test case class using class name followed by path to test file `vendor/bin/phpunit core_phpunit_basic_testcase lib/tests/phpunit_test.php`
+* it is also possible to create custom configuration files in xml format and use `vendor/bin/phpunit -c mytestsuites.xml`
 
 
 How to add more tests?
index dda8714..6046e66 100644 (file)
@@ -207,10 +207,21 @@ function rss_get_file_full_name($componentname, $filename) {
  *
  * @param stdClass $instance the instance of the source of the RSS feed
  * @param string $sql the SQL used to produce the RSS feed
+ * @param array $params the parameters used in the SQL query
  * @return string the name of the RSS file
  */
-function rss_get_file_name($instance, $sql) {
-    return $instance->id.'_'.md5($sql);
+function rss_get_file_name($instance, $sql, $params = array()) {
+    if ($params) {
+        // If a parameters array is passed, then we want to
+        // serialize it and then concatenate it with the sql.
+        // The reason for this is to generate a unique filename
+        // for queries using the same sql but different parameters.
+        asort($parms);
+        $serializearray = serialize($params);
+        return $instance->id.'_'.md5($sql . $serializearray);
+    } else {
+        return $instance->id.'_'.md5($sql);
+    }
 }
 
 /**
index be15e14..b40927d 100644 (file)
@@ -1069,6 +1069,10 @@ function get_moodle_cookie() {
 function session_set_user($user) {
     $_SESSION['USER'] = $user;
     unset($_SESSION['USER']->description); // conserve memory
+    if (isset($_SESSION['USER']->lang)) {
+        // Make sure it is a valid lang pack name.
+        $_SESSION['USER']->lang = clean_param($_SESSION['USER']->lang, PARAM_LANG);
+    }
     sesskey(); // init session key
 
     if (PHPUNIT_TEST) {
index 51f8d82..9b03ff0 100644 (file)
@@ -356,7 +356,7 @@ function default_exception_handler($ex) {
     }
 
     if (is_early_init($info->backtrace)) {
-        echo bootstrap_renderer::early_error($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo);
+        echo bootstrap_renderer::early_error($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo, $info->errorcode);
     } else {
         try {
             if ($DB) {
@@ -370,7 +370,7 @@ function default_exception_handler($ex) {
             // so we just print at least something instead of "Exception thrown without a stack frame in Unknown on line 0":-(
             if (CLI_SCRIPT or AJAX_SCRIPT) {
                 // just ignore the error and send something back using the safest method
-                echo bootstrap_renderer::early_error($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo);
+                echo bootstrap_renderer::early_error($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo, $info->errorcode);
             } else {
                 echo bootstrap_renderer::early_error_content($info->message, $info->moreinfourl, $info->link, $info->backtrace, $info->debuginfo);
                 $outinfo = get_exception_info($out_ex);
@@ -761,6 +761,20 @@ function initialise_fullme() {
             if (!defined('NO_MOODLE_COOKIES')) {
                 define('NO_MOODLE_COOKIES', true);
             }
+            // The login/token.php script should call the correct url/port.
+            if (defined('REQUIRE_CORRECT_ACCESS') && REQUIRE_CORRECT_ACCESS) {
+                $wwwrootport = empty($wwwroot['port'])?'':$wwwroot['port'];
+                $calledurl = $rurl['host'];
+                if (!empty($rurl['port'])) {
+                    $calledurl .=  ':'. $rurl['port'];
+                }
+                $correcturl = $wwwroot['host'];
+                if (!empty($wwwrootport)) {
+                    $correcturl .=  ':'. $wwwrootport;
+                }
+                throw new moodle_exception('requirecorrectaccess', 'error', '', null,
+                    'You called ' . $calledurl .', you should have called ' . $correcturl);
+            }
             redirect($CFG->wwwroot, get_string('wwwrootmismatch', 'error', $CFG->wwwroot), 3);
         }
     }
@@ -1497,7 +1511,7 @@ width: 80%; -moz-border-radius: 20px; padding: 15px">
      * @param string $debuginfo extra information for developers
      * @return string
      */
-    public static function early_error($message, $moreinfourl, $link, $backtrace, $debuginfo = null) {
+    public static function early_error($message, $moreinfourl, $link, $backtrace, $debuginfo = null, $errorcode = null) {
         global $CFG;
 
         if (CLI_SCRIPT) {
@@ -1525,6 +1539,7 @@ width: 80%; -moz-border-radius: 20px; padding: 15px">
                     $e->stacktrace = format_backtrace($backtrace, true);
                 }
             }
+            $e->errorcode  = $errorcode;
             @header('Content-Type: application/json; charset=utf-8');
             echo json_encode($e);
             return;
index 2a08616..62bb077 100644 (file)
@@ -60,6 +60,7 @@ class flexible_table {
     var $column_class    = array();
     var $column_suppress = array();
     var $column_nosort   = array('userpic');
+    private $column_textsort = array();
     var $setup           = false;
     var $sess            = NULL;
     var $baseurl         = NULL;
@@ -214,6 +215,14 @@ class flexible_table {
         $this->sort_default_order  = $defaultorder;
     }
 
+    /**
+     * Use text sorting functions for this column (required for text columns with Oracle).
+     * @param string column name
+     */
+    function text_sorting($column) {
+        $this->column_textsort[] = $column;
+    }
+
     /**
      * Do not sort using this column
      * @param string column name
@@ -410,6 +419,7 @@ class flexible_table {
             $SESSION->flextable[$this->uniqueid]->sortby   = array();
             $SESSION->flextable[$this->uniqueid]->i_first  = '';
             $SESSION->flextable[$this->uniqueid]->i_last   = '';
+            $SESSION->flextable[$this->uniqueid]->textsort = $this->column_textsort;
         }
 
         $this->sess = &$SESSION->flextable[$this->uniqueid];
@@ -504,8 +514,11 @@ class flexible_table {
         if (empty($sess->sortby)) {
             return '';
         }
+        if (empty($sess->textsort)) {
+            $sess->textsort = array();
+        }
 
-        return self::construct_order_by($sess->sortby);
+        return self::construct_order_by($sess->sortby, $sess->textsort);
     }
 
     /**
@@ -513,10 +526,14 @@ class flexible_table {
      * @param array $cols column name => SORT_ASC or SORT_DESC
      * @return SQL fragment that can be used in an ORDER BY clause.
      */
-    public static function construct_order_by($cols) {
+    public static function construct_order_by($cols, $textsortcols=array()) {
+        global $DB;
         $bits = array();
 
         foreach ($cols as $column => $order) {
+            if (in_array($column, $textsortcols)) {
+                $column = $DB->sql_order_by_text($column);
+            }
             if ($order == SORT_ASC) {
                 $bits[] = $column . ' ASC';
             } else {
@@ -531,7 +548,7 @@ class flexible_table {
      * @return SQL fragment that can be used in an ORDER BY clause.
      */
     public function get_sql_sort() {
-        return self::construct_order_by($this->get_sort_columns());
+        return self::construct_order_by($this->get_sort_columns(), $this->column_textsort);
     }
 
     /**
@@ -1487,7 +1504,7 @@ class table_spreadsheet_export_format_parent extends table_default_export_format
     }
 
     function start_table($sheettitle) {
-        $this->worksheet =& $this->workbook->add_worksheet($sheettitle);
+        $this->worksheet = $this->workbook->add_worksheet($sheettitle);
         $this->rownum=0;
     }
 
index c26bab7..f5045c3 100644 (file)
@@ -979,9 +979,23 @@ class moodlelib_testcase extends advanced_testcase {
             '0'                              => '0',
             '0.0'                            => '0.0',
             '0.5'                            => '0.5',
+            '9.0'                            => '9.0',
+            '-9.0'                           => '-9.0',
+            '+9.0'                           => '+9.0',
+            '9.5'                            => '9.5',
+            '-9.5'                           => '-9.5',
+            '+9.5'                           => '+9.5',
+            '12.0'                           => '12.0',
+            '-12.0'                          => '-12.0',
+            '+12.0'                          => '+12.0',
+            '12.5'                           => '12.5',
             '-12.5'                          => '-12.5',
             '+12.5'                          => '+12.5',
+            '13.0'                           => '13.0',
+            '-13.0'                          => '-13.0',
+            '+13.0'                          => '+13.0',
             '13.5'                           => '',
+            '+13.5'                          => '',
             '-13.5'                          => '',
             '0.2'                            => '');
 
index 04814d0..0594466 100644 (file)
@@ -187,7 +187,10 @@ class moodle_page_test extends advanced_testcase {
     }
 
     public function test_pagetype_defaults_to_script() {
+        global $SCRIPT;
         // Exercise SUT and validate
+        $SCRIPT = '/index.php';
+        $this->testpage->initialise_default_pagetype();
         $this->assertEquals('site-index', $this->testpage->pagetype);
     }
 
index 261cfdd..7a6e843 100644 (file)
@@ -62,29 +62,35 @@ class core_textlib_testcase extends basic_testcase {
         $this->assertSame(textlib::convert($iso2, 'iso-8859-2', 'win-1250'), $win);
         $this->assertSame(textlib::convert($iso2, 'iso-8859-2', 'iso-8859-2'), $iso2);
         $this->assertSame(textlib::convert($win, 'win-1250', 'cp1250'), $win);
+        $this->assertSame(textlib::convert($utf8, 'utf-8', 'utf-8'), $utf8);
 
 
         $utf8 = '言語設定';
         $str = pack("H*", "b8c0b8ecc0dfc4ea"); //EUC-JP
         $this->assertSame(textlib::convert($utf8, 'utf-8', 'EUC-JP'), $str);
         $this->assertSame(textlib::convert($str, 'EUC-JP', 'utf-8'), $utf8);
+        $this->assertSame(textlib::convert($utf8, 'utf-8', 'utf-8'), $utf8);
 
         $str = pack("H*", "1b24423840386c405f446a1b2842"); //ISO-2022-JP
         $this->assertSame(textlib::convert($utf8, 'utf-8', 'ISO-2022-JP'), $str);
         $this->assertSame(textlib::convert($str, 'ISO-2022-JP', 'utf-8'), $utf8);
+        $this->assertSame(textlib::convert($utf8, 'utf-8', 'utf-8'), $utf8);
 
         $str = pack("H*", "8cbe8cea90dd92e8"); //SHIFT-JIS
         $this->assertSame(textlib::convert($utf8, 'utf-8', 'SHIFT-JIS'), $str);
         $this->assertSame(textlib::convert($str, 'SHIFT-JIS', 'utf-8'), $utf8);
+        $this->assertSame(textlib::convert($utf8, 'utf-8', 'utf-8'), $utf8);
 
         $utf8 = '简体中文';
         $str = pack("H*", "bcf2cce5d6d0cec4"); //GB2312
         $this->assertSame(textlib::convert($utf8, 'utf-8', 'GB2312'), $str);
         $this->assertSame(textlib::convert($str, 'GB2312', 'utf-8'), $utf8);
+        $this->assertSame(textlib::convert($utf8, 'utf-8', 'utf-8'), $utf8);
 
         $str = pack("H*", "bcf2cce5d6d0cec4"); //GB18030
         $this->assertSame(textlib::convert($utf8, 'utf-8', 'GB18030'), $str);
         $this->assertSame(textlib::convert($str, 'GB18030', 'utf-8'), $utf8);
+        $this->assertSame(textlib::convert($utf8, 'utf-8', 'utf-8'), $utf8);
     }
 
     /**
@@ -287,8 +293,8 @@ class core_textlib_testcase extends basic_testcase {
      * @return void
      */
     public function test_entities_to_utf8() {
-        $str = "&#x17d;lu&#x165;ou&#x10d;k&#xfd; kon&#237;&#269;ek";
-        $this->assertSame(textlib::entities_to_utf8($str), "Žluťoučký koníček");
+        $str = "&#x17d;lu&#x165;ou&#x10d;k&#xfd; kon&iacute;&#269;ek&copy;&quot;&amp;&lt;&gt;&sect;&laquo;";
+        $this->assertSame("Žluťoučký koníček©\"&<>§«", textlib::entities_to_utf8($str));
     }
 
     /**
@@ -296,10 +302,13 @@ class core_textlib_testcase extends basic_testcase {
      * @return void
      */
     public function test_utf8_to_entities() {
-        $str = "Žluťoučký koníček";
-        $this->assertSame(textlib::utf8_to_entities($str), "&#x17d;lu&#x165;ou&#x10d;k&#xfd; kon&#xed;&#x10d;ek");
-        $this->assertSame(textlib::utf8_to_entities($str, true), "&#381;lu&#357;ou&#269;k&#253; kon&#237;&#269;ek");
+        $str = "&#x17d;luťoučký kon&iacute;ček&copy;&quot;&amp;&lt;&gt;&sect;&laquo;";
+        $this->assertSame("&#x17d;lu&#x165;ou&#x10d;k&#xfd; kon&iacute;&#x10d;ek&copy;&quot;&amp;&lt;&gt;&sect;&laquo;", textlib::utf8_to_entities($str));
+        $this->assertSame("&#381;lu&#357;ou&#269;k&#253; kon&iacute;&#269;ek&copy;&quot;&amp;&lt;&gt;&sect;&laquo;", textlib::utf8_to_entities($str, true));
 
+        $str = "&#381;luťoučký kon&iacute;ček&copy;&quot;&amp;&lt;&gt;&sect;&laquo;";
+        $this->assertSame("&#x17d;lu&#x165;ou&#x10d;k&#xfd; kon&#xed;&#x10d;ek&#xa9;\"&<>&#xa7;&#xab;", textlib::utf8_to_entities($str, false, true));
+        $this->assertSame("&#381;lu&#357;ou&#269;k&#253; kon&#237;&#269;ek&#169;\"&<>&#167;&#171;", textlib::utf8_to_entities($str, true, true));
     }
 
     /**
index 77fafc1..bddcaa7 100644 (file)
@@ -161,8 +161,7 @@ class textlib {
 
     /**
      * Converts the text between different encodings. It uses iconv extension with //TRANSLIT parameter,
-     * falls back to typo3.
-     * Returns false if fails.
+     * falls back to typo3. If both source and target are utf-8 it tries to fix invalid characters only.
      *
      * @param string $text
      * @param string $fromCS source encoding
@@ -179,6 +178,10 @@ class textlib {
             return '';
         }
 
+        if ($toCS === 'utf-8' and $fromCS === 'utf-8') {
+            return fix_utf8($text);
+        }
+
         $result = iconv($fromCS, $toCS.'//TRANSLIT', $text);
 
         if ($result === false or $result === '') {
@@ -438,6 +441,34 @@ class textlib {
         return $encoded;
     }
 
+    /**
+     * Returns HTML entity transliteration table.
+     * @return array with (html entity => utf-8) elements
+     */
+    protected static function get_entities_table() {
+        static $trans_tbl = null;
+
+        // Generate/create $trans_tbl
+        if (!isset($trans_tbl)) {
+            if (version_compare(phpversion(), '5.3.4') < 0) {
+                $trans_tbl = array();
+                foreach (get_html_translation_table(HTML_ENTITIES) as $val=>$key) {
+                    $trans_tbl[$key] = textlib::convert($val, 'ISO-8859-1', 'utf-8');
+                }
+
+            } else if (version_compare(phpversion(), '5.4.0') < 0) {
+                $trans_tbl = get_html_translation_table(HTML_ENTITIES, ENT_COMPAT, 'UTF-8');
+                $trans_tbl = array_flip($trans_tbl);
+
+            } else {
+                $trans_tbl = get_html_translation_table(HTML_ENTITIES, ENT_COMPAT | ENT_HTML401, 'UTF-8');
+                $trans_tbl = array_flip($trans_tbl);
+            }
+        }
+
+        return $trans_tbl;
+    }
+
     /**
      * Converts all the numeric entities &#nnnn; or &#xnnn; to UTF-8
      * Original from laurynas dot butkus at gmail at:
@@ -447,28 +478,24 @@ class textlib {
      * @param string $str input string
      * @param boolean $htmlent convert also html entities (defaults to true)
      * @return string encoded UTF-8 string
-     *
-     * NOTE: we could have used typo3 entities_to_utf8() here
-     *       but the direct alternative used runs 400% quicker
-     *       and uses 0.5Mb less memory, so, let's use it
-     *       (tested against 10^6 conversions)
      */
     public static function entities_to_utf8($str, $htmlent=true) {
-        static $trans_tbl; // Going to use static transliteration table
+        static $callback1 = null ;
+        static $callback2 = null ;
 
-        // Replace numeric entities
-        $result = preg_replace('~&#x([0-9a-f]+);~ei', 'textlib::code2utf8(hexdec("\\1"))', $str);
-        $result = preg_replace('~&#([0-9]+);~e', 'textlib::code2utf8(\\1)', $result);
+        if (!$callback1 or !$callback2) {
+            $callback1 = create_function('$matches', 'return textlib::code2utf8(hexdec($matches[1]));');
+            $callback2 = create_function('$matches', 'return textlib::code2utf8($matches[1]);');
+        }
+
+        $result = (string)$str;
+        $result = preg_replace_callback('/&#x([0-9a-f]+);/i', $callback1, $result);
+        $result = preg_replace_callback('/&#([0-9]+);/', $callback2, $result);
 
         // Replace literal entities (if desired)
         if ($htmlent) {
-            // Generate/create $trans_tbl
-            if (!isset($trans_tbl)) {
-                $trans_tbl = array();
-                foreach (get_html_translation_table(HTML_ENTITIES) as $val=>$key) {
-                    $trans_tbl[$key] = utf8_encode($val);
-                }
-            }
+            $trans_tbl = self::get_entities_table();
+            // It should be safe to search for ascii strings and replace them with utf-8 here.
             $result = strtr($result, $trans_tbl);
         }
         // Return utf8-ised string
@@ -484,17 +511,24 @@ class textlib {
      * @return string converted string
      */
     public static function utf8_to_entities($str, $dec=false, $nonnum=false) {
-        // Avoid some notices from Typo3 code
-        $oldlevel = error_reporting(E_PARSE);
+        static $callback = null ;
+
         if ($nonnum) {
-            $str = self::typo3()->entities_to_utf8((string)$str, true);
+            $str = self::entities_to_utf8($str, true);
         }
+
+        // Avoid some notices from Typo3 code
+        $oldlevel = error_reporting(E_PARSE);
         $result = self::typo3()->utf8_to_entities((string)$str);
+        error_reporting($oldlevel);
+
         if ($dec) {
-            $result = preg_replace('/&#x([0-9a-f]+);/ie', "'&#'.hexdec('$1').';'", $result);
+            if (!$callback) {
+                $callback = create_function('$matches', 'return \'&#\'.(hexdec($matches[1])).\';\';');
+            }
+            $result = preg_replace_callback('/&#x([0-9a-f]+);/i', $callback, $result);
         }
-        // Restore original debug level
-        error_reporting($oldlevel);
+
         return $result;
     }
 
index 6818d2d..8b62f18 100644 (file)
@@ -54,2201 +54,2216 @@ id,name,year,tzrule,gmtoff,dstoff,dst_month,dst_startday,dst_weekday,dst_skipwee
 53,Africa/Tripoli,1985,Libya,60,60,4,6,-1,0,01:00,10,1,-1,0,00:00
 54,Africa/Tripoli,1986,Libya,60,60,4,4,-1,0,01:00,10,3,-1,0,00:00
 55,Africa/Tripoli,1987,Libya,60,60,4,1,-1,0,01:00,10,1,-1,0,00:00
-56,Africa/Tripoli,1989,Libya,60,0,4,1,-1,0,01:00,10,1,-1,0,00:00
-57,Africa/Tripoli,1990,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-58,Africa/Tripoli,1996,,60,0,0,0,0,0,00:00,0,0,0,0,00:00
-59,Africa/Tripoli,1997,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-60,Indian/Antananarivo,1970,,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-61,Africa/Blantyre,1970,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-62,Africa/Bamako,1970,,0,0,0,0,0,0,00:00,0,0,0,0,00:00
-63,Africa/Nouakchott,1970,,0,0,0,0,0,0,00:00,0,0,0,0,00:00
-64,Indian/Mauritius,1970,Mauritius,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-65,Indian/Mauritius,1982,Mauritius,240,60,10,10,-1,0,04:00,1,1,-1,0,15:00
-66,Indian/Mauritius,1983,Mauritius,240,0,12,31,-1,0,16:00,3,21,-1,0,03:00
-67,Indian/Mauritius,2008,Mauritius,240,60,10,-1,0,0,06:00,1,1,-1,0,15:00
-68,Indian/Mauritius,2009,Mauritius,240,0,12,31,-1,0,16:00,3,-1,0,0,05:00
-69,Indian/Mayotte,1970,,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-70,Africa/Casablanca,1970,Morocco,0,60,6,3,-1,0,12:00,10,1,-1,0,-1:00
-71,Africa/Casablanca,1974,Morocco,0,60,6,24,-1,0,00:00,9,1,-1,0,-1:00
-72,Africa/Casablanca,1976,Morocco,0,60,5,1,-1,0,00:00,8,1,-1,0,-1:00
-73,Africa/Casablanca,1977,Morocco,0,60,5,1,-1,0,00:00,9,28,-1,0,-1:00
-74,Africa/Casablanca,1978,Morocco,0,60,6,1,-1,0,00:00,8,4,-1,0,-1:00
-75,Africa/Casablanca,1984,,60,0,0,0,0,0,00:00,0,0,0,0,00:00
-76,Africa/Casablanca,1986,Morocco,0,0,0,0,0,0,00:00,0,0,0,0,00:00
-77,Africa/Casablanca,2008,Morocco,0,60,6,1,-1,0,00:00,9,1,-1,0,-1:00
-78,Africa/Casablanca,2009,Morocco,0,60,6,1,-1,0,00:00,8,21,-1,0,-1:00
-79,Africa/Casablanca,2010,Morocco,0,60,5,2,-1,0,00:00,8,8,-1,0,-1:00
-80,Africa/Casablanca,2011,Morocco,0,60,4,3,-1,0,00:00,7,31,-1,0,-1:00
-81,Africa/Casablanca,2012,Morocco,0,0,4,3,-1,0,00:00,7,31,-1,0,-1:00
-82,Africa/El_Aaiun,1970,,-60,0,0,0,0,0,00:00,0,0,0,0,00:00
-83,Africa/El_Aaiun,1976,,0,0,0,0,0,0,00:00,0,0,0,0,00:00
-84,Africa/Maputo,1970,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-85,Africa/Windhoek,1970,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-86,Africa/Windhoek,1990,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-87,Africa/Windhoek,1994,Namibia,60,60,9,1,0,0,03:00,1,1,-1,0,12:00
-88,Africa/Windhoek,1995,Namibia,60,60,9,1,0,0,03:00,4,1,0,0,02:00
-89,Africa/Niamey,1970,,60,0,0,0,0,0,00:00,0,0,0,0,00:00
-90,Africa/Lagos,1970,,60,0,0,0,0,0,00:00,0,0,0,0,00:00
-91,Indian/Reunion,1970,,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-92,Africa/Kigali,1970,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-93,Atlantic/St_Helena,1970,,0,0,0,0,0,0,00:00,0,0,0,0,00:00
-94,Africa/Sao_Tome,1970,,0,0,0,0,0,0,00:00,0,0,0,0,00:00
-95,Africa/Dakar,1970,,0,0,0,0,0,0,00:00,0,0,0,0,00:00
-96,Indian/Mahe,1970,,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-97,Africa/Freetown,1970,SL,0,0,6,1,-1,0,00:00,9,1,-1,0,-1:00
-98,Africa/Mogadishu,1970,,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-99,Africa/Johannesburg,1970,SA,120,0,12,31,-1,0,14:00,3,15,0,0,03:00
-100,Africa/Khartoum,1970,Sudan,120,60,5,1,-1,0,02:00,10,15,-1,0,01:00
-101,Africa/Khartoum,1971,Sudan,120,60,4,30,-1,0,02:00,10,15,-1,0,01:00
-102,Africa/Khartoum,1972,Sudan,120,60,4,-1,0,0,02:00,10,15,-1,0,01:00
-103,Africa/Khartoum,1985,Sudan,120,0,4,-1,0,0,02:00,10,15,-1,0,01:00
-104,Africa/Khartoum,2000,,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-105,Africa/Juba,1970,Sudan,120,60,5,1,-1,0,02:00,10,15,-1,0,01:00
-106,Africa/Juba,1971,Sudan,120,60,4,30,-1,0,02:00,10,15,-1,0,01:00
-107,Africa/Juba,1972,Sudan,120,60,4,-1,0,0,02:00,10,15,-1,0,01:00
-108,Africa/Juba,1985,Sudan,120,0,4,-1,0,0,02:00,10,15,-1,0,01:00
-109,Africa/Juba,2000,,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-110,Africa/Mbabane,1970,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-111,Africa/Dar_es_Salaam,1970,,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-112,Africa/Lome,1970,,0,0,0,0,0,0,00:00,0,0,0,0,00:00
-113,Africa/Tunis,1970,Tunisia,60,60,4,1,1,0,03:00,9,16,-1,0,00:00
-114,Africa/Tunis,1977,Tunisia,60,60,4,30,-1,0,01:00,9,24,-1,0,01:00
-115,Africa/Tunis,1978,Tunisia,60,60,5,1,-1,0,01:00,10,1,-1,0,01:00
-116,Africa/Tunis,1988,Tunisia,60,60,6,1,-1,0,01:00,9,-1,0,0,01:00
-117,Africa/Tunis,1989,Tunisia,60,60,3,26,-1,0,01:00,9,-1,0,0,01:00
-118,Africa/Tunis,1990,Tunisia,60,60,5,1,-1,0,01:00,9,-1,0,0,01:00
-119,Africa/Tunis,2005,Tunisia,60,60,5,1,-1,0,01:00,9,30,-1,0,02:00
-120,Africa/Tunis,2006,Tunisia,60,60,3,-1,0,0,03:00,10,-1,0,0,03:00
-121,Africa/Tunis,2008,Tunisia,60,0,3,-1,0,0,03:00,10,-1,0,0,03:00
-122,Africa/Kampala,1970,,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-123,Africa/Lusaka,1970,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-124,Africa/Harare,1970,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-125,Antarctica/Casey,1970,,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-126,Antarctica/Casey,2009,,660,0,0,0,0,0,00:00,0,0,0,0,00:00
-127,Antarctica/Casey,2010,,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-128,Antarctica/Davis,1970,,420,0,0,0,0,0,00:00,0,0,0,0,00:00
-129,Antarctica/Davis,2009,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-130,Antarctica/Davis,2010,,420,0,0,0,0,0,00:00,0,0,0,0,00:00
-131,Antarctica/Mawson,1970,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-132,Antarctica/Mawson,2009,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-133,Antarctica/Macquarie,1970,ATAQ,600,60,10,-1,0,0,12:00,3,8,0,0,12:00
-134,Antarctica/Macquarie,1972,ATAQ,600,60,10,-1,0,0,12:00,2,-1,0,0,12:00
-135,Antarctica/Macquarie,1973,ATAQ,600,60,10,-1,0,0,12:00,3,1,0,0,12:00
-136,Antarctica/Macquarie,1982,ATAQ,600,60,10,-1,0,0,12:00,3,-1,0,0,12:00
-137,Antarctica/Macquarie,1984,ATAQ,600,60,10,-1,0,0,12:00,3,1,0,0,12:00
-138,Antarctica/Macquarie,1986,ATAQ,600,60,10,15,0,0,12:00,3,1,0,0,12:00
-139,Antarctica/Macquarie,1987,ATAQ,600,60,10,22,0,0,12:00,3,15,0,0,12:00
-140,Antarctica/Macquarie,1988,ATAQ,600,60,10,-1,0,0,12:00,3,15,0,0,12:00
-141,Antarctica/Macquarie,1991,ATAQ,600,60,10,1,0,0,12:00,3,-1,0,0,12:00
-142,Antarctica/Macquarie,2000,ATAQ,600,60,8,-1,0,0,12:00,3,-1,0,0,12:00
-143,Antarctica/Macquarie,2001,ATAQ,600,60,10,1,0,0,12:00,3,-1,0,0,12:00
-144,Antarctica/Macquarie,2006,ATAQ,600,60,10,1,0,0,12:00,4,1,0,0,12:00
-145,Antarctica/Macquarie,2007,ATAQ,600,60,10,1,0,0,12:00,3,-1,0,0,12:00
-146,Antarctica/Macquarie,2008,ATAQ,600,60,10,1,0,0,12:00,4,1,0,0,12:00
-147,Antarctica/Macquarie,2010,,660,0,0,0,0,0,00:00,0,0,0,0,00:00
-148,Indian/Kerguelen,1970,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-149,Antarctica/DumontDUrville,1970,,600,0,0,0,0,0,00:00,0,0,0,0,00:00
-150,Antarctica/Syowa,1970,,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-151,Antarctica/Vostok,1970,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-152,Antarctica/Rothera,1970,,0,0,0,0,0,0,00:00,0,0,0,0,00:00
-153,Antarctica/Rothera,1976,,-180,0,0,0,0,0,00:00,0,0,0,0,00:00
-154,Antarctica/Palmer,1970,ArgAQ,-180,0,12,31,-1,0,09:00,4,1,0,0,-4:00
-155,Antarctica/Palmer,1974,ArgAQ,-180,60,1,23,-1,0,-3:00,5,1,-1,0,-4:00
-156,Antarctica/Palmer,1975,ArgAQ,-180,0,1,23,-1,0,-3:00,5,1,-1,0,-4:00
-157,Antarctica/Palmer,1982,ChileAQ,-240,60,10,9,0,0,4:00,3,9,0,0,3:00
-158,Antarctica/Palmer,1987,ChileAQ,-240,60,10,9,0,0,4:00,4,12,-1,0,3:00
-159,Antarctica/Palmer,1988,ChileAQ,-240,60,10,1,0,0,4:00,3,9,0,0,3:00
-160,Antarctica/Palmer,1989,ChileAQ,-240,60,10,9,0,0,4:00,3,9,0,0,3:00
-161,Antarctica/Palmer,1990,ChileAQ,-240,60,9,16,-1,0,4:00,3,18,-1,0,3:00
-162,Antarctica/Palmer,1991,ChileAQ,-240,60,10,9,0,0,4:00,3,9,0,0,3:00
-163,Antarctica/Palmer,1997,ChileAQ,-240,60,10,9,0,0,4:00,3,30,-1,0,3:00
-164,Antarctica/Palmer,1998,ChileAQ,-240,60,9,27,-1,0,4:00,3,9,0,0,3:00
-165,Antarctica/Palmer,1999,ChileAQ,-240,60,10,9,0,0,4:00,4,4,-1,0,3:00
-166,Antarctica/Palmer,2000,ChileAQ,-240,60,10,9,0,0,4:00,3,9,0,0,3:00
-167,Antarctica/McMurdo,1970,NZAQ,720,0,0,0,0,0,00:00,0,0,0,0,00:00
-168,Antarctica/McMurdo,1974,NZAQ,720,60,11,3,-1,0,14:00,1,1,-1,0,23:00
-169,Antarctica/McMurdo,1975,NZAQ,720,60,10,-1,0,0,14:00,2,23,-1,0,14:00
-170,Antarctica/McMurdo,1976,NZAQ,720,60,10,-1,0,0,14:00,3,1,0,0,14:00
-171,Antarctica/McMurdo,1989,NZAQ,720,60,10,8,-1,0,14:00,3,1,0,0,14:00
-172,Antarctica/McMurdo,1990,NZAQ,720,60,10,1,0,0,14:00,3,15,0,0,14:00
-173,Antarctica/McMurdo,2007,NZAQ,720,60,9,-1,0,0,14:00,3,15,0,0,14:00
-174,Antarctica/McMurdo,2008,NZAQ,720,60,9,-1,0,0,14:00,4,1,0,0,14:00
-175,Asia/Kabul,1970,,270,0,0,0,0,0,00:00,0,0,0,0,00:00
-176,Asia/Yerevan,1970,RussiaAsia,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-177,Asia/Yerevan,1981,RussiaAsia,240,60,4,1,-1,0,04:00,10,1,-1,0,03:00
-178,Asia/Yerevan,1984,RussiaAsia,240,60,4,1,-1,0,04:00,9,-1,0,0,06:00
-179,Asia/Yerevan,1985,RussiaAsia,240,60,3,-1,0,0,06:00,9,-1,0,0,06:00
-180,Asia/Yerevan,1991,RussiaAsia,180,60,3,-1,0,0,05:00,9,-1,0,0,05:00
-181,Asia/Yerevan,1992,RussiaAsia,180,60,3,-1,6,0,26:00,9,-1,6,0,25:00
-182,Asia/Yerevan,1993,RussiaAsia,180,60,3,-1,0,0,05:00,9,-1,0,0,05:00
-183,Asia/Yerevan,1995,,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-184,Asia/Yerevan,1997,RussiaAsia,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-185,Asia/Baku,1970,RussiaAsia,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-186,Asia/Baku,1981,RussiaAsia,240,60,4,1,-1,0,04:00,10,1,-1,0,03:00
-187,Asia/Baku,1984,RussiaAsia,240,60,4,1,-1,0,04:00,9,-1,0,0,06:00
-188,Asia/Baku,1985,RussiaAsia,240,60,3,-1,0,0,06:00,9,-1,0,0,06:00
-189,Asia/Baku,1991,RussiaAsia,180,60,3,-1,0,0,05:00,9,-1,0,0,05:00
-190,Asia/Baku,1992,,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-191,Asia/Baku,1996,EUAsia,240,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-192,Asia/Baku,1997,Azer,240,60,3,-1,0,0,08:00,10,-1,0,0,08:00
-193,Asia/Bahrain,1970,,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-194,Asia/Bahrain,1972,,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-195,Asia/Dhaka,1970,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-196,Asia/Dhaka,1971,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-197,Asia/Dhaka,2009,Dhaka,360,60,6,19,-1,0,29:00,12,31,-1,0,28:59
-198,Asia/Dhaka,2010,Dhaka,360,0,6,19,-1,0,29:00,12,31,-1,0,28:59
-199,Asia/Thimphu,1970,,330,0,0,0,0,0,00:00,0,0,0,0,00:00
-200,Asia/Thimphu,1987,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-201,Indian/Chagos,1970,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-202,Indian/Chagos,1996,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-203,Asia/Brunei,1970,,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-204,Asia/Rangoon,1970,,390,0,0,0,0,0,00:00,0,0,0,0,00:00
-205,Asia/Phnom_Penh,1970,,420,0,0,0,0,0,00:00,0,0,0,0,00:00
-206,Asia/Harbin,1970,,510,0,0,0,0,0,00:00,0,0,0,0,00:00
-207,Asia/Harbin,1980,PRC,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-208,Asia/Harbin,1986,PRC,480,60,5,4,-1,0,08:00,9,11,0,0,07:00
-209,Asia/Harbin,1987,PRC,480,60,4,10,0,0,08:00,9,11,0,0,07:00
-210,Asia/Harbin,1991,PRC,480,0,4,10,0,0,08:00,9,11,0,0,07:00
-211,Asia/Shanghai,1970,PRC,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-212,Asia/Shanghai,1986,PRC,480,60,5,4,-1,0,08:00,9,11,0,0,07:00
-213,Asia/Shanghai,1987,PRC,480,60,4,10,0,0,08:00,9,11,0,0,07:00
-214,Asia/Shanghai,1991,PRC,480,0,4,10,0,0,08:00,9,11,0,0,07:00
-215,Asia/Chongqing,1970,,420,0,0,0,0,0,00:00,0,0,0,0,00:00
-216,Asia/Chongqing,1980,PRC,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-217,Asia/Chongqing,1986,PRC,480,60,5,4,-1,0,08:00,9,11,0,0,07:00
-218,Asia/Chongqing,1987,PRC,480,60,4,10,0,0,08:00,9,11,0,0,07:00
-219,Asia/Chongqing,1991,PRC,480,0,4,10,0,0,08:00,9,11,0,0,07:00
-220,Asia/Urumqi,1970,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-221,Asia/Urumqi,1980,PRC,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-222,Asia/Urumqi,1986,PRC,480,60,5,4,-1,0,08:00,9,11,0,0,07:00
-223,Asia/Urumqi,1987,PRC,480,60,4,10,0,0,08:00,9,11,0,0,07:00
-224,Asia/Urumqi,1991,PRC,480,0,4,10,0,0,08:00,9,11,0,0,07:00
-225,Asia/Kashgar,1970,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-226,Asia/Kashgar,1980,PRC,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-227,Asia/Kashgar,1986,PRC,480,60,5,4,-1,0,08:00,9,11,0,0,07:00
-228,Asia/Kashgar,1987,PRC,480,60,4,10,0,0,08:00,9,11,0,0,07:00
-229,Asia/Kashgar,1991,PRC,480,0,4,10,0,0,08:00,9,11,0,0,07:00
-230,Asia/Hong_Kong,1970,HK,480,60,4,16,0,0,11:30,10,16,0,0,10:30
-231,Asia/Hong_Kong,1973,HK,480,60,12,30,-1,0,11:30,10,16,0,0,10:30
-232,Asia/Hong_Kong,1974,HK,480,60,4,16,0,0,11:30,10,16,0,0,10:30
-233,Asia/Hong_Kong,1979,HK,480,60,5,8,0,0,11:30,10,16,0,0,10:30
-234,Asia/Hong_Kong,1980,HK,480,0,5,8,0,0,11:30,10,16,0,0,10:30
-235,Asia/Taipei,1970,Taiwan,480,60,6,1,-1,0,08:00,10,1,-1,0,07:00
-236,Asia/Taipei,1974,Taiwan,480,60,4,1,-1,0,08:00,10,1,-1,0,07:00
-237,Asia/Taipei,1979,Taiwan,480,60,6,30,-1,0,08:00,9,30,-1,0,07:00
-238,Asia/Taipei,1980,Taiwan,480,0,6,30,-1,0,08:00,9,30,-1,0,07:00
-239,Asia/Macau,1970,Macau,480,60,4,16,0,0,11:30,10,16,0,0,10:30
-240,Asia/Macau,1972,Macau,480,60,4,15,0,0,08:00,10,15,0,0,07:00
-241,Asia/Macau,1974,Macau,480,60,4,15,0,0,08:00,10,15,0,0,10:30
-242,Asia/Macau,1975,Macau,480,60,4,15,0,0,11:30,10,15,0,0,10:30
-243,Asia/Macau,1978,Macau,480,60,4,15,0,0,08:00,10,15,0,0,07:00
-244,Asia/Macau,1980,Macau,480,0,4,15,0,0,08:00,10,15,0,0,07:00
-245,Asia/Macau,1999,PRC,480,0,4,15,0,0,08:00,10,15,0,0,07:00
-246,Asia/Nicosia,1970,Cyprus,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-247,Asia/Nicosia,1975,Cyprus,120,60,4,13,-1,0,02:00,10,12,-1,0,01:00
-248,Asia/Nicosia,1976,Cyprus,120,60,5,15,-1,0,02:00,10,11,-1,0,01:00
-249,Asia/Nicosia,1977,Cyprus,120,60,4,1,0,0,02:00,9,25,-1,0,01:00
-250,Asia/Nicosia,1978,Cyprus,120,60,4,1,0,0,02:00,10,2,-1,0,01:00
-251,Asia/Nicosia,1979,Cyprus,120,60,4,1,0,0,02:00,9,-1,0,0,01:00
-252,Asia/Nicosia,1981,Cyprus,120,60,3,-1,0,0,02:00,9,-1,0,0,01:00
-253,Asia/Nicosia,1998,EUAsia,120,60,3,-1,0,0,02:00,9,-1,0,0,01:00
-254,Asia/Tbilisi,1970,RussiaAsia,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-255,Asia/Tbilisi,1981,RussiaAsia,240,60,4,1,-1,0,04:00,10,1,-1,0,03:00
-256,Asia/Tbilisi,1984,RussiaAsia,240,60,4,1,-1,0,04:00,9,-1,0,0,06:00
-257,Asia/Tbilisi,1985,RussiaAsia,240,60,3,-1,0,0,06:00,9,-1,0,0,06:00
-258,Asia/Tbilisi,1991,RussiaAsia,180,60,3,-1,0,0,05:00,9,-1,0,0,05:00
-259,Asia/Tbilisi,1992,E-EurAsia,180,60,3,-1,0,0,03:00,9,-1,0,0,02:00
-260,Asia/Tbilisi,1994,E-EurAsia,240,60,3,-1,0,0,04:00,9,-1,0,0,03:00
-261,Asia/Tbilisi,1995,E-EurAsia,240,0,12,31,-1,0,16:00,9,-1,0,0,03:00
-262,Asia/Tbilisi,1996,,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-263,Asia/Tbilisi,1997,E-EurAsia,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-264,Asia/Tbilisi,2004,RussiaAsia,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-265,Asia/Tbilisi,2005,,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-266,Asia/Dili,1970,,540,0,0,0,0,0,00:00,0,0,0,0,00:00
-267,Asia/Dili,1976,,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-268,Asia/Dili,2000,,540,0,0,0,0,0,00:00,0,0,0,0,00:00
-269,Asia/Kolkata,1970,,330,0,0,0,0,0,00:00,0,0,0,0,00:00
-270,Asia/Jakarta,1970,,420,0,0,0,0,0,00:00,0,0,0,0,00:00
-271,Asia/Pontianak,1970,,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-272,Asia/Pontianak,1988,,420,0,0,0,0,0,00:00,0,0,0,0,00:00
-273,Asia/Makassar,1970,,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-274,Asia/Jayapura,1970,,540,0,0,0,0,0,00:00,0,0,0,0,00:00
-275,Asia/Tehran,1970,,210,0,0,0,0,0,00:00,0,0,0,0,00:00
-276,Asia/Tehran,1977,Iran,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-277,Asia/Tehran,1978,Iran,240,60,3,21,-1,0,04:00,10,21,-1,0,03:00
-278,Asia/Tehran,1979,Iran,210,60,3,21,-1,0,03:30,9,19,-1,0,02:30
-279,Asia/Tehran,1980,Iran,210,60,3,21,-1,0,03:30,9,23,-1,0,02:30
-280,Asia/Tehran,1991,Iran,210,60,5,3,-1,0,03:30,9,22,-1,0,02:30
-281,Asia/Tehran,1992,Iran,210,60,3,22,-1,0,03:30,9,22,-1,0,02:30
-282,Asia/Tehran,1996,Iran,210,60,3,21,-1,0,03:30,9,21,-1,0,02:30
-283,Asia/Tehran,1997,Iran,210,60,3,22,-1,0,03:30,9,22,-1,0,02:30
-284,Asia/Tehran,2000,Iran,210,60,3,21,-1,0,03:30,9,21,-1,0,02:30
-285,Asia/Tehran,2001,Iran,210,60,3,22,-1,0,03:30,9,22,-1,0,02:30
-286,Asia/Tehran,2004,Iran,210,60,3,21,-1,0,03:30,9,21,-1,0,02:30
-287,Asia/Tehran,2005,Iran,210,60,3,22,-1,0,03:30,9,22,-1,0,02:30
-288,Asia/Tehran,2008,Iran,210,60,3,21,-1,0,03:30,9,21,-1,0,02:30
-289,Asia/Tehran,2009,Iran,210,60,3,22,-1,0,03:30,9,22,-1,0,02:30
-290,Asia/Tehran,2012,Iran,210,60,3,21,-1,0,03:30,9,21,-1,0,02:30
-291,Asia/Tehran,2013,Iran,210,60,3,22,-1,0,03:30,9,22,-1,0,02:30
-292,Asia/Tehran,2016,Iran,210,60,3,21,-1,0,03:30,9,21,-1,0,02:30
-293,Asia/Tehran,2017,Iran,210,60,3,22,-1,0,03:30,9,22,-1,0,02:30
-294,Asia/Tehran,2020,Iran,210,60,3,21,-1,0,03:30,9,21,-1,0,02:30
-295,Asia/Tehran,2021,Iran,210,60,3,22,-1,0,03:30,9,22,-1,0,02:30
-296,Asia/Baghdad,1970,,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-297,Asia/Baghdad,1982,Iraq,180,60,5,1,-1,0,03:00,10,1,-1,0,02:00
-298,Asia/Baghdad,1983,Iraq,180,60,3,31,-1,0,03:00,10,1,-1,0,02:00
-299,Asia/Baghdad,1984,Iraq,180,60,4,1,-1,0,03:00,10,1,-1,0,02:00
-300,Asia/Baghdad,1985,Iraq,180,60,4,1,-1,0,03:00,9,-1,0,0,04:00
-301,Asia/Baghdad,1986,Iraq,180,60,3,-1,0,0,04:00,9,-1,0,0,04:00
-302,Asia/Baghdad,1991,Iraq,180,60,4,1,-1,0,06:00,10,1,-1,0,06:00
-303,Asia/Baghdad,2007,Iraq,180,0,4,1,-1,0,06:00,10,1,-1,0,06:00
-304,Asia/Jerusalem,1970,Zion,120,60,4,29,-1,0,04:00,9,22,-1,0,01:00
-305,Asia/Jerusalem,1974,Zion,120,60,7,7,-1,0,02:00,10,13,-1,0,01:00
-306,Asia/Jerusalem,1975,Zion,120,60,4,20,-1,0,02:00,8,31,-1,0,01:00
-307,Asia/Jerusalem,1985,Zion,120,60,4,14,-1,0,02:00,9,15,-1,0,01:00
-308,Asia/Jerusalem,1986,Zion,120,60,5,18,-1,0,02:00,9,7,-1,0,01:00
-309,Asia/Jerusalem,1987,Zion,120,60,4,15,-1,0,02:00,9,13,-1,0,01:00
-310,Asia/Jerusalem,1988,Zion,120,60,4,9,-1,0,02:00,9,3,-1,0,01:00
-311,Asia/Jerusalem,1989,Zion,120,60,4,30,-1,0,02:00,9,3,-1,0,01:00
-312,Asia/Jerusalem,1990,Zion,120,60,3,25,-1,0,02:00,8,26,-1,0,01:00
-313,Asia/Jerusalem,1991,Zion,120,60,3,24,-1,0,02:00,9,1,-1,0,01:00
-314,Asia/Jerusalem,1992,Zion,120,60,3,29,-1,0,02:00,9,6,-1,0,01:00
-315,Asia/Jerusalem,1993,Zion,120,60,4,2,-1,0,02:00,9,5,-1,0,01:00
-316,Asia/Jerusalem,1994,Zion,120,60,4,1,-1,0,02:00,8,28,-1,0,01:00
-317,Asia/Jerusalem,1995,Zion,120,60,3,31,-1,0,02:00,9,3,-1,0,01:00
-318,Asia/Jerusalem,1996,Zion,120,60,3,15,-1,0,02:00,9,16,-1,0,01:00
-319,Asia/Jerusalem,1997,Zion,120,60,3,21,-1,0,02:00,9,14,-1,0,01:00
-320,Asia/Jerusalem,1998,Zion,120,60,3,20,-1,0,02:00,9,6,-1,0,01:00
-321,Asia/Jerusalem,1999,Zion,120,60,4,2,-1,0,04:00,9,3,-1,0,03:00
-322,Asia/Jerusalem,2000,Zion,120,60,4,14,-1,0,04:00,10,6,-1,0,02:00
-323,Asia/Jerusalem,2001,Zion,120,60,4,9,-1,0,03:00,9,24,-1,0,02:00
-324,Asia/Jerusalem,2002,Zion,120,60,3,29,-1,0,03:00,10,7,-1,0,02:00
-325,Asia/Jerusalem,2003,Zion,120,60,3,28,-1,0,03:00,10,3,-1,0,02:00
-326,Asia/Jerusalem,2004,Zion,120,60,4,7,-1,0,03:00,9,22,-1,0,02:00
-327,Asia/Jerusalem,2005,Zion,120,60,4,1,-1,0,04:00,10,9,-1,0,03:00
-328,Asia/Jerusalem,2006,Zion,120,60,3,26,5,0,04:00,10,1,-1,0,03:00
-329,Asia/Jerusalem,2007,Zion,120,60,3,26,5,0,04:00,9,16,-1,0,03:00
-330,Asia/Jerusalem,2008,Zion,120,60,3,26,5,0,04:00,10,5,-1,0,03:00
-331,Asia/Jerusalem,2009,Zion,120,60,3,26,5,0,04:00,9,27,-1,0,03:00
-332,Asia/Jerusalem,2010,Zion,120,60,3,26,5,0,04:00,9,12,-1,0,03:00
-333,Asia/Jerusalem,2011,Zion,120,60,4,1,-1,0,04:00,10,2,-1,0,03:00
-334,Asia/Jerusalem,2012,Zion,120,60,3,26,5,0,04:00,9,23,-1,0,03:00
-335,Asia/Jerusalem,2013,Zion,120,60,3,26,5,0,04:00,9,8,-1,0,03:00
-336,Asia/Jerusalem,2014,Zion,120,60,3,26,5,0,04:00,9,28,-1,0,03:00
-337,Asia/Jerusalem,2015,Zion,120,60,3,26,5,0,04:00,9,20,-1,0,03:00
-338,Asia/Jerusalem,2016,Zion,120,60,4,1,-1,0,04:00,10,9,-1,0,03:00
-339,Asia/Jerusalem,2017,Zion,120,60,3,26,5,0,04:00,9,24,-1,0,03:00
-340,Asia/Jerusalem,2018,Zion,120,60,3,26,5,0,04:00,9,16,-1,0,03:00
-341,Asia/Jerusalem,2019,Zion,120,60,3,26,5,0,04:00,10,6,-1,0,03:00
-342,Asia/Jerusalem,2020,Zion,120,60,3,26,5,0,04:00,9,27,-1,0,03:00
-343,Asia/Jerusalem,2021,Zion,120,60,3,26,5,0,04:00,9,12,-1,0,03:00
-344,Asia/Tokyo,1970,Japan,540,0,5,1,0,0,11:00,9,8,6,0,10:00
-345,Asia/Amman,1970,Jordan,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-346,Asia/Amman,1973,Jordan,120,60,6,6,-1,0,02:00,10,1,-1,0,01:00
-347,Asia/Amman,1974,Jordan,120,60,5,1,-1,0,02:00,10,1,-1,0,01:00
-348,Asia/Amman,1976,Jordan,120,60,5,1,-1,0,02:00,11,1,-1,0,01:00
-349,Asia/Amman,1977,Jordan,120,60,5,1,-1,0,02:00,10,1,-1,0,01:00
-350,Asia/Amman,1978,Jordan,120,60,4,30,-1,0,02:00,9,30,-1,0,01:00
-351,Asia/Amman,1985,Jordan,120,60,4,1,-1,0,02:00,10,1,-1,0,01:00
-352,Asia/Amman,1986,Jordan,120,60,4,1,5,0,02:00,10,1,5,0,01:00
-353,Asia/Amman,1989,Jordan,120,60,5,8,-1,0,02:00,10,1,5,0,01:00
-354,Asia/Amman,1990,Jordan,120,60,4,27,-1,0,02:00,10,1,5,0,01:00
-355,Asia/Amman,1991,Jordan,120,60,4,17,-1,0,02:00,9,27,-1,0,01:00
-356,Asia/Amman,1992,Jordan,120,60,4,10,-1,0,02:00,10,1,5,0,01:00
-357,Asia/Amman,1993,Jordan,120,60,4,1,5,0,02:00,10,1,5,0,01:00
-358,Asia/Amman,1994,Jordan,120,60,4,1,5,0,02:00,9,15,5,0,01:00
-359,Asia/Amman,1995,Jordan,120,60,4,1,5,0,02:00,9,15,5,0,02:00
-360,Asia/Amman,1999,Jordan,120,60,7,1,-1,0,02:00,9,-1,5,0,02:00
-361,Asia/Amman,2000,Jordan,120,60,3,-1,4,0,02:00,9,-1,5,0,02:00
-362,Asia/Amman,2002,Jordan,120,60,3,-1,4,0,26:00,9,-1,5,0,02:00
-363,Asia/Amman,2003,Jordan,120,60,3,-1,4,0,26:00,10,24,-1,0,02:00
-364,Asia/Amman,2004,Jordan,120,60,3,-1,4,0,26:00,10,15,-1,0,02:00
-365,Asia/Amman,2005,Jordan,120,60,3,-1,4,0,26:00,9,-1,5,0,02:00
-366,Asia/Amman,2006,Jordan,120,60,3,-1,4,0,26:00,10,-1,5,0,02:00
-367,Asia/Almaty,1970,RussiaAsia,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-368,Asia/Almaty,1981,RussiaAsia,360,60,4,1,-1,0,06:00,10,1,-1,0,05:00
-369,Asia/Almaty,1984,RussiaAsia,360,60,4,1,-1,0,06:00,9,-1,0,0,08:00
-370,Asia/Almaty,1985,RussiaAsia,360,60,3,-1,0,0,08:00,9,-1,0,0,08:00
-371,Asia/Almaty,1991,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-372,Asia/Almaty,1992,RussiaAsia,360,60,3,-1,6,0,29:00,9,-1,6,0,28:00
-373,Asia/Almaty,1993,RussiaAsia,360,60,3,-1,0,0,08:00,9,-1,0,0,08:00
-374,Asia/Almaty,1996,RussiaAsia,360,60,3,-1,0,0,08:00,10,-1,0,0,08:00
-375,Asia/Almaty,2005,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-376,Asia/Qyzylorda,1970,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-377,Asia/Qyzylorda,1981,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-378,Asia/Qyzylorda,1982,RussiaAsia,300,60,4,1,-1,0,05:00,10,1,-1,0,04:00
-379,Asia/Qyzylorda,1984,RussiaAsia,300,60,4,1,-1,0,05:00,9,-1,0,0,07:00
-380,Asia/Qyzylorda,1985,RussiaAsia,300,60,3,-1,0,0,07:00,9,-1,0,0,07:00
-381,Asia/Qyzylorda,1991,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-382,Asia/Qyzylorda,1992,RussiaAsia,360,60,3,-1,6,0,29:00,9,-1,6,0,28:00
-383,Asia/Qyzylorda,1993,RussiaAsia,360,60,3,-1,0,0,08:00,9,-1,0,0,08:00
-384,Asia/Qyzylorda,1996,RussiaAsia,360,60,3,-1,0,0,08:00,10,-1,0,0,08:00
-385,Asia/Qyzylorda,2005,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-386,Asia/Aqtobe,1970,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-387,Asia/Aqtobe,1981,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-388,Asia/Aqtobe,1982,RussiaAsia,300,60,4,1,-1,0,05:00,10,1,-1,0,04:00
-389,Asia/Aqtobe,1984,RussiaAsia,300,60,4,1,-1,0,05:00,9,-1,0,0,07:00
-390,Asia/Aqtobe,1985,RussiaAsia,300,60,3,-1,0,0,07:00,9,-1,0,0,07:00
-391,Asia/Aqtobe,1992,RussiaAsia,300,60,3,-1,6,0,28:00,9,-1,6,0,27:00
-392,Asia/Aqtobe,1993,RussiaAsia,300,60,3,-1,0,0,07:00,9,-1,0,0,07:00
-393,Asia/Aqtobe,1996,RussiaAsia,300,60,3,-1,0,0,07:00,10,-1,0,0,07:00
-394,Asia/Aqtobe,2005,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-395,Asia/Aqtau,1970,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-396,Asia/Aqtau,1981,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-397,Asia/Aqtau,1982,RussiaAsia,300,60,4,1,-1,0,05:00,10,1,-1,0,04:00
-398,Asia/Aqtau,1984,RussiaAsia,300,60,4,1,-1,0,05:00,9,-1,0,0,07:00
-399,Asia/Aqtau,1985,RussiaAsia,300,60,3,-1,0,0,07:00,9,-1,0,0,07:00
-400,Asia/Aqtau,1992,RussiaAsia,300,60,3,-1,6,0,28:00,9,-1,6,0,27:00
-401,Asia/Aqtau,1993,RussiaAsia,300,60,3,-1,0,0,07:00,9,-1,0,0,07:00
-402,Asia/Aqtau,1995,RussiaAsia,240,60,3,-1,0,0,06:00,9,-1,0,0,06:00
-403,Asia/Aqtau,1996,RussiaAsia,240,60,3,-1,0,0,06:00,10,-1,0,0,06:00
-404,Asia/Aqtau,2005,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-405,Asia/Oral,1970,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-406,Asia/Oral,1981,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-407,Asia/Oral,1982,RussiaAsia,300,60,4,1,-1,0,05:00,10,1,-1,0,04:00
-408,Asia/Oral,1984,RussiaAsia,300,60,4,1,-1,0,05:00,9,-1,0,0,07:00
-409,Asia/Oral,1985,RussiaAsia,300,60,3,-1,0,0,07:00,9,-1,0,0,07:00
-410,Asia/Oral,1989,RussiaAsia,240,60,3,-1,0,0,06:00,9,-1,0,0,06:00
-411,Asia/Oral,1992,RussiaAsia,240,60,3,-1,6,0,27:00,9,-1,6,0,26:00
-412,Asia/Oral,1993,RussiaAsia,240,60,3,-1,0,0,06:00,9,-1,0,0,06:00
-413,Asia/Oral,1996,RussiaAsia,240,60,3,-1,0,0,06:00,10,-1,0,0,06:00
-414,Asia/Oral,2005,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-415,Asia/Bishkek,1970,RussiaAsia,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-416,Asia/Bishkek,1981,RussiaAsia,360,60,4,1,-1,0,06:00,10,1,-1,0,05:00
-417,Asia/Bishkek,1984,RussiaAsia,360,60,4,1,-1,0,06:00,9,-1,0,0,08:00
-418,Asia/Bishkek,1985,RussiaAsia,360,60,3,-1,0,0,08:00,9,-1,0,0,08:00
-419,Asia/Bishkek,1991,Kyrgyz,300,60,3,-1,0,0,07:00,9,-1,0,0,07:00
-420,Asia/Bishkek,1992,Kyrgyz,300,60,4,7,0,0,05:00,9,-1,0,0,04:00
-421,Asia/Bishkek,1997,Kyrgyz,300,60,3,-1,0,0,07:30,10,-1,0,0,06:30
-422,Asia/Bishkek,2005,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-423,Asia/Seoul,1970,ROK,540,60,5,15,-1,0,09:00,9,13,-1,0,08:00
-424,Asia/Seoul,1987,ROK,540,60,5,8,0,0,09:00,10,8,0,0,08:00
-425,Asia/Seoul,1988,ROK,540,0,5,8,0,0,09:00,10,8,0,0,08:00
-426,Asia/Pyongyang,1970,,540,0,0,0,0,0,00:00,0,0,0,0,00:00
-427,Asia/Kuwait,1970,,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-428,Asia/Vientiane,1970,,420,0,0,0,0,0,00:00,0,0,0,0,00:00
-429,Asia/Beirut,1970,Lebanon,120,60,5,1,-1,0,02:00,10,1,-1,0,01:00
-430,Asia/Beirut,1972,Lebanon,120,60,6,22,-1,0,02:00,10,1,-1,0,01:00
-431,Asia/Beirut,1973,Lebanon,120,60,5,1,-1,0,02:00,10,1,-1,0,01:00
-432,Asia/Beirut,1978,Lebanon,120,60,4,30,-1,0,02:00,9,30,-1,0,01:00
-433,Asia/Beirut,1984,Lebanon,120,60,5,1,-1,0,02:00,10,16,-1,0,01:00
-434,Asia/Beirut,1988,Lebanon,120,60,6,1,-1,0,02:00,10,16,-1,0,01:00
-435,Asia/Beirut,1989,Lebanon,120,60,5,10,-1,0,02:00,10,16,-1,0,01:00
-436,Asia/Beirut,1990,Lebanon,120,60,5,1,-1,0,02:00,10,16,-1,0,01:00
-437,Asia/Beirut,1992,Lebanon,120,60,5,1,-1,0,02:00,10,4,-1,0,01:00
-438,Asia/Beirut,1993,Lebanon,120,60,3,-1,0,0,02:00,9,-1,0,0,01:00
-439,Asia/Beirut,1999,Lebanon,120,60,3,-1,0,0,02:00,10,-1,0,0,01:00
-440,Asia/Kuala_Lumpur,1970,,450,0,0,0,0,0,00:00,0,0,0,0,00:00
-441,Asia/Kuala_Lumpur,1982,,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-442,Asia/Kuching,1970,,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-443,Asia/Kuching,1982,,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-444,Indian/Maldives,1970,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-445,Asia/Hovd,1970,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-446,Asia/Hovd,1978,Mongol,420,0,0,0,0,0,00:00,0,0,0,0,00:00
-447,Asia/Hovd,1983,Mongol,420,60,4,1,-1,0,07:00,10,1,-1,0,06:00
-448,Asia/Hovd,1984,Mongol,420,60,4,1,-1,0,07:00,9,-1,0,0,06:00
-449,Asia/Hovd,1985,Mongol,420,60,3,-1,0,0,07:00,9,-1,0,0,06:00
-450,Asia/Hovd,2001,Mongol,420,60,4,-1,6,0,09:00,9,-1,6,0,08:00
-451,Asia/Hovd,2002,Mongol,420,60,3,-1,6,0,09:00,9,-1,6,0,08:00
-452,Asia/Hovd,2006,Mongol,420,0,3,-1,6,0,09:00,9,-1,6,0,08:00
-453,Asia/Ulaanbaatar,1970,,420,0,0,0,0,0,00:00,0,0,0,0,00:00
-454,Asia/Ulaanbaatar,1978,Mongol,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-455,Asia/Ulaanbaatar,1983,Mongol,480,60,4,1,-1,0,08:00,10,1,-1,0,07:00
-456,Asia/Ulaanbaatar,1984,Mongol,480,60,4,1,-1,0,08:00,9,-1,0,0,07:00
-457,Asia/Ulaanbaatar,1985,Mongol,480,60,3,-1,0,0,08:00,9,-1,0,0,07:00
-458,Asia/Ulaanbaatar,2001,Mongol,480,60,4,-1,6,0,10:00,9,-1,6,0,09:00
-459,Asia/Ulaanbaatar,2002,Mongol,480,60,3,-1,6,0,10:00,9,-1,6,0,09:00
-460,Asia/Ulaanbaatar,2006,Mongol,480,0,3,-1,6,0,10:00,9,-1,6,0,09:00
-461,Asia/Choibalsan,1970,,420,0,0,0,0,0,00:00,0,0,0,0,00:00
-462,Asia/Choibalsan,1978,,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-463,Asia/Choibalsan,1983,Mongol,540,60,4,1,-1,0,09:00,10,1,-1,0,08:00
-464,Asia/Choibalsan,1984,Mongol,540,60,4,1,-1,0,09:00,9,-1,0,0,08:00
-465,Asia/Choibalsan,1985,Mongol,540,60,3,-1,0,0,09:00,9,-1,0,0,08:00
-466,Asia/Choibalsan,2001,Mongol,540,60,4,-1,6,0,11:00,9,-1,6,0,10:00
-467,Asia/Choibalsan,2002,Mongol,540,60,3,-1,6,0,11:00,9,-1,6,0,10:00
-468,Asia/Choibalsan,2006,Mongol,540,0,3,-1,6,0,11:00,9,-1,6,0,10:00
-469,Asia/Choibalsan,2008,Mongol,480,0,3,-1,6,0,10:00,9,-1,6,0,09:00
-470,Asia/Kathmandu,1970,,330,0,0,0,0,0,00:00,0,0,0,0,00:00
-471,Asia/Kathmandu,1986,,345,0,0,0,0,0,00:00,0,0,0,0,00:00
-472,Asia/Muscat,1970,,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-473,Asia/Karachi,1970,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-474,Asia/Karachi,1971,Pakistan,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-475,Asia/Karachi,2002,Pakistan,300,60,4,2,0,0,05:01,10,2,0,0,04:01
-476,Asia/Karachi,2008,Pakistan,300,60,6,1,-1,0,05:00,11,1,-1,0,04:00
-477,Asia/Karachi,2009,Pakistan,300,60,4,15,-1,0,05:00,11,1,-1,0,04:00
-478,Asia/Karachi,2010,Pakistan,300,0,4,15,-1,0,05:00,11,1,-1,0,04:00
-479,Asia/Gaza,1970,Zion,120,60,4,29,-1,0,04:00,9,22,-1,0,01:00
-480,Asia/Gaza,1974,Zion,120,60,7,7,-1,0,02:00,10,13,-1,0,01:00
-481,Asia/Gaza,1975,Zion,120,60,4,20,-1,0,02:00,8,31,-1,0,01:00
-482,Asia/Gaza,1985,Zion,120,60,4,14,-1,0,02:00,9,15,-1,0,01:00
-483,Asia/Gaza,1986,Zion,120,60,5,18,-1,0,02:00,9,7,-1,0,01:00
-484,Asia/Gaza,1987,Zion,120,60,4,15,-1,0,02:00,9,13,-1,0,01:00
-485,Asia/Gaza,1988,Zion,120,60,4,9,-1,0,02:00,9,3,-1,0,01:00
-486,Asia/Gaza,1989,Zion,120,60,4,30,-1,0,02:00,9,3,-1,0,01:00
-487,Asia/Gaza,1990,Zion,120,60,3,25,-1,0,02:00,8,26,-1,0,01:00
-488,Asia/Gaza,1991,Zion,120,60,3,24,-1,0,02:00,9,1,-1,0,01:00
-489,Asia/Gaza,1992,Zion,120,60,3,29,-1,0,02:00,9,6,-1,0,01:00
-490,Asia/Gaza,1993,Zion,120,60,4,2,-1,0,02:00,9,5,-1,0,01:00
-491,Asia/Gaza,1994,Zion,120,60,4,1,-1,0,02:00,8,28,-1,0,01:00
-492,Asia/Gaza,1995,Zion,120,60,3,31,-1,0,02:00,9,3,-1,0,01:00
-493,Asia/Gaza,1996,Jordan,120,60,4,1,5,0,02:00,9,15,5,0,02:00
-494,Asia/Gaza,1999,Palestine,120,60,4,15,5,0,02:00,10,15,5,0,01:00
-495,Asia/Gaza,2004,Palestine,120,60,4,15,5,0,02:00,10,1,-1,0,02:00
-496,Asia/Gaza,2005,Palestine,120,60,4,15,5,0,02:00,10,4,-1,0,03:00
-497,Asia/Gaza,2006,Palestine,120,60,4,1,-1,0,02:00,9,22,-1,0,01:00
-498,Asia/Gaza,2007,Palestine,120,60,4,1,-1,0,02:00,9,8,4,0,03:00
-499,Asia/Gaza,2008,Palestine,120,60,4,1,-1,0,02:00,8,-1,5,0,01:00
-500,Asia/Gaza,2009,Palestine,120,60,3,-1,5,0,02:00,9,1,5,0,03:00
-501,Asia/Gaza,2010,Palestine,120,60,3,-1,6,0,02:01,8,11,-1,0,01:00
-502,Asia/Gaza,2011,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-503,Asia/Hebron,1970,Zion,120,60,4,29,-1,0,04:00,9,22,-1,0,01:00
-504,Asia/Hebron,1974,Zion,120,60,7,7,-1,0,02:00,10,13,-1,0,01:00
-505,Asia/Hebron,1975,Zion,120,60,4,20,-1,0,02:00,8,31,-1,0,01:00
-506,Asia/Hebron,1985,Zion,120,60,4,14,-1,0,02:00,9,15,-1,0,01:00
-507,Asia/Hebron,1986,Zion,120,60,5,18,-1,0,02:00,9,7,-1,0,01:00
-508,Asia/Hebron,1987,Zion,120,60,4,15,-1,0,02:00,9,13,-1,0,01:00
-509,Asia/Hebron,1988,Zion,120,60,4,9,-1,0,02:00,9,3,-1,0,01:00
-510,Asia/Hebron,1989,Zion,120,60,4,30,-1,0,02:00,9,3,-1,0,01:00
-511,Asia/Hebron,1990,Zion,120,60,3,25,-1,0,02:00,8,26,-1,0,01:00
-512,Asia/Hebron,1991,Zion,120,60,3,24,-1,0,02:00,9,1,-1,0,01:00
-513,Asia/Hebron,1992,Zion,120,60,3,29,-1,0,02:00,9,6,-1,0,01:00
-514,Asia/Hebron,1993,Zion,120,60,4,2,-1,0,02:00,9,5,-1,0,01:00
-515,Asia/Hebron,1994,Zion,120,60,4,1,-1,0,02:00,8,28,-1,0,01:00
-516,Asia/Hebron,1995,Zion,120,60,3,31,-1,0,02:00,9,3,-1,0,01:00
-517,Asia/Hebron,1996,Jordan,120,60,4,1,5,0,02:00,9,15,5,0,02:00
-518,Asia/Hebron,1999,Palestine,120,60,4,15,5,0,02:00,10,15,5,0,01:00
-519,Asia/Hebron,2004,Palestine,120,60,4,15,5,0,02:00,10,1,-1,0,02:00
-520,Asia/Hebron,2005,Palestine,120,60,4,15,5,0,02:00,10,4,-1,0,03:00
-521,Asia/Hebron,2006,Palestine,120,60,4,1,-1,0,02:00,9,22,-1,0,01:00
-522,Asia/Hebron,2007,Palestine,120,60,4,1,-1,0,02:00,9,8,4,0,03:00
-523,Asia/Hebron,2008,Palestine,120,60,4,1,-1,0,02:00,8,-1,5,0,01:00
-524,Asia/Hebron,2009,Palestine,120,60,3,-1,5,0,02:00,9,1,5,0,03:00
-525,Asia/Hebron,2010,Palestine,120,60,3,-1,6,0,02:01,8,11,-1,0,01:00
-526,Asia/Hebron,2011,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-527,Asia/Manila,1970,Phil,480,60,4,12,-1,0,08:00,7,1,-1,0,07:00
-528,Asia/Manila,1978,Phil,480,60,3,22,-1,0,08:00,9,21,-1,0,07:00
-529,Asia/Manila,1979,Phil,480,0,3,22,-1,0,08:00,9,21,-1,0,07:00
-530,Asia/Qatar,1970,,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-531,Asia/Qatar,1972,,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-532,Asia/Riyadh,1970,,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-533,Asia/Singapore,1970,,450,0,0,0,0,0,00:00,0,0,0,0,00:00
-534,Asia/Singapore,1982,,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-535,Asia/Colombo,1970,,330,0,0,0,0,0,00:00,0,0,0,0,00:00
-536,Asia/Colombo,1996,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-537,Asia/Colombo,2006,,330,0,0,0,0,0,00:00,0,0,0,0,00:00
-538,Asia/Damascus,1970,Syria,120,60,5,1,-1,0,04:00,10,1,-1,0,03:00
-539,Asia/Damascus,1977,Syria,120,60,5,1,-1,0,04:00,9,1,-1,0,03:00
-540,Asia/Damascus,1983,Syria,120,60,4,9,-1,0,04:00,10,1,-1,0,03:00
-541,Asia/Damascus,1986,Syria,120,60,2,16,-1,0,04:00,10,9,-1,0,03:00
-542,Asia/Damascus,1987,Syria,120,60,3,1,-1,0,04:00,10,31,-1,0,03:00
-543,Asia/Damascus,1988,Syria,120,60,3,15,-1,0,04:00,10,31,-1,0,03:00
-544,Asia/Damascus,1989,Syria,120,60,3,31,-1,0,04:00,10,1,-1,0,03:00
-545,Asia/Damascus,1990,Syria,120,60,4,1,-1,0,04:00,9,30,-1,0,03:00
-546,Asia/Damascus,1991,Syria,120,60,4,1,-1,0,02:00,10,1,-1,0,01:00
-547,Asia/Damascus,1992,Syria,120,60,4,8,-1,0,02:00,10,1,-1,0,01:00
-548,Asia/Damascus,1993,Syria,120,60,3,26,-1,0,02:00,9,25,-1,0,01:00
-549,Asia/Damascus,1994,Syria,120,60,4,1,-1,0,02:00,10,1,-1,0,01:00
-550,Asia/Damascus,1997,Syria,120,60,3,-1,1,0,02:00,10,1,-1,0,01:00
-551,Asia/Damascus,1999,Syria,120,60,4,1,-1,0,02:00,10,1,-1,0,01:00
-552,Asia/Damascus,2006,Syria,120,60,4,1,-1,0,02:00,9,22,-1,0,01:00
-553,Asia/Damascus,2007,Syria,120,60,3,-1,5,0,02:00,11,1,5,0,01:00
-554,Asia/Damascus,2008,Syria,120,60,4,1,5,0,02:00,11,1,-1,0,01:00
-555,Asia/Damascus,2009,Syria,120,60,3,-1,5,0,02:00,10,-1,5,0,01:00
-556,Asia/Damascus,2010,Syria,120,60,4,1,5,0,02:00,10,-1,5,0,01:00
-557,Asia/Dushanbe,1970,RussiaAsia,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-558,Asia/Dushanbe,1981,RussiaAsia,360,60,4,1,-1,0,06:00,10,1,-1,0,05:00
-559,Asia/Dushanbe,1984,RussiaAsia,360,60,4,1,-1,0,06:00,9,-1,0,0,08:00
-560,Asia/Dushanbe,1985,RussiaAsia,360,60,3,-1,0,0,08:00,9,-1,0,0,08:00
-561,Asia/Dushanbe,1991,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-562,Asia/Bangkok,1970,,420,0,0,0,0,0,00:00,0,0,0,0,00:00
-563,Asia/Ashgabat,1970,RussiaAsia,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-564,Asia/Ashgabat,1981,RussiaAsia,300,60,4,1,-1,0,05:00,10,1,-1,0,04:00
-565,Asia/Ashgabat,1984,RussiaAsia,300,60,4,1,-1,0,05:00,9,-1,0,0,07:00
-566,Asia/Ashgabat,1985,RussiaAsia,300,60,3,-1,0,0,07:00,9,-1,0,0,07:00
-567,Asia/Ashgabat,1991,RussiaAsia,240,60,3,-1,0,0,06:00,9,-1,0,0,06:00
-568,Asia/Ashgabat,1992,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-569,Asia/Dubai,1970,,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-570,Asia/Samarkand,1970,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-571,Asia/Samarkand,1981,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-572,Asia/Samarkand,1982,RussiaAsia,300,60,4,1,-1,0,05:00,10,1,-1,0,04:00
-573,Asia/Samarkand,1984,RussiaAsia,300,60,4,1,-1,0,05:00,9,-1,0,0,07:00
-574,Asia/Samarkand,1985,RussiaAsia,300,60,3,-1,0,0,07:00,9,-1,0,0,07:00
-575,Asia/Samarkand,1992,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-576,Asia/Tashkent,1970,RussiaAsia,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-577,Asia/Tashkent,1981,RussiaAsia,360,60,4,1,-1,0,06:00,10,1,-1,0,05:00
-578,Asia/Tashkent,1984,RussiaAsia,360,60,4,1,-1,0,06:00,9,-1,0,0,08:00
-579,Asia/Tashkent,1985,RussiaAsia,360,60,3,-1,0,0,08:00,9,-1,0,0,08:00
-580,Asia/Tashkent,1991,RussiaAsia,300,60,3,-1,0,0,07:00,9,-1,0,0,07:00
-581,Asia/Tashkent,1992,,300,0,0,0,0,0,00:00,0,0,0,0,00:00
-582,Asia/Ho_Chi_Minh,1970,,420,0,0,0,0,0,00:00,0,0,0,0,00:00
-583,Asia/Aden,1970,,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-584,Australia/Darwin,1970,Aus,570,0,12,31,-1,0,21:30,3,-1,0,0,10:30
-585,Australia/Perth,1970,AW,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-586,Australia/Perth,1974,AW,480,60,10,-1,0,0,10:00,1,1,-1,0,19:00
-587,Australia/Perth,1975,AW,480,0,12,31,-1,0,20:00,3,1,0,0,10:00
-588,Australia/Perth,1983,AW,480,60,10,-1,0,0,10:00,1,1,-1,0,19:00
-589,Australia/Perth,1984,AW,480,0,12,31,-1,0,20:00,3,1,0,0,10:00
-590,Australia/Perth,1991,AW,480,60,11,17,-1,0,10:00,1,1,-1,0,19:00
-591,Australia/Perth,1992,AW,480,0,12,31,-1,0,20:00,3,1,0,0,10:00
-592,Australia/Perth,2006,AW,480,60,12,3,-1,0,10:00,1,1,-1,0,19:00
-593,Australia/Perth,2007,AW,480,60,10,-1,0,0,10:00,3,-1,0,0,10:00
-594,Australia/Perth,2009,AW,480,0,12,31,-1,0,20:00,3,-1,0,0,10:00
-595,Australia/Eucla,1970,AW,525,0,0,0,0,0,00:00,0,0,0,0,00:00
-596,Australia/Eucla,1974,AW,525,60,10,-1,0,0,10:45,1,1,-1,0,19:45
-597,Australia/Eucla,1975,AW,525,0,12,31,-1,0,20:45,3,1,0,0,10:45
-598,Australia/Eucla,1983,AW,525,60,10,-1,0,0,10:45,1,1,-1,0,19:45
-599,Australia/Eucla,1984,AW,525,0,12,31,-1,0,20:45,3,1,0,0,10:45
-600,Australia/Eucla,1991,AW,525,60,11,17,-1,0,10:45,1,1,-1,0,19:45
-601,Australia/Eucla,1992,AW,525,0,12,31,-1,0,20:45,3,1,0,0,10:45
-602,Australia/Eucla,2006,AW,525,60,12,3,-1,0,10:45,1,1,-1,0,19:45
-603,Australia/Eucla,2007,AW,525,60,10,-1,0,0,10:45,3,-1,0,0,10:45
-604,Australia/Eucla,2009,AW,525,0,12,31,-1,0,20:45,3,-1,0,0,10:45
-605,Australia/Brisbane,1970,Aus,600,0,12,31,-1,0,22:00,3,-1,0,0,11:00
-606,Australia/Brisbane,1971,AQ,600,60,10,-1,0,0,12:00,1,1,-1,0,21:00
-607,Australia/Brisbane,1972,AQ,600,0,12,31,-1,0,22:00,2,-1,0,0,12:00
-608,Australia/Brisbane,1989,AQ,600,60,10,-1,0,0,12:00,1,1,-1,0,21:00
-609,Australia/Brisbane,1990,AQ,600,60,10,-1,0,0,12:00,3,1,0,0,12:00
-610,Australia/Brisbane,1992,AQ,600,0,12,31,-1,0,22:00,3,1,0,0,12:00
-611,Australia/Lindeman,1970,Aus,600,0,12,31,-1,0,22:00,3,-1,0,0,11:00
-612,Australia/Lindeman,1971,AQ,600,60,10,-1,0,0,12:00,1,1,-1,0,21:00
-613,Australia/Lindeman,1972,AQ,600,0,12,31,-1,0,22:00,2,-1,0,0,12:00
-614,Australia/Lindeman,1989,AQ,600,60,10,-1,0,0,12:00,1,1,-1,0,21:00
-615,Australia/Lindeman,1990,AQ,600,60,10,-1,0,0,12:00,3,1,0,0,12:00
-616,Australia/Lindeman,1992,Holiday,600,60,10,-1,0,0,12:00,1,1,-1,0,21:00
-617,Australia/Lindeman,1993,Holiday,600,60,10,-1,0,0,12:00,3,1,0,0,12:00
-618,Australia/Lindeman,1994,Holiday,600,0,12,31,-1,0,22:00,3,1,0,0,12:00
-619,Australia/Adelaide,1970,Aus,570,0,12,31,-1,0,21:30,3,-1,0,0,10:30
-620,Australia/Adelaide,1971,AS,570,60,10,-1,0,0,11:30,1,1,-1,0,20:30
-621,Australia/Adelaide,1972,AS,570,60,10,-1,0,0,11:30,2,27,-1,0,11:30
-622,Australia/Adelaide,1973,AS,570,60,10,-1,0,0,11:30,3,1,0,0,11:30
-623,Australia/Adelaide,1986,AS,570,60,10,19,-1,0,11:30,3,15,0,0,11:30
-624,Australia/Adelaide,1987,AS,570,60,10,-1,0,0,11:30,3,15,0,0,11:30
-625,Australia/Adelaide,1991,AS,570,60,10,-1,0,0,11:30,3,3,-1,0,11:30
-626,Australia/Adelaide,1992,AS,570,60,10,-1,0,0,11:30,3,22,-1,0,11:30
-627,Australia/Adelaide,1993,AS,570,60,10,-1,0,0,11:30,3,7,-1,0,11:30
-628,Australia/Adelaide,1994,AS,570,60,10,-1,0,0,11:30,3,20,-1,0,11:30
-629,Australia/Adelaide,1995,AS,570,60,10,-1,0,0,11:30,3,-1,0,0,11:30
-630,Australia/Adelaide,2006,AS,570,60,10,-1,0,0,11:30,4,2,-1,0,11:30
-631,Australia/Adelaide,2007,AS,570,60,10,-1,0,0,11:30,3,-1,0,0,11:30
-632,Australia/Adelaide,2008,AS,570,60,10,1,0,0,11:30,4,1,0,0,11:30
-633,Australia/Hobart,1970,AT,600,60,10,-1,0,0,12:00,3,8,0,0,12:00
-634,Australia/Hobart,1972,AT,600,60,10,-1,0,0,12:00,2,-1,0,0,12:00
-635,Australia/Hobart,1973,AT,600,60,10,-1,0,0,12:00,3,1,0,0,12:00
-636,Australia/Hobart,1982,AT,600,60,10,-1,0,0,12:00,3,-1,0,0,12:00
-637,Australia/Hobart,1984,AT,600,60,10,-1,0,0,12:00,3,1,0,0,12:00
-638,Australia/Hobart,1986,AT,600,60,10,15,0,0,12:00,3,1,0,0,12:00
-639,Australia/Hobart,1987,AT,600,60,10,22,0,0,12:00,3,15,0,0,12:00
-640,Australia/Hobart,1988,AT,600,60,10,-1,0,0,12:00,3,15,0,0,12:00
-641,Australia/Hobart,1991,AT,600,60,10,1,0,0,12:00,3,-1,0,0,12:00
-642,Australia/Hobart,2000,AT,600,60,8,-1,0,0,12:00,3,-1,0,0,12:00
-643,Australia/Hobart,2001,AT,600,60,10,1,0,0,12:00,3,-1,0,0,12:00
-644,Australia/Hobart,2006,AT,600,60,10,1,0,0,12:00,4,1,0,0,12:00
-645,Australia/Hobart,2007,AT,600,60,10,1,0,0,12:00,3,-1,0,0,12:00
-646,Australia/Hobart,2008,AT,600,60,10,1,0,0,12:00,4,1,0,0,12:00
-647,Australia/Currie,1970,Aus,600,0,12,31,-1,0,22:00,3,-1,0,0,11:00
-648,Australia/Currie,1971,AT,600,60,10,-1,0,0,12:00,3,8,0,0,12:00
-649,Australia/Currie,1972,AT,600,60,10,-1,0,0,12:00,2,-1,0,0,12:00
-650,Australia/Currie,1973,AT,600,60,10,-1,0,0,12:00,3,1,0,0,12:00
-651,Australia/Currie,1982,AT,600,60,10,-1,0,0,12:00,3,-1,0,0,12:00
-652,Australia/Currie,1984,AT,600,60,10,-1,0,0,12:00,3,1,0,0,12:00
-653,Australia/Currie,1986,AT,600,60,10,15,0,0,12:00,3,1,0,0,12:00
-654,Australia/Currie,1987,AT,600,60,10,22,0,0,12:00,3,15,0,0,12:00
-655,Australia/Currie,1988,AT,600,60,10,-1,0,0,12:00,3,15,0,0,12:00
-656,Australia/Currie,1991,AT,600,60,10,1,0,0,12:00,3,-1,0,0,12:00
-657,Australia/Currie,2000,AT,600,60,8,-1,0,0,12:00,3,-1,0,0,12:00
-658,Australia/Currie,2001,AT,600,60,10,1,0,0,12:00,3,-1,0,0,12:00
-659,Australia/Currie,2006,AT,600,60,10,1,0,0,12:00,4,1,0,0,12:00
-660,Australia/Currie,2007,AT,600,60,10,1,0,0,12:00,3,-1,0,0,12:00
-661,Australia/Currie,2008,AT,600,60,10,1,0,0,12:00,4,1,0,0,12:00
-662,Australia/Melbourne,1970,Aus,600,0,12,31,-1,0,22:00,3,-1,0,0,11:00
-663,Australia/Melbourne,1971,AV,600,60,10,-1,0,0,12:00,1,1,-1,0,21:00
-664,Australia/Melbourne,1972,AV,600,60,10,-1,0,0,12:00,2,-1,0,0,12:00
-665,Australia/Melbourne,1973,AV,600,60,10,-1,0,0,12:00,3,1,0,0,12:00
-666,Australia/Melbourne,1986,AV,600,60,10,15,0,0,12:00,3,15,0,0,12:00
-667,Australia/Melbourne,1988,AV,600,60,10,-1,0,0,12:00,3,15,0,0,12:00
-668,Australia/Melbourne,1991,AV,600,60,10,-1,0,0,12:00,3,1,0,0,12:00
-669,Australia/Melbourne,1995,AV,600,60,10,-1,0,0,12:00,3,-1,0,0,12:00
-670,Australia/Melbourne,2000,AV,600,60,8,-1,0,0,12:00,3,-1,0,0,12:00
-671,Australia/Melbourne,2001,AV,600,60,10,-1,0,0,12:00,3,-1,0,0,12:00
-672,Australia/Melbourne,2006,AV,600,60,10,-1,0,0,12:00,4,1,0,0,12:00
-673,Australia/Melbourne,2007,AV,600,60,10,-1,0,0,12:00,3,-1,0,0,12:00
-674,Australia/Melbourne,2008,AV,600,60,10,1,0,0,12:00,4,1,0,0,12:00
-675,Australia/Sydney,1970,Aus,600,0,12,31,-1,0,22:00,3,-1,0,0,11:00
-676,Australia/Sydney,1971,AN,600,60,10,-1,0,0,12:00,1,1,-1,0,21:00
-677,Australia/Sydney,1972,AN,600,60,10,-1,0,0,12:00,2,27,-1,0,12:00
-678,Australia/Sydney,1973,AN,600,60,10,-1,0,0,12:00,3,1,0,0,12:00
-679,Australia/Sydney,1982,AN,600,60,10,-1,0,0,12:00,4,1,0,0,12:00
-680,Australia/Sydney,1983,AN,600,60,10,-1,0,0,12:00,3,1,0,0,12:00
-681,Australia/Sydney,1986,AN,600,60,10,19,-1,0,12:00,3,15,0,0,12:00
-682,Australia/Sydney,1987,AN,600,60,10,-1,0,0,12:00,3,15,0,0,12:00
-683,Australia/Sydney,1990,AN,600,60,10,-1,0,0,12:00,3,1,0,0,12:00
-684,Australia/Sydney,1996,AN,600,60,10,-1,0,0,12:00,3,-1,0,0,12:00
-685,Australia/Sydney,2000,AN,600,60,8,-1,0,0,12:00,3,-1,0,0,12:00
-686,Australia/Sydney,2001,AN,600,60,10,-1,0,0,12:00,3,-1,0,0,12:00
-687,Australia/Sydney,2006,AN,600,60,10,-1,0,0,12:00,4,1,0,0,12:00
-688,Australia/Sydney,2007,AN,600,60,10,-1,0,0,12:00,3,-1,0,0,12:00
-689,Australia/Sydney,2008,AN,600,60,10,1,0,0,12:00,4,1,0,0,12:00
-690,Australia/Broken_Hill,1970,Aus,570,0,12,31,-1,0,21:30,3,-1,0,0,10:30
-691,Australia/Broken_Hill,1971,AN,570,60,10,-1,0,0,11:30,1,1,-1,0,20:30
-692,Australia/Broken_Hill,1972,AN,570,60,10,-1,0,0,11:30,2,27,-1,0,11:30
-693,Australia/Broken_Hill,1973,AN,570,60,10,-1,0,0,11:30,3,1,0,0,11:30
-694,Australia/Broken_Hill,1982,AN,570,60,10,-1,0,0,11:30,4,1,0,0,11:30
-695,Australia/Broken_Hill,1983,AN,570,60,10,-1,0,0,11:30,3,1,0,0,11:30
-696,Australia/Broken_Hill,1986,AN,570,60,10,19,-1,0,11:30,3,15,0,0,11:30
-697,Australia/Broken_Hill,1987,AN,570,60,10,-1,0,0,11:30,3,15,0,0,11:30
-698,Australia/Broken_Hill,1990,AN,570,60,10,-1,0,0,11:30,3,1,0,0,11:30
-699,Australia/Broken_Hill,1996,AN,570,60,10,-1,0,0,11:30,3,-1,0,0,11:30
-700,Australia/Broken_Hill,2000,AS,570,60,10,-1,0,0,11:30,3,-1,0,0,11:30
-701,Australia/Broken_Hill,2006,AS,570,60,10,-1,0,0,11:30,4,2,-1,0,11:30
-702,Australia/Broken_Hill,2007,AS,570,60,10,-1,0,0,11:30,3,-1,0,0,11:30
-703,Australia/Broken_Hill,2008,AS,570,60,10,1,0,0,11:30,4,1,0,0,11:30
-704,Australia/Lord_Howe,1970,,600,0,0,0,0,0,00:00,0,0,0,0,00:00
-705,Australia/Lord_Howe,1981,LH,630,60,10,-1,0,0,12:30,1,1,-1,0,21:30
-706,Australia/Lord_Howe,1982,LH,630,60,10,-1,0,0,12:30,3,1,0,0,11:30
-707,Australia/Lord_Howe,1985,LH,630,30,10,-1,0,0,12:30,3,1,0,0,11:30
-708,Australia/Lord_Howe,1986,LH,630,30,10,19,-1,0,12:30,3,15,0,0,11:30
-709,Australia/Lord_Howe,1987,LH,630,30,10,-1,0,0,12:30,3,15,0,0,11:30
-710,Australia/Lord_Howe,1990,LH,630,30,10,-1,0,0,12:30,3,1,0,0,11:30
-711,Australia/Lord_Howe,1996,LH,630,30,10,-1,0,0,12:30,3,-1,0,0,11:30
-712,Australia/Lord_Howe,2000,LH,630,30,8,-1,0,0,12:30,3,-1,0,0,11:30
-713,Australia/Lord_Howe,2001,LH,630,30,10,-1,0,0,12:30,3,-1,0,0,11:30
-714,Australia/Lord_Howe,2006,LH,630,30,10,-1,0,0,12:30,4,1,0,0,11:30
-715,Australia/Lord_Howe,2007,LH,630,30,10,-1,0,0,12:30,3,-1,0,0,11:30
-716,Australia/Lord_Howe,2008,LH,630,30,10,1,0,0,12:30,4,1,0,0,11:30
-717,Indian/Christmas,1970,,420,0,0,0,0,0,00:00,0,0,0,0,00:00
-718,Pacific/Rarotonga,1970,,-630,0,0,0,0,0,00:00,0,0,0,0,00:00
-719,Pacific/Rarotonga,1978,Cook,-600,30,11,12,-1,0,-10:00,1,1,-1,0,01:00
-720,Pacific/Rarotonga,1979,Cook,-600,30,10,-1,0,0,-10:00,3,1,0,0,-11:00
-721,Pacific/Rarotonga,1991,Cook,-600,0,12,31,-1,0,02:00,3,1,0,0,-11:00
-722,Indian/Cocos,1970,,390,0,0,0,0,0,00:00,0,0,0,0,00:00
-723,Pacific/Fiji,1970,Fiji,720,0,0,0,0,0,00:00,0,0,0,0,00:00
-724,Pacific/Fiji,1998,Fiji,720,60,11,1,0,0,14:00,1,1,-1,0,23:00
-725,Pacific/Fiji,1999,Fiji,720,60,11,1,0,0,14:00,2,-1,0,0,14:00
-726,Pacific/Fiji,2000,Fiji,720,0,12,31,-1,0,24:00,2,-1,0,0,14:00
-727,Pacific/Fiji,2009,Fiji,720,60,11,29,-1,0,14:00,1,1,-1,0,23:00
-728,Pacific/Fiji,2010,Fiji,720,60,10,24,-1,0,14:00,3,-1,0,0,14:00
-729,Pacific/Fiji,2011,Fiji,720,60,10,23,-1,0,14:00,3,1,0,0,14:00
-730,Pacific/Fiji,2012,Fiji,720,0,12,31,-1,0,24:00,1,22,-1,0,14:00
-731,Pacific/Gambier,1970,,-540,0,0,0,0,0,00:00,0,0,0,0,00:00
-732,Pacific/Marquesas,1970,,-570,0,0,0,0,0,00:00,0,0,0,0,00:00
-733,Pacific/Tahiti,1970,,-600,0,0,0,0,0,00:00,0,0,0,0,00:00
-734,Pacific/Guam,1970,,600,0,0,0,0,0,00:00,0,0,0,0,00:00
-735,Pacific/Guam,2000,,600,0,0,0,0,0,00:00,0,0,0,0,00:00
-736,Pacific/Tarawa,1970,,720,0,0,0,0,0,00:00,0,0,0,0,00:00
-737,Pacific/Enderbury,1970,,-720,0,0,0,0,0,00:00,0,0,0,0,00:00
-738,Pacific/Enderbury,1979,,-660,0,0,0,0,0,00:00,0,0,0,0,00:00
-739,Pacific/Enderbury,1995,,780,0,0,0,0,0,00:00,0,0,0,0,00:00
-740,Pacific/Kiritimati,1970,,-640,0,0,0,0,0,00:00,0,0,0,0,00:00
-741,Pacific/Kiritimati,1979,,-600,0,0,0,0,0,00:00,0,0,0,0,00:00
-742,Pacific/Kiritimati,1995,,840,0,0,0,0,0,00:00,0,0,0,0,00:00
-743,Pacific/Saipan,1970,,600,0,0,0,0,0,00:00,0,0,0,0,00:00
-744,Pacific/Saipan,2000,,600,0,0,0,0,0,00:00,0,0,0,0,00:00
-745,Pacific/Majuro,1970,,720,0,0,0,0,0,00:00,0,0,0,0,00:00
-746,Pacific/Kwajalein,1970,,-720,0,0,0,0,0,00:00,0,0,0,0,00:00
-747,Pacific/Kwajalein,1993,,720,0,0,0,0,0,00:00,0,0,0,0,00:00
-748,Pacific/Chuuk,1970,,600,0,0,0,0,0,00:00,0,0,0,0,00:00
-749,Pacific/Pohnpei,1970,,660,0,0,0,0,0,00:00,0,0,0,0,00:00
-750,Pacific/Kosrae,1970,,720,0,0,0,0,0,00:00,0,0,0,0,00:00
-751,Pacific/Kosrae,1999,,660,0,0,0,0,0,00:00,0,0,0,0,00:00
-752,Pacific/Nauru,1970,,690,0,0,0,0,0,00:00,0,0,0,0,00:00
-753,Pacific/Nauru,1979,,720,0,0,0,0,0,00:00,0,0,0,0,00:00
-754,Pacific/Noumea,1970,NC,660,0,0,0,0,0,00:00,0,0,0,0,00:00
-755,Pacific/Noumea,1977,NC,660,60,12,1,0,0,11:00,1,1,-1,0,22:00
-756,Pacific/Noumea,1978,NC,660,60,12,1,0,0,11:00,2,27,-1,0,10:00
-757,Pacific/Noumea,1979,NC,660,0,12,31,-1,0,23:00,2,27,-1,0,10:00
-758,Pacific/Noumea,1996,NC,660,60,12,1,-1,0,13:00,1,1,-1,0,22:00
-759,Pacific/Noumea,1997,NC,660,0,12,31,-1,0,23:00,3,2,-1,0,13:00
-760,Pacific/Auckland,1970,NZ,720,0,12,31,-1,0,24:00,1,1,-1,0,11:00
-761,Pacific/Auckland,1974,NZ,720,60,11,1,0,0,14:00,1,1,-1,0,23:00
-762,Pacific/Auckland,1975,NZ,720,60,10,-1,0,0,14:00,2,-1,0,0,14:00
-763,Pacific/Auckland,1976,NZ,720,60,10,-1,0,0,14:00,3,1,0,0,14:00
-764,Pacific/Auckland,1989,NZ,720,60,10,8,0,0,14:00,3,1,0,0,14:00
-765,Pacific/Auckland,1990,NZ,720,60,10,1,0,0,14:00,3,15,0,0,14:00
-766,Pacific/Auckland,2007,NZ,720,60,9,-1,0,0,14:00,3,15,0,0,14:00
-767,Pacific/Auckland,2008,NZ,720,60,9,-1,0,0,14:00,4,1,0,0,14:00
-768,Pacific/Chatham,1970,Chatham,765,0,0,0,0,0,00:00,0,0,0,0,00:00
-769,Pacific/Chatham,1974,Chatham,765,60,11,1,0,0,15:30,1,1,-1,0,23:45
-770,Pacific/Chatham,1975,Chatham,765,60,10,-1,0,0,15:30,2,-1,0,0,15:30
-771,Pacific/Chatham,1976,Chatham,765,60,10,-1,0,0,15:30,3,1,0,0,15:30
-772,Pacific/Chatham,1989,Chatham,765,60,10,8,0,0,15:30,3,1,0,0,15:30
-773,Pacific/Chatham,1990,Chatham,765,60,10,1,0,0,15:30,3,15,0,0,15:30
-774,Pacific/Chatham,2007,Chatham,765,60,9,-1,0,0,15:30,3,15,0,0,15:30
-775,Pacific/Chatham,2008,Chatham,765,60,9,-1,0,0,15:30,4,1,0,0,15:30
-776,Pacific/Niue,1970,,-690,0,0,0,0,0,00:00,0,0,0,0,00:00
-777,Pacific/Niue,1978,,-660,0,0,0,0,0,00:00,0,0,0,0,00:00
-778,Pacific/Norfolk,1970,,690,0,0,0,0,0,00:00,0,0,0,0,00:00
-779,Pacific/Palau,1970,,540,0,0,0,0,0,00:00,0,0,0,0,00:00
-780,Pacific/Port_Moresby,1970,,600,0,0,0,0,0,00:00,0,0,0,0,00:00
-781,Pacific/Pitcairn,1970,,-510,0,0,0,0,0,00:00,0,0,0,0,00:00
-782,Pacific/Pitcairn,1998,,-480,0,0,0,0,0,00:00,0,0,0,0,00:00
-783,Pacific/Pago_Pago,1970,,-660,0,0,0,0,0,00:00,0,0,0,0,00:00
-784,Pacific/Pago_Pago,1983,,-660,0,0,0,0,0,00:00,0,0,0,0,00:00
-785,Pacific/Apia,1970,,-660,0,0,0,0,0,00:00,0,0,0,0,00:00
-786,Pacific/Apia,2010,,-660,0,0,0,0,0,00:00,0,0,0,0,00:00
-787,Pacific/Apia,2011,,780,0,0,0,0,0,00:00,0,0,0,0,00:00
-788,Pacific/Guadalcanal,1970,,660,0,0,0,0,0,00:00,0,0,0,0,00:00
-789,Pacific/Fakaofo,1970,,-600,0,0,0,0,0,00:00,0,0,0,0,00:00
-790,Pacific/Tongatapu,1970,,780,0,0,0,0,0,00:00,0,0,0,0,00:00
-791,Pacific/Tongatapu,1999,Tonga,780,60,10,7,-1,0,15:00,1,1,-1,0,24:00
-792,Pacific/Tongatapu,2000,Tonga,780,60,11,1,0,0,15:00,3,19,-1,0,15:00
-793,Pacific/Tongatapu,2001,Tonga,780,60,11,1,0,0,15:00,1,-1,0,0,14:00
-794,Pacific/Tongatapu,2002,Tonga,780,0,12,31,-1,0,25:00,1,-1,0,0,14:00
-795,Pacific/Funafuti,1970,,720,0,0,0,0,0,00:00,0,0,0,0,00:00
-796,Pacific/Johnston,1970,,-600,0,0,0,0,0,00:00,0,0,0,0,00:00
-797,Pacific/Midway,1970,,-660,0,0,0,0,0,00:00,0,0,0,0,00:00
-798,Pacific/Midway,1983,,-660,0,0,0,0,0,00:00,0,0,0,0,00:00
-799,Pacific/Wake,1970,,720,0,0,0,0,0,00:00,0,0,0,0,00:00
-800,Pacific/Efate,1970,Vanuatu,660,0,0,0,0,0,00:00,0,0,0,0,00:00
-801,Pacific/Efate,1983,Vanuatu,660,60,9,25,-1,0,11:00,1,1,-1,0,22:00
-802,Pacific/Efate,1984,Vanuatu,660,60,10,23,-1,0,11:00,3,23,0,0,10:00
-803,Pacific/Efate,1985,Vanuatu,660,60,9,23,0,0,11:00,3,23,0,0,10:00
-804,Pacific/Efate,1992,Vanuatu,660,60,10,23,0,0,11:00,1,23,0,0,10:00
-805,Pacific/Efate,1993,Vanuatu,660,0,12,31,-1,0,23:00,1,23,0,0,10:00
-806,Pacific/Wallis,1970,,720,0,0,0,0,0,00:00,0,0,0,0,00:00
-807,Europe/London,1970,,60,0,0,0,0,0,00:00,0,0,0,0,00:00
-808,Europe/London,1971,GB-Eire,0,0,0,0,0,0,00:00,0,0,0,0,00:00
-809,Europe/London,1972,GB-Eire,0,60,3,16,0,0,02:00,10,23,0,0,02:00
-810,Europe/London,1981,GB-Eire,0,60,3,-1,0,0,1:00,10,23,0,0,1:00
-811,Europe/London,1990,GB-Eire,0,60,3,-1,0,0,1:00,10,22,0,0,1:00
-812,Europe/London,1995,GB-Eire,0,0,3,-1,0,0,1:00,10,22,0,0,1:00
-813,Europe/London,1996,EU,0,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-814,Europe/Dublin,1970,,60,0,0,0,0,0,00:00,0,0,0,0,00:00
-815,Europe/Dublin,1971,GB-Eire,0,0,0,0,0,0,00:00,0,0,0,0,00:00
-816,Europe/Dublin,1972,GB-Eire,0,60,3,16,0,0,02:00,10,23,0,0,02:00
-817,Europe/Dublin,1981,GB-Eire,0,60,3,-1,0,0,1:00,10,23,0,0,1:00
-818,Europe/Dublin,1990,GB-Eire,0,60,3,-1,0,0,1:00,10,22,0,0,1:00
-819,Europe/Dublin,1995,GB-Eire,0,0,3,-1,0,0,1:00,10,22,0,0,1:00
-820,Europe/Dublin,1996,EU,0,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-821,WET,1970,EU,0,0,0,0,0,0,00:00,0,0,0,0,00:00
-822,WET,1977,EU,0,60,4,1,0,0,1:00,9,-1,0,0,1:00
-823,WET,1978,EU,0,60,4,1,0,0,1:00,10,1,-1,0,1:00
-824,WET,1979,EU,0,60,4,1,0,0,1:00,9,-1,0,0,1:00
-825,WET,1981,EU,0,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-826,WET,1996,EU,0,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-827,CET,1970,C-Eur,60,60,4,1,1,0,03:00,9,16,-1,0,03:00
-828,CET,1977,C-Eur,60,60,4,1,0,0,03:00,9,-1,0,0,03:00
-829,CET,1978,C-Eur,60,60,4,1,0,0,03:00,10,1,-1,0,03:00
-830,CET,1979,C-Eur,60,60,4,1,0,0,03:00,9,-1,0,0,03:00
-831,CET,1981,C-Eur,60,60,3,-1,0,0,03:00,9,-1,0,0,03:00
-832,CET,1996,C-Eur,60,60,3,-1,0,0,03:00,10,-1,0,0,03:00
-833,MET,1970,C-Eur,60,60,4,1,1,0,03:00,9,16,-1,0,03:00
-834,MET,1977,C-Eur,60,60,4,1,0,0,03:00,9,-1,0,0,03:00
-835,MET,1978,C-Eur,60,60,4,1,0,0,03:00,10,1,-1,0,03:00
-836,MET,1979,C-Eur,60,60,4,1,0,0,03:00,9,-1,0,0,03:00
-837,MET,1981,C-Eur,60,60,3,-1,0,0,03:00,9,-1,0,0,03:00
-838,MET,1996,C-Eur,60,60,3,-1,0,0,03:00,10,-1,0,0,03:00
-839,EET,1970,EU,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-840,EET,1977,EU,120,60,4,1,0,0,1:00,9,-1,0,0,1:00
-841,EET,1978,EU,120,60,4,1,0,0,1:00,10,1,-1,0,1:00
-842,EET,1979,EU,120,60,4,1,0,0,1:00,9,-1,0,0,1:00
-843,EET,1981,EU,120,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-844,EET,1996,EU,120,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-845,Europe/Tirane,1970,Albania,60,60,3,29,-1,0,03:00,4,10,-1,0,03:00
-846,Europe/Tirane,1974,Albania,60,60,5,4,-1,0,01:00,10,2,-1,0,00:00
-847,Europe/Tirane,1975,Albania,60,60,5,1,-1,0,01:00,10,2,-1,0,00:00
-848,Europe/Tirane,1976,Albania,60,60,5,2,-1,0,01:00,10,3,-1,0,00:00
-849,Europe/Tirane,1977,Albania,60,60,5,8,-1,0,01:00,10,2,-1,0,00:00
-850,Europe/Tirane,1978,Albania,60,60,5,6,-1,0,01:00,10,1,-1,0,00:00
-851,Europe/Tirane,1979,Albania,60,60,5,5,-1,0,01:00,9,30,-1,0,00:00
-852,Europe/Tirane,1980,Albania,60,60,5,3,-1,0,01:00,10,4,-1,0,00:00
-853,Europe/Tirane,1981,Albania,60,60,4,26,-1,0,01:00,9,27,-1,0,00:00
-854,Europe/Tirane,1982,Albania,60,60,5,2,-1,0,01:00,10,3,-1,0,00:00
-855,Europe/Tirane,1983,Albania,60,60,4,18,-1,0,01:00,10,1,-1,0,00:00
-856,Europe/Tirane,1984,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-857,Europe/Tirane,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-858,Europe/Andorra,1970,,60,0,0,0,0,0,00:00,0,0,0,0,00:00
-859,Europe/Andorra,1985,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-860,Europe/Andorra,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-861,Europe/Vienna,1970,Austria,60,60,4,18,-1,0,03:00,10,1,0,0,03:00
-862,Europe/Vienna,1980,Austria,60,60,4,6,-1,0,01:00,9,28,-1,0,00:00
-863,Europe/Vienna,1981,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-864,Europe/Vienna,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-865,Europe/Minsk,1970,Russia,180,60,9,1,-1,0,03:00,10,1,-1,0,02:00
-866,Europe/Minsk,1981,Russia,180,60,4,1,-1,0,03:00,10,1,-1,0,02:00
-867,Europe/Minsk,1984,Russia,180,60,4,1,-1,0,03:00,9,-1,0,0,05:00
-868,Europe/Minsk,1985,Russia,180,60,3,-1,0,0,05:00,9,-1,0,0,05:00
-869,Europe/Minsk,1990,,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-870,Europe/Minsk,1991,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-871,Europe/Minsk,1992,Russia,120,60,3,-1,6,0,25:00,9,-1,6,0,24:00
-872,Europe/Minsk,1993,Russia,120,60,3,-1,0,0,04:00,9,-1,0,0,04:00
-873,Europe/Minsk,1996,Russia,120,60,3,-1,0,0,04:00,10,-1,0,0,04:00
-874,Europe/Minsk,2010,Russia,120,0,3,-1,0,0,04:00,10,-1,0,0,04:00
-875,Europe/Minsk,2011,,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-876,Europe/Brussels,1970,Belgium,60,0,5,19,-1,0,03:00,10,7,-1,0,03:00
-877,Europe/Brussels,1977,EU,60,60,4,1,0,0,1:00,9,-1,0,0,1:00
-878,Europe/Brussels,1978,EU,60,60,4,1,0,0,1:00,10,1,-1,0,1:00
-879,Europe/Brussels,1979,EU,60,60,4,1,0,0,1:00,9,-1,0,0,1:00
-880,Europe/Brussels,1981,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-881,Europe/Brussels,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-882,Europe/Sofia,1970,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-883,Europe/Sofia,1979,Bulg,120,60,3,31,-1,0,25:00,10,1,-1,0,02:00
-884,Europe/Sofia,1980,Bulg,120,60,4,1,6,0,25:00,9,29,-1,0,02:00
-885,Europe/Sofia,1981,Bulg,120,60,4,1,6,0,25:00,9,27,-1,0,03:00
-886,Europe/Sofia,1982,C-Eur,120,60,3,-1,0,0,04:00,9,-1,0,0,04:00
-887,Europe/Sofia,1991,E-Eur,120,60,3,-1,0,0,02:00,9,-1,0,0,01:00
-888,Europe/Sofia,1996,E-Eur,120,60,3,-1,0,0,02:00,10,-1,0,0,01:00
-889,Europe/Sofia,1997,EU,120,60,3,-1,0,0,02:00,10,-1,0,0,01:00
-890,Europe/Prague,1970,Czech,60,0,4,9,-1,0,03:00,10,1,0,0,03:00
-891,Europe/Prague,1979,EU,60,60,4,1,0,0,1:00,9,-1,0,0,1:00
-892,Europe/Prague,1981,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-893,Europe/Prague,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-894,Europe/Copenhagen,1970,Denmark,60,0,5,9,-1,0,03:00,8,8,-1,0,03:00
-895,Europe/Copenhagen,1980,EU,60,60,4,1,0,0,1:00,9,-1,0,0,1:00
-896,Europe/Copenhagen,1981,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-897,Europe/Copenhagen,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-898,Atlantic/Faroe,1970,,0,0,0,0,0,0,00:00,0,0,0,0,00:00
-899,Atlantic/Faroe,1981,EU,0,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-900,Atlantic/Faroe,1996,EU,0,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-901,America/Danmarkshavn,1970,,-180,0,0,0,0,0,00:00,0,0,0,0,00:00
-902,America/Danmarkshavn,1980,EU,-180,60,4,1,0,0,1:00,9,-1,0,0,1:00
-903,America/Danmarkshavn,1981,EU,-180,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-904,America/Danmarkshavn,1996,,0,0,0,0,0,0,00:00,0,0,0,0,00:00
-905,America/Scoresbysund,1970,,-120,0,0,0,0,0,00:00,0,0,0,0,00:00
-906,America/Scoresbysund,1980,C-Eur,-120,60,4,1,0,0,00:00,9,-1,0,0,00:00
-907,America/Scoresbysund,1981,EU,-60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-908,America/Scoresbysund,1996,EU,-60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-909,America/Godthab,1970,,-180,0,0,0,0,0,00:00,0,0,0,0,00:00
-910,America/Godthab,1980,EU,-180,60,4,1,0,0,1:00,9,-1,0,0,1:00
-911,America/Godthab,1981,EU,-180,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-912,America/Godthab,1996,EU,-180,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-913,America/Thule,1970,Thule,-240,0,0,0,0,0,00:00,0,0,0,0,00:00
-914,America/Thule,1991,Thule,-240,60,3,-1,0,0,-2:00,9,-1,0,0,-3:00
-915,America/Thule,1993,Thule,-240,60,4,1,0,0,-2:00,10,-1,0,0,-3:00
-916,America/Thule,2007,Thule,-240,60,3,8,0,0,-2:00,11,1,0,0,-3:00
-917,Europe/Tallinn,1970,Russia,180,60,9,1,-1,0,03:00,10,1,-1,0,02:00
-918,Europe/Tallinn,1981,Russia,180,60,4,1,-1,0,03:00,10,1,-1,0,02:00
-919,Europe/Tallinn,1984,Russia,180,60,4,1,-1,0,03:00,9,-1,0,0,05:00
-920,Europe/Tallinn,1985,Russia,180,60,3,-1,0,0,05:00,9,-1,0,0,05:00
-921,Europe/Tallinn,1989,C-Eur,120,60,3,-1,0,0,04:00,9,-1,0,0,04:00
-922,Europe/Tallinn,1996,C-Eur,120,60,3,-1,0,0,04:00,10,-1,0,0,04:00
-923,Europe/Tallinn,1998,EU,120,60,3,-1,0,0,04:00,10,-1,0,0,04:00
-924,Europe/Tallinn,1999,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-925,Europe/Tallinn,2002,EU,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-926,Europe/Helsinki,1970,Finland,120,60,4,3,-1,0,02:00,10,3,-1,0,01:00
-927,Europe/Helsinki,1981,Finland,120,60,3,-1,0,0,04:00,9,-1,0,0,04:00
-928,Europe/Helsinki,1982,Finland,120,0,3,-1,0,0,04:00,9,-1,0,0,04:00
-929,Europe/Helsinki,1983,EU,120,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-930,Europe/Helsinki,1996,EU,120,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-931,Europe/Paris,1970,France,60,120,4,2,-1,0,03:00,9,16,-1,0,03:00
-932,Europe/Paris,1976,France,60,60,3,28,-1,0,02:00,9,26,-1,0,01:00
-933,Europe/Paris,1977,EU,60,60,4,1,0,0,1:00,9,-1,0,0,1:00
-934,Europe/Paris,1978,EU,60,60,4,1,0,0,1:00,10,1,-1,0,1:00
-935,Europe/Paris,1979,EU,60,60,4,1,0,0,1:00,9,-1,0,0,1:00
-936,Europe/Paris,1981,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-937,Europe/Paris,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-938,Europe/Berlin,1970,Germany,60,0,4,10,-1,0,03:00,10,1,0,0,03:00
-939,Europe/Berlin,1980,EU,60,60,4,1,0,0,1:00,9,-1,0,0,1:00
-940,Europe/Berlin,1981,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-941,Europe/Berlin,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-942,Europe/Gibraltar,1970,,60,0,0,0,0,0,00:00,0,0,0,0,00:00
-943,Europe/Gibraltar,1982,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-944,Europe/Gibraltar,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-945,Europe/Athens,1970,Greece,120,60,7,1,-1,0,02:00,11,2,-1,0,01:00
-946,Europe/Athens,1975,Greece,120,60,4,12,-1,0,02:00,11,26,-1,0,02:00
-947,Europe/Athens,1976,Greece,120,60,4,11,-1,0,04:00,10,10,-1,0,04:00
-948,Europe/Athens,1977,Greece,120,60,4,1,0,0,04:00,9,26,-1,0,04:00
-949,Europe/Athens,1978,Greece,120,60,4,1,0,0,04:00,9,24,-1,0,05:00
-950,Europe/Athens,1979,Greece,120,60,4,1,-1,0,11:00,9,29,-1,0,03:00
-951,Europe/Athens,1980,Greece,120,60,4,1,-1,0,02:00,9,28,-1,0,01:00
-952,Europe/Athens,1981,EU,120,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-953,Europe/Athens,1996,EU,120,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-954,Europe/Budapest,1970,Hungary,60,60,6,1,0,0,02:00,9,-1,0,0,03:00
-955,Europe/Budapest,1980,EU,60,60,4,1,0,0,1:00,9,-1,0,0,1:00
-956,Europe/Budapest,1981,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-957,Europe/Budapest,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-958,Atlantic/Reykjavik,1970,,0,0,0,0,0,0,00:00,0,0,0,0,00:00
-959,Europe/Rome,1970,Italy,60,60,5,31,-1,0,01:00,9,-1,0,0,00:00
-960,Europe/Rome,1971,Italy,60,60,5,22,0,0,01:00,9,-1,0,0,01:00
-961,Europe/Rome,1972,Italy,60,60,5,22,0,0,01:00,10,1,-1,0,00:00
-962,Europe/Rome,1973,Italy,60,60,6,3,-1,0,01:00,9,-1,0,0,00:00
-963,Europe/Rome,1974,Italy,60,60,5,26,-1,0,01:00,9,-1,0,0,00:00
-964,Europe/Rome,1975,Italy,60,60,6,1,-1,0,01:00,9,-1,0,0,01:00
-965,Europe/Rome,1976,Italy,60,60,5,30,-1,0,01:00,9,-1,0,0,01:00
-966,Europe/Rome,1977,Italy,60,60,5,22,0,0,01:00,9,-1,0,0,01:00
-967,Europe/Rome,1978,Italy,60,60,5,22,0,0,01:00,10,1,-1,0,01:00
-968,Europe/Rome,1979,Italy,60,60,5,22,0,0,01:00,9,30,-1,0,01:00
-969,Europe/Rome,1980,EU,60,60,4,1,0,0,1:00,9,-1,0,0,1:00
-970,Europe/Rome,1981,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-971,Europe/Rome,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-972,Europe/Riga,1970,Russia,180,60,9,1,-1,0,03:00,10,1,-1,0,02:00
-973,Europe/Riga,1981,Russia,180,60,4,1,-1,0,03:00,10,1,-1,0,02:00
-974,Europe/Riga,1984,Russia,180,60,4,1,-1,0,03:00,9,-1,0,0,05:00
-975,Europe/Riga,1985,Russia,180,60,3,-1,0,0,05:00,9,-1,0,0,05:00
-976,Europe/Riga,1989,Latvia,120,60,3,-1,0,0,04:00,9,-1,0,0,04:00
-977,Europe/Riga,1996,Latvia,120,0,3,-1,0,0,04:00,9,-1,0,0,04:00
-978,Europe/Riga,1997,EU,120,0,3,-1,0,0,04:00,9,-1,0,0,04:00
-979,Europe/Riga,2000,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-980,Europe/Riga,2001,EU,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-981,Europe/Vaduz,1970,,60,0,0,0,0,0,00:00,0,0,0,0,00:00
-982,Europe/Vaduz,1981,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-983,Europe/Vaduz,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-984,Europe/Vilnius,1970,Russia,180,60,9,1,-1,0,03:00,10,1,-1,0,02:00
-985,Europe/Vilnius,1981,Russia,180,60,4,1,-1,0,03:00,10,1,-1,0,02:00
-986,Europe/Vilnius,1984,Russia,180,60,4,1,-1,0,03:00,9,-1,0,0,05:00
-987,Europe/Vilnius,1985,Russia,180,60,3,-1,0,0,05:00,9,-1,0,0,05:00
-988,Europe/Vilnius,1991,C-Eur,120,60,3,-1,0,0,04:00,9,-1,0,0,04:00
-989,Europe/Vilnius,1996,C-Eur,120,60,3,-1,0,0,04:00,10,-1,0,0,04:00
-990,Europe/Vilnius,1998,EU,60,60,3,-1,0,0,03:00,10,-1,0,0,03:00
-991,Europe/Vilnius,1999,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-992,Europe/Vilnius,2003,EU,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-993,Europe/Luxembourg,1970,Belgium,60,0,5,19,-1,0,03:00,10,7,-1,0,03:00
-994,Europe/Luxembourg,1977,EU,60,60,4,1,0,0,1:00,9,-1,0,0,1:00
-995,Europe/Luxembourg,1978,EU,60,60,4,1,0,0,1:00,10,1,-1,0,1:00
-996,Europe/Luxembourg,1979,EU,60,60,4,1,0,0,1:00,9,-1,0,0,1:00
-997,Europe/Luxembourg,1981,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-998,Europe/Luxembourg,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-999,Europe/Malta,1970,Italy,60,60,5,31,-1,0,01:00,9,-1,0,0,00:00
-1000,Europe/Malta,1971,Italy,60,60,5,22,0,0,01:00,9,-1,0,0,01:00
-1001,Europe/Malta,1972,Italy,60,60,5,22,0,0,01:00,10,1,-1,0,00:00
-1002,Europe/Malta,1973,Malta,60,60,3,31,-1,0,01:00,9,29,-1,0,01:00
-1003,Europe/Malta,1974,Malta,60,60,4,21,-1,0,01:00,9,16,-1,0,01:00
-1004,Europe/Malta,1975,Malta,60,60,4,15,0,0,03:00,9,15,0,0,02:00
-1005,Europe/Malta,1980,Malta,60,0,3,31,-1,0,03:00,9,15,0,0,02:00
-1006,Europe/Malta,1981,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-1007,Europe/Malta,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-1008,Europe/Chisinau,1970,Russia,180,60,9,1,-1,0,03:00,10,1,-1,0,02:00
-1009,Europe/Chisinau,1981,Russia,180,60,4,1,-1,0,03:00,10,1,-1,0,02:00
-1010,Europe/Chisinau,1984,Russia,180,60,4,1,-1,0,03:00,9,-1,0,0,05:00
-1011,Europe/Chisinau,1985,Russia,180,60,3,-1,0,0,05:00,9,-1,0,0,05:00
-1012,Europe/Chisinau,1990,,120,0,0,0,0,0,00:00,0,0,0,0,00:00
-1013,Europe/Chisinau,1991,Russia,120,60,3,-1,0,0,04:00,9,-1,0,0,04:00
-1014,Europe/Chisinau,1992,E-Eur,120,60,3,-1,0,0,02:00,9,-1,0,0,01:00
-1015,Europe/Chisinau,1996,E-Eur,120,60,3,-1,0,0,02:00,10,-1,0,0,01:00
-1016,Europe/Chisinau,1997,EU,120,60,3,-1,0,0,02:00,10,-1,0,0,01:00
-1017,Europe/Monaco,1970,France,60,120,4,2,-1,0,03:00,9,16,-1,0,03:00
-1018,Europe/Monaco,1976,France,60,60,3,28,-1,0,02:00,9,26,-1,0,01:00
-1019,Europe/Monaco,1977,EU,60,60,4,1,0,0,1:00,9,-1,0,0,1:00
-1020,Europe/Monaco,1978,EU,60,60,4,1,0,0,1:00,10,1,-1,0,1:00
-1021,Europe/Monaco,1979,EU,60,60,4,1,0,0,1:00,9,-1,0,0,1:00
-1022,Europe/Monaco,1981,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-1023,Europe/Monaco,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-1024,Europe/Amsterdam,1970,Neth,60,0,4,2,-1,0,03:00,9,16,-1,0,03:00
-1025,Europe/Amsterdam,1977,EU,60,60,4,1,0,0,1:00,9,-1,0,0,1:00
-1026,Europe/Amsterdam,1978,EU,60,60,4,1,0,0,1:00,10,1,-1,0,1:00
-1027,Europe/Amsterdam,1979,EU,60,60,4,1,0,0,1:00,9,-1,0,0,1:00
-1028,Europe/Amsterdam,1981,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-1029,Europe/Amsterdam,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-1030,Europe/Oslo,1970,Norway,60,0,4,25,-1,0,03:00,9,15,0,0,03:00
-1031,Europe/Oslo,1980,EU,60,60,4,1,0,0,1:00,9,-1,0,0,1:00
-1032,Europe/Oslo,1981,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-1033,Europe/Oslo,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-1034,Europe/Warsaw,1970,Poland,60,0,5,-1,0,0,02:00,9,-1,0,0,02:00
-1035,Europe/Warsaw,1977,W-Eur,60,60,4,1,0,0,02:00,9,-1,0,0,02:00
-1036,Europe/Warsaw,1978,W-Eur,60,60,4,1,0,0,02:00,10,1,-1,0,02:00
-1037,Europe/Warsaw,1979,W-Eur,60,60,4,1,0,0,02:00,9,-1,0,0,02:00
-1038,Europe/Warsaw,1981,W-Eur,60,60,3,-1,0,0,02:00,9,-1,0,0,02:00
-1039,Europe/Warsaw,1988,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-1040,Europe/Warsaw,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-1041,Europe/Lisbon,1970,,60,0,0,0,0,0,00:00,0,0,0,0,00:00
-1042,Europe/Lisbon,1976,Port,0,0,0,0,0,0,00:00,0,0,0,0,00:00
-1043,Europe/Lisbon,1977,Port,0,60,3,27,-1,0,00:00,9,25,-1,0,00:00
-1044,Europe/Lisbon,1978,Port,0,60,4,1,0,0,00:00,10,1,-1,0,00:00
-1045,Europe/Lisbon,1979,Port,0,60,4,1,0,0,00:00,9,-1,0,0,01:00
-1046,Europe/Lisbon,1980,Port,0,60,3,-1,0,0,00:00,9,-1,0,0,01:00
-1047,Europe/Lisbon,1981,Port,0,60,3,-1,0,0,01:00,9,-1,0,0,01:00
-1048,Europe/Lisbon,1983,W-Eur,0,60,3,-1,0,0,01:00,9,-1,0,0,01:00
-1049,Europe/Lisbon,1992,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-1050,Europe/Lisbon,1996,EU,0,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-1051,Atlantic/Azores,1970,Port,-60,60,4,1,0,0,01:00,10,1,0,0,01:00
-1052,Atlantic/Azores,1977,Port,-60,60,3,27,-1,0,-1:00,9,25,-1,0,-1:00
-1053,Atlantic/Azores,1978,Port,-60,60,4,1,0,0,-1:00,10,1,-1,0,-1:00
-1054,Atlantic/Azores,1979,Port,-60,60,4,1,0,0,-1:00,9,-1,0,0,00:00
-1055,Atlantic/Azores,1980,Port,-60,60,3,-1,0,0,-1:00,9,-1,0,0,00:00
-1056,Atlantic/Azores,1981,Port,-60,60,3,-1,0,0,00:00,9,-1,0,0,00:00
-1057,Atlantic/Azores,1983,W-Eur,-60,60,3,-1,0,0,00:00,9,-1,0,0,00:00
-1058,Atlantic/Azores,1992,EU,0,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-1059,Atlantic/Azores,1993,EU,-60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-1060,Atlantic/Azores,1996,EU,-60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-1061,Atlantic/Madeira,1970,Port,0,60,4,1,0,0,02:00,10,1,0,0,02:00
-1062,Atlantic/Madeira,1977,Port,0,60,3,27,-1,0,00:00,9,25,-1,0,00:00
-1063,Atlantic/Madeira,1978,Port,0,60,4,1,0,0,00:00,10,1,-1,0,00:00
-1064,Atlantic/Madeira,1979,Port,0,60,4,1,0,0,00:00,9,-1,0,0,01:00
-1065,Atlantic/Madeira,1980,Port,0,60,3,-1,0,0,00:00,9,-1,0,0,01:00
-1066,Atlantic/Madeira,1981,Port,0,60,3,-1,0,0,01:00,9,-1,0,0,01:00
-1067,Atlantic/Madeira,1983,EU,0,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-1068,Atlantic/Madeira,1996,EU,0,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-1069,Europe/Bucharest,1970,Romania,120,60,4,2,0,0,02:00,10,1,0,0,02:00
-1070,Europe/Bucharest,1979,Romania,120,60,5,27,-1,0,02:00,9,-1,0,0,01:00
-1071,Europe/Bucharest,1980,Romania,120,60,4,5,-1,0,25:00,9,-1,0,0,02:00
-1072,Europe/Bucharest,1981,C-Eur,120,60,3,-1,0,0,04:00,9,-1,0,0,04:00
-1073,Europe/Bucharest,1991,Romania,120,60,3,-1,0,0,02:00,9,-1,0,0,02:00
-1074,Europe/Bucharest,1993,Romania,120,0,3,-1,0,0,02:00,9,-1,0,0,02:00
-1075,Europe/Bucharest,1994,E-Eur,120,60,3,-1,0,0,02:00,9,-1,0,0,01:00
-1076,Europe/Bucharest,1996,E-Eur,120,60,3,-1,0,0,02:00,10,-1,0,0,01:00
-1077,Europe/Bucharest,1997,EU,120,60,3,-1,0,0,02:00,10,-1,0,0,01:00
-1078,Europe/Kaliningrad,1970,Russia,180,60,9,1,-1,0,03:00,10,1,-1,0,02:00
-1079,Europe/Kaliningrad,1981,Russia,180,60,4,1,-1,0,03:00,10,1,-1,0,02:00
-1080,Europe/Kaliningrad,1984,Russia,180,60,4,1,-1,0,03:00,9,-1,0,0,05:00
-1081,Europe/Kaliningrad,1985,Russia,180,60,3,-1,0,0,05:00,9,-1,0,0,05:00
-1082,Europe/Kaliningrad,1991,Russia,120,60,3,-1,0,0,04:00,9,-1,0,0,04:00
-1083,Europe/Kaliningrad,1992,Russia,120,60,3,-1,6,0,25:00,9,-1,6,0,24:00
-1084,Europe/Kaliningrad,1993,Russia,120,60,3,-1,0,0,04:00,9,-1,0,0,04:00
-1085,Europe/Kaliningrad,1996,Russia,120,60,3,-1,0,0,04:00,10,-1,0,0,04:00
-1086,Europe/Kaliningrad,2010,Russia,120,0,3,-1,0,0,04:00,10,-1,0,0,04:00
-1087,Europe/Kaliningrad,2011,,180,0,0,0,0,0,00:00,0,0,0,0,00:00
-1088,Europe/Moscow,1970,Russia,180,60,9,1,-1,0,03:00,10,1,-1,0,02:00
-1089,Europe/Moscow,1981,Russia,180,60,4,1,-1,0,03:00,10,1,-1,0,02:00
-1090,Europe/Moscow,1984,Russia,180,60,4,1,-1,0,03:00,9,-1,0,0,05:00
-1091,Europe/Moscow,1985,Russia,180,60,3,-1,0,0,05:00,9,-1,0,0,05:00
-1092,Europe/Moscow,1991,Russia,120,60,3,-1,0,0,04:00,9,-1,0,0,04:00
-1093,Europe/Moscow,1992,Russia,180,60,3,-1,6,0,26:00,9,-1,6,0,25:00
-1094,Europe/Moscow,1993,Russia,180,60,3,-1,0,0,05:00,9,-1,0,0,05:00
-1095,Europe/Moscow,1996,Russia,180,60,3,-1,0,0,05:00,10,-1,0,0,05:00
-1096,Europe/Moscow,2010,Russia,180,0,3,-1,0,0,05:00,10,-1,0,0,05:00
-1097,Europe/Moscow,2011,,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-1098,Europe/Volgograd,1970,Russia,240,60,9,1,-1,0,04:00,10,1,-1,0,03:00
-1099,Europe/Volgograd,1981,Russia,240,60,4,1,-1,0,04:00,10,1,-1,0,03:00
-1100,Europe/Volgograd,1984,Russia,240,60,4,1,-1,0,04:00,9,-1,0,0,06:00
-1101,Europe/Volgograd,1985,Russia,240,60,3,-1,0,0,06:00,9,-1,0,0,06:00
-1102,Europe/Volgograd,1989,Russia,180,60,3,-1,0,0,05:00,9,-1,0,0,05:00
-1103,Europe/Volgograd,1991,,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-1104,Europe/Volgograd,1992,Russia,180,60,3,-1,6,0,26:00,9,-1,6,0,25:00
-1105,Europe/Volgograd,1993,Russia,180,60,3,-1,0,0,05:00,9,-1,0,0,05:00
-1106,Europe/Volgograd,1996,Russia,180,60,3,-1,0,0,05:00,10,-1,0,0,05:00
-1107,Europe/Volgograd,2010,Russia,180,0,3,-1,0,0,05:00,10,-1,0,0,05:00
-1108,Europe/Volgograd,2011,,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-1109,Europe/Samara,1970,Russia,240,60,9,1,-1,0,04:00,10,1,-1,0,03:00
-1110,Europe/Samara,1981,Russia,240,60,4,1,-1,0,04:00,10,1,-1,0,03:00
-1111,Europe/Samara,1984,Russia,240,60,4,1,-1,0,04:00,9,-1,0,0,06:00
-1112,Europe/Samara,1985,Russia,240,60,3,-1,0,0,06:00,9,-1,0,0,06:00
-1113,Europe/Samara,1989,Russia,180,60,3,-1,0,0,05:00,9,-1,0,0,05:00
-1114,Europe/Samara,1991,Russia,240,60,3,-1,0,0,06:00,9,-1,0,0,06:00
-1115,Europe/Samara,1992,Russia,240,60,3,-1,6,0,27:00,9,-1,6,0,26:00
-1116,Europe/Samara,1993,Russia,240,60,3,-1,0,0,06:00,9,-1,0,0,06:00
-1117,Europe/Samara,1996,Russia,240,60,3,-1,0,0,06:00,10,-1,0,0,06:00
-1118,Europe/Samara,2010,Russia,180,0,3,-1,0,0,05:00,10,-1,0,0,05:00
-1119,Europe/Samara,2011,,240,0,0,0,0,0,00:00,0,0,0,0,00:00
-1120,Asia/Yekaterinburg,1970,Russia,300,60,9,1,-1,0,05:00,10,1,-1,0,04:00
-1121,Asia/Yekaterinburg,1981,Russia,300,60,4,1,-1,0,05:00,10,1,-1,0,04:00
-1122,Asia/Yekaterinburg,1984,Russia,300,60,4,1,-1,0,05:00,9,-1,0,0,07:00
-1123,Asia/Yekaterinburg,1985,Russia,300,60,3,-1,0,0,07:00,9,-1,0,0,07:00
-1124,Asia/Yekaterinburg,1991,Russia,240,60,3,-1,0,0,06:00,9,-1,0,0,06:00
-1125,Asia/Yekaterinburg,1992,Russia,300,60,3,-1,6,0,28:00,9,-1,6,0,27:00
-1126,Asia/Yekaterinburg,1993,Russia,300,60,3,-1,0,0,07:00,9,-1,0,0,07:00
-1127,Asia/Yekaterinburg,1996,Russia,300,60,3,-1,0,0,07:00,10,-1,0,0,07:00
-1128,Asia/Yekaterinburg,2010,Russia,300,0,3,-1,0,0,07:00,10,-1,0,0,07:00
-1129,Asia/Yekaterinburg,2011,,360,0,0,0,0,0,00:00,0,0,0,0,00:00
-1130,Asia/Omsk,1970,Russia,360,60,9,1,-1,0,06:00,10,1,-1,0,05:00
-1131,Asia/Omsk,1981,Russia,360,60,4,1,-1,0,06:00,10,1,-1,0,05:00
-1132,Asia/Omsk,1984,Russia,360,60,4,1,-1,0,06:00,9,-1,0,0,08:00
-1133,Asia/Omsk,1985,Russia,360,60,3,-1,0,0,08:00,9,-1,0,0,08:00
-1134,Asia/Omsk,1991,Russia,300,60,3,-1,0,0,07:00,9,-1,0,0,07:00
-1135,Asia/Omsk,1992,Russia,360,60,3,-1,6,0,29:00,9,-1,6,0,28:00
-1136,Asia/Omsk,1993,Russia,360,60,3,-1,0,0,08:00,9,-1,0,0,08:00
-1137,Asia/Omsk,1996,Russia,360,60,3,-1,0,0,08:00,10,-1,0,0,08:00
-1138,Asia/Omsk,2010,Russia,360,0,3,-1,0,0,08:00,10,-1,0,0,08:00
-1139,Asia/Omsk,2011,,420,0,0,0,0,0,00:00,0,0,0,0,00:00
-1140,Asia/Novosibirsk,1970,Russia,420,60,9,1,-1,0,07:00,10,1,-1,0,06:00
-1141,Asia/Novosibirsk,1981,Russia,420,60,4,1,-1,0,07:00,10,1,-1,0,06:00
-1142,Asia/Novosibirsk,1984,Russia,420,60,4,1,-1,0,07:00,9,-1,0,0,09:00
-1143,Asia/Novosibirsk,1985,Russia,420,60,3,-1,0,0,09:00,9,-1,0,0,09:00
-1144,Asia/Novosibirsk,1991,Russia,360,60,3,-1,0,0,08:00,9,-1,0,0,08:00
-1145,Asia/Novosibirsk,1992,Russia,420,60,3,-1,6,0,30:00,9,-1,6,0,29:00
-1146,Asia/Novosibirsk,1993,Russia,360,60,3,-1,0,0,08:00,9,-1,0,0,08:00
-1147,Asia/Novosibirsk,1996,Russia,360,60,3,-1,0,0,08:00,10,-1,0,0,08:00
-1148,Asia/Novosibirsk,2010,Russia,360,0,3,-1,0,0,08:00,10,-1,0,0,08:00
-1149,Asia/Novosibirsk,2011,,420,0,0,0,0,0,00:00,0,0,0,0,00:00
-1150,Asia/Novokuznetsk,1970,Russia,420,60,9,1,-1,0,07:00,10,1,-1,0,06:00
-1151,Asia/Novokuznetsk,1981,Russia,420,60,4,1,-1,0,07:00,10,1,-1,0,06:00
-1152,Asia/Novokuznetsk,1984,Russia,420,60,4,1,-1,0,07:00,9,-1,0,0,09:00
-1153,Asia/Novokuznetsk,1985,Russia,420,60,3,-1,0,0,09:00,9,-1,0,0,09:00
-1154,Asia/Novokuznetsk,1991,Russia,360,60,3,-1,0,0,08:00,9,-1,0,0,08:00
-1155,Asia/Novokuznetsk,1992,Russia,420,60,3,-1,6,0,30:00,9,-1,6,0,29:00
-1156,Asia/Novokuznetsk,1993,Russia,420,60,3,-1,0,0,09:00,9,-1,0,0,09:00
-1157,Asia/Novokuznetsk,1996,Russia,420,60,3,-1,0,0,09:00,10,-1,0,0,09:00
-1158,Asia/Novokuznetsk,2010,Russia,360,0,3,-1,0,0,08:00,10,-1,0,0,08:00
-1159,Asia/Novokuznetsk,2011,,420,0,0,0,0,0,00:00,0,0,0,0,00:00
-1160,Asia/Krasnoyarsk,1970,Russia,420,60,9,1,-1,0,07:00,10,1,-1,0,06:00
-1161,Asia/Krasnoyarsk,1981,Russia,420,60,4,1,-1,0,07:00,10,1,-1,0,06:00
-1162,Asia/Krasnoyarsk,1984,Russia,420,60,4,1,-1,0,07:00,9,-1,0,0,09:00
-1163,Asia/Krasnoyarsk,1985,Russia,420,60,3,-1,0,0,09:00,9,-1,0,0,09:00
-1164,Asia/Krasnoyarsk,1991,Russia,360,60,3,-1,0,0,08:00,9,-1,0,0,08:00
-1165,Asia/Krasnoyarsk,1992,Russia,420,60,3,-1,6,0,30:00,9,-1,6,0,29:00
-1166,Asia/Krasnoyarsk,1993,Russia,420,60,3,-1,0,0,09:00,9,-1,0,0,09:00
-1167,Asia/Krasnoyarsk,1996,Russia,420,60,3,-1,0,0,09:00,10,-1,0,0,09:00
-1168,Asia/Krasnoyarsk,2010,Russia,420,0,3,-1,0,0,09:00,10,-1,0,0,09:00
-1169,Asia/Krasnoyarsk,2011,,480,0,0,0,0,0,00:00,0,0,0,0,00:00
-1170,Asia/Irkutsk,1970,Russia,480,60,9,1,-1,0,08:00,10,1,-1,0,07:00
-1171,Asia/Irkutsk,1981,Russia,480,60,4,1,-1,0,08:00,10,1,-1,0,07:00
-1172,Asia/Irkutsk,1984,Russia,480,60,4,1,-1,0,08:00,9,-1,0,0,10:00
-1173,Asia/Irkutsk,1985,Russia,480,60,3,-1,0,0,10:00,9,-1,0,0,10:00
-1174,Asia/Irkutsk,1991,Russia,420,60,3,-1,0,0,09:00,9,-1,0,0,09:00
-1175,Asia/Irkutsk,1992,Russia,480,60,3,-1,6,0,31:00,9,-1,6,0,30:00
-1176,Asia/Irkutsk,1993,Russia,480,60,3,-1,0,0,10:00,9,-1,0,0,10:00
-1177,Asia/Irkutsk,1996,Russia,480,60,3,-1,0,0,10:00,10,-1,0,0,10:00
-1178,Asia/Irkutsk,2010,Russia,480,0,3,-1,0,0,10:00,10,-1,0,0,10:00
-1179,Asia/Irkutsk,2011,,540,0,0,0,0,0,00:00,0,0,0,0,00:00
-1180,Asia/Yakutsk,1970,Russia,540,60,9,1,-1,0,09:00,10,1,-1,0,08:00
-1181,Asia/Yakutsk,1981,Russia,540,60,4,1,-1,0,09:00,10,1,-1,0,08:00
-1182,Asia/Yakutsk,1984,Russia,540,60,4,1,-1,0,09:00,9,-1,0,0,11:00
-1183,Asia/Yakutsk,1985,Russia,540,60,3,-1,0,0,11:00,9,-1,0,0,11:00
-1184,Asia/Yakutsk,1991,Russia,480,60,3,-1,0,0,10:00,9,-1,0,0,10:00
-1185,Asia/Yakutsk,1992,Russia,540,60,3,-1,6,0,32:00,9,-1,6,0,31:00
-1186,Asia/Yakutsk,1993,Russia,540,60,3,-1,0,0,11:00,9,-1,0,0,11:00
-1187,Asia/Yakutsk,1996,Russia,540,60,3,-1,0,0,11:00,10,-1,0,0,11:00
-1188,Asia/Yakutsk,2010,Russia,540,0,3,-1,0,0,11:00,10,-1,0,0,11:00
-1189,Asia/Yakutsk,2011,,600,0,0,0,0,0,00:00,0,0,0,0,00:00
-1190,Asia/Vladivostok,1970,Russia,600,60,9,1,-1,0,10:00,10,1,-1,0,09:00
-1191,Asia/Vladivostok,1981,Russia,600,60,4,1,-1,0,10:00,10,1,-1,0,09:00
-1192,Asia/Vladivostok,1984,Russia,600,60,4,1,-1,0,10:00,9,-1,0,0,12:00
-1193,Asia/Vladivostok,1985,Russia,600,60,3,-1,0,0,12:00,9,-1,0,0,12:00
-1194,Asia/Vladivostok,1991,Russia,540,60,3,-1,0,0,11:00,9,-1,0,0,11:00
-1195,Asia/Vladivostok,1992,Russia,600,60,3,-1,6,0,33:00,9,-1,6,0,32:00
-1196,Asia/Vladivostok,1993,Russia,600,60,3,-1,0,0,12:00,9,-1,0,0,12:00
-1197,Asia/Vladivostok,1996,Russia,600,60,3,-1,0,0,12:00,10,-1,0,0,12:00
-1198,Asia/Vladivostok,2010,Russia,600,0,3,-1,0,0,12:00,10,-1,0,0,12:00
-1199,Asia/Vladivostok,2011,,660,0,0,0,0,0,00:00,0,0,0,0,00:00
-1200,Asia/Sakhalin,1970,Russia,660,60,9,1,-1,0,11:00,10,1,-1,0,10:00
-1201,Asia/Sakhalin,1981,Russia,660,60,4,1,-1,0,11:00,10,1,-1,0,10:00
-1202,Asia/Sakhalin,1984,Russia,660,60,4,1,-1,0,11:00,9,-1,0,0,13:00
-1203,Asia/Sakhalin,1985,Russia,660,60,3,-1,0,0,13:00,9,-1,0,0,13:00
-1204,Asia/Sakhalin,1991,Russia,600,60,3,-1,0,0,12:00,9,-1,0,0,12:00
-1205,Asia/Sakhalin,1992,Russia,660,60,3,-1,6,0,34:00,9,-1,6,0,33:00
-1206,Asia/Sakhalin,1993,Russia,660,60,3,-1,0,0,13:00,9,-1,0,0,13:00
-1207,Asia/Sakhalin,1996,Russia,660,60,3,-1,0,0,13:00,10,-1,0,0,13:00
-1208,Asia/Sakhalin,1997,Russia,600,60,3,-1,0,0,12:00,10,-1,0,0,12:00
-1209,Asia/Sakhalin,2010,Russia,600,0,3,-1,0,0,12:00,10,-1,0,0,12:00
-1210,Asia/Sakhalin,2011,,660,0,0,0,0,0,00:00,0,0,0,0,00:00
-1211,Asia/Magadan,1970,Russia,660,60,9,1,-1,0,11:00,10,1,-1,0,10:00
-1212,Asia/Magadan,1981,Russia,660,60,4,1,-1,0,11:00,10,1,-1,0,10:00
-1213,Asia/Magadan,1984,Russia,660,60,4,1,-1,0,11:00,9,-1,0,0,13:00
-1214,Asia/Magadan,1985,Russia,660,60,3,-1,0,0,13:00,9,-1,0,0,13:00
-1215,Asia/Magadan,1991,Russia,600,60,3,-1,0,0,12:00,9,-1,0,0,12:00
-1216,Asia/Magadan,1992,Russia,660,60,3,-1,6,0,34:00,9,-1,6,0,33:00
-1217,Asia/Magadan,1993,Russia,660,60,3,-1,0,0,13:00,9,-1,0,0,13:00
-1218,Asia/Magadan,1996,Russia,660,60,3,-1,0,0,13:00,10,-1,0,0,13:00
-1219,Asia/Magadan,2010,Russia,660,0,3,-1,0,0,13:00,10,-1,0,0,13:00
-1220,Asia/Magadan,2011,,720,0,0,0,0,0,00:00,0,0,0,0,00:00
-1221,Asia/Kamchatka,1970,Russia,720,60,9,1,-1,0,12:00,10,1,-1,0,11:00
-1222,Asia/Kamchatka,1981,Russia,720,60,4,1,-1,0,12:00,10,1,-1,0,11:00
-1223,Asia/Kamchatka,1984,Russia,720,60,4,1,-1,0,12:00,9,-1,0,0,14:00
-1224,Asia/Kamchatka,1985,Russia,720,60,3,-1,0,0,14:00,9,-1,0,0,14:00
-1225,Asia/Kamchatka,1991,Russia,660,60,3,-1,0,0,13:00,9,-1,0,0,13:00
-1226,Asia/Kamchatka,1992,Russia,720,60,3,-1,6,0,35:00,9,-1,6,0,34:00
-1227,Asia/Kamchatka,1993,Russia,720,60,3,-1,0,0,14:00,9,-1,0,0,14:00
-1228,Asia/Kamchatka,1996,Russia,720,60,3,-1,0,0,14:00,10,-1,0,0,14:00
-1229,Asia/Kamchatka,2010,Russia,660,0,3,-1,0,0,13:00,10,-1,0,0,13:00
-1230,Asia/Kamchatka,2011,,720,0,0,0,0,0,00:00,0,0,0,0,00:00
-1231,Asia/Anadyr,1970,Russia,780,60,9,1,-1,0,13:00,10,1,-1,0,12:00
-1232,Asia/Anadyr,1981,Russia,780,60,4,1,-1,0,13:00,10,1,-1,0,12:00
-1233,Asia/Anadyr,1982,Russia,720,60,4,1,-1,0,12:00,10,1,-1,0,11:00
-1234,Asia/Anadyr,1984,Russia,720,60,4,1,-1,0,12:00,9,-1,0,0,14:00
-1235,Asia/Anadyr,1985,Russia,720,60,3,-1,0,0,14:00,9,-1,0,0,14:00
-1236,Asia/Anadyr,1991,Russia,660,60,3,-1,0,0,13:00,9,-1,0,0,13:00
-1237,Asia/Anadyr,1992,Russia,720,60,3,-1,6,0,35:00,9,-1,6,0,34:00
-1238,Asia/Anadyr,1993,Russia,720,60,3,-1,0,0,14:00,9,-1,0,0,14:00
-1239,Asia/Anadyr,1996,Russia,720,60,3,-1,0,0,14:00,10,-1,0,0,14:00
-1240,Asia/Anadyr,2010,Russia,660,0,3,-1,0,0,13:00,10,-1,0,0,13:00
-1241,Asia/Anadyr,2011,,720,0,0,0,0,0,00:00,0,0,0,0,00:00
-1242,Europe/Belgrade,1970,,60,0,0,0,0,0,00:00,0,0,0,0,00:00
-1243,Europe/Belgrade,1982,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-1244,Europe/Belgrade,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-1245,Europe/Madrid,1970,Spain,60,60,4,30,-1,0,24:00,9,30,-1,0,01:00
-1246,Europe/Madrid,1974,Spain,60,60,4,13,6,0,24:00,10,1,0,0,01:00
-1247,Europe/Madrid,1976,Spain,60,60,3,27,-1,0,24:00,9,-1,0,0,01:00
-1248,Europe/Madrid,1977,Spain,60,60,4,2,-1,0,24:00,9,-1,0,0,01:00
-1249,Europe/Madrid,1978,Spain,60,60,4,2,-1,0,24:00,10,1,-1,0,01:00
-1250,Europe/Madrid,1979,EU,60,60,4,1,0,0,1:00,9,-1,0,0,1:00
-1251,Europe/Madrid,1981,EU,60,60,3,-1,0,0,1:00,9,-1,0,0,1:00
-1252,Europe/Madrid,1996,EU,60,60,3,-1,0,0,1:00,10,-1,0,0,1:00
-1253,Africa/Ceuta,1970,SpainAfrica,0,60,6,3,-1,0,12:00,10,1,-1,0,-1:00
-1254,