/**
  * Get an object from cache by IP address
  *
  * Load into cache if necessary
  *
  * @param string IP address
  * @param boolean false if you want to return false on error
  * @param boolean true if function should die on empty/null
  */
 function &get_by_ip($req_ip, $halt_on_error = false, $halt_on_empty = false)
 {
     global $DB, $Debuglog;
     if (!isset($this->ip_index[$req_ip])) {
         // not yet in cache:
         $IP = ip2int($req_ip);
         $SQL = new SQL('Get ID of IP range by IP address');
         $SQL->SELECT('aipr_ID');
         $SQL->FROM('T_antispam__iprange');
         $SQL->WHERE('aipr_IPv4start <= ' . $DB->quote($IP));
         $SQL->WHERE_and('aipr_IPv4end >= ' . $DB->quote($IP));
         $IPRange_ID = $DB->get_var($SQL->get());
         // Get object from IPRangeCache bi ID
         $IPRange = $this->get_by_ID($IPRange_ID, $halt_on_error, $halt_on_empty);
         if ($IPRange) {
             // It is in IPRangeCache
             $this->ip_index[$req_ip] = $IPRange;
         } else {
             // not in the IPRangeCache
             if ($halt_on_error) {
                 debug_die("Requested {$this->objtype} does not exist!");
             }
             $this->ip_index[$req_ip] = false;
         }
     } else {
         $Debuglog->add("Retrieving <strong>{$this->objtype}({$req_ip})</strong> from cache");
     }
     return $this->ip_index[$req_ip];
 }
Exemple #2
0
 /**
  * Get an object from cache by its urltitle
  *
  * Load into cache if necessary
  *
  * @param string stub of object to load
  * @param boolean false if you want to return false on error
  */
 function &get_by_urltitle($req_urltitle, $halt_on_error = true)
 {
     global $DB, $Debuglog;
     if (!isset($this->urltitle_index[$req_urltitle])) {
         // not yet in cache:
         // Load just the requested object:
         $Debuglog->add("Loading <strong>{$this->objtype}({$req_urltitle})</strong> into cache");
         $sql = "SELECT *\r\n\t\t\t          FROM {$this->dbtablename}\r\n\t\t\t         WHERE post_urltitle = " . $DB->quote($req_urltitle);
         $row = $DB->get_row($sql);
         if (empty($row)) {
             // Requested object does not exist
             if ($halt_on_error) {
                 debug_die("Requested {$this->objtype} does not exist!");
             }
             // put into index:
             $this->urltitle_index[$req_urltitle] = false;
             return $this->urltitle_index[$req_urltitle];
         }
         $this->instantiate($row);
         // put into index:
         $this->urltitle_index[$req_urltitle] =& $this->cache[$row->post_ID];
     } else {
         $Debuglog->add("Retrieving <strong>{$this->objtype}({$req_urltitle})</strong> from cache");
     }
     return $this->urltitle_index[$req_urltitle];
 }
 /**
  * Load the cache **extensively**
  */
 function load_all()
 {
     if ($this->all_loaded) {
         // Already loaded
         return false;
     }
     debug_die('Load all is not allowed for FileCache!');
 }
 /**
  * Constructor
  *
  * {@internal This gets tested in _libs.misc.simpletest.php}}
  *
  * @param string Context
  * @param boolean Allow CSS tweaks?
  * @param boolean Allow IFrames?
  * @param boolean Allow Javascript?
  * @param boolean Allow Objects?
  * @param string Input encoding to use ('ISO-8859-1', 'UTF-8', 'US-ASCII' or '' for auto-detect)
  * @param string Message type for errors
  */
 function XHTML_Validator($context = 'posting', $allow_css_tweaks = false, $allow_iframes = false, $allow_javascript = false, $allow_objects = false, $encoding = NULL, $msg_type = 'error')
 {
     global $inc_path;
     require $inc_path . 'xhtml_validator/_xhtml_dtd.inc.php';
     $this->context = $context;
     switch ($context) {
         case 'posting':
         case 'xmlrpc_posting':
             $this->tags =& $allowed_tags;
             $this->tagattrs =& $allowed_attributes;
             break;
         case 'commenting':
             $this->tags =& $comments_allowed_tags;
             $this->tagattrs =& $comments_allowed_attributes;
             break;
         case 'head_extension':
             $this->tags = array('body' => 'meta link style script', 'meta' => '', 'link' => '', 'style' => '#PCDATA', 'script' => '#PCDATA');
             $this->tagattrs = array('meta' => 'name content charset http-equiv', 'link' => 'charset href hreflang media rel sizes type', 'style' => 'media scoped type', 'script' => 'async charset defer src type');
             break;
         default:
             debug_die('unknown context: ' . $context);
     }
     // Attributes that need to be checked for a valid URI:
     $this->uri_attrs = array('xmlns', 'profile', 'href', 'src', 'cite', 'classid', 'codebase', 'data', 'archive', 'usemap', 'longdesc', 'action');
     $this->allowed_uri_scheme = get_allowed_uri_schemes($context);
     $this->msg_type = $msg_type;
     if (empty($encoding)) {
         global $io_charset;
         $encoding = $io_charset;
     }
     $encoding = strtoupper($encoding);
     // we might get 'iso-8859-1' for example
     $this->encoding = $encoding;
     if (!in_array($encoding, array('ISO-8859-1', 'UTF-8', 'US-ASCII'))) {
         // passed encoding not supported by xml_parser_create()
         $this->xml_parser_encoding = '';
         // auto-detect (in PHP4, in PHP5 anyway)
     } else {
         $this->xml_parser_encoding = $this->encoding;
     }
     $this->parser = xml_parser_create($this->xml_parser_encoding);
     $this->last_checked_pos = 0;
     $this->error = false;
     // Creates the parser
     xml_set_object($this->parser, $this);
     // set functions to call when a start or end tag is encountered
     xml_set_element_handler($this->parser, 'tag_open', 'tag_close');
     // set function to call for the actual data
     xml_set_character_data_handler($this->parser, 'cdata');
     xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
 }
/**
 * Display the permissions for the type file
 */
function display_perm($perm)
{
    switch ($perm) {
        case 'any':
            $r = get_icon('file_allowed');
            break;
        case 'registered':
            $r = get_icon('file_allowed_registered');
            break;
        case 'admin':
            $r = get_icon('file_not_allowed');
            break;
        default:
            debug_die('Wrong filetype allowed value!');
    }
    return $r;
}
/**
 * Create a new category
 *
 * This funtion has to handle all needed DB dependencies!
 *
 * @param string Category name
 * @param string Category ID ('NULL' as string(!) for root)
 * @param integer|NULL Blog ID (will be taken from parent cat, if empty)
 * @param string Category description
 * @param boolean Set to true if the new object needs to be added into the ChapterCache after it was created
 * @param integer Category order
 * @param boolean Is meta category?
 */
function cat_create($cat_name, $cat_parent_ID, $cat_blog_ID = NULL, $cat_description = NULL, $add_to_cache = false, $cat_order = NULL, $subcat_ordering = NULL, $meta = false)
{
    global $DB;
    load_class('chapters/model/_chapter.class.php', 'Chapter');
    if (!$cat_blog_ID) {
        if (empty($cat_parent_ID)) {
            debug_die('cat_create(-) missing parameters (cat_parent_ID)!');
        }
        $ChapterCache =& get_ChapterCache();
        $Chapter = $ChapterCache->get_by_ID($cat_parent_ID);
        $cat_blog_ID = $Chapter->blog_ID;
    }
    if ($cat_parent_ID === 'NULL') {
        // fix old use case
        $cat_parent_ID = NULL;
    }
    $new_Chapter = new Chapter(NULL, $cat_blog_ID);
    $new_Chapter->set('name', $cat_name);
    $new_Chapter->set('parent_ID', $cat_parent_ID);
    if (!empty($cat_description)) {
        // Set decription
        $new_Chapter->set('description', $cat_description);
    }
    $new_Chapter->set('order', $cat_order);
    $new_Chapter->set('subcat_ordering', $subcat_ordering);
    if ($meta) {
        // Set this category as meta
        $new_Chapter->set('meta', 1);
    }
    if (!$new_Chapter->dbinsert()) {
        return 0;
    }
    if ($add_to_cache) {
        // add new Category into the Cache
        $ChapterCache =& get_ChapterCache();
        $ChapterCache->add($new_Chapter);
    }
    return $new_Chapter->ID;
}
Exemple #7
0
            $Session->assert_received_crumb('users');
            // Check required permission
            $current_User->check_perm('users', 'edit', true);
            // get the type of the removable sender customization
            $type = param('type', 'string', true);
            // Set remove custom settings query
            $remove_query = 'DELETE FROM T_users__usersettings WHERE uset_name = "%s" AND uset_value != %s';
            if ($type == 'sender_email') {
                // Remove custom sender emails
                $DB->query(sprintf($remove_query, 'notification_sender_email', $DB->quote($Settings->get('notification_sender_email'))));
            } elseif ($type == 'sender_name') {
                // Remove custom sender names
                $DB->query(sprintf($remove_query, 'notification_sender_name', $DB->quote($Settings->get('notification_sender_name'))));
            } else {
                // The customization param is not valid
                debug_die('Invalid remove sender customization action!');
            }
            $Messages->add(T_('Customizations have been removed!'), 'success');
            $redirect_to = param('redirect_to', 'url', regenerate_url('action'));
            // Redirect so that a reload doesn't write to the DB twice:
            header_redirect($redirect_to);
            /* EXITED */
            break;
        case 'remove_report':
            // Remove one report on user:
            // Check that this action request is not a CSRF hacked request:
            $Session->assert_received_crumb('users');
            $reporter_ID = param('reporter_ID', 'integer', true);
            // Remove the report from DB:
            $DB->query('DELETE FROM T_users__reports
					WHERE urep_target_user_ID = ' . $DB->quote($edited_User->ID) . '
Exemple #8
0
     } else {
         // Duplicate object in order no to mess with the cache:
         $edited_Thread = duplicate($edited_Message->Thread);
         // PHP4/5 abstraction
         $edited_Message = duplicate($edited_Message);
         // PHP4/5 abstraction
         $edited_Message->ID = 0;
     }
     $edited_Message->Thread =& $edited_Thread;
     init_tokeninput_js();
     break;
 case 'create':
     // Record new thread
     if (check_create_thread_limit()) {
         // max new threads limit reached, don't allow to create new thread
         debug_die('Invalid request, new conversation limit already reached!');
     }
     // the create_new_thread() funciton will create required Thread and Message objects
     if (create_new_thread()) {
         // new thread has been created successful
         // Redirect so that a reload doesn't write to the DB twice:
         header_redirect('?ctrl=threads', 303);
         // Will EXIT
         // We have EXITed already at this point!!
     }
     init_tokeninput_js();
     break;
 case 'delete':
     // Delete thread:
     // Check permission:
     $current_User->check_perm('perm_messaging', 'delete', true);
 /**
  * Load data from Request form fields.
  *
  * @return boolean true if loaded data seems valid.
  */
 function load_from_Request($cron_job_names = array(), $cron_job_params = array())
 {
     if ($this->ID > 0 || get_param('ctsk_ID') > 0) {
         // Update or copy cron job
         $cjob_name = param('cjob_name', 'string', true);
         param_check_not_empty('cjob_name', T_('Please enter job name'));
     } else {
         // Create new cron job
         $cjob_type = param('cjob_type', 'string', true);
         if (!isset($cron_job_params[$cjob_type])) {
             // This cron job type doesn't exist, so this is an invalid state
             debug_die('Invalid job type received');
             $cjob_name = '';
         } else {
             $cjob_name = $cron_job_names[$cjob_type];
         }
     }
     // start datetime:
     param_date('cjob_date', T_('Please enter a valid date.'), true);
     param_time('cjob_time');
     $this->set('start_datetime', form_date(get_param('cjob_date'), get_param('cjob_time')));
     // repeat after:
     $cjob_repeat_after = param_duration('cjob_repeat_after');
     if ($cjob_repeat_after == 0) {
         $cjob_repeat_after = NULL;
     }
     $this->set('repeat_after', $cjob_repeat_after);
     // name:
     if (!empty($cjob_name) && $cjob_name != $this->get('name')) {
         $this->set('name', $cjob_name);
     }
     if ($this->ID == 0 && get_param('ctsk_ID') == 0) {
         // Set these params only on creating and copying actions
         // controller:
         $this->set('controller', $cron_job_params[$cjob_type]['ctrl']);
         // params:
         $this->set('params', $cron_job_params[$cjob_type]['params']);
     }
     return !param_errors_detected();
 }
Exemple #10
0
}
// EXTERNAL FEED PROVIDER?
$rss2_redirect = $Blog->get_setting('rss2_redirect');
if (!empty($rss2_redirect) && empty($Chapter) && $redir == 'yes') {
    header_redirect($rss2_redirect, 301);
    exit(0);
}
// Note: even if we request the same post as $Item earlier, the following will do more restrictions (dates, etc.)
// Init the MainList object:
init_MainList($Blog->get_setting('posts_per_feed'));
// What level of detail do we want?
$feed_content = $Blog->get_setting('feed_content');
if ($feed_content == 'none') {
    // We don't want to provide this feed!
    // This will normaly have been detected earlier but just for security:
    debug_die('Feeds are disabled.');
}
$image_size = $Blog->get_setting('image_size');
headers_content_mightcache('application/xml');
// In most situations, you do NOT want to cache dynamic content!
// Add caching headers
header('Last-Modified: ' . $MainList->get_lastpostdate('r'));
header('Expires: ' . date('r', time() + 300));
// TODO: dh> should be a centralized setting. Maybe through the Skin class, if type is "feed"?
echo '<?xml version="1.0" encoding="' . $io_charset . '"?' . '>';
?>
<!-- generator="<?php 
echo $app_name;
?>
/<?php 
echo $app_version;
Exemple #11
0
        $DB->commit();
        break;
    case 'delete':
        // Remove a widget from container:
        $msg = sprintf(T_('Widget &laquo;%s&raquo; removed.'), $edited_ComponentWidget->get_name());
        $edited_ComponentWidget->dbdelete(true);
        unset($edited_ComponentWidget);
        forget_param('wi_ID');
        $Messages->add($msg, 'success');
        // PREVENT RELOAD & Switch to list mode:
        header_redirect('?ctrl=widgets&blog=' . $blog);
        break;
    case 'list':
        break;
    default:
        debug_die('Action: unhandled action');
}
/**
 * Display page header, menus & messages:
 */
$AdminUI->set_coll_list_params('blog_properties', 'edit', array('ctrl' => 'widgets'), T_('List'), '?ctrl=collections&amp;blog=0');
$AdminUI->set_path('blogs', 'widgets');
// Display <html><head>...</head> section! (Note: should be done early if actions do not redirect)
$AdminUI->disp_html_head();
// Display title, menu, messages, etc. (Note: messages MUST be displayed AFTER the actions)
$AdminUI->disp_body_top();
/**
 * Display payload:
 */
switch ($action) {
    case 'nil':
Exemple #12
0
    /**
     * Send email notifications to subscribed users:
     *
     * efy-asimo> moderatation and subscription notifications have been separated
     *
     * @param boolean true if send only moderation email, false otherwise
     * @param boolean true if send for everyone else but not for moterators, because a moderation email was sent for them
     * @param integer the user ID who executed the action which will be notified, or NULL if it was executed by an anonymous user
     */
    function send_email_notifications($only_moderators = false, $except_moderators = false, $executed_by_userid = NULL)
    {
        global $DB, $admin_url, $baseurl, $debug, $Debuglog, $htsrv_url;
        global $Settings, $UserSettings;
        if ($only_moderators && $except_moderators) {
            // at least one of them must be false
            return;
        }
        $edited_Item =& $this->get_Item();
        $edited_Blog =& $edited_Item->get_Blog();
        $owner_User = $edited_Blog->get_owner_User();
        $notify_users = array();
        $moderators = array();
        if ($only_moderators || $except_moderators) {
            // we need the list of moderators:
            $sql = 'SELECT DISTINCT user_email, user_ID, uset_value as notify_moderation
						FROM T_users
							LEFT JOIN T_coll_user_perms ON bloguser_user_ID = user_ID
							LEFT JOIN T_coll_group_perms ON bloggroup_group_ID = user_grp_ID
							LEFT JOIN T_users__usersettings ON uset_user_ID = user_ID AND uset_name = "notify_comment_moderation"
							LEFT JOIN T_groups ON grp_ID = user_grp_ID
						WHERE ( ( bloguser_blog_ID = ' . $edited_Blog->ID . ' AND bloguser_perm_edit_cmt IN ( "anon", "lt", "le", "all" ) )
								OR ( bloggroup_blog_ID = ' . $edited_Blog->ID . ' AND bloggroup_perm_edit_cmt IN ( "anon", "lt", "le", "all" ) )
								OR ( grp_perm_blogs = "editall" ) )
							AND LENGTH(TRIM(user_email)) > 0';
            $moderators_to_notify = $DB->get_results($sql);
            foreach ($moderators_to_notify as $moderator) {
                $notify_moderator = is_null($moderator->notify_moderation) ? $Settings->get('def_notify_comment_moderation') : $moderator->notify_moderation;
                if ($notify_moderator) {
                    // add user to notify
                    $moderators[] = $moderator->user_ID;
                }
            }
            if ($UserSettings->get('notify_comment_moderation', $owner_User->ID) && is_email($owner_User->get('email'))) {
                // add blog owner
                $moderators[] = $owner_User->ID;
            }
            // Load all moderators, and check each edit permission on this comment
            $UserCache =& get_UserCache();
            $UserCache->load_list($moderators);
            foreach ($moderators as $index => $moderator_ID) {
                $moderator_User = $UserCache->get_by_ID($moderator_ID, false);
                if (!$moderator_User || !$moderator_User->check_perm('comment!CURSTATUS', 'edit', false, $this)) {
                    // User doesn't exists any more, or has no permission to edit this comment!
                    unset($moderators[$index]);
                } elseif ($only_moderators) {
                    $notify_users[$moderator_ID] = 'moderator';
                }
            }
        }
        if (!$only_moderators) {
            // Not only moderators needs to be notified:
            $except_condition = '';
            if ($except_moderators && !empty($moderators)) {
                // Set except moderators condition. Exclude moderators who already got a notification email.
                $except_condition = ' AND user_ID NOT IN ( "' . implode('", "', $moderators) . '" )';
            }
            // Check if we need to include the item creator user:
            $creator_User =& $edited_Item->get_creator_User();
            if ($UserSettings->get('notify_published_comments', $creator_User->ID) && !empty($creator_User->email) && !in_array($creator_User->ID, $moderators)) {
                // Post creator wants to be notified, and post author is not a moderator...
                $notify_users[$creator_User->ID] = 'creator';
            }
            // Get list of users who want to be notified about the this post comments:
            if ($edited_Blog->get_setting('allow_item_subscriptions')) {
                // item subscriptions is allowed
                $sql = 'SELECT DISTINCT user_ID
									FROM T_items__subscriptions INNER JOIN T_users ON isub_user_ID = user_ID
								 WHERE isub_item_ID = ' . $edited_Item->ID . '
								   AND isub_comments <> 0
								   AND LENGTH(TRIM(user_email)) > 0' . $except_condition;
                $notify_list = $DB->get_results($sql);
                // Preprocess list:
                foreach ($notify_list as $notification) {
                    $notify_users[$notification->user_ID] = 'item_subscription';
                }
            }
            // Get list of users who want to be notfied about this blog comments:
            if ($edited_Blog->get_setting('allow_subscriptions')) {
                // blog subscription is allowed
                $sql = 'SELECT DISTINCT user_ID
								FROM T_subscriptions INNER JOIN T_users ON sub_user_ID = user_ID
							 WHERE sub_coll_ID = ' . $edited_Blog->ID . '
							   AND sub_comments <> 0
							   AND LENGTH(TRIM(user_email)) > 0' . $except_condition;
                $notify_list = $DB->get_results($sql);
                // Preprocess list:
                foreach ($notify_list as $notification) {
                    $notify_users[$notification->user_ID] = 'blog_subscription';
                }
            }
        }
        if ($executed_by_userid != NULL && isset($notify_users[$executed_by_userid])) {
            // don't notify the user who just created/updated this comment
            unset($notify_users[$executed_by_userid]);
        }
        if (!count($notify_users)) {
            // No-one to notify:
            return false;
        }
        /*
         * We have a list of user IDs to notify:
         */
        // TODO: dh> this reveals the comments author's email address to all subscribers!!
        //           $notify_from should get used by default, unless the user has opted in to be the sender!
        // fp>If the subscriber has permission to moderate the comments, he SHOULD receive the email address.
        // Get author email address. It will be visible for moderators/blog/post owners only -- NOT for other subscribers
        if ($this->get_author_User()) {
            // Comment from a registered user:
            $reply_to = $this->author_User->get('email');
            $author_name = $this->author_User->get('login');
            $author_ID = $this->author_User->ID;
        } elseif (!empty($this->author_email)) {
            // non-member, but with email address:
            $reply_to = $this->author_email;
            $author_name = $this->dget('author');
            $author_ID = NULL;
        } else {
            // Fallback (we have no email address):  fp>TODO: or the subscriber is not allowed to view it.
            $reply_to = NULL;
            $author_name = $this->dget('author');
            $author_ID = NULL;
        }
        // Load all users who will be notified, becasuse another way the send_mail_to_User funtion would load them one by one
        $UserCache =& get_UserCache();
        $UserCache->load_list(array_keys($notify_users));
        // Load a list with the blocked emails  in cache
        load_blocked_emails(array_keys($notify_users));
        // Send emails:
        foreach ($notify_users as $notify_user_ID => $notify_type) {
            // get data content
            $notify_User = $UserCache->get_by_ID($notify_user_ID);
            $notify_email = $notify_User->get('email');
            // init notification setting
            locale_temp_switch($notify_User->get('locale'));
            $notify_user_Group = $notify_User->get_Group();
            $notify_full = $notify_type == 'moderator' && $notify_user_Group->check_perm('comment_moderation_notif', 'full') || $notify_user_Group->check_perm('comment_subscription_notif', 'full');
            switch ($this->type) {
                case 'trackback':
                    /* TRANS: Subject of the mail to send on new trackbacks. First %s is the blog's shortname, the second %s is the item's title. */
                    $subject = T_('[%s] New trackback on "%s"');
                    break;
                default:
                    /* TRANS: Subject of the mail to send on new comments. */
                    // In case of full notification the first %s is blog name, the second %s is the item's title.
                    // In case of short notification the first %s is author login, the second %s is the item's title.
                    $subject = $notify_full ? T_('[%s] New comment on "%s"') : T_('%s posted a new comment on "%s"');
                    if ($only_moderators) {
                        if ($this->status == 'draft') {
                            $subject = $notify_full ? T_('[%s] New comment awaiting moderation on "%s"') : T_('New comment awaiting moderation: ') . $subject;
                        } else {
                            $subject = $notify_full ? T_('[%s] New comment may need moderation on "%s"') : T_('New comment may need moderation: ') . $subject;
                        }
                    }
            }
            if ($notify_type == 'moderator') {
                // moderation email
                $user_reply_to = $reply_to;
            } else {
                if ($notify_type == 'blog_subscription') {
                    // blog subscription
                    $user_reply_to = NULL;
                } else {
                    if ($notify_type == 'item_subscription') {
                        // item subscription
                        $user_reply_to = NULL;
                    } else {
                        if ($notify_type == 'creator') {
                            // user is the creator of the post
                            $user_reply_to = $reply_to;
                        } else {
                            debug_die('Unknown user subscription type');
                        }
                    }
                }
            }
            $subject = sprintf($subject, $notify_full ? $edited_Blog->get('shortname') : $author_name, $edited_Item->get('title'));
            $email_template_params = array('notify_full' => $notify_full, 'Comment' => $this, 'Blog' => $edited_Blog, 'Item' => $edited_Item, 'author_name' => $author_name, 'author_ID' => $author_ID, 'notify_type' => $notify_type);
            if ($debug) {
                $notify_message = mail_template('comment_new', 'text', $email_template_params);
                $mail_dump = "Sending notification to {$notify_email}:<pre>Subject: {$subject}\n{$notify_message}</pre>";
                if ($debug >= 2) {
                    // output mail content - NOTE: this will kill sending of headers.
                    echo "<p>{$mail_dump}</p>";
                }
                $Debuglog->add($mail_dump, 'notification');
            }
            // Send the email:
            // Note: Note activated users won't get notification email
            send_mail_to_User($notify_user_ID, $subject, 'comment_new', $email_template_params, false, array('Reply-To' => $user_reply_to));
            blocked_emails_memorize($notify_User->email);
            locale_restore_previous();
        }
        blocked_emails_display();
    }
Exemple #13
0
 /**
  * @static
  */
 function gen_ID($root_type, $root_in_type_ID)
 {
     switch ($root_type) {
         case 'user':
         case 'collection':
         case 'skins':
             return $root_type . '_' . $root_in_type_ID;
     }
     debug_die("Root_type={$root_type} not supported");
 }
Exemple #14
0
 /**
  * Get a param.
  *
  * @param string Parameter name
  * @return false|string The value as string or false in case of error (e.g. media dir is disabled).
  */
 function get($parname)
 {
     global $xmlsrv_url, $baseurl, $basepath, $media_url, $current_User, $Settings, $Debuglog;
     switch ($parname) {
         case 'blogurl':
             // Deprecated
         // Deprecated
         case 'link':
             // Deprecated
         // Deprecated
         case 'url':
             return $this->gen_blogurl('default');
         case 'dynurl':
             return $this->gen_blogurl('dynamic');
         case 'staticurl':
             return $this->gen_blogurl('static');
         case 'dynfilepath':
             // Source file for static page:
             return $basepath . $this->get_setting('source_file');
         case 'staticfilepath':
             // Destiantion file for static page:
             return $basepath . $this->get_setting('static_file');
         case 'baseurl':
             return $this->gen_baseurl();
         case 'baseurlroot':
             // fp>> TODO: cleanup
             if (preg_match('#^(https?://(.+?)(:.+?)?)/#', $this->gen_baseurl(), $matches)) {
                 // TODO: shouldn't that include a trailing slash?:
                 return $matches[1];
             }
             debug_die('Blog::get(baseurl)/baseurlroot - assertion failed [baseurl: ' . $this->gen_baseurl() . '].');
         case 'lastcommentsurl':
             return url_add_param($this->gen_blogurl(), 'disp=comments');
         case 'arcdirurl':
             return url_add_param($this->gen_blogurl(), 'disp=arcdir');
         case 'catdirurl':
             return url_add_param($this->gen_blogurl(), 'disp=catdir');
         case 'mediaidxurl':
             return url_add_param($this->gen_blogurl(), 'disp=mediaidx');
         case 'msgformurl':
             return url_add_param($this->gen_blogurl(), 'disp=msgform');
         case 'description':
             // RSS wording
         // RSS wording
         case 'shortdesc':
             return $this->shortdesc;
         case 'rdf_url':
             return $this->get_item_feed_url('_rdf');
         case 'rss_url':
             return $this->get_item_feed_url('_rss');
         case 'rss2_url':
             return $this->get_item_feed_url('_rss2');
         case 'atom_url':
             return $this->get_item_feed_url('_atom');
         case 'comments_rdf_url':
             return $this->get_comment_feed_url('_rdf');
         case 'comments_rss_url':
             return $this->get_comment_feed_url('_rss');
         case 'comments_rss2_url':
             return $this->get_comment_feed_url('_rss2');
         case 'comments_atom_url':
             return $this->get_comment_feed_url('_atom');
             /* Add the html for a blog-specified stylesheet
              * All stylesheets will be included if the blog settings allow it
              * and the file "style.css" exists. CSS rules say that the latter style sheets can
              * override earlier stylesheets.
              */
         /* Add the html for a blog-specified stylesheet
          * All stylesheets will be included if the blog settings allow it
          * and the file "style.css" exists. CSS rules say that the latter style sheets can
          * override earlier stylesheets.
          */
         case 'blog_css':
             if ($this->allowblogcss && file_exists($this->get_media_dir(false) . 'style.css')) {
                 return '<link rel="stylesheet" href="' . $this->get_media_url() . 'style.css" type="text/css" />';
             } else {
                 return '';
             }
             /* Add the html for a user-specified stylesheet
              * All stylesheets will be included if the blog settings allow it
              * and the file "style.css" exists. CSS rules say that the latter style sheets can
              * override earlier stylesheets. A user-specified stylesheet will
              * override a blog-specified stylesheet which will override a skin stylesheet.
              */
         /* Add the html for a user-specified stylesheet
          * All stylesheets will be included if the blog settings allow it
          * and the file "style.css" exists. CSS rules say that the latter style sheets can
          * override earlier stylesheets. A user-specified stylesheet will
          * override a blog-specified stylesheet which will override a skin stylesheet.
          */
         case 'user_css':
             if ($this->allowusercss && isset($current_User) && file_exists($current_User->get_media_dir(false) . 'style.css')) {
                 return '<link rel="stylesheet" href="' . $current_User->get_media_url() . 'style.css" type="text/css" />';
             } else {
                 return '';
             }
         default:
             // All other params:
             return parent::get($parname);
     }
 }
 * @var instance of User class
 */
global $edited_User;
/**
 * @var current action
 */
global $action;
/**
 * @var user permission, if user is only allowed to edit his profile
 */
global $user_profile_only;
global $user_tab, $user_ID;
global $current_User, $UserSettings;
if (!$current_User->check_perm('users', 'edit')) {
    // Check permission:
    debug_die(T_('You have no permission to see this tab!'));
}
memorize_param('user_tab', 'string', '', $user_tab);
memorize_param('user_ID', 'integer', 0, $user_ID);
// ------------------- PREV/NEXT USER LINKS -------------------
user_prevnext_links(array('block_start' => '<table class="prevnext_user"><tr>', 'prev_start' => '<td width="33%">', 'prev_end' => '</td>', 'prev_no_user' => '<td width="33%">&nbsp;</td>', 'back_start' => '<td width="33%" class="back_users_list">', 'back_end' => '</td>', 'next_start' => '<td width="33%" class="right">', 'next_end' => '</td>', 'next_no_user' => '<td width="33%">&nbsp;</td>', 'block_end' => '</tr></table>', 'user_tab' => 'activity'));
// ------------- END OF PREV/NEXT USER LINKS -------------------
if (!$user_profile_only) {
    // echo user edit action icons
    $Widget = new Widget();
    echo_user_actions($Widget, $edited_User, 'edit');
    echo '<span class="floatright">' . $Widget->gen_global_icons() . '</span>';
}
echo '<div>' . get_usertab_header($edited_User, $user_tab, $current_User->ID == $edited_User->ID ? T_('My Activity') : T_('User Activity')) . '</div>';
// Display IP address from where this user was created
echo '<div style="margin-top:25px;font-weight:bold;"><span>' . T_('User created from IP') . ': ' . int2ip($UserSettings->get('created_fromIPv4', $edited_User->ID)) . '</span></div>';
Exemple #16
0
     $Form->fieldend = '#fieldend#';
     $Form->labelclass = '#labelclass#';
     $Form->labelstart = '#labelstart#';
     $Form->labelend = '#labelend#';
     $Form->inputstart = '#inputstart#';
     $Form->inputend = '#inputend#';
     $org_suffix .= ' ' . get_icon('add', 'imgtag', array('class' => 'add_org', 'style' => 'cursor:pointer'));
     $org_suffix .= ' ' . get_icon('minus', 'imgtag', array('class' => 'remove_org', 'style' => 'cursor:pointer'));
     $Form->select_input_object('organizations[]', 0, $OrganizationCache, T_('Organization'), array('allow_none' => $first_org ? true : false, 'field_suffix' => $org_suffix));
     break;
 case 'autocomplete_usernames':
     // Get usernames by first chars for autocomplete jQuery plugin & TinyMCE autocomplete plugin
     $q = param('q', 'string', '');
     if (!is_valid_login($q) || evo_strlen($q) < 4) {
         // Restrict a wrong request
         debug_die('Wrong request');
     }
     // Add backslash for special char of sql operator LIKE
     $q = str_replace('_', '\\_', $q);
     if (utf8_strlen($q) == 0) {
         // Don't search logins with empty request
         $usernames = array();
     } else {
         $SQL = new SQL();
         $SQL->SELECT('user_login');
         $SQL->FROM('T_users');
         $SQL->WHERE('user_login LIKE ' . $DB->quote($q . '%'));
         $SQL->WHERE_and('user_status = "activated" OR user_status = "autoactivated"');
         $SQL->ORDER_BY('user_login');
         $usernames = $DB->get_col($SQL->get());
     }
Exemple #17
0
/**
 * Get htsrv url on the same domain as the http request came from
 * _init_hit.inc.php should be called before this call, because ReqHost and ReqPath must be initialized
 */
function get_samedomain_htsrv_url($secure = false)
{
    global $ReqHost, $ReqPath, $htsrv_url, $htsrv_url_sensitive, $Blog;
    if ($secure) {
        $req_htsrv_url = $htsrv_url_sensitive;
    } else {
        $req_htsrv_url = $htsrv_url;
    }
    if (strpos($ReqHost . $ReqPath, $req_htsrv_url) !== false) {
        return $req_htsrv_url;
    }
    $req_url_parts = @parse_url($ReqHost);
    $hsrv_url_parts = @parse_url($req_htsrv_url);
    if (!isset($req_url_parts['host']) || !isset($hsrv_url_parts['host'])) {
        debug_die('Invalid hosts!');
    }
    $req_domain = $req_url_parts['host'];
    $htsrv_domain = $hsrv_url_parts['host'];
    $samedomain_htsrv_url = substr_replace($req_htsrv_url, $req_domain, strpos($req_htsrv_url, $htsrv_domain), strlen($htsrv_domain));
    if (!is_admin_page() && !empty($Blog) && $samedomain_htsrv_url != $Blog->get_local_htsrv_url()) {
        debug_die('Inconsistent state!');
    }
    return $samedomain_htsrv_url;
}
Exemple #18
0
/**
 * Initialize list mode; Several actions need this.
 */
function init_list_mode()
{
    global $tab, $Blog, $UserSettings, $ItemList, $AdminUI, $posttypes_perms;
    // set default itemslist param prefix
    $items_list_param_prefix = 'items_';
    if (param('p', 'integer', NULL) || param('title', 'string', NULL)) {
        // Single post requested, do not filter any post types. If the user
        // has clicked a post link on the dashboard and previously has selected
        // a tab which would filter this post, it wouldn't be displayed now.
        $tab = 'full';
        // in case of single item view params prefix must be empty
        $items_list_param_prefix = NULL;
    } else {
        // Store/retrieve preferred tab from UserSettings:
        $UserSettings->param_Request('tab', 'pref_browse_tab', 'string', NULL, true, true);
    }
    /*
     * Init list of posts to display:
     */
    load_class('items/model/_itemlist.class.php', 'ItemList2');
    if (!empty($tab) && !empty($items_list_param_prefix)) {
        // Use different param prefix for each tab
        $items_list_param_prefix .= substr($tab, 0, 7) . '_';
    }
    // Create empty List:
    $ItemList = new ItemList2($Blog, NULL, NULL, $UserSettings->get('results_per_page'), 'ItemCache', $items_list_param_prefix, $tab);
    // COPY (func)
    $ItemList->set_default_filters(array('visibility_array' => get_visibility_statuses('keys')));
    if ($Blog->get_setting('orderby') == 'RAND') {
        // Do not display random posts in backoffice for easy management
        $ItemList->set_default_filters(array('orderby' => 'datemodified'));
    }
    switch ($tab) {
        case 'full':
            $ItemList->set_default_filters(array('types' => NULL));
            // $AdminUI->breadcrumbpath_add( T_('All items'), '?ctrl=items&amp;blog=$blog$&amp;tab='.$tab.'&amp;filter=restore' );
            // require colorbox js
            require_js_helper('colorbox');
            break;
        case 'manual':
            if ($Blog->get('type') != 'manual') {
                // Display this tab only for manual blogs
                global $admin_url;
                header_redirect($admin_url . '?ctrl=items&blog=' . $Blog->ID . '&tab=list&filter=restore');
            }
            $AdminUI->breadcrumbpath_add(T_('Manual Pages'), '?ctrl=items&amp;blog=$blog$&amp;tab=' . $tab . '&amp;filter=restore');
            break;
        case 'list':
            // Nothing special
            $AdminUI->breadcrumbpath_add(T_('Regular posts'), '?ctrl=items&amp;blog=$blog$&amp;tab=' . $tab . '&amp;filter=restore');
            break;
        case 'pages':
            $ItemList->set_default_filters(array('types' => implode(',', $posttypes_perms['page'])));
            $AdminUI->breadcrumbpath_add(T_('Pages'), '?ctrl=items&amp;blog=$blog$&amp;tab=' . $tab . '&amp;filter=restore');
            break;
        case 'intros':
            $ItemList->set_default_filters(array('types' => implode(',', $posttypes_perms['intro'])));
            $AdminUI->breadcrumbpath_add(T_('Intro posts'), '?ctrl=items&amp;blog=$blog$&amp;tab=' . $tab . '&amp;filter=restore');
            break;
        case 'podcasts':
            $ItemList->set_default_filters(array('types' => implode(',', $posttypes_perms['podcast'])));
            $AdminUI->breadcrumbpath_add(T_('Podcasts'), '?ctrl=items&amp;blog=$blog$&amp;tab=' . $tab . '&amp;filter=restore');
            break;
        case 'links':
            $ItemList->set_default_filters(array('types' => '3000'));
            $AdminUI->breadcrumbpath_add(T_('Links'), '?ctrl=items&amp;blog=$blog$&amp;tab=' . $tab . '&amp;filter=restore');
            break;
        case 'ads':
            $ItemList->set_default_filters(array('types' => '4000'));
            $AdminUI->breadcrumbpath_add(T_('Advertisements'), '?ctrl=items&amp;blog=$blog$&amp;tab=' . $tab . '&amp;filter=restore');
            break;
        case 'tracker':
            // In tracker mode, we want a different default sort:
            $ItemList->set_default_filters(array('orderby' => 'priority', 'order' => 'ASC'));
            break;
        default:
            // Delete the pref_browse_tab setting so that the default
            // (full) gets used the next time the user wants to browse
            // a blog and we don't run into the same error again.
            $UserSettings->delete('pref_browse_tab');
            $UserSettings->dbupdate();
            debug_die('Unknown filterset [' . $tab . ']');
    }
    // Init filter params:
    if (!$ItemList->load_from_Request()) {
        // If we could not init a filterset from request
        // typically happens when we could no fall back to previously saved filterset...
        // echo ' no filterset!';
    }
}
Exemple #19
0
/**
 * Get the delta query to adjust the current database according to a given (list of)
 * "CREATE TABLE"-, "CREATE DATABASE"-, "INSERT"- or "UPDATE"-statement(s).
 *
 * It's not recommended to use INSERT or UPDATE statements with this function, as they
 * are just handled "as-is".
 *
 * NOTE:
 *   - You should use single quotes (') to give string type values (this is in fact
 *     required for ENUM and SET fields).
 *   - KEYs for AUTO_INCREMENT fields should be defined in column_definition, otherwise
 *     we had to detect the key type from the INDEX query and add it to the ALTER/ADD query.
 *   - If a column changes from "NULL" to "NOT NULL" we generate an extra UPDATE query
 *     to prevent "Data truncated for column 'X' at row Y" errors.
 *
 * The following query types are generated/marked and can be excluded:
 *  - 'create_table'
 *  - 'create_database'
 *  - 'insert'
 *  - 'update'
 *  - 'drop_column'
 *  - 'change_column'
 *  - 'change_default'
 *  - 'add_column'
 *  - 'add_index'
 *  - 'drop_index'
 *  - 'alter_engine'
 * NOTE: it may be needed to merge an 'add_index' or 'drop_index' type query into an
 *       'add_column'/'change_column' query (adding "AUTO_INCREMENT" for example)!
 *
 * NOTE: collations and charset changes are ignored. It seems quite difficult to support this,
 *       and it seems to be best to handle this "manually".
 *
 * @author Originally taken from Wordpress, heavily enhanced and modified by blueyed
 *
 * @todo Handle COMMENT for tables?!
 *
 * @see http://dev.mysql.com/doc/refman/4.1/en/create-table.html
 *
 * @param array The list of queries for which the DB should be adjusted
 * @param array Exclude query types (see list above).
 * @param boolean Execute generated queries?  TODO: get this outta here!!!! (sooooo bloated!)
 * @return array The generated queries.
 *        table_name => array of arrays (queries with keys 'queries' (array), 'note' (string) and 'type' (string))
 *        There's usually just a single query in "queries", but in some cases additional queries
 *        are needed (e.g., 'UPDATE' before we can change "NULL" setting).
 */
function db_delta($queries, $exclude_types = array(), $execute = false)
{
    global $Debuglog, $DB, $debug;
    if (!is_array($queries)) {
        $queries = array($queries);
    }
    if (!is_array($exclude_types)) {
        $exclude_types = empty($exclude_types) ? array() : array($exclude_types);
    }
    /**
     * Generated query items, indexed by table name.
     */
    $items = array();
    // Split the queries into $items, by their type:
    foreach ($queries as $qry) {
        // Remove any comments from the SQL:
        $qry = remove_comments_from_query($qry);
        if (preg_match('|^(\\s*CREATE TABLE\\s+)(IF NOT EXISTS\\s+)?([^\\s(]+)(.*)$|is', $qry, $match)) {
            $tablename = db_delta_remove_quotes(preg_replace($DB->dbaliases, $DB->dbreplaces, $match[3]));
            $qry = $match[1] . (empty($match[2]) ? '' : $match[2]) . $tablename . $match[4];
            $items[strtolower($tablename)][] = array('queries' => array($qry), 'note' => sprintf('Created table &laquo;<strong>%s</strong>&raquo;', $tablename), 'type' => 'create_table');
        } elseif (preg_match('|^\\s*CREATE DATABASE\\s([\\S]+)|i', $qry, $match)) {
            // add to the beginning
            array_unshift($items, array('queries' => array($qry), 'note' => sprintf('Created database &laquo;<strong>%s</strong>&raquo;', $match[1]), 'type' => 'create_database'));
        } elseif (preg_match('|^(\\s*INSERT INTO\\s+)([\\S]+)(.*)$|is', $qry, $match)) {
            $tablename = db_delta_remove_quotes(preg_replace($DB->dbaliases, $DB->dbreplaces, $match[2]));
            $items[strtolower($tablename)][] = array('queries' => array($match[1] . $tablename . $match[3]), 'note' => '', 'type' => 'insert');
        } elseif (preg_match('|^(\\s*UPDATE\\s+)([\\S]+)(.*)$|is', $qry, $match)) {
            $tablename = db_delta_remove_quotes(preg_replace($DB->dbaliases, $DB->dbreplaces, $match[2]));
            $items[strtolower($tablename)][] = array('queries' => array($match[1] . $tablename . $match[3]), 'note' => '', 'type' => 'update');
        } else {
            $Debuglog->add('db_delta: Unrecognized query type: ' . $qry, 'note');
        }
    }
    /**
     * @global array Available tables in the current database
     */
    $tables = $DB->get_col('SHOW TABLES');
    // Loop through existing tables and check which tables and fields exist
    foreach ($tables as $table) {
        // For every table in the database
        $table_lowered = strtolower($table);
        // table names are treated case insensitive
        if (!isset($items[$table_lowered])) {
            // This table exists in the database, but not in the creation queries.
            continue;
        }
        /**
         * @global array Hold the indices we want to create/have, with meta data keys.
         */
        $indices = array();
        /**
         * @global array Initially all existing indices. Any index, that does not get unset here, generates a 'drop_index' type query.
         */
        $obsolete_indices = array();
        /**
         * @global array Fields of the existing primary key (if any)
         */
        $existing_primary_fields = array();
        /**
         * @global array Fields of existing keys (including PRIMARY), lowercased (if any)
         */
        $existing_key_fields = array();
        /**
         * @global array Column field names of PRIMARY KEY, lowercased (if any)
         */
        $primary_key_fields = array();
        /**
         * @global array Column field names of FOREIGN KEY, lowercased (if any)
         */
        $foreign_key_fields = array();
        /**
         * @global array of col_names that have KEYs (including PRIMARY; lowercased). We use this for AUTO_INCREMENT magic.
         */
        $fields_with_keys = array();
        /**
         * @global string Holds the fielddef of an obsolete ("drop_column") AUTO_INCREMENT field. We must alter this with a PK "ADD COLUMN" query.
         */
        $obsolete_autoincrement = NULL;
        /**
         * @global array List of fields (and definition from query)
         *   <code>fieldname (lowercase) => array(
         *         'field' => "column_definition",
         *         'where' => "[FIRST|AFTER xxx]" )
         *   </code>
         */
        $wanted_fields = array();
        /**
         * @global boolean Do we have any variable-length fields? (see http://dev.mysql.com/doc/refman/4.1/en/silent-column-changes.html)
         */
        $has_variable_length_field = false;
        // Get all of the field names in the query from between the parens
        $flds = get_fieldlines_from_query($items[$table_lowered][0]['queries'][0]);
        //echo "<hr/><pre>\n".print_r(strtolower($table), true).":\n".print_r($items, true)."</pre><hr/>";
        // ALTER ENGINE, if different (and given in query):
        if (($wanted_engine = get_engine_from_query($items[$table_lowered][0]['queries'][0])) !== false) {
            $current_engine = $DB->get_row('
				SHOW TABLE STATUS LIKE ' . $DB->quote($table));
            $current_engine = $current_engine->Engine;
            if (strtolower($current_engine) != strtolower($wanted_engine)) {
                $items[$table_lowered][] = array('queries' => array('ALTER TABLE ' . $table . ' ENGINE=' . $wanted_engine), 'note' => 'Alter engine of <strong>' . $table . '.</strong> to <strong>' . $wanted_engine . '</strong>', 'type' => 'alter_engine');
            }
        }
        $prev_fld = '';
        foreach ($flds as $create_definition) {
            // For every field line specified in the query
            // Extract the field name
            preg_match('|^([^\\s(]+)|', trim($create_definition), $match);
            $fieldname = db_delta_remove_quotes($match[1]);
            $fieldname_lowered = strtolower($fieldname);
            $create_definition = trim($create_definition, ", \r\n\t");
            if (in_array($fieldname_lowered, array('', 'primary', 'foreign', 'index', 'fulltext', 'unique', 'key'))) {
                // INDEX (but not in column_definition - those get handled later)
                $add_index = array('create_definition' => $create_definition);
                if (!preg_match('~^(PRIMARY(?:\\s+KEY)|(?:FULLTEXT|UNIQUE)(?:\\s+(?:INDEX|KEY))?|KEY|INDEX) (?:\\s+()     (\\w+)      )? (\\s+USING\\s+\\w+)? \\s* \\((.*)\\)$~ix', $create_definition, $match) && !preg_match('~^(PRIMARY(?:\\s+KEY)|(?:FULLTEXT|UNIQUE)(?:\\s+(?:INDEX|KEY))?|KEY|INDEX) (?:\\s+([`"])([\\w\\s]+)\\2)? (\\s+USING\\s+\\w+)? \\s* \\((.*)\\)$~ix', $create_definition, $match) && !preg_match('~^(FOREIGN\\s+KEY) \\s* \\((.*)\\) \\s* (REFERENCES) \\s* ([^( ]*) \\s* \\((.*)\\) \\s* (.*)$~ixs', $create_definition, $match)) {
                    // invalid type, should not happen
                    debug_die('Invalid type in $indices: ' . $create_definition);
                    // TODO: add test: Invalid type in $indices: KEY "coord" ("lon","lat")
                }
                if ($fieldname_lowered == 'foreign') {
                    // Remember FOREIGN KEY fields, but they don't have to be indexed
                    $reference_table_name = db_delta_remove_quotes(preg_replace($DB->dbaliases, $DB->dbreplaces, $match[4]));
                    $foreign_key_fields[] = array('fk_fields' => $match[2], 'reference_table' => $reference_table_name, 'reference_columns' => $match[5], 'fk_definition' => $match[6], 'create' => true);
                    continue;
                }
                $add_index['keyword'] = $match[1];
                $add_index['name'] = strtoupper($match[3]);
                $add_index['type'] = $match[4];
                // "USING [type_name]"
                $add_index['col_names'] = explode(',', $match[5]);
                foreach ($add_index['col_names'] as $k => $v) {
                    $add_index['col_names'][$k] = strtolower(db_delta_remove_quotes(trim($v)));
                }
                if ($fieldname_lowered == 'primary') {
                    // Remember PRIMARY KEY fields to be indexed (used for NULL check)
                    $primary_key_fields = $add_index['col_names'];
                    $add_index['is_PK'] = true;
                } else {
                    $add_index['is_PK'] = false;
                }
                $fields_with_keys = array_unique(array_merge($fields_with_keys, $add_index['col_names']));
                $indices[] = $add_index;
            } else {
                // "normal" field, add it to the field array
                $wanted_fields[strtolower($fieldname_lowered)] = array('field' => $create_definition, 'where' => empty($prev_fld) ? 'FIRST' : 'AFTER ' . $prev_fld);
                $prev_fld = $fieldname;
                if (preg_match('~^\\S+\\s+(VARCHAR|TEXT|BLOB)~i', $create_definition)) {
                    $has_variable_length_field = true;
                }
            }
        }
        // INDEX STUFF:
        /**
         * @global array Holds the existing indices (with array's key UPPERcased)
         */
        $existing_indices = array();
        // Fetch the table index structure from the database
        $tableindices = $DB->get_results('SHOW INDEX FROM ' . $table);
        if (!empty($tableindices)) {
            // For every index in the table
            foreach ($tableindices as $tableindex) {
                // Add the index to the index data array
                $keyname = strtoupper($tableindex->Key_name);
                $existing_indices[$keyname]['name'] = $tableindex->Key_name;
                // original case
                $existing_indices[$keyname]['columns'][] = array('fieldname' => $tableindex->Column_name, 'subpart' => $tableindex->Sub_part);
                $existing_indices[$keyname]['unique'] = $tableindex->Non_unique == 0 ? true : false;
            }
            unset($tableindices);
            // Let's see which indices are present already for the table:
            // TODO: dh> use meta data available now in $indices, instead of building a regular expression!?
            $obsolete_indices = $existing_indices;
            // will get unset as found
        }
        // Pre-run KEYs defined in "column_definition" (e.g. used for AUTO_INCREMENT handling)
        foreach ($wanted_fields as $fieldname_lowered => $field_info) {
            $parse = $field_info['field'];
            if (preg_match('~ \\b UNIQUE (?:\\s+ KEY)? \\b ~ix ', $parse, $match)) {
                // This has an "inline" UNIQUE index:
                if (!is_in_quote($parse, ' ' . $match[0])) {
                    // isn't between quotation marks, so it must be a primary key.
                    $indices[] = array('name' => $fieldname_lowered, 'is_PK' => false, 'create_definition' => NULL, 'col_names' => array($fieldname_lowered), 'keyword' => NULL);
                    unset($obsolete_indices[strtoupper($fieldname_lowered)]);
                    $parse = str_replace($match[0], '', $parse);
                    $fields_with_keys[] = $fieldname_lowered;
                }
            }
            if (preg_match('~ \\b (PRIMARY\\s+)? KEY \\b ~ix', $parse, $match)) {
                // inline PK:
                // Check if this key is between quotation marks
                if (!is_in_quote($parse, ' ' . $match[0])) {
                    // it isn't between quotation marks, so it must be a primary key.
                    $indices[] = array('name' => 'PRIMARY', 'is_PK' => true, 'create_definition' => NULL, 'col_names' => array($fieldname_lowered), 'keyword' => NULL);
                    $fields_with_keys[] = $fieldname_lowered;
                    $primary_key_fields = array($fieldname_lowered);
                    unset($obsolete_indices['PRIMARY']);
                }
            }
        }
        $fields_with_keys = array_unique($fields_with_keys);
        foreach ($existing_indices as $index_name => $index_data) {
            // Build a create string to compare to the query
            $index_pattern = '^';
            if ($index_name == 'PRIMARY') {
                $index_pattern .= 'PRIMARY(\\s+KEY)?';
                // optional primary key name:
                $index_pattern .= '(\\s+[`"]?\\w+[`"]?)?';
            } elseif ($index_data['unique']) {
                $index_pattern .= 'UNIQUE(\\s+(?:INDEX|KEY))?';
            } else {
                $index_pattern .= '(INDEX|(?:FULLTEXT\\s+)?KEY)';
            }
            if ($index_name != 'PRIMARY') {
                $index_pattern .= '(\\s+[`"]?' . $index_name . '[`"]?)?';
                // optionally in backticks (and index name is optionally itself)
            }
            $index_columns = '';
            // For each column in the index
            foreach ($index_data['columns'] as $column_data) {
                if ($index_columns != '') {
                    $index_columns .= '\\s*,\\s*';
                }
                // Add the field to the column list string
                $index_columns .= '[`"]?' . $column_data['fieldname'] . '[`"]?';
                // optionally in backticks
                if (!empty($column_data['subpart'])) {
                    $index_columns .= '\\s*\\(\\s*' . $column_data['subpart'] . '\\s*\\)\\s*';
                }
            }
            // Sort index definitions with names to the beginning:
            /*
            usort( $indices, create_function( '$a, $b', '
            	if( preg_match( "~^\w+\s+[^(]~", $a["create_definition"] )
            	{
            
            	}' ) );
            */
            $used_auto_keys = array();
            foreach ($indices as $k => $index) {
                $pattern = $index_pattern;
                if (!preg_match('~^\\w+\\s+[^(]~', $index['create_definition'], $match)) {
                    // no key name given, make the name part optional, if it's the default one:
                    // (Default key name seems to be the first column, eventually with "_\d+"-suffix)
                    $auto_key = db_delta_remove_quotes(strtoupper($index['col_names'][0]));
                    if (isset($used_auto_keys[$auto_key])) {
                        $used_auto_keys[$auto_key]++;
                        $auto_key .= '_' . $used_auto_keys[$auto_key];
                    }
                    $used_auto_keys[$auto_key] = 1;
                    if ($auto_key == $index_name) {
                        // the auto-generated keyname is the same as the one we have, so make it optional in the pattern:
                        $pattern .= '?';
                    }
                }
                // Add the column list to the index create string
                $pattern .= '\\s*\\(\\s*' . $index_columns . '\\s*\\)';
                #pre_dump( '~'.$pattern.'~i', trim($index['create_definition']) );
                if (preg_match('~' . $pattern . '~i', trim($index['create_definition']))) {
                    // This index already exists: remove the index from our indices to create
                    unset($indices[$k]);
                    unset($obsolete_indices[$index_name]);
                    break;
                }
            }
            if (isset($obsolete_indices[$index_name])) {
                #echo "<pre style=\"border:1px solid #ccc;margin-top:5px;\">{$table}:<br/><b>Did not find index:</b>".$index_name.'/'.$index_pattern."<br/>".print_r($indices, true)."</pre>\n";
            }
        }
        // Set $existing_primary_fields and $existing_key_fields
        foreach ($existing_indices as $l_key_name => $l_key_info) {
            $l_key_fields = array();
            foreach ($l_key_info['columns'] as $l_col) {
                $l_key_fields[] = strtolower($l_col['fieldname']);
            }
            if ($l_key_name == 'PRIMARY') {
                // Remember _existing_ PRIMARY KEYs
                $existing_primary_fields = $l_key_fields;
            }
            $existing_key_fields = array_merge($existing_key_fields, $l_key_fields);
        }
        $existing_key_fields = array_unique($existing_key_fields);
        #pre_dump( 'existing_primary_fields', $existing_primary_fields );
        #pre_dump( 'existing_key_fields', $existing_key_fields );
        // Fetch the table column structure from the database
        $tablefields = $DB->get_results('SHOW FULL COLUMNS FROM ' . $table);
        // If "drop_column" is not excluded we have to check if all existing cols would get dropped,
        // to prevent "You can't delete all columns with ALTER TABLE; use DROP TABLE instead(Errno=1090)"
        if (!in_array('drop_column', $exclude_types)) {
            $at_least_one_col_stays = false;
            foreach ($tablefields as $tablefield) {
                $fieldname_lowered = strtolower($tablefield->Field);
                if (isset($wanted_fields[$fieldname_lowered])) {
                    $at_least_one_col_stays = true;
                }
            }
            if (!$at_least_one_col_stays) {
                // all columns get dropped: so we need to DROP TABLE and then use the original CREATE TABLE
                array_unshift($items[$table_lowered], array('queries' => array('DROP TABLE ' . $table), 'note' => 'Dropped <strong>' . $table . '.</strong>', 'type' => 'drop_column'));
                continue;
                // next $table
            }
        }
        // For every field in the existing table
        foreach ($tablefields as $tablefield) {
            $fieldname_lowered = strtolower($tablefield->Field);
            if (!isset($wanted_fields[$fieldname_lowered])) {
                // This field exists in the table, but not in the creation queries
                if (in_array('drop_column', $exclude_types)) {
                    if (preg_match('~\\bAUTO_INCREMENT\\b~i', $tablefield->Extra)) {
                        // must be modified with a ADD COLUMN which drops a PK
                        $obsolete_autoincrement = $tablefield;
                    }
                } else {
                    $items[$table_lowered][] = array('queries' => array('ALTER TABLE ' . $table . ' DROP COLUMN ' . $tablefield->Field), 'note' => 'Dropped ' . $table . '.<strong>' . $tablefield->Field . '</strong>', 'type' => 'drop_column');
                    // Unset in key indices:
                    if (($k = array_search($fieldname_lowered, $existing_key_fields)) !== false) {
                        unset($existing_key_fields[$k]);
                    }
                    if (($k = array_search($fieldname_lowered, $existing_primary_fields)) !== false) {
                        unset($existing_primary_fields[$k]);
                    }
                }
                continue;
            }
            $column_definition = trim($wanted_fields[$fieldname_lowered]['field']);
            unset($type_matches);
            // have we detected the type as matching (for optional length param)
            $fieldtype = '';
            $pattern_field = '[`"]?' . $tablefield->Field . '[`"]?';
            // optionally in backticks
            // Get the field type from the query
            if (preg_match('~^' . $pattern_field . '\\s+ (TINYINT|SMALLINT|MEDIUMINT|INTEGER|INT|BIGINT|REAL|DOUBLE|FLOAT|DECIMAL|DEC|NUMERIC) ( \\s* \\([\\d\\s,]+\\) )? (\\s+ UNSIGNED)? (\\s+ ZEROFILL)? (.*)$~ix', $column_definition, $match)) {
                $fieldtype = strtoupper($match[1]);
                if ($fieldtype == 'INTEGER') {
                    // synonym
                    $fieldtype = 'INT';
                } elseif ($fieldtype == 'DEC') {
                    // synonym
                    $fieldtype = 'DECIMAL';
                }
                if (isset($match[2])) {
                    // append optional "length" param (trimmed)
                    $fieldtype .= preg_replace('~\\s+~', '', $match[2]);
                }
                if (!empty($match[3])) {
                    // "unsigned"
                    $fieldtype .= ' ' . trim($match[3]);
                }
                if (!empty($match[4])) {
                    // "zerofill"
                    $fieldtype .= ' ' . trim($match[4]);
                }
                $field_to_parse = $match[5];
                // The length param is optional:
                if (substr($fieldtype, 0, 7) == 'DECIMAL') {
                    $matches_pattern = '~^' . preg_quote($tablefield->Type, '~') . '$~i';
                } else {
                    $matches_pattern = '~^' . preg_replace('~\\((\\d+)\\)~', '(\\(\\d+\\))?', $tablefield->Type) . '$~i';
                }
                $type_matches = preg_match($matches_pattern, $fieldtype);
            } elseif (preg_match('~^' . $pattern_field . '\\s+(DATETIME|DATE|TIMESTAMP|TIME|YEAR|TINYBLOB|BLOB|MEDIUMBLOB|LONGBLOB|TINYTEXT|TEXT|MEDIUMTEXT|LONGTEXT) ( \\s+ BINARY )? (.*)$~ix', $column_definition, $match)) {
                $fieldtype = strtoupper($match[1]);
                if (isset($match[2])) {
                    // "binary"
                    $fieldtype .= trim($match[2]);
                }
                $field_to_parse = $match[3];
                // There's a bug with a "NOT NULL" field reported as "NULL", work around it (http://bugs.mysql.com/bug.php?id=20910):
                if ($fieldtype == 'TIMESTAMP') {
                    $ct_sql = $DB->get_var('SHOW CREATE TABLE ' . $table, 1, 0);
                    if (preg_match('~^\\s*`' . $tablefield->Field . '`\\s+TIMESTAMP\\s+(NOT )?NULL~im', $ct_sql, $match)) {
                        $tablefield->Null = empty($match[1]) ? 'YES' : 'NO';
                    }
                }
            } elseif (preg_match('~^' . $pattern_field . '\\s+ (CHAR|VARCHAR|BINARY|VARBINARY) \\s* \\( ([\\d\\s]+) \\) (\\s+ (BINARY|ASCII|UNICODE) )? (.*)$~ix', $column_definition, $match)) {
                $len = trim($match[2]);
                $fieldtype = strtoupper($match[1]) . '(' . $len . ')';
                if (!empty($match[3])) {
                    // "binary", "ascii", "unicode"
                    $fieldtype .= ' ' . $match[3];
                }
                $field_to_parse = $match[5];
                if (strtoupper($match[1]) == 'VARCHAR') {
                    if ($len < 4) {
                        // VARCHAR shorter than 4 get converted to CHAR (but reported as VARCHAR in MySQL 5.0)
                        $type_matches = preg_match('~^(VAR)?CHAR\\(' . $len . '\\)' . ($match[3] ? ' ' . $match[3] : '') . '$~i', $tablefield->Type);
                    }
                } elseif ($has_variable_length_field && strtoupper($match[1]) == 'CHAR') {
                    // CHARs in a row with variable length fields get silently converted to VARCHAR (but reported as CHAR in MySQL 5.0)
                    $type_matches = preg_match('~^(VAR)?' . preg_quote($fieldtype, '~') . '$~i', $tablefield->Type);
                }
            } elseif (preg_match('~^' . $pattern_field . '\\s+ (ENUM|SET) \\s* \\( (.*) \\) (.*)$~ix', $column_definition, $match)) {
                $values = preg_split('~\\s*,\\s*~', trim($match[2]), -1, PREG_SPLIT_NO_EMPTY);
                // TODO: will fail for values containing ","..
                $values = implode(',', $values);
                $fieldtype = strtoupper($match[1]) . '(' . $values . ')';
                $field_compare = strtolower($match[1]) . '(' . $values . ')';
                // compare case-sensitive
                $type_matches = $field_compare == $tablefield->Type;
                $field_to_parse = $match[3];
            } else {
                if ($debug) {
                    debug_die('db_delta(): Cannot find existing types field in column definition (' . $pattern_field . '/' . $column_definition . ')');
                }
                continue;
            }
            // DEFAULT
            $want_default = false;
            if (preg_match('~^(.*?) \\s DEFAULT \\s+ (?: (?: (["\']) (.*?) \\2 ) | (\\w+) ) (\\s .*)?$~ix', $field_to_parse, $match)) {
                if (isset($match[4]) && $match[4] !== '') {
                    $want_default = $match[4];
                    $want_default_set = $match[4];
                } else {
                    $want_default = $match[3];
                    $want_default_set = $match[2] . $match[3] . $match[2];
                    // encapsulate in quotes again
                }
                $field_to_parse = $match[1] . (isset($match[5]) ? $match[5] : '');
            }
            // KEY
            $has_inline_primary_key = false;
            if (preg_match('~^(.*) \\b (?: (UNIQUE) (?:\\s+ (?:INDEX|KEY))? | (?:PRIMARY \\s+)? KEY ) \\b (.*)$~ix', $field_to_parse, $match)) {
                // fields got added to primary_key_fields and fields_with_keys before
                // Check if this key is between quotation marks
                if (!has_open_quote($match[1])) {
                    // is not between quotation marks, so it must be a key.
                    $field_to_parse = $match[1] . $match[3];
                    if (empty($match[2])) {
                        $has_inline_primary_key = true;
                        // we need to DROP the PK if this column definition does not match
                    }
                }
            }
            // AUTO_INCREMENT (with special index handling: AUTO_INCREMENT fields need to be PRIMARY or UNIQUE)
            $is_auto_increment = false;
            if (preg_match('~(.*?) \\b AUTO_INCREMENT \\b (.*)$~ix', $field_to_parse, $match)) {
                $is_auto_increment = true;
                $field_to_parse = $match[1] . $match[2];
                if (!preg_match('~\\bAUTO_INCREMENT\\b~i', $tablefield->Extra)) {
                    // not AUTO_INCREMENT yet
                    $type_matches = false;
                }
                if (!in_array($fieldname_lowered, $fields_with_keys)) {
                    // no KEY defined (but required for AUTO_INCREMENT fields)
                    debug_die('No KEY/INDEX defined for AUTO_INCREMENT column!');
                }
                if (in_array($fieldname_lowered, $existing_key_fields)) {
                    if (!empty($primary_key_fields)) {
                        $column_definition .= ', DROP PRIMARY KEY';
                        unset($obsolete_indices['PRIMARY']);
                    }
                } else {
                    // a key for this AUTO_INCREMENT field does not exist yet, we search it in $indices
                    foreach ($indices as $k_index => $l_index) {
                        // go through the indexes we want to have
                        if (array_search($fieldname_lowered, $l_index['col_names']) === false) {
                            // this is not an index for our column
                            continue;
                        }
                        // this index definition affects us, we have to add it to our ALTER statement..
                        // See if we need to drop it, before adding it:
                        if ($l_index['is_PK']) {
                            // Part of a PRIMARY key..
                            if (!empty($existing_primary_fields)) {
                                // and a PRIMARY key exists already
                                $column_definition .= ', DROP PRIMARY KEY';
                                unset($obsolete_indices['PRIMARY']);
                            }
                            $existing_primary_fields = array();
                            // we expect no existing primary key anymore
                            $primary_key_fields = $l_index['col_names'];
                            // this becomes our primary key
                        } elseif (isset($existing_indices[$l_index['name']])) {
                            // this index already exists, drop it:
                            $column_definition .= ', DROP INDEX ' . $existing_indices[$l_index['name']];
                            // original case
                            unset($existing_indices[$l_index['name']]);
                            // we expect that it does not exist anymore
                            if (!in_array($fieldname_lowered, $fields_with_keys)) {
                                // add te field to the list of keys we want/expect to have:
                                $fields_with_keys[] = $fieldname_lowered;
                            }
                        }
                        // Merge the INDEX creation into our ALTER query:
                        $column_definition .= ', ADD ' . $l_index['create_definition'];
                        unset($indices[$k_index]);
                    }
                }
            }
            // "[NOT] NULL" (requires $primary_key_fields to be finalized)
            if (preg_match('~(.*?) \\b (NOT\\s+)? NULL \\b (.*)$~ix', $field_to_parse, $match)) {
                // if "NOT" not matched it's NULL
                $want_null = empty($match[2]);
                $field_to_parse = $match[1] . $match[3];
            } else {
                // not specified: "NULL" is default
                $want_null = true;
            }
            if (in_array($fieldname_lowered, $primary_key_fields) || $is_auto_increment) {
                // If part of PRIMARY KEY or AUTO_INCREMENT field "NULL" is implicit
                $change_null = false;
                // implicit NULL
                $want_null = 'IMPLICIT';
            } elseif (in_array($fieldname_lowered, $existing_primary_fields) && !in_array($fieldname_lowered, $primary_key_fields)) {
                // the field was in PRIMARY KEY, but is no longer. It should get altered only if we want "NOT NULL"
                $change_null = !$want_null && $tablefield->Null == 'YES';
                #pre_dump( $want_null );
                #$want_null = 'IMPLICIT2';
                #pre_dump( $primary_key_fields );
            } else {
                if ($tablefield->Null == 'YES') {
                    $change_null = !$want_null;
                } else {
                    // I've seen '' and 'NO' for no..
                    $change_null = $want_null;
                }
            }
            // COMMENT ( check if there is difference in field comment )
            if (preg_match('~^(.*?) \\s COMMENT \\s+ (?: (?: (["\']) (.*?) \\2 ) ) (\\s .*)?$~ix', $field_to_parse, $match)) {
                if (isset($match[4]) && $match[4] !== '') {
                    $want_comment = $match[4];
                } else {
                    $want_comment = $match[3];
                }
                $want_comment = stripslashes($want_comment);
                $type_matches = $tablefield->Comment == $want_comment;
                $field_to_parse = $match[1] . (isset($match[5]) ? $match[5] : '');
            }
            // TODO: "COLLATE" and other attribute handling should happen here, based on $field_to_parse
            if (!isset($type_matches)) {
                // not tried to match before
                $type_matches = strtoupper($tablefield->Type) == $fieldtype;
            }
            #pre_dump( 'change_null ($change_null, $tablefield, $want_null)', $change_null, $tablefield, $want_null );
            #pre_dump( 'type_matches', $type_matches, strtolower($tablefield->Type), $fieldtype );
            // See what DEFAULT we would get or want
            $update_default = NULL;
            $update_default_set = NULL;
            if ($want_default !== false) {
                $update_default = $want_default;
                $update_default_set = $want_default_set;
            } else {
                // implicit default, see http://dev.mysql.com/doc/refman/4.1/en/data-type-defaults.html
                if (preg_match('~^(TINYINT|SMALLINT|MEDIUMINT|INTEGER|INT|BIGINT|REAL|DOUBLE|FLOAT|DECIMAL|DEC|NUMERIC)~', $fieldtype)) {
                    // numeric
                    $update_default = '0';
                    $update_default_set = '0';
                } elseif ($fieldtype == 'TIMESTAMP') {
                    // TODO: the default should be current date and time for the first field - but AFAICS we won't have NULL fields anyway
                } elseif (preg_match('~^(DATETIME|DATE|TIME|YEAR)$~', $fieldtype)) {
                    $update_default = '0';
                    // short form for various special "zero" values
                    $update_default_set = '0';
                } elseif (substr($fieldtype, 0, 4) == 'ENUM') {
                    preg_match('~["\']?.*?["\']?\\s*[,)]~x', substr($fieldtype, 5), $match);
                    $update_default_set = trim($match[0], "\n\r\t\vB (),");
                    // strip default whitespace, braces & comma
                    // first value (until "," or end) of $fieldtype_param:
                    $update_default = preg_replace('~^(["\'])(.*)\\1$~', '$2', $update_default_set);
                    // without quotes
                } else {
                    $update_default_set = "''";
                    // empty string for string types
                    $update_default = '';
                }
            }
            // Is actual field type different from the field type in query?
            if (!$type_matches || $change_null) {
                // Change the whole column to $column_definition:
                /*
                echo '<h2>No_Match</h2>';
                pre_dump( $type_matches, $change_null, $want_null );
                pre_dump( $tablefield, $column_definition );
                pre_dump( 'flds', $flds );
                pre_dump( 'wanted_fields', $wanted_fields );
                pre_dump( strtolower($tablefield->Type), $fieldtype, $column_definition );
                */
                $queries = array('ALTER TABLE ' . $table);
                // Handle inline PRIMARY KEY definition:
                if ($has_inline_primary_key && !empty($existing_primary_fields)) {
                    // the column is part of the PRIMARY KEY, which needs to get dropped before (we already handle that for AUTO_INCREMENT fields)
                    $queries[0] .= ' DROP PRIMARY KEY,';
                    $existing_primary_fields = array();
                    // we expect no existing primary key anymore
                    unset($obsolete_indices['PRIMARY']);
                }
                $queries[0] .= ' CHANGE COLUMN ' . $tablefield->Field . ' ' . $column_definition;
                // Handle changes from "NULL" to "NOT NULL"
                if ($change_null && !$want_null && isset($update_default_set)) {
                    // Prepend query to update NULL fields to default
                    array_unshift($queries, 'UPDATE ' . $table . ' SET ' . $tablefield->Field . ' = ' . $update_default_set . ' WHERE ' . $tablefield->Field . ' IS NULL');
                    if (substr($tablefield->Type, 0, 5) == 'enum(') {
                        $existing_enum_field_values = preg_split('~\\s*,\\s*~', substr($tablefield->Type, 5, -1), -1, PREG_SPLIT_NO_EMPTY);
                        foreach ($existing_enum_field_values as $k => $v) {
                            $existing_enum_field_values[$k] = preg_replace('~^(["\'])(.*)\\1$~', '$2', $v);
                            // strip quotes
                        }
                        if (!in_array($update_default, $existing_enum_field_values)) {
                            // we cannot update straight to the new default, because it does not exist yet!
                            // Update the column first, without the NULL change
                            array_unshift($queries, 'ALTER TABLE ' . $table . ' CHANGE COLUMN ' . $tablefield->Field . ' ' . preg_replace('~\\sNOT\\s+NULL~i', '', $column_definition));
                        }
                    }
                }
                // Add a query to change the column type
                $items[$table_lowered][] = array('queries' => $queries, 'note' => 'Changed type of ' . $table . '.<strong>' . $tablefield->Field . '</strong> from ' . $tablefield->Type . ' to ' . $column_definition, 'type' => 'change_column');
            } else {
                // perhaps alter or drop DEFAULT:
                if ($want_default !== false) {
                    // DEFAULT given
                    $existing_default = $tablefield->Default === NULL ? 'NULL' : $tablefield->Default;
                    if ($existing_default != $want_default) {
                        // Add a query to change the column's default value
                        $items[$table_lowered][] = array('queries' => array('ALTER TABLE ' . $table . ' ALTER COLUMN ' . $tablefield->Field . ' SET DEFAULT ' . $want_default_set), 'note' => "Changed default value of {$table}.<strong>{$tablefield->Field}</strong> from {$existing_default} to {$want_default_set}", 'type' => 'change_default');
                    }
                } elseif (!empty($tablefield->Default) && $tablefield->Default != $update_default) {
                    // No DEFAULT given, but it exists one, so drop it (IF not a TIMESTAMP or DATETIME field)
                    if ($tablefield->Type != 'timestamp' && $tablefield->Type != 'datetime') {
                        $items[$table_lowered][] = array('queries' => array('ALTER TABLE ' . $table . ' ALTER COLUMN ' . $tablefield->Field . ' DROP DEFAULT'), 'note' => "Dropped default value of {$table}.<strong>{$tablefield->Field}</strong>", 'type' => 'change_default');
                        // might be also 'drop_default'
                    }
                }
            }
            // Remove the field from the array (so it's not added)
            unset($wanted_fields[$fieldname_lowered]);
        }
        foreach ($wanted_fields as $fieldname_lowered => $fielddef) {
            // For every remaining field specified for the table
            $column_definition = $fielddef['field'] . ' ' . $fielddef['where'];
            $is_auto_increment = false;
            // AUTO_INCREMENT (with special index handling: AUTO_INCREMENT fields need to be PRIMARY or UNIQUE)
            if (preg_match('~(.*?) \\b AUTO_INCREMENT \\b (.*)$~ix', $fielddef['field'], $match)) {
                if (!in_array($fieldname_lowered, $fields_with_keys)) {
                    // no KEY defined (but required for AUTO_INCREMENT fields)
                    debug_die('No KEY/INDEX defined for AUTO_INCREMENT column!');
                }
                $is_auto_increment = true;
                foreach ($indices as $k_index => $l_index) {
                    // go through the indexes we want to have
                    if (array_search($fieldname_lowered, $l_index['col_names']) === false) {
                        // this is not an index for our column
                        continue;
                    }
                    // this index definition affects us, we have to add it to our ALTER statement..
                    // See if we need to drop it, before adding it:
                    if ($l_index['is_PK']) {
                        // Part of a PRIMARY key..
                        if (!empty($existing_primary_fields)) {
                            // and a PRIMARY key exists already
                            $column_definition .= ', DROP PRIMARY KEY';
                            unset($obsolete_indices['PRIMARY']);
                        }
                        $existing_primary_fields = array();
                        // we expect no existing primary key anymore
                        $primary_key_fields = $l_index['col_names'];
                        // this becomes our primary key
                    } elseif (isset($existing_indices[$l_index['name']])) {
                        // this index already exists, drop it:
                        $column_definition .= ', DROP INDEX ' . $existing_indices[$l_index['name']];
                        // original case
                        unset($existing_indices[$l_index['name']]);
                        // we expect that it does not exist anymore
                        if (!in_array($fieldname_lowered, $fields_with_keys)) {
                            // add te field to the list of keys we want/expect to have:
                            $fields_with_keys[] = $fieldname_lowered;
                        }
                    }
                    // Merge the INDEX creation into our ALTER query:
                    $column_definition .= ', ADD ' . $l_index['create_definition'];
                    unset($indices[$k_index]);
                }
            }
            // Push a query line into $items that adds the field to that table
            $query = 'ALTER TABLE ' . $table . ' ADD COLUMN ' . $column_definition;
            // Handle inline PRIMARY KEY definition:
            if (preg_match('~^(.*) \\b (?: (UNIQUE) (?:\\s+ (?:INDEX|KEY))? | (?:PRIMARY \\s+)? KEY ) \\b (.*)$~ix', $column_definition, $match) && count($existing_primary_fields) && !in_array($fieldname_lowered, $existing_primary_fields)) {
                // the column is part of the PRIMARY KEY, which needs to get dropped before (we already handle that for AUTO_INCREMENT fields)
                $query .= ', DROP PRIMARY KEY';
                $existing_primary_fields = array();
                // we expect no existing primary key anymore
                unset($obsolete_indices['PRIMARY']);
                if (isset($obsolete_autoincrement)) {
                    $query .= ', MODIFY COLUMN ' . $obsolete_autoincrement->Field . ' ' . $obsolete_autoincrement->Type . ' ' . ($obsolete_autoincrement->Field == 'YES' ? 'NULL' : 'NOT NULL');
                }
            }
            $items[$table_lowered][] = array('queries' => array($query), 'note' => 'Added column ' . $table . '.<strong>' . $fielddef['field'] . '</strong>', 'type' => 'add_column');
        }
        // Remove the original table creation query from processing
        array_shift($items[$table_lowered]);
        // Add foreign key constraints
        $result = db_delta_foreign_keys($foreign_key_fields, $table, false);
        foreach ($result as $foreign_key_update) {
            // loop through foreign key differences in this table
            if ($foreign_key_update['type'] == 'alter_engine') {
                // this is an alter engine command, check if this command was already added during engine difference detection, and skip to the next if it was added
                $skip = false;
                foreach ($items[$table_lowered] as $itemlist) {
                    if ($itemlist['type'] == 'alter_engine' && $itemlist['queries'][0] == $foreign_key_update['queries'][0]) {
                        // the same command was already added, don't add again
                        $skip = true;
                        break;
                    }
                }
                if ($skip) {
                    // skip is set, don't add the alter engine command again
                    continue;
                }
            }
            // add FK updates
            $items[$table_lowered][] = $foreign_key_update;
        }
        // Add the remaining indices (which are not "inline" with a column definition and therefor already handled):
        $add_index_queries = array();
        foreach ($indices as $k => $index) {
            if (empty($index['create_definition'])) {
                // skip "inline"
                continue;
            }
            $query = 'ALTER TABLE ' . $table;
            if ($index['is_PK'] && $existing_primary_fields) {
                $query .= ' DROP PRIMARY KEY,';
                unset($obsolete_indices['PRIMARY']);
            }
            // Create a query that adds the index to the table
            $query = array('queries' => array($query . ' ADD ' . $index['create_definition']), 'note' => 'Added index <strong>' . $index['create_definition'] . '</strong>', 'type' => 'add_index', 'name' => $index['name']);
            // Check if the index creation has to get appended after any DROPs (required for indices with the same name)
            $append_after_drops = false;
            foreach ($obsolete_indices as $obsolete_index) {
                if (strtolower($obsolete_index['name']) == strtolower($index['name'])) {
                    $append_after_drops = true;
                    break;
                }
            }
            if ($append_after_drops) {
                // do this after any DROPs (i.e. KEY name changes)
                $add_index_queries[] = $query;
            } else {
                // this needs to get done before any other DROPs
                // to prevent e.g. "Incorrect table definition; there can be only one auto column and it must be defined as a key(Errno=1075)"
                $items[$table_lowered][] = $query;
            }
        }
        // Now add queries to drop any (maybe changed!) indices
        foreach ($obsolete_indices as $index_info) {
            // Push a query line into $items that drops the index from the table
            $items[$table_lowered][] = array('queries' => array("ALTER TABLE {$table} DROP " . ($index_info['name'] == 'PRIMARY' ? 'PRIMARY KEY' : 'INDEX ' . $index_info['name'])), 'note' => 'Dropped index <strong>' . $index_info['name'] . '</strong>', 'type' => 'drop_index', 'name' => $index_info['name']);
        }
        // Add queries to (re)create (maybe changed indices) to the end
        $items[$table_lowered] = array_merge($items[$table_lowered], $add_index_queries);
    }
    // Filter types we want to exclude:
    if (!empty($exclude_types)) {
        foreach ($items as $table => $itemlist) {
            $removed_one = false;
            foreach ($itemlist as $k => $item) {
                if (in_array($item['type'], $exclude_types)) {
                    // this type of update should be excluded
                    if ($item['type'] == 'drop_index') {
                        // drop index command should not be excluded in case when we would like to update an index!
                        $skip = false;
                        foreach ($itemlist as $other_item) {
                            // check if there are an add_index command for the same table with the same index name
                            if ($other_item['type'] == 'add_index' && strcasecmp($item['name'], $other_item['name']) === 0) {
                                // add index with the same index name was found so we need to process this drop_index command to be able to add a new correct index with the same name
                                $skip = true;
                                break;
                            }
                        }
                        if ($skip) {
                            // skip excluding this item
                            continue;
                        }
                    }
                    unset($items[$table][$k]);
                    $removed_one = true;
                }
            }
            if ($removed_one) {
                // Re-order (0, 1, 2, ..)
                $items[$table] = array_values($items[$table]);
            }
        }
    }
    // Unset empty table indices:
    foreach ($items as $table => $itemlist) {
        if (empty($itemlist)) {
            unset($items[$table]);
            continue;
        }
        // Check if we have alter engine and drop foreign key queries for the same table. In this case the drop query must be processed before the alter engine query!
        $alter_engine_index = NULL;
        for ($i = 0; $i < count($itemlist); $i++) {
            if ($itemlist[$i]['type'] == 'alter_engine' && $alter_engine_index == NULL) {
                // save alter engine query index
                $alter_engine_index = $i;
            } elseif ($itemlist[$i]['type'] == 'drop_foreign_key' && $alter_engine_index !== NULL && $alter_engine_index < $i) {
                // switch engine update and drop foreign key queries, because in many cases we must drop the foreign key first to be able to chagne the table engine
                $switch_item = $itemlist[$alter_engine_index];
                $items[$table][$alter_engine_index] = $itemlist[$i];
                $items[$table][$i] = $switch_item;
                // save new alter engine index and the alter engine command in case of we have to drop multiple foreign keys
                $alter_engine_index = $i;
                $itemlist[$i] = $switch_item;
            }
        }
    }
    if ($execute) {
        foreach ($items as $table => $itemlist) {
            foreach ($itemlist as $item) {
                foreach ($item['queries'] as $query) {
                    #pre_dump( $query );
                    $DB->query($query);
                }
            }
        }
    }
    return $items;
}
Exemple #20
0
 /**
  * Validate renderer list.
  *
  * @param array renderer codes ('default' will include all "opt-out"-ones)
  * @params array params to set Blog and apply_rendering setting_name ( see {@link load_index_apply_rendering()} )
  * @return array validated array of renderer codes
  */
 function validate_renderer_list($renderers = array('default'), $params)
 {
     // Init Blog and $setting_name from the given params
     if (isset($params['Item'])) {
         // Validate post renderers
         $Item =& $params['Item'];
         $Blog =& $Item->get_Blog();
         $setting_name = 'coll_apply_rendering';
     } elseif (isset($params['Comment'])) {
         // Validate comment renderers
         $Comment =& $params['Comment'];
         $Item =& $Comment->get_Item();
         $Blog =& $Item->get_Blog();
         $setting_name = 'coll_apply_comment_rendering';
     } elseif (isset($params['Blog']) && isset($params['setting_name'])) {
         // Validate the given rendering option in the give Blog
         $Blog =& $params['Blog'];
         $setting_name = $params['setting_name'];
         if (!in_array($setting_name, array('coll_apply_rendering', 'coll_apply_comment_rendering'))) {
             debug_die('Invalid apply rendering param name received!');
         }
     } else {
         // Invalid params to validate renderers!
         return array();
     }
     // Make sure the requested apply_rendering settings are loaded
     $this->load_index_apply_rendering($setting_name, $Blog);
     $validated_renderers = array();
     // Get requested apply_rendering setting array
     $index =& $this->index_apply_rendering_codes[$Blog->ID][$setting_name];
     if (isset($index['stealth'])) {
         // pre_dump( 'stealth:', $index['stealth'] );
         $validated_renderers = array_merge($validated_renderers, $index['stealth']);
     }
     if (isset($index['always'])) {
         // pre_dump( 'always:', $index['always'] );
         $validated_renderers = array_merge($validated_renderers, $index['always']);
     }
     if (isset($index['opt-out'])) {
         foreach ($index['opt-out'] as $l_code) {
             if (in_array($l_code, $renderers) || in_array('default', $renderers)) {
                 // pre_dump( 'opt-out:', $l_code );
                 $validated_renderers[] = $l_code;
             }
         }
     }
     if (isset($index['opt-in'])) {
         foreach ($index['opt-in'] as $l_code) {
             if (in_array($l_code, $renderers)) {
                 // pre_dump( 'opt-in:', $l_code );
                 $validated_renderers[] = $l_code;
             }
         }
     }
     if (isset($index['lazy'])) {
         foreach ($index['lazy'] as $l_code) {
             if (in_array($l_code, $renderers)) {
                 // pre_dump( 'lazy:', $l_code );
                 $validated_renderers[] = $l_code;
             }
         }
     }
     // Make sure there's no renderer code with a dot, as the list gets imploded by that when saved:
     foreach ($validated_renderers as $k => $l_code) {
         if (empty($l_code) || strpos($l_code, '.') !== false) {
             unset($validated_renderers[$k]);
         }
         /*
         dh> not required, now that the method has been moved back to Plugins (from ~_admin)
         else
         { // remove the ones which are not enabled:
         	$Plugin = & $this->get_by_code($l_code);
         	if( ! $Plugin || $Plugin->status != 'enabled' )
         	{
         		unset( $validated_renderers[$k] );
         	}
         }
         */
     }
     // echo 'validated Renderers: '.count( $validated_renderers );
     return $validated_renderers;
 }
/**
 * Get perm post/comment statuses for a user or group
 * 
 * @param object db row
 * @param string the prefix of the db row: 'bloguser_' or 'bloggroup_'
 * @param string current perm status
 * @param string the title of the chekbox
 * @param string the type of the permission: 'post' or 'comment'
 */
function coll_perm_status_checkbox($row, $prefix, $perm_status, $title, $type)
{
    global $edited_Blog, $permission_to_change_admin;
    $row_id_coll = get_id_coll_from_prefix($prefix);
    $default_status = NULL;
    switch ($type) {
        case 'post':
            $perm_statuses = 'perm_poststatuses';
            $type_param = '';
            break;
        case 'comment':
            $perm_statuses = 'perm_cmtstatuses';
            if (!check_default_create_comment_perm($row->{$perm_statuses})) {
                // Doesn't have at least as high comment create permission as anonymous users have
                $default_status = $edited_Blog->get_setting('new_feedback_status');
            }
            $type_param = 'cmt_';
            break;
        default:
            debug_die('Invalid $type param on advanced perms form!');
    }
    $r = '<input type="checkbox"';
    if (!empty($id)) {
        $r .= ' id="' . $id . '"';
    }
    $r .= ' name="blog_perm_' . $perm_status . '_' . $type_param . $row->{$row_id_coll} . '"';
    if ($prefix == 'bloguser_' && $edited_Blog->owner_user_ID == $row->user_ID) {
        // Collection owner has the permissions to edit all item/comment statuses by default
        $r .= ' checked="checked" disabled="disabled"';
    } else {
        // Not owner
        if (get_status_permvalue($perm_status) & $row->{$perm_statuses}) {
            $r .= ' checked="checked"';
        }
        if (!$permission_to_change_admin && $row->{$prefix . 'perm_admin'}) {
            $r .= ' disabled="disabled"';
        }
    }
    if ($perm_status == $default_status) {
        $title .= "\n" . T_('Note: Anonymous users may create comments with this status. You will probably want to give the same permission to this user/group.');
    }
    $r .= ' class="checkbox" value="1" title="' . $title . '" />';
    if ($perm_status == $default_status) {
        // This is the default comment status checkbox, and user has no permission to create comment with this status ( like anonymous users ) or a higher status
        $r = '<span class="red-bordered-checkbox">' . $r . '</span>';
    }
    return $r;
}
Exemple #22
0
    } else {
        $recipient_name = $Comment->get_author_name();
        $recipient_address = $Comment->get_author_email();
    }
}
if (empty($sender_name)) {
    $Messages->add(T_('Please fill in your name.'), 'error');
}
if (empty($sender_address)) {
    $Messages->add(T_('Please fill in your email.'), 'error');
} elseif (!is_email($sender_address) || antispam_check($sender_address)) {
    $Messages->add(T_('Supplied email address is invalid.'), 'error');
}
if (empty($recipient_User) && empty($recipient_address)) {
    // should be prevented by UI
    debug_die('No recipient specified!');
}
// opt-out links:
if ($recipient_User) {
    // Member:
    // Change the locale so the email is in the recipients language
    locale_temp_switch($recipient_User->locale);
} else {
    // Visitor:
    // We don't know the recipient's language - Change the locale so the email is in the blog's language:
    locale_temp_switch($Blog->locale);
}
// Trigger event: a Plugin could add a $category="error" message here..
$Plugins->trigger_event('MessageFormSent', array('recipient_ID' => $recipient_id, 'item_ID' => $post_id, 'comment_ID' => $comment_id, 'subject' => &$subject, 'message' => &$message, 'Blog' => &$Blog, 'sender_name' => &$sender_name, 'sender_email' => &$sender_address));
$success_message = !$Messages->has_errors();
if ($success_message) {
Exemple #23
0
/**
 * Initialize internal states for the most common skin displays.
 *
 * For more specific skins, this function may not be called and
 * equivalent code may be customized within the skin.
 *
 * @param string What are we going to display. Most of the time the global $disp should be passed.
 */
function skin_init($disp)
{
    /**
     * @var Blog
     */
    global $Blog;
    /**
     * @var Item
     */
    global $Item;
    /**
     * @var Skin
     */
    global $Skin;
    global $robots_index;
    global $seo_page_type;
    global $redir, $ReqURL, $ReqURI, $m, $w, $preview;
    global $Chapter;
    global $Debuglog;
    /**
     * @var ItemList2
     */
    global $MainList;
    /**
     * This will give more detail when $disp == 'posts'; otherwise it will have the same content as $disp
     * @var string
     */
    global $disp_detail, $Settings;
    global $Timer;
    global $Messages, $PageCache;
    global $Session, $current_User;
    $Timer->resume('skin_init');
    if (empty($disp_detail)) {
        $disp_detail = $disp;
    }
    $Debuglog->add('skin_init: $disp=' . $disp, 'skins');
    // This is the main template; it may be used to display very different things.
    // Do inits depending on current $disp:
    switch ($disp) {
        case 'front':
        case 'posts':
        case 'single':
        case 'page':
        case 'terms':
        case 'download':
        case 'feedback-popup':
            // We need to load posts for this display:
            if ($disp == 'terms') {
                // Initialize the redirect param to know what page redirect after accepting of terms:
                param('redirect_to', 'url', '');
            }
            // Note: even if we request the same post as $Item above, the following will do more restrictions (dates, etc.)
            // Init the MainList object:
            init_MainList($Blog->get_setting('posts_per_page'));
            // Init post navigation
            $post_navigation = $Skin->get_post_navigation();
            if (empty($post_navigation)) {
                $post_navigation = $Blog->get_setting('post_navigation');
            }
            if (!empty($MainList) && $MainList->single_post && ($single_Item =& mainlist_get_item())) {
                // If we are currently viewing a single post
                // We assume the current user will have read the entire post and all its current comments:
                $single_Item->update_read_timestamps(true, true);
                // Restart the items list:
                $MainList->restart();
            }
            break;
        case 'search':
            // Searching post, comments and categories
            load_funcs('collections/_search.funcs.php');
            // Check previous search keywords so it can be displayed in the search input box
            param('s', 'string', '', true);
            break;
    }
    // SEO stuff & redirects if necessary:
    $seo_page_type = NULL;
    switch ($disp) {
        // CONTENT PAGES:
        case 'single':
        case 'page':
        case 'terms':
            if ($disp == 'terms' && !$Item) {
                // Wrong post ID for terms page:
                global $disp;
                $disp = '404';
                $Messages->add(sprintf(T_('Terms not found. (post ID #%s)'), get_param('p')), 'error');
                break;
            }
            if (!$preview && empty($Item)) {
                // No Item, incorrect request and incorrect state of the application, a 404 redirect should have already happened
                //debug_die( 'Invalid page URL!' );
            }
            if ($disp == 'single') {
                $seo_page_type = 'Single post page';
            } else {
                $seo_page_type = '"Page" page';
            }
            if (!$preview) {
                // Check if item has a goal to insert a hit into DB
                $Item->check_goal();
            }
            // Check if the post has 'redirected' status:
            if (!$preview && $Item->status == 'redirected' && $redir == 'yes') {
                // $redir=no here allows to force a 'single post' URL for commenting
                // Redirect to the URL specified in the post:
                $Debuglog->add('Redirecting to post URL [' . $Item->url . '].');
                header_redirect($Item->url, true, true);
            }
            // Check if we want to redirect to a canonical URL for the post
            // Please document encountered problems.
            if (!$preview && ($Blog->get_setting('canonical_item_urls') && $redir == 'yes' || $Blog->get_setting('relcanonical_item_urls'))) {
                // We want to redirect to the Item's canonical URL:
                $canonical_url = $Item->get_permanent_url('', '', '&');
                if (preg_match('|[&?](page=\\d+)|', $ReqURI, $page_param)) {
                    // A certain post page has been requested, keep only this param and discard all others:
                    $canonical_url = url_add_param($canonical_url, $page_param[1], '&');
                }
                if (preg_match('|[&?](mode=quote&[qcp]+=\\d+)|', $ReqURI, $page_param)) {
                    // A quote of comment/post, keep only these params and discard all others:
                    $canonical_url = url_add_param($canonical_url, $page_param[1], '&');
                }
                if (!is_same_url($ReqURL, $canonical_url)) {
                    // The requested URL does not look like the canonical URL for this post...
                    // url difference was resolved
                    $url_resolved = false;
                    // Check if the difference is because of an allowed post navigation param
                    if (preg_match('|[&?]cat=(\\d+)|', $ReqURI, $cat_param)) {
                        // A category post navigation param is set
                        $extended_url = '';
                        if ($post_navigation == 'same_category' && isset($cat_param[1])) {
                            // navigatie through posts from the same category
                            $category_ids = postcats_get_byID($Item->ID);
                            if (in_array($cat_param[1], $category_ids)) {
                                // cat param is one of this Item categories
                                $extended_url = $Item->add_navigation_param($canonical_url, $post_navigation, $cat_param[1], '&');
                                // Set MainList navigation target to the requested category
                                $MainList->nav_target = $cat_param[1];
                            }
                        }
                        $url_resolved = is_same_url($ReqURL, $extended_url);
                    }
                    if (preg_match('|[&?]tag=([^&A-Z]+)|', $ReqURI, $tag_param)) {
                        // A tag post navigation param is set
                        $extended_url = '';
                        if ($post_navigation == 'same_tag' && isset($tag_param[1])) {
                            // navigatie through posts from the same tag
                            $tag_names = $Item->get_tags();
                            if (in_array($tag_param[1], $tag_names)) {
                                // tag param is one of this Item tags
                                $extended_url = $Item->add_navigation_param($canonical_url, $post_navigation, $tag_param[1], '&');
                                // Set MainList navigation target to the requested tag
                                $MainList->nav_target = $tag_param[1];
                            }
                        }
                        $url_resolved = is_same_url($ReqURL, $extended_url);
                    }
                    if (!$url_resolved && $Blog->get_setting('canonical_item_urls') && $redir == 'yes' && !$Item->check_cross_post_nav('auto', $Blog->ID)) {
                        // REDIRECT TO THE CANONICAL URL:
                        $Debuglog->add('Redirecting to canonical URL [' . $canonical_url . '].');
                        header_redirect($canonical_url, true);
                    } else {
                        // Use rel="canoncial":
                        add_headline('<link rel="canonical" href="' . $canonical_url . '" />');
                    }
                    // EXITED.
                }
            }
            if (!$MainList->result_num_rows) {
                // There is nothing to display for this page, don't index it!
                $robots_index = false;
            }
            break;
        case 'download':
            if (empty($Item)) {
                // No Item, incorrect request and incorrect state of the application, a 404 redirect should have already happened
                debug_die('Invalid page URL!');
            }
            $download_link_ID = param('download', 'integer', 0);
            // Check if we can allow to download the selected file
            $LinkCache =& get_LinkCache();
            if (!(($download_Link =& $LinkCache->get_by_ID($download_link_ID, false, false)) && ($LinkItem =& $download_Link->get_LinkOwner()) && ($LinkItem->Item && $LinkItem->Item->ID == $Item->ID) && ($download_File =& $download_Link->get_File()) && $download_File->exists())) {
                // Bad request, Redirect to Item permanent url
                $Messages->add(T_('The requested file is not available for download.'), 'error');
                $canonical_url = $Item->get_permanent_url('', '', '&');
                $Debuglog->add('Redirecting to canonical URL [' . $canonical_url . '].');
                header_redirect($canonical_url, true);
            }
            // Save the downloading Link to the global vars
            $GLOBALS['download_Link'] =& $download_Link;
            // Save global $Item to $download_Item, because $Item can be rewritten by function get_featured_Item() in some skins
            $GLOBALS['download_Item'] =& $Item;
            init_ajax_forms('blog');
            // auto requires jQuery
            // Initialize JavaScript to download file after X seconds
            add_js_headline('
jQuery( document ).ready( function ()
{
	jQuery( "#download_timer_js" ).show();
} );

var b2evo_download_timer = ' . intval($Blog->get_setting('download_delay')) . ';
var downloadInterval = setInterval( function()
{
	jQuery( "#download_timer" ).html( b2evo_download_timer );
	if( b2evo_download_timer == 0 )
	{ // Stop timer and download a file
		clearInterval( downloadInterval );
		jQuery( "#download_help_url" ).show();
	}
	b2evo_download_timer--;
}, 1000 );');
            // Use meta tag to download file when JavaScript is NOT enabled
            add_headline('<meta http-equiv="refresh" content="' . intval($Blog->get_setting('download_delay')) . '; url=' . $download_Link->get_download_url(array('type' => 'action')) . '" />');
            $seo_page_type = 'Download page';
            if ($Blog->get_setting($disp . '_noindex')) {
                // We prefer robots not to index these pages:
                $robots_index = false;
            }
            break;
        case 'posts':
            init_ajax_forms('blog');
            // auto requires jQuery
            // fp> if we add this here, we have to exetnd the inner if()
            // init_ratings_js( 'blog' );
            // Get list of active filters:
            $active_filters = $MainList->get_active_filters();
            if (!empty($active_filters)) {
                // The current page is being filtered...
                if (array_diff($active_filters, array('page')) == array()) {
                    // This is just a follow "paged" page
                    $disp_detail = 'posts-next';
                    $seo_page_type = 'Next page';
                    if ($Blog->get_setting('paged_noindex')) {
                        // We prefer robots not to index category pages:
                        $robots_index = false;
                    }
                } elseif (array_diff($active_filters, array('cat_array', 'cat_modifier', 'cat_focus', 'posts', 'page')) == array()) {
                    // This is a category page
                    $disp_detail = 'posts-cat';
                    $seo_page_type = 'Category page';
                    if ($Blog->get_setting('chapter_noindex')) {
                        // We prefer robots not to index category pages:
                        $robots_index = false;
                    }
                    global $cat, $catsel;
                    if (empty($catsel) && preg_match('~^[0-9]+$~', $cat)) {
                        // We are on a single cat page:
                        // NOTE: we must have selected EXACTLY ONE CATEGORY through the cat parameter
                        // BUT: - this can resolve to including children
                        //      - selecting exactly one cat through catsel[] is NOT OK since not equivalent (will exclude children)
                        // echo 'SINGLE CAT PAGE';
                        if ($Blog->get_setting('canonical_cat_urls') && $redir == 'yes' || $Blog->get_setting('relcanonical_cat_urls')) {
                            // Check if the URL was canonical:
                            if (!isset($Chapter)) {
                                $ChapterCache =& get_ChapterCache();
                                /**
                                 * @var Chapter
                                 */
                                $Chapter =& $ChapterCache->get_by_ID($MainList->filters['cat_array'][0], false);
                            }
                            if ($Chapter) {
                                if ($Chapter->parent_ID) {
                                    // This is a sub-category page (i-e: not a level 1 category)
                                    $disp_detail = 'posts-subcat';
                                }
                                $canonical_url = $Chapter->get_permanent_url(NULL, NULL, $MainList->get_active_filter('page'), NULL, '&');
                                if (!is_same_url($ReqURL, $canonical_url)) {
                                    // fp> TODO: we're going to lose the additional params, it would be better to keep them...
                                    // fp> what additional params actually?
                                    if ($Blog->get_setting('canonical_cat_urls') && $redir == 'yes') {
                                        // REDIRECT TO THE CANONICAL URL:
                                        header_redirect($canonical_url, true);
                                    } else {
                                        // Use rel="canonical":
                                        add_headline('<link rel="canonical" href="' . $canonical_url . '" />');
                                    }
                                }
                            } else {
                                // If the requested chapter was not found display 404 page
                                $Messages->add(T_('The requested chapter was not found'));
                                global $disp;
                                $disp = '404';
                                break;
                            }
                        }
                        if ($post_navigation == 'same_category') {
                            // Category is set and post navigation should go through the same category, set navigation target param
                            $MainList->nav_target = $cat;
                        }
                    }
                } elseif (array_diff($active_filters, array('tags', 'posts', 'page')) == array()) {
                    // This is a tag page
                    $disp_detail = 'posts-tag';
                    $seo_page_type = 'Tag page';
                    if ($Blog->get_setting('tag_noindex')) {
                        // We prefer robots not to index tag pages:
                        $robots_index = false;
                    }
                    if ($Blog->get_setting('canonical_tag_urls') && $redir == 'yes' || $Blog->get_setting('relcanonical_tag_urls')) {
                        // Check if the URL was canonical:
                        $canonical_url = $Blog->gen_tag_url($MainList->get_active_filter('tags'), $MainList->get_active_filter('page'), '&');
                        if (!is_same_url($ReqURL, $canonical_url)) {
                            if ($Blog->get_setting('canonical_tag_urls') && $redir == 'yes') {
                                // REDIRECT TO THE CANONICAL URL:
                                header_redirect($canonical_url, true);
                            } else {
                                // Use rel="canoncial":
                                add_headline('<link rel="canonical" href="' . $canonical_url . '" />');
                            }
                        }
                    }
                    $tag = $MainList->get_active_filter('tags');
                    if ($post_navigation == 'same_tag' && !empty($tag)) {
                        // Tag is set and post navigation should go through the same tag, set navigation target param
                        $MainList->nav_target = $tag;
                    }
                } elseif (array_diff($active_filters, array('ymdhms', 'week', 'posts', 'page')) == array()) {
                    // This is an archive page
                    // echo 'archive page';
                    $disp_detail = 'posts-date';
                    $seo_page_type = 'Date archive page';
                    if ($Blog->get_setting('canonical_archive_urls') && $redir == 'yes' || $Blog->get_setting('relcanonical_archive_urls')) {
                        // Check if the URL was canonical:
                        $canonical_url = $Blog->gen_archive_url(substr($m, 0, 4), substr($m, 4, 2), substr($m, 6, 2), $w, '&', $MainList->get_active_filter('page'));
                        if (!is_same_url($ReqURL, $canonical_url)) {
                            if ($Blog->get_setting('canonical_archive_urls') && $redir == 'yes') {
                                // REDIRECT TO THE CANONICAL URL:
                                header_redirect($canonical_url, true);
                            } else {
                                // Use rel="canoncial":
                                add_headline('<link rel="canonical" href="' . $canonical_url . '" />');
                            }
                        }
                    }
                    if ($Blog->get_setting('archive_noindex')) {
                        // We prefer robots not to index archive pages:
                        $robots_index = false;
                    }
                } else {
                    // Other filtered pages:
                    // pre_dump( $active_filters );
                    $disp_detail = 'posts-filtered';
                    $seo_page_type = 'Other filtered page';
                    if ($Blog->get_setting('filtered_noindex')) {
                        // We prefer robots not to index other filtered pages:
                        $robots_index = false;
                    }
                }
            } elseif ($Blog->get_setting('front_disp') == 'posts') {
                // This is the default blog page only if the 'front_disp' is set to 'posts'
                $disp_detail = 'posts-default';
                $seo_page_type = 'Default page';
                if ($Blog->get_setting('default_noindex')) {
                    // We prefer robots not to index archive pages:
                    $robots_index = false;
                }
            }
            break;
        case 'search':
            $seo_page_type = 'Search page';
            if ($Blog->get_setting('filtered_noindex')) {
                // We prefer robots not to index these pages:
                $robots_index = false;
            }
            break;
            // SPECIAL FEATURE PAGES:
        // SPECIAL FEATURE PAGES:
        case 'feedback-popup':
            $seo_page_type = 'Comment popup';
            if ($Blog->get_setting($disp . '_noindex')) {
                // We prefer robots not to index these pages:
                $robots_index = false;
            }
            break;
        case 'arcdir':
            $seo_page_type = 'Date archive directory';
            if ($Blog->get_setting($disp . '_noindex')) {
                // We prefer robots not to index these pages:
                $robots_index = false;
            }
            break;
        case 'catdir':
            $seo_page_type = 'Category directory';
            if ($Blog->get_setting($disp . '_noindex')) {
                // We prefer robots not to index these pages:
                $robots_index = false;
            }
            break;
        case 'msgform':
            global $disp;
            // get expected message form type
            $msg_type = param('msg_type', 'string', '');
            // initialize
            $recipient_User = NULL;
            $Comment = NULL;
            $allow_msgform = NULL;
            // get possible params
            $recipient_id = param('recipient_id', 'integer', 0, true);
            $comment_id = param('comment_id', 'integer', 0, true);
            $post_id = param('post_id', 'integer', 0, true);
            $subject = param('subject', 'string', '');
            // try to init recipient_User
            if (!empty($recipient_id)) {
                $UserCache =& get_UserCache();
                $recipient_User =& $UserCache->get_by_ID($recipient_id);
            } elseif (!empty($comment_id)) {
                // comment id is set, try to get comment author user
                $CommentCache =& get_CommentCache();
                $Comment = $CommentCache->get_by_ID($comment_id, false);
                if ($Comment = $CommentCache->get_by_ID($comment_id, false)) {
                    $recipient_User =& $Comment->get_author_User();
                    if (empty($recipient_User) && $Comment->allow_msgform && is_email($Comment->get_author_email())) {
                        // set allow message form to email because comment author (not registered) accepts email
                        $allow_msgform = 'email';
                        param('recipient_address', 'string', $Comment->get_author_email());
                        param('recipient_name', 'string', $Comment->get_author_name());
                    }
                }
            } else {
                // Recipient was not defined, try set the blog owner as recipient
                global $Blog;
                if (empty($Blog)) {
                    // Blog is not set, this is an invalid request
                    debug_die('Invalid send message request!');
                }
                $recipient_User = $Blog->get_owner_User();
            }
            if ($recipient_User) {
                // recipient User is set
                // get_msgform_possibility returns NULL (false), only if there is no messaging option between current_User and recipient user
                $allow_msgform = $recipient_User->get_msgform_possibility();
                if ($msg_type == 'email' && $recipient_User->get_msgform_possibility(NULL, 'email') != 'email') {
                    // User doesn't want to receive email messages, Restrict if this was requested by wrong url:
                    $msg_type = '';
                }
                if ($allow_msgform == 'login') {
                    // user must login first to be able to send a message to this User
                    $disp = 'login';
                    param('action', 'string', 'req_login');
                    // override redirect to param
                    param('redirect_to', 'url', regenerate_url(), true, true);
                    if (($msg_Blog =& get_setting_Blog('msg_blog_ID')) && $Blog->ID != $msg_Blog->ID) {
                        // Redirect to special blog for messaging actions if it is defined in general settings
                        header_redirect(url_add_param($msg_Blog->get('msgformurl', array('glue' => '&')), 'redirect_to=' . rawurlencode($redirect_to), '&'));
                    }
                    $Messages->add(T_('You must log in before you can contact this user'));
                } elseif ($allow_msgform == 'PM' && check_user_status('can_be_validated')) {
                    // user is not activated
                    if ($recipient_User->accepts_email()) {
                        // recipient User accepts email allow to send email
                        $allow_msgform = 'email';
                        $msg_type = 'email';
                        $activateinfo_link = 'href="' . get_activate_info_url(NULL, '&amp;') . '"';
                        $Messages->add(sprintf(T_('You must activate your account before you can send a private message to %s. However you can send them an email if you\'d like. <a %s>More info &raquo;</a>'), $recipient_User->get('login'), $activateinfo_link), 'warning');
                    } else {
                        // Redirect to the activate info page for not activated users
                        $Messages->add(T_('You must activate your account before you can contact a user. <b>See below:</b>'));
                        header_redirect(get_activate_info_url(), 302);
                        // will have exited
                    }
                } elseif ($msg_type == 'PM' && $allow_msgform == 'email') {
                    // only email is allowed but user expect private message form
                    if (!empty($current_User) && $recipient_id == $current_User->ID) {
                        $Messages->add(T_('You cannot send a private message to yourself. However you can send yourself an email if you\'d like.'), 'warning');
                    } else {
                        $Messages->add(sprintf(T_('You cannot send a private message to %s. However you can send them an email if you\'d like.'), $recipient_User->get('login')), 'warning');
                    }
                } elseif ($msg_type != 'email' && $allow_msgform == 'PM') {
                    // private message form should be displayed, change display to create new individual thread with the given recipient user
                    // check if creating new PM is allowed
                    if (check_create_thread_limit(true)) {
                        // thread limit reached
                        header_redirect();
                        // exited here
                    }
                    global $edited_Thread, $edited_Message, $recipients_selected;
                    // Load classes
                    load_class('messaging/model/_thread.class.php', 'Thread');
                    load_class('messaging/model/_message.class.php', 'Message');
                    // Set global variable to auto define the FB autocomplete plugin field
                    $recipients_selected = array(array('id' => $recipient_User->ID, 'title' => $recipient_User->login));
                    init_tokeninput_js('blog');
                    $disp = 'threads';
                    $edited_Thread = new Thread();
                    $edited_Message = new Message();
                    $edited_Message->Thread =& $edited_Thread;
                    $edited_Thread->recipients = $recipient_User->login;
                    param('action', 'string', 'new', true);
                    param('thrdtype', 'string', 'individual', true);
                }
                if ($allow_msgform == 'email') {
                    // set recippient user param
                    set_param('recipient_id', $recipient_User->ID);
                }
            }
            if ($allow_msgform == NULL) {
                // should be Prevented by UI
                if (!empty($recipient_User)) {
                    $Messages->add(sprintf(T_('The user "%s" does not want to be contacted through the message form.'), $recipient_User->get('login')), 'error');
                } elseif (!empty($Comment)) {
                    $Messages->add(T_('This commentator does not want to get contacted through the message form.'), 'error');
                }
                $blogurl = $Blog->gen_blogurl();
                // If it was a front page request or the front page is set to 'msgform' then we must not redirect to the front page because it is forbidden for the current User
                $redirect_to = is_front_page() || $Blog->get_setting('front_disp') == 'msgform' ? url_add_param($blogurl, 'disp=403', '&') : $blogurl;
                header_redirect($redirect_to, 302);
                // exited here
            }
            if ($allow_msgform == 'PM' || $allow_msgform == 'email') {
                // Some message form is available
                // Get the suggested subject for the email:
                if (empty($subject)) {
                    // no subject provided by param:
                    global $DB;
                    if (!empty($comment_id)) {
                        // fp>TODO there should be NO SQL in this file. Make a $ItemCache->get_by_comment_ID().
                        $row = $DB->get_row('
							SELECT post_title
								FROM T_items__item, T_comments
							 WHERE comment_ID = ' . $DB->quote($comment_id) . '
								 AND post_ID = comment_item_ID');
                        if ($row) {
                            $subject = T_('Re:') . ' ' . sprintf(T_('Comment on %s'), $row->post_title);
                        }
                    }
                    if (empty($subject) && !empty($post_id)) {
                        // fp>TODO there should be NO SQL in this file. Use $ItemCache->get_by_ID.
                        $row = $DB->get_row('
								SELECT post_title
									FROM T_items__item
								 WHERE post_ID = ' . $post_id);
                        if ($row) {
                            $subject = T_('Re:') . ' ' . $row->post_title;
                        }
                    }
                }
                if ($allow_msgform == 'PM' && isset($edited_Thread)) {
                    $edited_Thread->title = $subject;
                } else {
                    param('subject', 'string', $subject, true);
                }
            }
            if (($msg_Blog =& get_setting_Blog('msg_blog_ID')) && $Blog->ID != $msg_Blog->ID) {
                // Redirect to special blog for messaging actions if it is defined in general settings
                header_redirect($msg_Blog->get('msgformurl', array('glue' => '&')));
            }
            $seo_page_type = 'Contact form';
            if ($Blog->get_setting($disp . '_noindex')) {
                // We prefer robots not to index these pages:
                $robots_index = false;
            }
            break;
        case 'messages':
        case 'contacts':
        case 'threads':
            switch ($disp) {
                case 'messages':
                    // Actions ONLY for disp=messages
                    // fp> The correct place to get thrd_ID is here, because we want it in redirect_to in case we need to ask for login.
                    $thrd_ID = param('thrd_ID', 'integer', '', true);
                    if (!is_logged_in()) {
                        // Redirect to the login page for anonymous users
                        $Messages->add(T_('You must log in to read your messages.'));
                        header_redirect(get_login_url('cannot see messages'), 302);
                        // will have exited
                    }
                    // check if user status allow to view messages
                    if (!$current_User->check_status('can_view_messages')) {
                        // user status does not allow to view messages
                        if ($current_User->check_status('can_be_validated')) {
                            // user is logged in but his/her account is not activate yet
                            $Messages->add(T_('You must activate your account before you can read & send messages. <b>See below:</b>'));
                            header_redirect(get_activate_info_url(), 302);
                            // will have exited
                        }
                        $Messages->add('You are not allowed to view Messages!');
                        header_redirect($Blog->gen_blogurl(), 302);
                        // will have exited
                    }
                    // check if user permissions allow to view messages
                    if (!$current_User->check_perm('perm_messaging', 'reply')) {
                        // Redirect to the blog url for users without messaging permission
                        $Messages->add('You are not allowed to view Messages!');
                        header_redirect($Blog->gen_blogurl(), 302);
                        // will have exited
                    }
                    if (!empty($thrd_ID)) {
                        // if this thread exists and current user is part of this thread update status because won't be any unread messages on this conversation
                        // we need to mark this early to make sure the unread message count will be correct in the evobar
                        mark_as_read_by_user($thrd_ID, $current_User->ID);
                    }
                    if (($unsaved_message_params = get_message_params_from_session()) !== NULL) {
                        // set Message and Thread saved params from Session
                        global $edited_Message, $action;
                        load_class('messaging/model/_message.class.php', 'Message');
                        $edited_Message = new Message();
                        $edited_Message->text = $unsaved_message_params['message'];
                        $edited_Message->original_text = $unsaved_message_params['message_original'];
                        $edited_Message->set_renderers($unsaved_message_params['renderers']);
                        $edited_Message->thread_ID = $thrd_ID;
                        $action = $unsaved_message_params['action'];
                    }
                    break;
                case 'contacts':
                    // Actions ONLY for disp=contacts
                    if (!is_logged_in()) {
                        // Redirect to the login page for anonymous users
                        $Messages->add(T_('You must log in to manage your contacts.'));
                        header_redirect(get_login_url('cannot see contacts'), 302);
                        // will have exited
                    }
                    if (!$current_User->check_status('can_view_contacts')) {
                        // user is logged in, but his status doesn't allow to view contacts
                        if ($current_User->check_status('can_be_validated')) {
                            // user is logged in but his/her account was not activated yet
                            // Redirect to the account activation page
                            $Messages->add(T_('You must activate your account before you can manage your contacts. <b>See below:</b>'));
                            header_redirect(get_activate_info_url(), 302);
                            // will have exited
                        }
                        // Redirect to the blog url for users without messaging permission
                        $Messages->add('You are not allowed to view Contacts!');
                        $blogurl = $Blog->gen_blogurl();
                        // If it was a front page request or the front page is set to display 'contacts' then we must not redirect to the front page because it is forbidden for the current User
                        $redirect_to = is_front_page() || $Blog->get_setting('front_disp') == 'contacts' ? url_add_param($blogurl, 'disp=403', '&') : $blogurl;
                        header_redirect($redirect_to, 302);
                    }
                    if (has_cross_country_restriction('any') && empty($current_User->ctry_ID)) {
                        // User may browse/contact other users only from the same country
                        $Messages->add(T_('Please specify your country before attempting to contact other users.'));
                        header_redirect(get_user_profile_url());
                    }
                    // Get action parameter from request:
                    $action = param_action();
                    if (!$current_User->check_perm('perm_messaging', 'reply')) {
                        // Redirect to the blog url for users without messaging permission
                        $Messages->add('You are not allowed to view Contacts!');
                        $blogurl = $Blog->gen_blogurl();
                        // If it was a front page request or the front page is set to display 'contacts' then we must not redirect to the front page because it is forbidden for the current User
                        $redirect_to = is_front_page() || $Blog->get_setting('front_disp') == 'contacts' ? url_add_param($blogurl, 'disp=403', '&') : $blogurl;
                        header_redirect($redirect_to, 302);
                        // will have exited
                    }
                    switch ($action) {
                        case 'add_user':
                            // Add user to contacts list
                            // Check that this action request is not a CSRF hacked request:
                            $Session->assert_received_crumb('messaging_contacts');
                            $user_ID = param('user_ID', 'integer', 0);
                            if ($user_ID > 0) {
                                // Add user to contacts
                                if (create_contacts_user($user_ID)) {
                                    // Add user to the group
                                    $group_ID = param('group_ID', 'string', '');
                                    if ($result = create_contacts_group_users($group_ID, $user_ID, 'group_ID_combo')) {
                                        // User has been added to the group
                                        $Messages->add(sprintf(T_('User has been added to the &laquo;%s&raquo; group.'), $result['group_name']), 'success');
                                    } else {
                                        // User has been added ONLY to the contacts list
                                        $Messages->add('User has been added to your contacts.', 'success');
                                    }
                                }
                                header_redirect($Blog->get('userurl', array('url_suffix' => 'user_ID=' . $user_ID, 'glue' => '&')));
                            }
                            break;
                        case 'unblock':
                            // Unblock user
                            // Check that this action request is not a CSRF hacked request:
                            $Session->assert_received_crumb('messaging_contacts');
                            $user_ID = param('user_ID', 'integer', 0);
                            if ($user_ID > 0) {
                                set_contact_blocked($user_ID, 0);
                                $Messages->add(T_('Contact was unblocked.'), 'success');
                            }
                            break;
                        case 'remove_user':
                            // Remove user from contacts group
                            // Check that this action request is not a CSRF hacked request:
                            $Session->assert_received_crumb('messaging_contacts');
                            $view = param('view', 'string', 'profile');
                            $user_ID = param('user_ID', 'integer', 0);
                            $group_ID = param('group_ID', 'integer', 0);
                            if ($user_ID > 0 && $group_ID > 0) {
                                // Remove user from selected group
                                if (remove_contacts_group_user($group_ID, $user_ID)) {
                                    // User has been removed from the group
                                    if ($view == 'contacts') {
                                        // Redirect to the contacts list
                                        header_redirect($Blog->get('contactsurl', array('glue' => '&')));
                                    } else {
                                        // Redirect to the user profile page
                                        header_redirect($Blog->get('userurl', array('url_suffix' => 'user_ID=' . $user_ID, 'glue' => '&')));
                                    }
                                }
                            }
                            break;
                        case 'add_group':
                            // Add users to the group
                            // Check that this action request is not a CSRF hacked request:
                            $Session->assert_received_crumb('messaging_contacts');
                            $group = param('group', 'string', '');
                            $users = param('users', 'string', '');
                            if ($result = create_contacts_group_users($group, $users)) {
                                // Users have been added to the group
                                $Messages->add(sprintf(T_('%d contacts have been added to the &laquo;%s&raquo; group.'), $result['count_users'], $result['group_name']), 'success');
                                $redirect_to = $Blog->get('contactsurl', array('glue' => '&'));
                                $item_ID = param('item_ID', 'integer', 0);
                                if ($item_ID > 0) {
                                    $redirect_to = url_add_param($redirect_to, 'item_ID=' . $item_ID, '&');
                                }
                                header_redirect($redirect_to);
                            }
                            break;
                        case 'rename_group':
                            // Rename the group
                            // Check that this action request is not a CSRF hacked request:
                            $Session->assert_received_crumb('messaging_contacts');
                            $group_ID = param('group_ID', 'integer', true);
                            if (rename_contacts_group($group_ID)) {
                                $item_ID = param('item_ID', 'integer', 0);
                                $redirect_to = url_add_param($Blog->get('contactsurl', array('glue' => '&')), 'g=' . $group_ID, '&');
                                if ($item_ID > 0) {
                                    $redirect_to = url_add_param($redirect_to, 'item_ID=' . $item_ID, '&');
                                }
                                $Messages->add(T_('The group has been renamed.'), 'success');
                                header_redirect($redirect_to);
                            }
                            break;
                        case 'delete_group':
                            // Delete the group
                            // Check that this action request is not a CSRF hacked request:
                            $Session->assert_received_crumb('messaging_contacts');
                            $group_ID = param('group_ID', 'integer', true);
                            if (delete_contacts_group($group_ID)) {
                                $item_ID = param('item_ID', 'integer', 0);
                                $redirect_to = $Blog->get('contactsurl', array('glue' => '&'));
                                if ($item_ID > 0) {
                                    $redirect_to = url_add_param($redirect_to, 'item_ID=' . $item_ID, '&');
                                }
                                $Messages->add(T_('The group has been deleted.'), 'success');
                                header_redirect($redirect_to);
                            }
                            break;
                    }
                    modules_call_method('switch_contacts_actions', array('action' => $action));
                    break;
                case 'threads':
                    // Actions ONLY for disp=threads
                    if (!is_logged_in()) {
                        // Redirect to the login page for anonymous users
                        $Messages->add(T_('You must log in to read your messages.'));
                        header_redirect(get_login_url('cannot see messages'), 302);
                        // will have exited
                    }
                    if (!$current_User->check_status('can_view_threads')) {
                        // user status does not allow to view threads
                        if ($current_User->check_status('can_be_validated')) {
                            // user is logged in but his/her account is not activate yet
                            $Messages->add(T_('You must activate your account before you can read & send messages. <b>See below:</b>'));
                            header_redirect(get_activate_info_url(), 302);
                            // will have exited
                        }
                        $Messages->add('You are not allowed to view Messages!');
                        $blogurl = $Blog->gen_blogurl();
                        // If it was a front page request or the front page is set to display 'threads' then we must not redirect to the front page because it is forbidden for the current User
                        $redirect_to = is_front_page() || $Blog->get_setting('front_disp') == 'threads' ? url_add_param($blogurl, 'disp=404', '&') : $blogurl;
                        header_redirect($redirect_to, 302);
                        // will have exited
                    }
                    if (!$current_User->check_perm('perm_messaging', 'reply')) {
                        // Redirect to the blog url for users without messaging permission
                        $Messages->add('You are not allowed to view Messages!');
                        $blogurl = $Blog->gen_blogurl();
                        // If it was a front page request or the front page is set to display 'threads' then we must not redirect to the front page because it is forbidden for the current User
                        $redirect_to = is_front_page() || $Blog->get_setting('front_disp') == 'threads' ? url_add_param($blogurl, 'disp=403', '&') : $blogurl;
                        header_redirect($redirect_to, 302);
                        // will have exited
                    }
                    $action = param('action', 'string', 'view');
                    if ($action == 'new') {
                        // Before new message form is displayed ...
                        if (has_cross_country_restriction('contact') && empty($current_User->ctry_ID)) {
                            // Cross country contact restriction is enabled, but user country is not set yet
                            $Messages->add(T_('Please specify your country before attempting to contact other users.'));
                            header_redirect(get_user_profile_url());
                        } elseif (check_create_thread_limit(true)) {
                            // don't allow to create new thread, because the new thread limit was already reached
                            set_param('action', 'view');
                        }
                    }
                    // Load classes
                    load_class('messaging/model/_thread.class.php', 'Thread');
                    load_class('messaging/model/_message.class.php', 'Message');
                    // Get action parameter from request:
                    $action = param_action('view');
                    switch ($action) {
                        case 'new':
                            // Check permission:
                            $current_User->check_perm('perm_messaging', 'reply', true);
                            global $edited_Thread, $edited_Message;
                            $edited_Thread = new Thread();
                            $edited_Message = new Message();
                            $edited_Message->Thread =& $edited_Thread;
                            modules_call_method('update_new_thread', array('Thread' => &$edited_Thread));
                            if (($unsaved_message_params = get_message_params_from_session()) !== NULL) {
                                // set Message and Thread saved params from Session
                                $edited_Message->text = $unsaved_message_params['message'];
                                $edited_Message->original_text = $unsaved_message_params['message_original'];
                                $edited_Message->set_renderers($unsaved_message_params['renderers']);
                                $edited_Thread->title = $unsaved_message_params['subject'];
                                $edited_Thread->recipients = $unsaved_message_params['thrd_recipients'];
                                $edited_Message->Thread = $edited_Thread;
                                global $thrd_recipients_array, $thrdtype, $action, $creating_success;
                                $thrd_recipients_array = $unsaved_message_params['thrd_recipients_array'];
                                $thrdtype = $unsaved_message_params['thrdtype'];
                                $action = $unsaved_message_params['action'];
                                $creating_success = !empty($unsaved_message_params['creating_success']) ? $unsaved_message_params['creating_success'] : false;
                            } else {
                                if (empty($edited_Thread->recipients)) {
                                    $edited_Thread->recipients = param('thrd_recipients', 'string', '');
                                }
                                if (empty($edited_Thread->title)) {
                                    $edited_Thread->title = param('subject', 'string', '');
                                }
                            }
                            break;
                        default:
                            // Check permission:
                            $current_User->check_perm('perm_messaging', 'reply', true);
                            break;
                    }
                    break;
            }
            // Actions for disp = messages, contacts, threads:
            if (($msg_Blog =& get_setting_Blog('msg_blog_ID')) && $Blog->ID != $msg_Blog->ID) {
                // Redirect to special blog for messaging actions if it is defined in general settings
                $blog_url_params = array('glue' => '&');
                if (!empty($thrd_ID)) {
                    // Don't forget the important param on redirect
                    $blog_url_params['url_suffix'] = 'thrd_ID=' . $thrd_ID;
                }
                header_redirect($msg_Blog->get($disp . 'url', $blog_url_params));
            }
            // just in case some robot would be logged in:
            $seo_page_type = 'Messaging module';
            $robots_index = false;
            // Display messages depending on user email status
            display_user_email_status_message();
            break;
        case 'login':
            global $Plugins, $transmit_hashed_password;
            if (is_logged_in()) {
                // User is already logged in
                if ($current_User->check_status('can_be_validated')) {
                    // account is not active yet, redirect to the account activation page
                    $Messages->add(T_('You are logged in but your account is not activated. You will find instructions about activating your account below:'));
                    header_redirect(get_activate_info_url(), 302);
                    // will have exited
                }
                // User is already logged in, redirect to "redirect_to" page
                $Messages->add(T_('You are already logged in.'), 'note');
                $redirect_to = param('redirect_to', 'url', NULL);
                if (empty($redirect_to)) {
                    // If empty redirect to referer page
                    $redirect_to = '';
                }
                header_redirect($redirect_to, 302);
                // will have exited
            }
            if (($login_Blog =& get_setting_Blog('login_blog_ID')) && $Blog->ID != $login_Blog->ID) {
                // Redirect to special blog for login/register actions if it is defined in general settings
                header_redirect($login_Blog->get('loginurl', array('glue' => '&')));
            }
            $seo_page_type = 'Login form';
            $robots_index = false;
            break;
        case 'register':
            if (is_logged_in()) {
                // If user is logged in the register form should not be displayed. In this case redirect to the blog home page.
                $Messages->add(T_('You are already logged in.'), 'note');
                header_redirect($Blog->gen_blogurl(), false);
            }
            if (($login_Blog =& get_setting_Blog('login_blog_ID')) && $Blog->ID != $login_Blog->ID) {
                // Redirect to special blog for login/register actions if it is defined in general settings
                header_redirect($login_Blog->get('registerurl', array('glue' => '&')));
            }
            $seo_page_type = 'Register form';
            $robots_index = false;
            // Check invitation code if it exists and registration is enabled
            global $display_invitation;
            $display_invitation = check_invitation_code();
            break;
        case 'lostpassword':
            if (is_logged_in()) {
                // If user is logged in the lost password form should not be displayed. In this case redirect to the blog home page.
                $Messages->add(T_('You are already logged in.'), 'note');
                header_redirect($Blog->gen_blogurl(), false);
            }
            if (($login_Blog =& get_setting_Blog('login_blog_ID')) && $Blog->ID != $login_Blog->ID) {
                // Redirect to special blog for login/register actions if it is defined in general settings
                header_redirect($login_Blog->get('lostpasswordurl', array('glue' => '&')));
            }
            $seo_page_type = 'Lost password form';
            $robots_index = false;
            break;
        case 'activateinfo':
            if (!is_logged_in()) {
                // Redirect to the login page for anonymous users
                $Messages->add(T_('You must log in before you can activate your account.'));
                header_redirect(get_login_url('cannot see messages'), 302);
                // will have exited
            }
            if (!$current_User->check_status('can_be_validated')) {
                // don't display activateinfo screen
                $after_email_validation = $Settings->get('after_email_validation');
                if ($after_email_validation == 'return_to_original') {
                    // we want to return to original page after account activation
                    // check if Session 'validatemail.redirect_to' param is still set
                    $redirect_to = $Session->get('core.validatemail.redirect_to');
                    if (empty($redirect_to)) {
                        // Session param is empty try to get general redirect_to param
                        $redirect_to = param('redirect_to', 'url', '');
                    } else {
                        // cleanup validateemail.redirect_to param from session
                        $Session->delete('core.validatemail.redirect_to');
                    }
                } else {
                    // go to after email validation url which is set in the user general settings form
                    $redirect_to = $after_email_validation;
                }
                if (empty($redirect_to) || preg_match('#disp=activateinfo#', $redirect_to)) {
                    // redirect_to is pointing to the activate info display or is empty
                    // redirect to referer page
                    $redirect_to = '';
                }
                if ($current_User->check_status('is_validated')) {
                    $Messages->add(T_('Your account has already been activated.'));
                }
                header_redirect($redirect_to, 302);
                // will have exited
            }
            if (($login_Blog =& get_setting_Blog('login_blog_ID')) && $Blog->ID != $login_Blog->ID) {
                // Redirect to special blog for login/register actions if it is defined in general settings
                header_redirect($login_Blog->get('activateinfourl', array('glue' => '&')));
            }
            break;
        case 'profile':
        case 'avatar':
            $action = param_action();
            if ($action == 'crop' && is_logged_in()) {
                // Check data for crop action:
                global $current_User, $cropped_File;
                $file_ID = param('file_ID', 'integer');
                if (!($cropped_File = $current_User->get_File_by_ID($file_ID, $error_code))) {
                    // Current user cannot crop this file
                    set_param('action', '');
                }
            }
        case 'pwdchange':
        case 'userprefs':
        case 'subs':
            $seo_page_type = 'Special feature page';
            if ($Blog->get_setting('special_noindex')) {
                // We prefer robots not to index these pages:
                $robots_index = false;
            }
            // Display messages depending on user email status
            display_user_email_status_message();
            break;
        case 'users':
            if (!is_logged_in() && !$Settings->get('allow_anonymous_user_list')) {
                // Redirect to the login page if not logged in and allow anonymous user setting is OFF
                $Messages->add(T_('You must log in to view the user directory.'));
                header_redirect(get_login_url('cannot see user'), 302);
                // will have exited
            }
            if (is_logged_in() && !check_user_status('can_view_users')) {
                // user status doesn't permit to view users list
                if (check_user_status('can_be_validated')) {
                    // user is logged in but his/her account is not active yet
                    // Redirect to the account activation page
                    $Messages->add(T_('You must activate your account before you can view the user directory. <b>See below:</b>'));
                    header_redirect(get_activate_info_url(), 302);
                    // will have exited
                }
                // set where to redirect
                $error_redirect_to = empty($Blog) ? $baseurl : $Blog->gen_blogurl();
                $Messages->add(T_('Your account status currently does not permit to view the user directory.'));
                header_redirect($error_redirect_to, 302);
                // will have exited
            }
            if (has_cross_country_restriction('users', 'list') && empty($current_User->ctry_ID)) {
                // User may browse other users only from the same country
                $Messages->add(T_('Please specify your country before attempting to contact other users.'));
                header_redirect(get_user_profile_url());
            }
            $seo_page_type = 'Users list';
            $robots_index = false;
            break;
        case 'user':
            // get user_ID because we want it in redirect_to in case we need to ask for login.
            $user_ID = param('user_ID', 'integer', '', true);
            // set where to redirect in case of error
            $error_redirect_to = empty($Blog) ? $baseurl : $Blog->gen_blogurl();
            if (!is_logged_in()) {
                // Redirect to the login page if not logged in and allow anonymous user setting is OFF
                $user_available_by_group_level = true;
                if (!empty($user_ID)) {
                    $UserCache =& get_UserCache();
                    if ($User =& $UserCache->get_by_ID($user_ID, false)) {
                        // If user exists we can check if the anonymous users have an access to view the user by group level limitation
                        $User->get_Group();
                        $user_available_by_group_level = $User->Group->level >= $Settings->get('allow_anonymous_user_level_min') && $User->Group->level <= $Settings->get('allow_anonymous_user_level_max');
                    }
                }
                if (!$Settings->get('allow_anonymous_user_profiles') || !$user_available_by_group_level || empty($user_ID)) {
                    // If this user is not available for anonymous users
                    $Messages->add(T_('You must log in to view this user profile.'));
                    header_redirect(get_login_url('cannot see user'), 302);
                    // will have exited
                }
            }
            if (is_logged_in() && !check_user_status('can_view_user', $user_ID)) {
                // user is logged in, but his/her status doesn't permit to view user profile
                if (check_user_status('can_be_validated')) {
                    // user is logged in but his/her account is not active yet
                    // Redirect to the account activation page
                    $Messages->add(T_('You must activate your account before you can view this user profile. <b>See below:</b>'));
                    header_redirect(get_activate_info_url(), 302);
                    // will have exited
                }
                $Messages->add(T_('Your account status currently does not permit to view this user profile.'));
                header_redirect($error_redirect_to, 302);
                // will have exited
            }
            if (!empty($user_ID)) {
                $UserCache =& get_UserCache();
                $User =& $UserCache->get_by_ID($user_ID, false);
                if (empty($User)) {
                    $Messages->add(T_('The requested user does not exist!'));
                    header_redirect($error_redirect_to);
                    // will have exited
                }
                if ($User->check_status('is_closed')) {
                    $Messages->add(T_('The requested user account is closed!'));
                    header_redirect($error_redirect_to);
                    // will have exited
                }
                if (has_cross_country_restriction('any')) {
                    if (empty($current_User->ctry_ID)) {
                        // Current User country is not set
                        $Messages->add(T_('Please specify your country before attempting to contact other users.'));
                        header_redirect(get_user_profile_url());
                        // will have exited
                    }
                    if (has_cross_country_restriction('users', 'profile') && $current_User->ctry_ID !== $User->ctry_ID) {
                        // Current user country is different then edited user country and cross country user browsing is not enabled.
                        $Messages->add(T_('You don\'t have permission to view this user profile.'));
                        header_redirect(url_add_param($error_redirect_to, 'disp=403', '&'));
                        // will have exited
                    }
                }
            }
            // Initialize users list from session cache in order to display prev/next links:
            // It is used to navigate between users
            load_class('users/model/_userlist.class.php', 'UserList');
            global $UserList;
            $UserList = new UserList();
            $UserList->memorize = false;
            $UserList->load_from_Request();
            $seo_page_type = 'User display';
            break;
        case 'edit':
            global $current_User, $post_ID;
            // Post ID, go from $_GET when we edit a post from Front-office
            //          or from $_POST when we switch from Back-office
            $post_ID = param('p', 'integer', empty($post_ID) ? 0 : $post_ID, true);
            if (!is_logged_in()) {
                // Redirect to the login page if not logged in and allow anonymous user setting is OFF
                $redirect_to = url_add_param($Blog->gen_blogurl(), 'disp=edit');
                $Messages->add(T_('You must log in to create & edit posts.'));
                header_redirect(get_login_url('cannot edit posts', $redirect_to), 302);
                // will have exited
            }
            if (!$current_User->check_status('can_edit_post')) {
                if ($current_User->check_status('can_be_validated')) {
                    // user is logged in but his/her account was not activated yet
                    // Redirect to the account activation page
                    $Messages->add(T_('You must activate your account before you can create & edit posts. <b>See below:</b>'));
                    header_redirect(get_activate_info_url(), 302);
                    // will have exited
                }
                // Redirect to the blog url for users without messaging permission
                $Messages->add(T_('You are not allowed to create & edit posts!'));
                header_redirect($Blog->gen_blogurl(), 302);
            }
            // user logged in and the account was activated
            check_item_perm_edit($post_ID);
            if (!blog_has_cats($Blog->ID)) {
                // No categories are in this blog
                $error_message = T_('Since this blog has no categories, you cannot post into it.');
                if ($current_User->check_perm('blog_cats', 'edit', false, $Blog->ID)) {
                    // If current user has a permission to create a category
                    global $admin_url;
                    $error_message .= ' ' . sprintf(T_('You must <a %s>create categories</a> first.'), 'href="' . $admin_url . '?ctrl=chapters&amp;blog=' . $Blog->ID . '"');
                }
                $Messages->add($error_message, 'error');
                header_redirect($Blog->gen_blogurl(), 302);
            }
            // Prepare the 'In-skin editing':
            init_inskin_editing();
            break;
        case 'edit_comment':
            global $current_User, $edited_Comment, $comment_Item, $Item, $comment_title, $comment_content, $display_params;
            // comment ID
            $comment_ID = param('c', 'integer', 0, true);
            if (!is_logged_in()) {
                // Redirect to the login page if not logged in and allow anonymous user setting is OFF
                $redirect_to = url_add_param($Blog->gen_blogurl(), 'disp=edit_comment');
                $Messages->add(T_('You must log in to edit comments.'));
                header_redirect(get_login_url('cannot edit comments', $redirect_to), 302);
                // will have exited
            }
            if (!$current_User->check_status('can_edit_comment')) {
                if ($current_User->check_status('can_be_validated')) {
                    // user is logged in but his/her account was not activated yet
                    // Redirect to the account activation page
                    $Messages->add(T_('You must activate your account before you can edit comments. <b>See below:</b>'));
                    header_redirect(get_activate_info_url(), 302);
                    // will have exited
                }
                // Redirect to the blog url for users without messaging permission
                $Messages->add('You are not allowed to edit comments!');
                header_redirect($Blog->gen_blogurl(), 302);
            }
            if (empty($comment_ID)) {
                // Can't edit a not exisiting comment
                $Messages->add('Invalid comment edit URL!');
                global $disp;
                $disp = 404;
                break;
            }
            $CommentCache =& get_CommentCache();
            $edited_Comment = $CommentCache->get_by_ID($comment_ID);
            $comment_Item = $edited_Comment->get_Item();
            if (!$current_User->check_perm('comment!CURSTATUS', 'edit', false, $edited_Comment)) {
                // If User has no permission to edit comments with this comment status:
                $Messages->add('You are not allowed to edit the previously selected comment!');
                header_redirect($Blog->gen_blogurl(), 302);
            }
            $comment_title = '';
            $comment_content = htmlspecialchars_decode($edited_Comment->content);
            // Format content for editing, if we were not already in editing...
            $Plugins_admin =& get_Plugins_admin();
            $comment_Item->load_Blog();
            $params = array('object_type' => 'Comment', 'object_Blog' => &$comment_Item->Blog);
            $Plugins_admin->unfilter_contents($comment_title, $comment_content, $edited_Comment->get_renderers_validated(), $params);
            $Item = $comment_Item;
            $display_params = array();
            break;
        case 'useritems':
        case 'usercomments':
            global $display_params, $viewed_User;
            // get user_ID because we want it in redirect_to in case we need to ask for login.
            $user_ID = param('user_ID', 'integer', true, true);
            if (empty($user_ID)) {
                bad_request_die(sprintf(T_('Parameter &laquo;%s&raquo; is required!'), 'user_ID'));
            }
            // set where to redirect in case of error
            $error_redirect_to = empty($Blog) ? $baseurl : $Blog->gen_blogurl();
            if (!is_logged_in()) {
                // Redirect to the login page if not logged in and allow anonymous user setting is OFF
                $Messages->add(T_('You must log in to view this user profile.'));
                header_redirect(get_login_url('cannot see user'), 302);
                // will have exited
            }
            if (is_logged_in() && !check_user_status('can_view_user', $user_ID)) {
                // user is logged in, but his/her status doesn't permit to view user profile
                if (check_user_status('can_be_validated')) {
                    // user is logged in but his/her account is not active yet
                    // Redirect to the account activation page
                    $Messages->add(T_('You must activate your account before you can view this user profile. <b>See below:</b>'));
                    header_redirect(get_activate_info_url(), 302);
                    // will have exited
                }
                $Messages->add(T_('Your account status currently does not permit to view this user profile.'));
                header_redirect($error_redirect_to, 302);
                // will have exited
            }
            if (!empty($user_ID)) {
                $UserCache =& get_UserCache();
                $viewed_User = $UserCache->get_by_ID($user_ID, false);
                if (empty($viewed_User)) {
                    $Messages->add(T_('The requested user does not exist!'));
                    header_redirect($error_redirect_to);
                    // will have exited
                }
                if ($viewed_User->check_status('is_closed')) {
                    $Messages->add(T_('The requested user account is closed!'));
                    header_redirect($error_redirect_to);
                    // will have exited
                }
            }
            $display_params = !empty($Skin) ? $Skin->get_template('Results') : NULL;
            if ($disp == 'useritems') {
                // Init items list
                global $user_ItemList;
                $useritems_Blog = NULL;
                $user_ItemList = new ItemList2($useritems_Blog, NULL, NULL, NULL, 'ItemCache', 'useritems_');
                $user_ItemList->load_from_Request();
                $user_ItemList->set_filters(array('authors' => $user_ID), true, true);
                $user_ItemList->query();
            } else {
                // Init comments list
                global $user_CommentList;
                $user_CommentList = new CommentList2(NULL, NULL, 'CommentCache', 'usercmts_');
                $user_CommentList->load_from_Request();
                $user_CommentList->set_filters(array('author_IDs' => $user_ID), true, true);
                $user_CommentList->query();
            }
            break;
        case 'comments':
            if (!$Blog->get_setting('comments_latest')) {
                // If latest comments page is disabled - Display 404 page with error message
                $Messages->add(T_('This feature is disabled.'), 'error');
                global $disp;
                $disp = '404';
            }
            break;
        case 'closeaccount':
            global $current_User;
            if (!$Settings->get('account_close_enabled') || is_logged_in() && $current_User->check_perm('users', 'edit', false) || !is_logged_in() && !$Session->get('account_closing_success')) {
                // If an account closing page is disabled - Display 404 page with error message
                // Don't allow admins close own accounts from front office
                // Don't display this message for not logged in users, except of one case to display a bye message after account closing
                global $disp;
                $disp = '404';
            } elseif ($Session->get('account_closing_success')) {
                // User has closed the account
                global $account_closing_success;
                $account_closing_success = $Session->get('account_closing_success');
                // Unset this temp session var to don't display the message twice
                $Session->delete('account_closing_success');
                if (is_logged_in()) {
                    // log out current User
                    logout();
                }
            }
            break;
        case 'tags':
            $seo_page_type = 'Tags';
            if ($Blog->get_setting($disp . '_noindex')) {
                // We prefer robots not to index these pages:
                $robots_index = false;
            }
            break;
    }
    $Debuglog->add('skin_init: $disp=' . $disp . ' / $disp_detail=' . $disp_detail . ' / $seo_page_type=' . $seo_page_type, 'skins');
    // Make this switch block special only for 404 page
    switch ($disp) {
        case '404':
            // We have a 404 unresolved content error
            // How do we want do deal with it?
            skin_404_header();
            // This MAY or MAY not have exited -- will exit on 30x redirect, otherwise will return here.
            // Just in case some dumb robot needs extra directives on this:
            $robots_index = false;
            break;
    }
    global $Hit, $check_browser_version;
    if ($check_browser_version && $Hit->get_browser_version() > 0 && $Hit->is_IE(9, '<')) {
        // Display info message if browser IE < 9 version and it is allowed by config var:
        global $debug;
        $Messages->add(T_('Your web browser is too old. For this site to work correctly, we recommend you use a more recent browser.'), 'note');
        if ($debug) {
            $Messages->add('User Agent: ' . $Hit->get_user_agent(), 'note');
        }
    }
    // dummy var for backward compatibility with versions < 2.4.1 -- prevents "Undefined variable"
    global $global_Cache, $credit_links;
    $credit_links = $global_Cache->get('creds');
    $Timer->pause('skin_init');
    // Check if user is logged in with a not active account, and display an error message if required
    check_allow_disp($disp);
    // initialize Blog enabled widgets, before displaying anything
    init_blog_widgets($Blog->ID);
    // Initialize displaying....
    $Timer->start('Skin:display_init');
    $Skin->display_init();
    $Timer->pause('Skin:display_init');
    // Send default headers:
    // See comments inside of this function:
    headers_content_mightcache('text/html');
    // In most situations, you do NOT want to cache dynamic content!
    // Never allow Messages to be cached!
    if ($Messages->count() && !empty($PageCache)) {
        // Abort PageCache collect
        $PageCache->abort_collect();
    }
}
 /**
  * Get link to Countries, where this Currencie is used
  * Use when try to delete a currencie
  *  
  * @param array restriction array 
  * @return string link to currency's countries
  */
 function get_restriction_link($restriction)
 {
     global $DB, $admin_url;
     if ($restriction['fk'] != 'ctry_curr_ID') {
         // currency restriction exists only for countries
         debug_die('Restriction does not exists');
     }
     // link to country object
     $link = '<a href="' . $admin_url . '?ctrl=countries&action=edit&ctry_ID=%d">%s</a>';
     // set sql to get country ID and name
     $objectID_query = 'SELECT ctry_ID, ctry_name' . ' FROM ' . $restriction['table'] . ' WHERE ' . $restriction['fk'] . ' = ' . $this->ID;
     $result_link = '';
     $query_result = $DB->get_results($objectID_query);
     foreach ($query_result as $row) {
         $result_link .= '<br/>' . sprintf($link, $row->ctry_ID, $row->ctry_name);
     }
     $result_link = sprintf($restriction['msg'] . $result_link, count($query_result));
     return $result_link;
 }
$block_item_Widget = new Widget('block_item');
$display_same_as_normal = false;
switch ($skin_type) {
    case 'normal':
        $block_item_Widget->title = T_('Choose a skin');
        break;
    case 'mobile':
        $block_item_Widget->title = T_('Choose a Mobile Phone skin');
        $display_same_as_normal = true;
        break;
    case 'tablet':
        $block_item_Widget->title = T_('Choose a Tablet skin');
        $display_same_as_normal = true;
        break;
    default:
        debug_die('Invalid skin type!');
}
// Get what is the current skin ID from this kind of skin type
$current_skin_ID = $edited_Blog->get_setting($skin_type . '_skin_ID', true);
if ($current_User->check_perm('options', 'edit', false)) {
    // We have permission to modify:
    $block_item_Widget->global_icon(T_('Install new skin...'), 'new', $dispatcher . '?ctrl=skins&amp;action=new&amp;redirect_to=' . rawurlencode(url_rel_to_same_host(regenerate_url('', 'skinpage=selection', '', '&'), $admin_url)), T_('Install new'), 3, 4);
    $block_item_Widget->global_icon(T_('Keep current skin!'), 'close', regenerate_url('skinpage'), ' ' . T_('Don\'t change'), 3, 4);
}
$block_item_Widget->disp_template_replaced('block_start');
$SkinCache =& get_SkinCache();
$SkinCache->load_all();
if ($display_same_as_normal) {
    $skinshot_title = T_('Same as normal skin');
    $select_url = '?ctrl=coll_settings&tab=skin&blog=' . $edited_Blog->ID . '&amp;action=update&amp;skinpage=selection&amp;' . $skin_type . '_skin_ID=0&amp;' . url_crumb('collection');
    $disp_params = array('function' => 'select', 'selected' => $current_skin_ID == '0', 'select_url' => $select_url);
/**
 * upgrade_b2evo_tables(-)
 *
 * @param string the action param value corresponding the current upgrade process ( evoupgrade, svn_upgrade, auto_upgrade )
 */
function upgrade_b2evo_tables($upgrade_action = 'evoupgrade')
{
    global $db_config, $tableprefix;
    global $baseurl, $old_db_version, $new_db_version;
    global $Group_Admins, $Group_Privileged, $Group_Bloggers, $Group_Users;
    global $locales, $locale;
    global $DB;
    global $admin_url;
    global $Settings, $Plugins;
    // used for defaults, when upgrading to 1.6
    global $use_fileupload, $fileupload_allowedtypes, $fileupload_maxk, $doubleCheckReferers;
    // new DB-delta functionality
    global $schema_queries, $inc_path;
    // used to check script time before starting to create db delta
    global $script_start_time;
    // Create an option which can be turned on if we need to regenerate the autogenerated excerpts in the end of the upgrade script
    global $recreate_autogenerated_excerpts;
    $recreate_autogenerated_excerpts = param('recreate_excerpts', 'boolean', 0);
    // Load DB schema from modules
    load_db_schema();
    // Update the progress bar status
    update_install_progress_bar();
    load_funcs('_core/model/db/_upgrade.funcs.php');
    // Force MySQL strict mode:
    $DB->query('SET sql_mode = ""', 'REMOVE MySQL "strict" mode in order not to worry about missing defaults until the end of the upgrade.');
    echo '<p>' . T_('Checking DB schema version...') . ' ';
    $old_db_version = get_db_version();
    if (empty($old_db_version)) {
        echo '<p><strong>OOPS! b2evolution doesn\'t seem to be installed yet.</strong></p>';
        return false;
    }
    echo $old_db_version, ' : ';
    if ($old_db_version < 8000) {
        debug_die(T_('This version is too old!'));
    }
    if ($old_db_version > $new_db_version) {
        debug_die(T_('This version is too recent! We cannot downgrade to the version you are trying to install...'));
    }
    echo "OK.<br />\n";
    if ($old_db_version < 8010) {
        echo 'Upgrading users table... ';
        $query = "ALTER TABLE T_users\n\t\t\t\t\t\t\tMODIFY COLUMN user_pass CHAR(32) NOT NULL";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Upgrading blogs table... ';
        $query = "ALTER TABLE T_blogs\n\t\t\t\t\t\t\tMODIFY COLUMN blog_lang VARCHAR(20) NOT NULL DEFAULT 'en_US',\n\t\t\t\t\t\t\tMODIFY COLUMN blog_longdesc TEXT NULL DEFAULT NULL";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Upgrading categories table... ';
        $query = "ALTER TABLE T_categories\n\t\t\t\t\t\t\tADD COLUMN cat_description VARCHAR(250) NULL DEFAULT NULL,\n\t\t\t\t\t\t\tADD COLUMN cat_longdesc TEXT NULL DEFAULT NULL,\n\t\t\t\t\t\t\tADD COLUMN cat_icon VARCHAR(30) NULL DEFAULT NULL";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Upgrading posts table... ';
        $query = "ALTER TABLE {$tableprefix}posts\n\t\t\t\t\t\t\tMODIFY COLUMN post_lang VARCHAR(20) NOT NULL DEFAULT 'en_US',\n\t\t\t\t\t\t\tADD COLUMN post_urltitle VARCHAR(50) NULL DEFAULT NULL AFTER post_title,\n\t\t\t\t\t\t\tADD COLUMN post_url VARCHAR(250) NULL DEFAULT NULL AFTER post_urltitle,\n\t\t\t\t\t\t\tADD COLUMN post_comments ENUM('disabled', 'open', 'closed') NOT NULL DEFAULT 'open' AFTER post_wordcount";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Generating wordcounts... ';
        load_funcs('items/model/_item.funcs.php');
        $query = "SELECT ID, post_content FROM {$tableprefix}posts WHERE post_wordcount IS NULL";
        $i = 0;
        foreach ($DB->get_results($query, ARRAY_A) as $row) {
            $query_update_wordcount = "UPDATE {$tableprefix}posts\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSET post_wordcount = " . bpost_count_words($row['post_content']) . "\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tWHERE ID = " . $row['ID'];
            $DB->query($query_update_wordcount);
            $i++;
        }
        echo "OK. ({$i} rows updated)<br />\n";
        set_upgrade_checkpoint('8010');
    }
    if ($old_db_version < 8020) {
        echo 'Encoding passwords... ';
        $query = "UPDATE T_users\n\t\t\t\t\t\t\tSET user_pass = MD5(user_pass)";
        $DB->query($query);
        echo "OK.<br />\n";
        set_upgrade_checkpoint('8020');
    }
    if ($old_db_version < 8030) {
        echo 'Deleting unecessary logs... ';
        $query = "DELETE FROM T_hitlog\n\t\t\t\t\t\t\tWHERE hit_ignore = 'badchar'";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Updating blog urls... ';
        $query = "SELECT blog_ID, blog_siteurl FROM T_blogs";
        $i = 0;
        foreach ($DB->get_results($query, ARRAY_A) as $row) {
            $blog_ID = $row['blog_ID'];
            $blog_siteurl = $row['blog_siteurl'];
            // echo $blog_ID.':'.$blog_siteurl;
            if (strpos($blog_siteurl . '/', $baseurl) !== 0) {
                // If not found at position 0
                echo ' <strong>WARNING: please check blog #', $blog_ID, ' manually.</strong><br /> ';
                continue;
            }
            // crop off the baseurl:
            $blog_siteurl = utf8_substr($blog_siteurl . '/', utf8_strlen($baseurl));
            // echo ' -> ', $blog_siteurl,'<br />';
            $query_update_blog = "UPDATE T_blogs SET blog_siteurl = '{$blog_siteurl}' WHERE blog_ID = {$blog_ID}";
            // echo $query_update_blog, '<br />';
            $DB->query($query_update_blog);
            $i++;
        }
        echo "OK. ({$i} rows updated)<br />\n";
        set_upgrade_checkpoint('8030');
    }
    if ($old_db_version < 8040) {
        // upgrade to 0.8.7
        echo 'Creating table for Antispam Blackist... ';
        $query = "CREATE TABLE {$tableprefix}antispam (\n\t\t\taspm_ID bigint(11) NOT NULL auto_increment,\n\t\t\taspm_string varchar(80) NOT NULL,\n\t\t\taspm_source enum( 'local','reported','central' ) NOT NULL default 'reported',\n\t\t\tPRIMARY KEY aspm_ID (aspm_ID),\n\t\t\tUNIQUE aspm_string (aspm_string)\n\t\t)";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Creating default blacklist entries... ';
        // This string contains antispam information that is obfuscated because some hosting
        // companies prevent uploading PHP files containing "spam" strings.
        // pre_dump(get_antispam_query());
        $query = get_antispam_query();
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Upgrading Settings table... ';
        $query = "ALTER TABLE T_settings\n\t\t\t\t\t\t\tADD COLUMN last_antispam_update datetime NOT NULL default '2000-01-01 00:00:00'";
        $DB->query($query);
        echo "OK.<br />\n";
        set_upgrade_checkpoint('8040');
    }
    if ($old_db_version < 8050) {
        // upgrade to 0.8.9
        echo 'Upgrading blogs table... ';
        $query = "ALTER TABLE T_blogs\n\t\t\t\t\t\t\tADD COLUMN blog_allowtrackbacks tinyint(1) NOT NULL default 1,\n\t\t\t\t\t\t\tADD COLUMN blog_allowpingbacks tinyint(1) NOT NULL default 0,\n\t\t\t\t\t\t\tADD COLUMN blog_pingb2evonet tinyint(1) NOT NULL default 0,\n\t\t\t\t\t\t\tADD COLUMN blog_pingtechnorati tinyint(1) NOT NULL default 0,\n\t\t\t\t\t\t\tADD COLUMN blog_pingweblogs tinyint(1) NOT NULL default 0,\n\t\t\t\t\t\t\tADD COLUMN blog_pingblodotgs tinyint(1) NOT NULL default 0,\n\t\t\t\t\t\t\tADD COLUMN blog_disp_bloglist tinyint NOT NULL DEFAULT 1";
        $DB->query($query);
        echo "OK.<br />\n";
        // Create User Groups
        global $Group_Admins, $Group_Privileged, $Group_Bloggers, $Group_Users;
        echo 'Creating table for Groups... ';
        $query = "CREATE TABLE T_groups (\n\t\t\tgrp_ID int(11) NOT NULL auto_increment,\n\t\t\tgrp_name varchar(50) NOT NULL default '',\n\t\t\tgrp_perm_admin enum('none','hidden','visible') NOT NULL default 'visible',\n\t\t\tgrp_perm_blogs enum('user','viewall','editall') NOT NULL default 'user',\n\t\t\tgrp_perm_stats enum('none','view','edit') NOT NULL default 'none',\n\t\t\tgrp_perm_spamblacklist enum('none','view','edit') NOT NULL default 'none',\n\t\t\tgrp_perm_options enum('none','view','edit') NOT NULL default 'none',\n\t\t\tgrp_perm_users enum('none','view','edit') NOT NULL default 'none',\n\t\t\tgrp_perm_templates TINYINT NOT NULL DEFAULT 0,\n\t\t\tgrp_perm_files enum('none','view','add','edit','all') NOT NULL default 'none',\n\t\t\tPRIMARY KEY grp_ID (grp_ID)\n\t\t)";
        $DB->query($query);
        echo "OK.<br />\n";
        // This table needs to be created here for proper group insertion
        task_begin('Creating table for Group Settings... ');
        $DB->query("CREATE TABLE T_groups__groupsettings (\n\t\t\tgset_grp_ID INT(11) UNSIGNED NOT NULL,\n\t\t\tgset_name VARCHAR(30) NOT NULL,\n\t\t\tgset_value VARCHAR(255) NULL,\n\t\t\tPRIMARY KEY (gset_grp_ID, gset_name)\n\t\t) ENGINE = innodb");
        task_end();
        echo 'Creating default groups... ';
        $Group_Admins = new Group();
        // COPY !
        $Group_Admins->set('name', 'Administrators');
        $Group_Admins->set('perm_admin', 'visible');
        $Group_Admins->set('perm_blogs', 'editall');
        $Group_Admins->set('perm_stats', 'edit');
        $Group_Admins->set('perm_spamblacklist', 'edit');
        $Group_Admins->set('perm_files', 'all');
        $Group_Admins->set('perm_options', 'edit');
        $Group_Admins->set('perm_templates', 1);
        $Group_Admins->set('perm_users', 'edit');
        $Group_Admins->dbinsert();
        $Group_Privileged = new Group();
        // COPY !
        $Group_Privileged->set('name', 'Privileged Bloggers');
        $Group_Privileged->set('perm_admin', 'visible');
        $Group_Privileged->set('perm_blogs', 'viewall');
        $Group_Privileged->set('perm_stats', 'view');
        $Group_Privileged->set('perm_spamblacklist', 'edit');
        $Group_Privileged->set('perm_files', 'add');
        $Group_Privileged->set('perm_options', 'view');
        $Group_Privileged->set('perm_templates', 0);
        $Group_Privileged->set('perm_users', 'view');
        $Group_Privileged->dbinsert();
        $Group_Bloggers = new Group();
        // COPY !
        $Group_Bloggers->set('name', 'Bloggers');
        $Group_Bloggers->set('perm_admin', 'visible');
        $Group_Bloggers->set('perm_blogs', 'user');
        $Group_Bloggers->set('perm_stats', 'none');
        $Group_Bloggers->set('perm_spamblacklist', 'view');
        $Group_Bloggers->set('perm_files', 'view');
        $Group_Bloggers->set('perm_options', 'none');
        $Group_Bloggers->set('perm_templates', 0);
        $Group_Bloggers->set('perm_users', 'none');
        $Group_Bloggers->dbinsert();
        $Group_Users = new Group();
        // COPY !
        $Group_Users->set('name', 'Basic Users');
        $Group_Users->set('perm_admin', 'none');
        $Group_Users->set('perm_blogs', 'user');
        $Group_Users->set('perm_stats', 'none');
        $Group_Users->set('perm_spamblacklist', 'none');
        $Group_Users->set('perm_files', 'none');
        $Group_Users->set('perm_options', 'none');
        $Group_Users->set('perm_templates', 0);
        $Group_Users->set('perm_users', 'none');
        $Group_Users->dbinsert();
        echo "OK.<br />\n";
        echo 'Creating table for Blog-User permissions... ';
        $query = "CREATE TABLE T_coll_user_perms (\n\t\t\tbloguser_blog_ID int(11) unsigned NOT NULL default 0,\n\t\t\tbloguser_user_ID int(11) unsigned NOT NULL default 0,\n\t\t\tbloguser_ismember tinyint NOT NULL default 0,\n\t\t\tbloguser_perm_poststatuses set('published','deprecated','protected','private','draft') NOT NULL default '',\n\t\t\tbloguser_perm_delpost tinyint NOT NULL default 0,\n\t\t\tbloguser_perm_comments tinyint NOT NULL default 0,\n\t\t\tbloguser_perm_cats tinyint NOT NULL default 0,\n\t\t\tbloguser_perm_properties tinyint NOT NULL default 0,\n\t\t\tbloguser_perm_media_upload tinyint NOT NULL default 0,\n\t\t\tbloguser_perm_media_browse tinyint NOT NULL default 0,\n\t\t\tbloguser_perm_media_change tinyint NOT NULL default 0,\n\t\t\tPRIMARY KEY bloguser_pk (bloguser_blog_ID,bloguser_user_ID)\n\t\t)";
        $DB->query($query);
        echo "OK.<br />\n";
        $tablegroups_isuptodate = true;
        $tableblogusers_isuptodate = true;
        echo 'Creating user blog permissions... ';
        // Admin: full rights for all blogs (look 'ma, doing a natural join! :>)
        $query = "INSERT INTO T_coll_user_perms( bloguser_blog_ID, bloguser_user_ID, bloguser_ismember,\n\t\t\t\t\t\t\t\tbloguser_perm_poststatuses, bloguser_perm_delpost, bloguser_perm_comments,\n\t\t\t\t\t\t\t\tbloguser_perm_cats, bloguser_perm_properties)\n\t\t\t\t\t\t\tSELECT blog_ID, ID, 1, 'published,deprecated,protected,private,draft', 1, 1, 1, 1\n\t\t\t\t\t\t\tFROM T_users, T_blogs\n\t\t\t\t\t\t\tWHERE user_level = 10";
        $DB->query($query);
        // Normal users: basic rights for all blogs (can't stop doing joins :P)
        $query = "INSERT INTO T_coll_user_perms( bloguser_blog_ID, bloguser_user_ID, bloguser_ismember,\n\t\t\t\t\t\t\t\tbloguser_perm_poststatuses, bloguser_perm_delpost, bloguser_perm_comments,\n\t\t\t\t\t\t\t\tbloguser_perm_cats, bloguser_perm_properties)\n\t\t\t\t\t\t\tSELECT blog_ID, ID, 1, 'published,protected,private,draft', 0, 1, 0, 0\n\t\t\t\t\t\t\tFROM T_users, T_blogs\n\t\t\t\t\t\t\tWHERE user_level > 0 AND user_level < 10";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Upgrading users table... ';
        $DB->query('UPDATE T_users
									  SET dateYMDhour = \'2000-01-01 00:00:00\'
									WHERE ( dateYMDhour = \'0000-00-00 00:00:00\' OR dateYMDhour = \'2000-00-00 00:00:01\' )');
        $DB->query('ALTER TABLE T_users
							MODIFY COLUMN dateYMDhour DATETIME NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $query = "ALTER TABLE T_users\n\t\t\t\t\t\t\tADD COLUMN user_notify tinyint(1) NOT NULL default 1,\n\t\t\t\t\t\t\tADD COLUMN user_grp_ID int(4) NOT NULL default 1,\n\t\t\t\t\t\t\tMODIFY COLUMN user_idmode varchar(20) NOT NULL DEFAULT 'login'";
        $DB->query($query);
        $query = "ALTER TABLE T_users\n\t\t\t\t\t\t\tADD KEY user_grp_ID (user_grp_ID)";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Assigning user groups... ';
        // Default is 1, so admins are already set.
        // Basic Users:
        $query = "UPDATE T_users\n\t\t\t\t\t\t\tSET user_grp_ID = {$Group_Users->ID}\n\t\t\t\t\t\t\tWHERE user_level = 0";
        $DB->query($query);
        // Bloggers:
        $query = "UPDATE T_users\n\t\t\t\t\t\t\tSET user_grp_ID = {$Group_Bloggers->ID}\n\t\t\t\t\t\t\tWHERE user_level > 0 AND user_level < 10";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Upgrading settings table... ';
        $query = "ALTER TABLE T_settings\n\t\t\t\t\t\t\tDROP COLUMN time_format,\n\t\t\t\t\t\t\tDROP COLUMN date_format,\n\t\t\t\t\t\t\tADD COLUMN pref_newusers_grp_ID int unsigned DEFAULT 4 NOT NULL,\n\t\t\t\t\t\t\tADD COLUMN pref_newusers_level tinyint unsigned DEFAULT 1 NOT NULL,\n\t\t\t\t\t\t\tADD COLUMN pref_newusers_canregister tinyint unsigned DEFAULT 0 NOT NULL";
        $DB->query($query);
        echo "OK.<br />\n";
        set_upgrade_checkpoint('8050');
    }
    if ($old_db_version < 8060) {
        // upgrade to 0.9
        // Important check:
        $stub_list = $DB->get_col("\n\t\t\tSELECT blog_stub\n\t\t\t  FROM T_blogs\n\t\t\t GROUP BY blog_stub\n\t\t\tHAVING COUNT(*) > 1");
        if (!empty($stub_list)) {
            echo '<div class="error"><p class="error">';
            printf(T_("It appears that the following blog stub names are used more than once: ['%s']"), implode("','", $stub_list));
            echo '</p><p>';
            printf(T_("I can't upgrade until you make them unique. DB field: [%s]"), $db_config['aliases']['T_blogs'] . '.blog_stub');
            echo '</p></div>';
            return false;
        }
        // Create locales
        echo 'Creating table for Locales... ';
        $query = "CREATE TABLE T_locales (\n\t\t\t\tloc_locale varchar(20) NOT NULL default '',\n\t\t\t\tloc_charset varchar(15) NOT NULL default 'iso-8859-1',\n\t\t\t\tloc_datefmt varchar(10) NOT NULL default 'y-m-d',\n\t\t\t\tloc_timefmt varchar(10) NOT NULL default 'H:i:s',\n\t\t\t\tloc_name varchar(40) NOT NULL default '',\n\t\t\t\tloc_messages varchar(20) NOT NULL default '',\n\t\t\t\tloc_priority tinyint(4) UNSIGNED NOT NULL default '0',\n\t\t\t\tloc_enabled tinyint(4) NOT NULL default '1',\n\t\t\t\tPRIMARY KEY loc_locale( loc_locale )\n\t\t\t) COMMENT='saves available locales'";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Upgrading posts table... ';
        $query = "UPDATE {$tableprefix}posts\n\t\t\t\t\t\t\tSET post_urltitle = NULL";
        $DB->query($query);
        $query = "ALTER TABLE {$tableprefix}posts\n\t\t\t\t\t\t\tCHANGE COLUMN post_date post_issue_date datetime NOT NULL default '1000-01-01 00:00:00',\n\t\t\t\t\t\t\tADD COLUMN post_mod_date datetime NOT NULL default '1000-01-01 00:00:00'\n\t\t\t\t\t\t\t\t\t\tAFTER post_issue_date,\n\t\t\t\t\t\t\tCHANGE COLUMN post_lang post_locale varchar(20) NOT NULL default 'en-EU',\n\t\t\t\t\t\t\tDROP COLUMN post_url,\n\t\t\t\t\t\t\tCHANGE COLUMN post_trackbacks post_url varchar(250) NULL default NULL,\n\t\t\t\t\t\t\tADD COLUMN post_renderers VARCHAR(179) NOT NULL default 'default'";
        $DB->query($query);
        $query = "ALTER TABLE {$tableprefix}posts\n\t\t\t\t\t\t\tADD INDEX post_issue_date( post_issue_date ),\n\t\t\t\t\t\t\tADD UNIQUE post_urltitle( post_urltitle )";
        $DB->query($query);
        $query = "ALTER TABLE {$tableprefix}posts\n\t\t\t\t\tDROP INDEX post_date";
        $DB->query($query);
        $query = "UPDATE {$tableprefix}posts\n\t\t\t\t\t\t\tSET post_mod_date = post_issue_date";
        $DB->query($query);
        echo "OK.<br />\n";
        // convert given languages to locales
        convert_lang_to_locale("{$tableprefix}posts", 'post_locale', 'ID');
        echo 'Upgrading blogs table... ';
        $query = "ALTER TABLE T_blogs\n\t\t\t\t\t\t\tCHANGE blog_lang blog_locale varchar(20) NOT NULL default 'en-EU',\n\t\t\t\t\t\t\tCHANGE blog_roll blog_notes TEXT NULL,\n\t\t\t\t\t\t\tMODIFY COLUMN blog_default_skin VARCHAR(30) NOT NULL DEFAULT 'custom',\n\t\t\t\t\t\t\tDROP COLUMN blog_filename,\n\t\t\t\t\t\t\tADD COLUMN blog_access_type VARCHAR(10) NOT NULL DEFAULT 'index.php' AFTER blog_locale,\n\t\t\t\t\t\t\tADD COLUMN blog_force_skin tinyint(1) NOT NULL default 0 AFTER blog_default_skin,\n\t\t\t\t\t\t\tADD COLUMN blog_in_bloglist tinyint(1) NOT NULL DEFAULT 1 AFTER blog_disp_bloglist,\n\t\t\t\t\t\t\tADD COLUMN blog_links_blog_ID INT(4) NOT NULL DEFAULT 0,\n\t\t\t\t\t\t\tADD UNIQUE KEY blog_stub (blog_stub)";
        $DB->query($query);
        $query = "UPDATE T_blogs\n\t\t\t\t\t\t\tSET blog_access_type = 'stub',\n\t\t\t\t\t\t\t\t\tblog_default_skin = 'custom'";
        $DB->query($query);
        echo "OK.<br />\n";
        // convert given languages to locales
        convert_lang_to_locale('T_blogs', 'blog_locale', 'blog_ID');
        echo 'Converting settings table... ';
        // get old settings
        $query = 'SELECT * FROM T_settings';
        $row = $DB->get_row($query, ARRAY_A);
        #echo 'oldrow:<br />'; pre_dump($row);
        $transform = array('posts_per_page' => array(5), 'what_to_show' => array('posts'), 'archive_mode' => array('monthly'), 'time_difference' => array(0), 'AutoBR' => array(0), 'last_antispam_update' => array('2000-01-01 00:00:00', 'antispam_last_update'), 'pref_newusers_grp_ID' => array($Group_Users->ID, 'newusers_grp_ID'), 'pref_newusers_level' => array(1, 'newusers_level'), 'pref_newusers_canregister' => array(0, 'newusers_canregister'));
        $_trans = array();
        foreach ($transform as $oldkey => $newarr) {
            $newname = isset($newarr[1]) ? $newarr[1] : $oldkey;
            if (!isset($row[$oldkey])) {
                echo '&nbsp;&middot;Setting ' . $oldkey . ' not found, using defaults.<br />';
                $_trans[$newname] = $newarr[0];
            } else {
                $_trans[$newname] = $row[$oldkey];
            }
        }
        // drop old table
        $DB->query('DROP TABLE IF EXISTS T_settings');
        // create new table
        $DB->query('CREATE TABLE T_settings (
				set_name VARCHAR( 30 ) NOT NULL ,
				set_value VARCHAR( 255 ) NULL ,
				PRIMARY KEY ( set_name )
			)');
        // insert defaults and use transformed settings
        create_default_settings($_trans);
        if (!isset($tableblogusers_isuptodate)) {
            echo 'Upgrading Blog-User permissions table... ';
            $query = "ALTER TABLE T_coll_user_perms\n\t\t\t\t\t\t\t\tADD COLUMN bloguser_ismember tinyint NOT NULL default 0 AFTER bloguser_user_ID";
            $DB->query($query);
            // Any row that is created holds at least one permission,
            // minimum permsission is to be a member, so we add that one too, to all existing rows.
            $DB->query("UPDATE T_coll_user_perms\n\t\t\t\t\t\t\t\t\t\t\tSET bloguser_ismember = 1");
            echo "OK.<br />\n";
        }
        echo 'Upgrading Comments table... ';
        $DB->query('UPDATE T_comments
									  SET comment_date = \'2000-01-01 00:00:00\'
									WHERE comment_date = \'0000-00-00 00:00:00\'');
        $DB->query('ALTER TABLE T_comments
							MODIFY COLUMN comment_date DATETIME NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $query = "ALTER TABLE T_comments\n\t\t\t\t\t\t\tADD COLUMN comment_author_ID int unsigned NULL default NULL AFTER comment_status,\n\t\t\t\t\t\t\tMODIFY COLUMN comment_author varchar(100) NULL,\n\t\t\t\t\t\t\tMODIFY COLUMN comment_author_email varchar(100) NULL,\n\t\t\t\t\t\t\tMODIFY COLUMN comment_author_url varchar(100) NULL,\n\t\t\t\t\t\t\tMODIFY COLUMN comment_author_IP varchar(23) NOT NULL default ''";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Upgrading Users table... ';
        $query = "ALTER TABLE T_users ADD user_locale VARCHAR( 20 ) DEFAULT 'en-EU' NOT NULL AFTER user_yim";
        $DB->query($query);
        echo "OK.<br />\n";
        set_upgrade_checkpoint('8060');
    }
    if ($old_db_version < 8062) {
        // upgrade to 0.9.0.4
        echo "Checking for extra quote escaping in posts... ";
        $query = "SELECT ID, post_title, post_content\n\t\t\t\t\t\t\t\tFROM {$tableprefix}posts\n\t\t\t\t\t\t\t WHERE post_title LIKE '%\\\\\\\\\\'%'\n\t\t\t\t\t\t\t\t\tOR post_title LIKE '%\\\\\\\\\"%'\n\t\t\t\t\t\t\t\t\tOR post_content LIKE '%\\\\\\\\\\'%'\n\t\t\t\t\t\t\t\t\tOR post_content LIKE '%\\\\\\\\\"%' ";
        /* FP: the above looks overkill, but MySQL is really full of surprises...
        			tested on 4.0.14-nt */
        // echo $query;
        $rows = $DB->get_results($query, ARRAY_A);
        if ($DB->num_rows) {
            echo 'Updating ' . $DB->num_rows . ' posts... ';
            foreach ($rows as $row) {
                // echo '<br />'.$row['post_title'];
                $query = "UPDATE {$tableprefix}posts\n\t\t\t\t\t\t\t\t\tSET post_title = " . $DB->quote(stripslashes($row['post_title'])) . ",\n\t\t\t\t\t\t\t\t\t\t\tpost_content = " . $DB->quote(stripslashes($row['post_content'])) . "\n\t\t\t\t\t\t\t\t\tWHERE ID = " . $row['ID'];
                // echo '<br />'.$query;
                $DB->query($query);
            }
        }
        echo "OK.<br />\n";
        set_upgrade_checkpoint('8062');
    }
    if ($old_db_version < 8064) {
        // upgrade to 0.9.0.6
        cleanup_comment_quotes();
        set_upgrade_checkpoint('8064');
    }
    if ($old_db_version < 8066) {
        // upgrade to 0.9.1
        echo 'Adding catpost index... ';
        $DB->query('ALTER TABLE T_postcats ADD UNIQUE catpost ( postcat_cat_ID, postcat_post_ID )');
        echo "OK.<br />\n";
        set_upgrade_checkpoint('8066');
    }
    if ($old_db_version < 8800) {
        // ---------------------------------- upgrade to 1.6 "phoenix ALPHA"
        echo 'Dropping old Hitlog table... ';
        $DB->query('DROP TABLE IF EXISTS T_hitlog');
        echo "OK.<br />\n";
        // New tables:
        echo 'Creating table for active sessions... ';
        $DB->query("CREATE TABLE T_sessions (\n\t\t\t\t\t\t\t\t\t\t\tsess_ID        INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,\n\t\t\t\t\t\t\t\t\t\t\tsess_key       CHAR(32) NULL,\n\t\t\t\t\t\t\t\t\t\t\tsess_lastseen  DATETIME NOT NULL,\n\t\t\t\t\t\t\t\t\t\t\tsess_ipaddress VARCHAR(15) NOT NULL DEFAULT '',\n\t\t\t\t\t\t\t\t\t\t\tsess_user_ID   INT(10) DEFAULT NULL,\n\t\t\t\t\t\t\t\t\t\t\tsess_agnt_ID   INT UNSIGNED NULL,\n\t\t\t\t\t\t\t\t\t\t\tsess_data      TEXT DEFAULT NULL,\n\t\t\t\t\t\t\t\t\t\t\tPRIMARY KEY( sess_ID )\n\t\t\t\t\t\t\t\t\t\t)");
        echo "OK.<br />\n";
        echo 'Creating user settings table... ';
        $DB->query("CREATE TABLE {$tableprefix}usersettings (\n\t\t\t\t\t\t\t\t\t\t\tuset_user_ID INT(11) UNSIGNED NOT NULL,\n\t\t\t\t\t\t\t\t\t\t\tuset_name    VARCHAR( 30 ) NOT NULL,\n\t\t\t\t\t\t\t\t\t\t\tuset_value   VARCHAR( 255 ) NULL,\n\t\t\t\t\t\t\t\t\t\t\tPRIMARY KEY ( uset_user_ID, uset_name )\n\t\t\t\t\t\t\t\t\t\t)");
        echo "OK.<br />\n";
        echo 'Creating plugins table... ';
        $DB->query("CREATE TABLE T_plugins (\n\t\t\t\t\t\t\t\t\t\t\tplug_ID        INT(11) UNSIGNED NOT NULL auto_increment,\n\t\t\t\t\t\t\t\t\t\t\tplug_priority  INT(11) NOT NULL default 50,\n\t\t\t\t\t\t\t\t\t\t\tplug_classname VARCHAR(40) NOT NULL default '',\n\t\t\t\t\t\t\t\t\t\t\tPRIMARY KEY ( plug_ID )\n\t\t\t\t\t\t\t\t\t\t)");
        echo "OK.<br />\n";
        echo 'Creating table for Post Statuses... ';
        $query = "CREATE TABLE {$tableprefix}poststatuses (\n\t\t\t\t\t\t\t\t\t\t\tpst_ID   int(11) unsigned not null AUTO_INCREMENT,\n\t\t\t\t\t\t\t\t\t\t\tpst_name varchar(30)      not null,\n\t\t\t\t\t\t\t\t\t\t\tprimary key ( pst_ID )\n\t\t\t\t\t\t\t\t\t\t)";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Creating table for Post Types... ';
        $query = "CREATE TABLE {$tableprefix}posttypes (\n\t\t\t\t\t\t\t\t\t\t\tptyp_ID   int(11) unsigned not null AUTO_INCREMENT,\n\t\t\t\t\t\t\t\t\t\t\tptyp_name varchar(30)      not null,\n\t\t\t\t\t\t\t\t\t\t\tprimary key (ptyp_ID)\n\t\t\t\t\t\t\t\t\t\t)";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Creating table for File Meta Data... ';
        $DB->query("CREATE TABLE T_files (\n\t\t\t\t\t\t\t\t\t\t file_ID        int(11) unsigned  not null AUTO_INCREMENT,\n\t\t\t\t\t\t\t\t\t\t file_root_type enum('absolute','user','group','collection') not null default 'absolute',\n\t\t\t\t\t\t\t\t\t\t file_root_ID   int(11) unsigned  not null default 0,\n\t\t\t\t\t\t\t\t\t\t file_path      varchar(255)      not null default '',\n\t\t\t\t\t\t\t\t\t\t file_title     varchar(255),\n\t\t\t\t\t\t\t\t\t\t file_alt       varchar(255),\n\t\t\t\t\t\t\t\t\t\t file_desc      text,\n\t\t\t\t\t\t\t\t\t\t primary key (file_ID),\n\t\t\t\t\t\t\t\t\t\t unique file (file_root_type, file_root_ID, file_path)\n\t\t\t\t\t\t\t\t\t)");
        echo "OK.<br />\n";
        echo 'Creating table for base domains... ';
        $DB->query("CREATE TABLE T_basedomains (\n\t\t\t\t\t\t\t\t\t\tdom_ID     INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,\n\t\t\t\t\t\t\t\t\t\tdom_name   VARCHAR(250) NOT NULL DEFAULT '',\n\t\t\t\t\t\t\t\t\t\tdom_status ENUM('unknown','whitelist','blacklist') NOT NULL DEFAULT 'unknown',\n\t\t\t\t\t\t\t\t\t\tdom_type   ENUM('unknown','normal','searcheng','aggregator') NOT NULL DEFAULT 'unknown',\n\t\t\t\t\t\t\t\t\t\tPRIMARY KEY (dom_ID),\n\t\t\t\t\t\t\t\t\t\tUNIQUE dom_name (dom_name)\n\t\t\t\t\t\t\t\t\t)");
        // fp> the unique key was only named in version 1.9. Crap. Put the name back here to save as many souls as possible. bulk has not upgraded from 0.9 yet :/
        echo "OK.<br />\n";
        set_upgrade_checkpoint('8820');
    }
    if ($old_db_version < 8840) {
        echo 'Creating table for user agents... ';
        $DB->query("CREATE TABLE {$tableprefix}useragents (\n\t\t\t\t\t\t\t\t\t\tagnt_ID        INT UNSIGNED NOT NULL AUTO_INCREMENT,\n\t\t\t\t\t\t\t\t\t\tagnt_signature VARCHAR(250) NOT NULL,\n\t\t\t\t\t\t\t\t\t\tagnt_type      ENUM('rss','robot','browser','unknown') DEFAULT 'unknown' NOT NULL,\n\t\t\t\t\t\t\t\t\t\tPRIMARY KEY (agnt_ID) )");
        echo "OK.<br />\n";
        echo 'Creating table for Hit-Logs... ';
        $query = "CREATE TABLE T_hitlog (\n\t\t\t\t\t\t\t\t\thit_ID             INT(11) NOT NULL AUTO_INCREMENT,\n\t\t\t\t\t\t\t\t\thit_sess_ID        INT UNSIGNED,\n\t\t\t\t\t\t\t\t\thit_datetime       DATETIME NOT NULL,\n\t\t\t\t\t\t\t\t\thit_uri            VARCHAR(250) DEFAULT NULL,\n\t\t\t\t\t\t\t\t\thit_referer_type   ENUM('search','blacklist','referer','direct','spam') NOT NULL,\n\t\t\t\t\t\t\t\t\thit_referer        VARCHAR(250) DEFAULT NULL,\n\t\t\t\t\t\t\t\t\thit_referer_dom_ID INT UNSIGNED DEFAULT NULL,\n\t\t\t\t\t\t\t\t\thit_blog_ID        int(11) UNSIGNED NULL DEFAULT NULL,\n\t\t\t\t\t\t\t\t\thit_remote_addr    VARCHAR(40) DEFAULT NULL,\n\t\t\t\t\t\t\t\t\tPRIMARY KEY (hit_ID),\n\t\t\t\t\t\t\t\t\tINDEX hit_datetime ( hit_datetime ),\n\t\t\t\t\t\t\t\t\tINDEX hit_blog_ID (hit_blog_ID)\n\t\t\t\t\t\t\t\t)";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Creating table for subscriptions... ';
        $DB->query("CREATE TABLE T_subscriptions (\n\t\t\t\t\t\t\t\t\t\t sub_coll_ID     int(11) unsigned    not null,\n\t\t\t\t\t\t\t\t\t\t sub_user_ID     int(11) unsigned    not null,\n\t\t\t\t\t\t\t\t\t\t sub_items       tinyint(1)          not null,\n\t\t\t\t\t\t\t\t\t\t sub_comments    tinyint(1)          not null,\n\t\t\t\t\t\t\t\t\t\t primary key (sub_coll_ID, sub_user_ID)\n\t\t\t\t\t\t\t\t\t\t)");
        echo "OK.<br />\n";
        echo 'Creating table for blog-group permissions... ';
        $DB->query("CREATE TABLE T_coll_group_perms (\n\t\t\t\t\t\t\t\t\t\t\tbloggroup_blog_ID int(11) unsigned NOT NULL default 0,\n\t\t\t\t\t\t\t\t\t\t\tbloggroup_group_ID int(11) unsigned NOT NULL default 0,\n\t\t\t\t\t\t\t\t\t\t\tbloggroup_ismember tinyint NOT NULL default 0,\n\t\t\t\t\t\t\t\t\t\t\tbloggroup_perm_poststatuses set('published','deprecated','protected','private','draft') NOT NULL default '',\n\t\t\t\t\t\t\t\t\t\t\tbloggroup_perm_delpost tinyint NOT NULL default 0,\n\t\t\t\t\t\t\t\t\t\t\tbloggroup_perm_comments tinyint NOT NULL default 0,\n\t\t\t\t\t\t\t\t\t\t\tbloggroup_perm_cats tinyint NOT NULL default 0,\n\t\t\t\t\t\t\t\t\t\t\tbloggroup_perm_properties tinyint NOT NULL default 0,\n\t\t\t\t\t\t\t\t\t\t\tbloggroup_perm_media_upload tinyint NOT NULL default 0,\n\t\t\t\t\t\t\t\t\t\t\tbloggroup_perm_media_browse tinyint NOT NULL default 0,\n\t\t\t\t\t\t\t\t\t\t\tbloggroup_perm_media_change tinyint NOT NULL default 0,\n\t\t\t\t\t\t\t\t\t\t\tPRIMARY KEY bloggroup_pk (bloggroup_blog_ID,bloggroup_group_ID) )");
        echo "OK.<br />\n";
        echo 'Upgrading blogs table... ';
        $query = "ALTER TABLE T_blogs\n\t\t\t\t\t\t\tMODIFY COLUMN blog_ID int(11) unsigned NOT NULL auto_increment,\n\t\t\t\t\t\t\tMODIFY COLUMN blog_links_blog_ID INT(11) NULL DEFAULT NULL,\n\t\t\t\t\t\t\tCHANGE COLUMN blog_stub blog_urlname VARCHAR(255) NOT NULL DEFAULT 'urlname',\n\t\t\t\t\t\t\tADD COLUMN blog_allowcomments VARCHAR(20) NOT NULL default 'post_by_post' AFTER blog_keywords,\n\t\t\t\t\t\t\tADD COLUMN blog_allowblogcss TINYINT(1) NOT NULL default 1 AFTER blog_allowpingbacks,\n\t\t\t\t\t\t\tADD COLUMN blog_allowusercss TINYINT(1) NOT NULL default 1 AFTER blog_allowblogcss,\n\t\t\t\t\t\t\tADD COLUMN blog_stub VARCHAR(255) NOT NULL DEFAULT 'stub' AFTER blog_staticfilename,\n\t\t\t\t\t\t\tADD COLUMN blog_commentsexpire INT(4) NOT NULL DEFAULT 0 AFTER blog_links_blog_ID,\n\t\t\t\t\t\t\tADD COLUMN blog_media_location ENUM( 'default', 'subdir', 'custom', 'none' ) DEFAULT 'default' NOT NULL AFTER blog_commentsexpire,\n\t\t\t\t\t\t\tADD COLUMN blog_media_subdir VARCHAR( 255 ) NOT NULL AFTER blog_media_location,\n\t\t\t\t\t\t\tADD COLUMN blog_media_fullpath VARCHAR( 255 ) NOT NULL AFTER blog_media_subdir,\n\t\t\t\t\t\t\tADD COLUMN blog_media_url VARCHAR(255) NOT NULL AFTER blog_media_fullpath";
        $DB->query($query);
        $query = "ALTER TABLE T_blogs\n\t\t\t\t\t\t\tADD UNIQUE blog_urlname ( blog_urlname )";
        $DB->query($query);
        $query = "ALTER TABLE T_blogs\n\t\t\t\t\t\t\tDROP INDEX blog_stub";
        $DB->query($query);
        echo "OK.<br />\n";
        set_upgrade_checkpoint('8840');
    }
    // sam2kb>fp: We need to make sure there are no values like "blog_a.php" in blog_urlname,
    //			after this upgrade blog URLs look like $baseurl.'blog_a.php' which might be OK in 0.x version,
    //			but this config will not work in b2evo 4. Blog URLs will be broken!
    if ($old_db_version < 8850) {
        echo 'Updating relative URLs... ';
        // We need to move the slashes to the end:
        $query = "UPDATE T_blogs\n\t\t\t\t\t\t\t\t SET blog_siteurl = CONCAT( SUBSTRING(blog_siteurl,2) , '/' )\n\t\t\t\t\t\t\t WHERE blog_siteurl LIKE '/%'";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Copying urlnames to stub names... ';
        $query = 'UPDATE T_blogs
							SET blog_stub = blog_urlname';
        $DB->query($query);
        echo "OK.<br />\n";
        set_upgrade_checkpoint('8850');
    }
    if ($old_db_version < 8855) {
        echo 'Upgrading posts table... ';
        $query = "ALTER TABLE {$tableprefix}posts\n\t\t\t\t\t\t\tDROP INDEX post_author,\n\t\t\t\t\t\t\tDROP INDEX post_issue_date,\n\t\t\t\t\t\t\tDROP INDEX post_category";
        $DB->query($query);
        $query = "ALTER TABLE {$tableprefix}posts\n\t\t\t\t\t\t\tDROP COLUMN post_karma,\n\t\t\t\t\t\t\tDROP COLUMN post_autobr,\n\t\t\t\t\t\t\tCHANGE COLUMN ID post_ID int(11) unsigned NOT NULL auto_increment,\n\t\t\t\t\t\t\tCHANGE COLUMN post_author\tpost_creator_user_ID int(11) unsigned NOT NULL,\n\t\t\t\t\t\t\tCHANGE COLUMN post_issue_date\tpost_datestart datetime NOT NULL,\n\t\t\t\t\t\t\tCHANGE COLUMN post_mod_date\tpost_datemodified datetime NOT NULL,\n\t\t\t\t\t\t\tCHANGE COLUMN post_category post_main_cat_ID int(11) unsigned NOT NULL,\n\t\t\t\t\t\t\tADD post_parent_ID\t\t\t\tint(11) unsigned NULL AFTER post_ID,\n\t\t\t\t\t\t\tADD post_lastedit_user_ID\tint(11) unsigned NULL AFTER post_creator_user_ID,\n\t\t\t\t\t\t\tADD post_assigned_user_ID\tint(11) unsigned NULL AFTER post_lastedit_user_ID,\n\t\t\t\t\t\t\tADD post_datedeadline \t\tdatetime NULL AFTER post_datestart,\n\t\t\t\t\t\t\tADD post_datecreated\t\t\tdatetime NULL AFTER post_datedeadline,\n\t\t\t\t\t\t\tADD post_pst_ID\t\t\t\t\t\tint(11) unsigned NULL AFTER post_status,\n\t\t\t\t\t\t\tADD post_ptyp_ID\t\t\t\t\tint(11) unsigned NULL AFTER post_pst_ID,\n\t\t\t\t\t\t\tADD post_views\t\t\t\t\t\tint(11) unsigned NOT NULL DEFAULT 0 AFTER post_flags,\n\t\t\t\t\t\t\tADD post_commentsexpire\t\tdatetime DEFAULT NULL AFTER post_comments,\n\t\t\t\t\t\t\tADD post_priority\t\t\t\t\tint(11) unsigned null";
        $DB->query($query);
        $query = "ALTER TABLE {$tableprefix}posts\n\t\t\t\t\t\t\tADD INDEX post_creator_user_ID( post_creator_user_ID ),\n\t\t\t\t\t\t\tADD INDEX post_parent_ID( post_parent_ID ),\n\t\t\t\t\t\t\tADD INDEX post_assigned_user_ID( post_assigned_user_ID ),\n\t\t\t\t\t\t\tADD INDEX post_datestart( post_datestart ),\n\t\t\t\t\t\t\tADD INDEX post_main_cat_ID( post_main_cat_ID ),\n\t\t\t\t\t\t\tADD INDEX post_ptyp_ID( post_ptyp_ID ),\n\t\t\t\t\t\t\tADD INDEX post_pst_ID( post_pst_ID ) ";
        $DB->query($query);
        echo "OK.<br />\n";
        set_upgrade_checkpoint('8855');
    }
    if ($old_db_version < 8860) {
        echo 'Updating post data... ';
        $query = "UPDATE {$tableprefix}posts\n\t\t\t\t\t\t\tSET post_lastedit_user_ID = post_creator_user_ID,\n\t\t\t\t\t\t\t\t\tpost_datecreated = post_datestart";
        $DB->query($query);
        echo "OK.<br />\n";
        task_begin('Upgrading users table... ');
        $DB->query('UPDATE T_users
									  SET dateYMDhour = \'2000-01-01 00:00:00\'
									WHERE dateYMDhour = \'0000-00-00 00:00:00\'');
        $DB->query('ALTER TABLE T_users
							MODIFY COLUMN dateYMDhour DATETIME NOT NULL DEFAULT \'2000-01-01 00:00:00\',
							CHANGE COLUMN ID user_ID int(11) unsigned NOT NULL auto_increment,
							MODIFY COLUMN user_icq int(11) unsigned DEFAULT 0 NOT NULL,
							ADD COLUMN user_showonline tinyint(1) NOT NULL default 1 AFTER user_notify');
        task_end();
        set_upgrade_checkpoint('8860');
    }
    if ($old_db_version < 8900) {
        echo 'Setting new defaults... ';
        $query = 'INSERT INTO T_settings (set_name, set_value)
							VALUES
								( "reloadpage_timeout", "300" ),
								( "upload_enabled", "' . (isset($use_fileupload) ? (int) $use_fileupload : '1') . '" ),
								( "upload_allowedext", "' . (isset($fileupload_allowedtypes) ? $fileupload_allowedtypes : 'jpg gif png') . '" ),
								( "upload_maxkb", "' . (isset($fileupload_maxk) ? (int) $fileupload_maxk : '96') . '" )
							';
        $DB->query($query);
        // Replace "paged" mode with "posts" // note: moved to blogsettings in 2.0
        $DB->query('UPDATE T_settings
										SET set_value = "posts"
									WHERE set_name = "what_to_show"
									  AND set_value = "paged"');
        echo "OK.<br />\n";
        if (!isset($tableblogusers_isuptodate)) {
            // We have created the blogusers table before and it's already clean!
            echo 'Altering table for Blog-User permissions... ';
            $DB->query('ALTER TABLE T_coll_user_perms
										MODIFY COLUMN bloguser_blog_ID int(11) unsigned NOT NULL default 0,
										MODIFY COLUMN bloguser_user_ID int(11) unsigned NOT NULL default 0,
										ADD COLUMN bloguser_perm_media_upload tinyint NOT NULL default 0,
										ADD COLUMN bloguser_perm_media_browse tinyint NOT NULL default 0,
										ADD COLUMN bloguser_perm_media_change tinyint NOT NULL default 0');
            echo "OK.<br />\n";
        }
        task_begin('Altering comments table...');
        $DB->query('UPDATE T_comments
									  SET comment_date = \'2000-01-01 00:00:00\'
									WHERE comment_date = \'0000-00-00 00:00:00\'');
        $DB->query('ALTER TABLE T_comments
									MODIFY COLUMN comment_date DATETIME NOT NULL DEFAULT \'2000-01-01 00:00:00\',
									MODIFY COLUMN comment_post_ID		int(11) unsigned NOT NULL default 0');
        task_end();
        set_upgrade_checkpoint('8900');
    }
    if ($old_db_version < 9000) {
        echo 'Altering Posts to Categories table... ';
        $DB->query("ALTER TABLE T_postcats\n\t\t\t\t\t\t\t\t\tMODIFY COLUMN postcat_post_ID int(11) unsigned NOT NULL,\n\t\t\t\t\t\t\t\t\tMODIFY COLUMN postcat_cat_ID int(11) unsigned NOT NULL");
        echo "OK.<br />\n";
        echo 'Altering Categories table... ';
        $DB->query("ALTER TABLE T_categories\n\t\t\t\t\t\t\t\t\tMODIFY COLUMN cat_ID int(11) unsigned NOT NULL auto_increment,\n\t\t\t\t\t\t\t\t\tMODIFY COLUMN cat_parent_ID int(11) unsigned NULL,\n\t\t\t\t\t\t\t\t\tMODIFY COLUMN cat_blog_ID int(11) unsigned NOT NULL default 2");
        echo "OK.<br />\n";
        echo 'Altering Locales table... ';
        $DB->query('ALTER TABLE T_locales
									ADD loc_startofweek TINYINT UNSIGNED NOT NULL DEFAULT 1 AFTER loc_timefmt');
        echo "OK.<br />\n";
        if (!isset($tablegroups_isuptodate)) {
            // We have created the groups table before and it's already clean!
            echo 'Altering Groups table... ';
            $DB->query("ALTER TABLE T_groups\n\t\t\t\t\t\t\t\t\t\tADD COLUMN grp_perm_admin enum('none','hidden','visible') NOT NULL default 'visible' AFTER grp_name,\n\t\t\t\t\t\t\t\t\t\tADD COLUMN grp_perm_files enum('none','view','add','edit') NOT NULL default 'none'");
            echo "OK.<br />\n";
        }
        echo 'Creating table for Post Links... ';
        $DB->query("CREATE TABLE T_links (\n\t\t\t\t\t\t\t\t\tlink_ID               int(11) unsigned  not null AUTO_INCREMENT,\n\t\t\t\t\t\t\t\t\tlink_datecreated      datetime          not null,\n\t\t\t\t\t\t\t\t\tlink_datemodified     datetime          not null,\n\t\t\t\t\t\t\t\t\tlink_creator_user_ID  int(11) unsigned  not null,\n\t\t\t\t\t\t\t\t\tlink_lastedit_user_ID int(11) unsigned  not null,\n\t\t\t\t\t\t\t\t\tlink_item_ID          int(11) unsigned  NOT NULL,\n\t\t\t\t\t\t\t\t\tlink_dest_item_ID     int(11) unsigned  NULL,\n\t\t\t\t\t\t\t\t\tlink_file_ID          int(11) unsigned  NULL,\n\t\t\t\t\t\t\t\t\tlink_ltype_ID         int(11) unsigned  NOT NULL default 1,\n\t\t\t\t\t\t\t\t\tlink_external_url     VARCHAR(255)      NULL,\n\t\t\t\t\t\t\t\t\tlink_title            TEXT              NULL,\n\t\t\t\t\t\t\t\t\tPRIMARY KEY (link_ID),\n\t\t\t\t\t\t\t\t\tINDEX link_item_ID( link_item_ID ),\n\t\t\t\t\t\t\t\t\tINDEX link_dest_item_ID (link_dest_item_ID),\n\t\t\t\t\t\t\t\t\tINDEX link_file_ID (link_file_ID)\n\t\t\t\t\t\t\t\t)");
        echo "OK.<br />\n";
        echo 'Creating default Post Types... ';
        $DB->query("\n\t\t\tINSERT INTO {$tableprefix}posttypes ( ptyp_ID, ptyp_name )\n\t\t\tVALUES ( 1, 'Post' ),\n\t\t\t       ( 2, 'Link' )");
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9000');
    }
    if ($old_db_version < 9100) {
        // 1.8 ALPHA
        echo 'Creating table for plugin events... ';
        $DB->query('
			CREATE TABLE T_pluginevents(
					pevt_plug_ID INT(11) UNSIGNED NOT NULL,
					pevt_event VARCHAR(40) NOT NULL,
					pevt_enabled TINYINT NOT NULL DEFAULT 1,
					PRIMARY KEY( pevt_plug_ID, pevt_event )
				)');
        echo "OK.<br />\n";
        echo 'Altering Links table... ';
        $DB->query('ALTER TABLE T_links
		             CHANGE link_item_ID link_itm_ID INT( 11 ) UNSIGNED NOT NULL,
		             CHANGE link_dest_item_ID link_dest_itm_ID INT( 11 ) UNSIGNED NULL');
        echo "OK.<br />\n";
        if ($old_db_version >= 9000) {
            // sess_agnt_ID used in Phoenix-Alpha
            echo 'Altering sessions table... ';
            $query = "\n\t\t\t\t\tALTER TABLE T_sessions\n\t\t\t\t\t DROP COLUMN sess_agnt_ID";
            $DB->query($query);
            echo "OK.<br />\n";
        }
        echo 'Creating table for file types... ';
        $DB->query('
				CREATE TABLE T_filetypes (
					ftyp_ID int(11) unsigned NOT NULL auto_increment,
					ftyp_extensions varchar(30) NOT NULL,
					ftyp_name varchar(30) NOT NULL,
					ftyp_mimetype varchar(50) NOT NULL,
					ftyp_icon varchar(20) default NULL,
					ftyp_viewtype varchar(10) NOT NULL,
					ftyp_allowed tinyint(1) NOT NULL default 0,
					PRIMARY KEY (ftyp_ID)
				)');
        echo "OK.<br />\n";
        echo 'Creating default file types... ';
        $DB->query("INSERT INTO T_filetypes\n\t\t\t\t(ftyp_ID, ftyp_extensions, ftyp_name, ftyp_mimetype, ftyp_icon, ftyp_viewtype, ftyp_allowed)\n\t\t\tVALUES\n\t\t\t\t(1, 'gif', 'GIF image', 'image/gif', 'image2.png', 'image', 1),\n\t\t\t\t(2, 'png', 'PNG image', 'image/png', 'image2.png', 'image', 1),\n\t\t\t\t(3, 'jpg jpeg', 'JPEG image', 'image/jpeg', 'image2.png', 'image', 1),\n\t\t\t\t(4, 'txt', 'Text file', 'text/plain', 'document.png', 'text', 1),\n\t\t\t\t(5, 'htm html', 'HTML file', 'text/html', 'html.png', 'browser', 0),\n\t\t\t\t(6, 'pdf', 'PDF file', 'application/pdf', 'pdf.png', 'browser', 1),\n\t\t\t\t(7, 'doc', 'Microsoft Word file', 'application/msword', 'doc.gif', 'external', 1),\n\t\t\t\t(8, 'xls', 'Microsoft Excel file', 'application/vnd.ms-excel', 'xls.gif', 'external', 1),\n\t\t\t\t(9, 'ppt', 'Powerpoint', 'application/vnd.ms-powerpoint', 'ppt.gif', 'external', 1),\n\t\t\t\t(10, 'pps', 'Slideshow', 'pps', 'pps.gif', 'external', 1),\n\t\t\t\t(11, 'zip', 'ZIP archive', 'application/zip', 'zip.gif', 'external', 1),\n\t\t\t\t(12, 'php php3 php4 php5 php6', 'PHP script', 'application/x-httpd-php', 'php.gif', 'text', 0),\n\t\t\t\t(13, 'css', 'Style sheet', 'text/css', '', 'text', 1)\n\t\t\t");
        echo "OK.<br />\n";
        echo 'Giving Administrator Group edit perms on files... ';
        $DB->query('UPDATE T_groups
		             SET grp_perm_files = "edit"
		             WHERE grp_ID = 1');
        // Later versions give 'all' on install, but we won't upgrade to that for security.
        echo "OK.<br />\n";
        echo 'Giving Administrator Group full perms on media for all blogs... ';
        $DB->query('UPDATE T_coll_group_perms
		             SET bloggroup_perm_media_upload = 1,
		                 bloggroup_perm_media_browse = 1,
		                 bloggroup_perm_media_change = 1
		             WHERE bloggroup_group_ID = 1');
        echo "OK.<br />\n";
        if ($old_db_version >= 9000) {
            // Uninstall all ALPHA (potentially incompatible) plugins
            echo 'Uninstalling all existing plugins... ';
            $DB->query('DELETE FROM T_plugins WHERE 1=1');
            echo "OK.<br />\n";
        }
        // NOTE: basic plugins get installed separatly for upgrade and install..
        set_upgrade_checkpoint('9100');
    }
    if ($old_db_version < 9190) {
        // 1.8 ALPHA (block #2)
        echo 'Altering Posts table... ';
        $DB->query("ALTER TABLE {$tableprefix}posts\n\t\t             CHANGE post_comments post_comment_status ENUM('disabled', 'open', 'closed') NOT NULL DEFAULT 'open'");
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9190');
    }
    if ($old_db_version < 9192) {
        // 1.8 ALPHA (block #3) - The payload that db_delta() handled before
        // This is a fix, which broke upgrade to 1.8 (from 1.6) in MySQL strict mode (inserted after 1.8 got released!):
        if ($DB->get_row('SHOW COLUMNS FROM T_hitlog LIKE "hit_referer_type"')) {
            // a niiiiiiiice extra check :p
            task_begin('Deleting all "spam" hitlog entries... ');
            $DB->query('
					DELETE FROM T_hitlog
					 WHERE hit_referer_type = "spam"');
            task_end();
        }
        task_begin('Upgrading users table... ');
        $DB->query('ALTER TABLE T_users
										CHANGE COLUMN user_firstname user_firstname varchar(50) NULL,
										CHANGE COLUMN user_lastname user_lastname varchar(50) NULL,
										CHANGE COLUMN user_nickname user_nickname varchar(50) NULL,
										CHANGE COLUMN user_icq user_icq int(11) unsigned NULL,
										CHANGE COLUMN user_email user_email varchar(255) NOT NULL,
										CHANGE COLUMN user_url user_url varchar(255) NULL,
										CHANGE COLUMN user_ip user_ip varchar(15) NULL,
										CHANGE COLUMN user_domain user_domain varchar(200) NULL,
										CHANGE COLUMN user_browser user_browser varchar(200) NULL,
										CHANGE COLUMN user_aim user_aim varchar(50) NULL,
										CHANGE COLUMN user_msn user_msn varchar(100) NULL,
										CHANGE COLUMN user_yim user_yim varchar(50) NULL,
										ADD COLUMN user_allow_msgform TINYINT NOT NULL DEFAULT \'1\' AFTER user_idmode,
										ADD COLUMN user_validated TINYINT(1) NOT NULL DEFAULT 0 AFTER user_grp_ID');
        task_end();
        task_begin('Creating blog settings...');
        $DB->query('CREATE TABLE T_coll_settings (
															cset_coll_ID INT(11) UNSIGNED NOT NULL,
															cset_name    VARCHAR( 30 ) NOT NULL,
															cset_value   VARCHAR( 255 ) NULL,
															PRIMARY KEY ( cset_coll_ID, cset_name )
											)');
        task_end();
        set_upgrade_checkpoint('9192');
    }
    if ($old_db_version < 9195) {
        task_begin('Upgrading posts table... ');
        $DB->query('ALTER TABLE ' . $tableprefix . 'posts
										CHANGE COLUMN post_content post_content         text NULL,
										CHANGE COLUMN post_url post_url              		VARCHAR(255) NULL DEFAULT NULL,
										CHANGE COLUMN post_renderers post_renderers     TEXT NOT NULL');
        task_end();
        task_begin('Upgrading comments table... ');
        $DB->query('ALTER TABLE T_comments
										CHANGE COLUMN comment_author_email comment_author_email varchar(255) NULL,
										CHANGE COLUMN comment_author_url comment_author_url varchar(255) NULL,
										ADD COLUMN comment_spam_karma TINYINT NULL AFTER comment_karma,
										ADD COLUMN comment_allow_msgform TINYINT NOT NULL DEFAULT 0 AFTER comment_spam_karma');
        task_end();
        set_upgrade_checkpoint('9195');
    }
    if ($old_db_version < 9200) {
        task_begin('Upgrading hitlog table... ');
        $DB->query('ALTER TABLE T_hitlog
										CHANGE COLUMN hit_referer_type hit_referer_type   ENUM(\'search\',\'blacklist\',\'referer\',\'direct\') NOT NULL,
										ADD COLUMN hit_agnt_ID        INT UNSIGNED NULL AFTER hit_remote_addr');
        task_end();
        task_begin('Upgrading post links table... ');
        $DB->query('ALTER TABLE T_links
										ADD INDEX link_itm_ID( link_itm_ID ),
										ADD INDEX link_dest_itm_ID (link_dest_itm_ID)');
        task_end();
        task_begin('Upgrading plugins table... ');
        $DB->query('ALTER TABLE T_plugins
										CHANGE COLUMN plug_priority plug_priority        TINYINT NOT NULL default 50,
										ADD COLUMN plug_code            VARCHAR(32) NULL AFTER plug_classname,
										ADD COLUMN plug_apply_rendering ENUM( \'stealth\', \'always\', \'opt-out\', \'opt-in\', \'lazy\', \'never\' ) NOT NULL DEFAULT \'never\' AFTER plug_code,
										ADD COLUMN plug_version         VARCHAR(42) NOT NULL default \'0\' AFTER plug_apply_rendering,
										ADD COLUMN plug_status          ENUM( \'enabled\', \'disabled\', \'needs_config\', \'broken\' ) NOT NULL AFTER plug_version,
										ADD COLUMN plug_spam_weight     TINYINT UNSIGNED NOT NULL DEFAULT 1 AFTER plug_status');
        $DB->query('ALTER TABLE T_plugins
										ADD UNIQUE plug_code( plug_code ),
										ADD INDEX plug_status( plug_status )');
        task_end();
        task_begin('Creating plugin settings table... ');
        $DB->query('CREATE TABLE T_pluginsettings (
															pset_plug_ID INT(11) UNSIGNED NOT NULL,
															pset_name VARCHAR( 30 ) NOT NULL,
															pset_value TEXT NULL,
															PRIMARY KEY ( pset_plug_ID, pset_name )
											)');
        task_end();
        task_begin('Creating plugin user settings table... ');
        $DB->query('CREATE TABLE T_pluginusersettings (
															puset_plug_ID INT(11) UNSIGNED NOT NULL,
															puset_user_ID INT(11) UNSIGNED NOT NULL,
															puset_name VARCHAR( 30 ) NOT NULL,
															puset_value TEXT NULL,
															PRIMARY KEY ( puset_plug_ID, puset_user_ID, puset_name )
											)');
        task_end();
        task_begin('Creating scheduled tasks table... ');
        $DB->query('CREATE TABLE T_cron__task(
												 ctsk_ID              int(10) unsigned      not null AUTO_INCREMENT,
												 ctsk_start_datetime  datetime              not null,
												 ctsk_repeat_after    int(10) unsigned,
												 ctsk_name            varchar(50)           not null,
												 ctsk_controller      varchar(50)           not null,
												 ctsk_params          text,
												 primary key (ctsk_ID)
											)');
        task_end();
        task_begin('Creating cron log table... ');
        $DB->query('CREATE TABLE T_cron__log(
															 clog_ctsk_ID              int(10) unsigned   not null,
															 clog_realstart_datetime   datetime           not null,
															 clog_realstop_datetime    datetime,
															 clog_status               enum(\'started\',\'finished\',\'error\',\'timeout\') not null default \'started\',
															 clog_messages             text,
															 primary key (clog_ctsk_ID)
											)');
        task_end();
        task_begin('Upgrading blogs table... ');
        // blog_allowpingbacks is "DEFAULT 1" in the 0.9.0.11 dump.. - changed in 0.9.2?!
        $DB->query('ALTER TABLE T_blogs
										ALTER COLUMN blog_allowpingbacks SET DEFAULT 0,
    								CHANGE COLUMN blog_media_subdir blog_media_subdir VARCHAR( 255 ) NULL,
										CHANGE COLUMN blog_media_fullpath blog_media_fullpath VARCHAR( 255 ) NULL,
										CHANGE COLUMN blog_media_url blog_media_url VARCHAR( 255 ) NULL');
        task_end();
        set_upgrade_checkpoint('9200');
        // at 1.8 "Summer Beta" release
    }
    // ____________________________ 1.9: ____________________________
    if ($old_db_version < 9290) {
        echo 'Post-fix hit_referer_type == NULL... ';
        // If you've upgraded from 1.6 to 1.8 and it did not break because of strict mode, there are now NULL values for what "spam" was:
        $DB->query('
					DELETE FROM T_hitlog
					 WHERE hit_referer_type IS NULL');
        echo "OK.<br />\n";
        echo 'Marking administrator accounts as validated... ';
        $DB->query('
				UPDATE T_users
				   SET user_validated = 1
				 WHERE user_grp_ID = 1');
        echo "OK.<br />\n";
        echo 'Converting auto_prune_stats setting... ';
        $old_auto_prune_stats = $DB->get_var('
				SELECT set_value
				  FROM T_settings
				 WHERE set_name = "auto_prune_stats"');
        if (!is_null($old_auto_prune_stats) && $old_auto_prune_stats < 1) {
            // This means it has been disabled before, so set auto_prune_stats_mode to "off"!
            $DB->query('
					REPLACE INTO T_settings ( set_name, set_value )
					 VALUES ( "auto_prune_stats_mode", "off" )');
        }
        echo "OK.<br />\n";
        echo 'Converting time_difference from hours to seconds... ';
        $DB->query('UPDATE T_settings SET set_value = set_value*3600 WHERE set_name = "time_difference"');
        echo "OK.<br />\n";
        echo 'Updating hitlog capabilities... ';
        $DB->query('
				ALTER TABLE ' . $tableprefix . 'useragents ADD INDEX agnt_type ( agnt_type )');
        $DB->query('
				ALTER TABLE T_hitlog
				  CHANGE COLUMN hit_referer_type hit_referer_type ENUM(\'search\',\'blacklist\',\'referer\',\'direct\',\'self\',\'admin\') NOT NULL');
        echo "OK.<br />\n";
        echo 'Updating plugin capabilities... ';
        $DB->query('
				ALTER TABLE T_plugins
					MODIFY COLUMN plug_status ENUM( \'enabled\', \'disabled\', \'needs_config\', \'broken\' ) NOT NULL');
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9290');
    }
    if ($old_db_version < 9300) {
        // This can be so long, it needs its own checkpoint protected block in case of failure
        echo 'Updating hitlog indexes... ';
        $DB->query('
				ALTER TABLE T_hitlog
				  ADD INDEX hit_agnt_ID        ( hit_agnt_ID ),
				  ADD INDEX hit_uri            ( hit_uri ),
				  ADD INDEX hit_referer_dom_ID ( hit_referer_dom_ID )
				');
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9300');
    }
    if ($old_db_version < 9310) {
        echo 'Updating basedomains... ';
        $DB->query('
				UPDATE T_basedomains
				   SET dom_status = "unknown"');
        // someone has filled this up with junk blacklists before
        $DB->query('
				ALTER TABLE T_basedomains  ADD INDEX dom_type (dom_type)');
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9310');
    }
    if ($old_db_version < 9315) {
        echo 'Altering locales table... ';
        $DB->query("ALTER TABLE T_locales CHANGE COLUMN loc_datefmt loc_datefmt varchar(20) NOT NULL default 'y-m-d'");
        $DB->query("ALTER TABLE T_locales CHANGE COLUMN loc_timefmt loc_timefmt varchar(20) NOT NULL default 'H:i:s'");
        echo "OK.<br />\n";
        echo 'Creating item prerendering cache table... ';
        $DB->query("\n\t\t\t\tCREATE TABLE {$tableprefix}item__prerendering(\n\t\t\t\t\titpr_itm_ID                   INT(11) UNSIGNED NOT NULL,\n\t\t\t\t\titpr_format                   ENUM('htmlbody', 'entityencoded', 'xml', 'text') NOT NULL,\n\t\t\t\t\titpr_renderers                TEXT NOT NULL,\n\t\t\t\t\titpr_content_prerendered      TEXT NULL,\n\t\t\t\t\titpr_datemodified             TIMESTAMP NOT NULL,\n\t\t\t\t\tPRIMARY KEY (itpr_itm_ID, itpr_format)\n\t\t\t\t)");
        echo "OK.<br />\n";
        echo 'Altering plugins table... ';
        $DB->query("ALTER TABLE T_plugins ADD COLUMN plug_name            VARCHAR(255) NULL default NULL AFTER plug_version");
        $DB->query("ALTER TABLE T_plugins ADD COLUMN plug_shortdesc       VARCHAR(255) NULL default NULL AFTER plug_name");
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9315');
    }
    if ($old_db_version < 9320) {
        // Dropping hit_datetime because it's very slow on INSERT (dh)
        // This can be so long, it needs its own checkpoint protected block in case of failure
        if (db_index_exists('T_hitlog', 'hit_datetime')) {
            // only drop, if it still exists (may have been removed manually)
            echo 'Updating hitlog indexes... ';
            $DB->query('
					ALTER TABLE T_hitlog
						DROP INDEX hit_datetime
					');
            echo "OK.<br />\n";
        }
        set_upgrade_checkpoint('9320');
    }
    if ($old_db_version < 9326) {
        echo 'Removing obsolete settings... ';
        $DB->query('DELETE FROM T_settings WHERE set_name = "upload_allowedext"');
        echo "OK.<br />\n";
        echo 'Updating blogs... ';
        db_drop_col('T_blogs', 'blog_allowpingbacks');
        // Remove and transform obsolete fields blog_pingb2evonet, blog_pingtechnorati, blog_pingweblogs, blog_pingblodotgs
        if (db_cols_exist('T_blogs', array('blog_pingb2evonet', 'blog_pingtechnorati', 'blog_pingweblogs', 'blog_pingblodotgs'))) {
            foreach ($DB->get_results('
					SELECT blog_ID, blog_pingb2evonet, blog_pingtechnorati, blog_pingweblogs, blog_pingblodotgs
						FROM T_blogs') as $row) {
                $ping_plugins = $DB->get_var('SELECT cset_value FROM T_coll_settings WHERE cset_coll_ID = ' . $row->blog_ID . ' AND cset_name = "ping_plugins"');
                $ping_plugins = explode(',', $ping_plugins);
                if ($row->blog_pingb2evonet) {
                    $ping_plugins[] = 'ping_b2evonet';
                }
                if ($row->blog_pingtechnorati || $row->blog_pingweblogs || $row->blog_pingblodotgs) {
                    // if either one of the previous pingers was enabled, add ping-o-matic:
                    $ping_plugins[] = 'ping_pingomatic';
                }
                // Insert transformed/generated ping plugins collection setting:
                $ping_plugins = array_unique($ping_plugins);
                $DB->query('REPLACE INTO T_coll_settings
						( cset_coll_ID, cset_name, cset_value )
						VALUES ( ' . $row->blog_ID . ', "ping_plugins", "' . implode(',', $ping_plugins) . '" )');
            }
            $DB->query('ALTER TABLE T_blogs
					DROP COLUMN blog_pingb2evonet,
					DROP COLUMN blog_pingtechnorati,
					DROP COLUMN blog_pingweblogs,
					DROP COLUMN blog_pingblodotgs');
        }
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9326');
    }
    if ($old_db_version < 9328) {
        echo 'Updating posts... ';
        db_add_col("{$tableprefix}posts", 'post_notifications_status', 'ENUM("noreq","todo","started","finished") NOT NULL DEFAULT "noreq" AFTER post_flags');
        db_add_col("{$tableprefix}posts", 'post_notifications_ctsk_ID', 'INT(10) unsigned NULL DEFAULT NULL AFTER post_notifications_status');
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9328');
    }
    if ($old_db_version < 9330) {
        if (db_col_exists("{$tableprefix}posts", 'post_flags')) {
            echo 'Updating post notifications... ';
            $DB->query("\n\t\t\t\tUPDATE {$tableprefix}posts\n\t\t\t\t\t SET post_notifications_status = 'finished'\n\t\t\t\t WHERE post_flags LIKE '%pingsdone%'");
            db_drop_col("{$tableprefix}posts", 'post_flags');
            echo "OK.<br />\n";
        }
        set_upgrade_checkpoint('9330');
    }
    if ($old_db_version < 9340) {
        echo 'Removing duplicate post link indexes... ';
        if (db_index_exists('T_links', 'link_item_ID')) {
            // only drop, if it still exists (may have been removed manually)
            $DB->query('
					ALTER TABLE T_links
						DROP INDEX link_item_ID
					');
        }
        if (db_index_exists('T_links', 'link_dest_item_ID')) {
            // only drop, if it still exists (may have been removed manually)
            $DB->query('
					ALTER TABLE T_links
						DROP INDEX link_dest_item_ID
					');
        }
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9340');
    }
    // ____________________________ 1.10: ____________________________
    if ($old_db_version < 9345) {
        echo 'Updating post table... ';
        $DB->query("ALTER TABLE {$tableprefix}posts CHANGE COLUMN post_content post_content MEDIUMTEXT NULL");
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9345');
    }
    if ($old_db_version < 9346) {
        echo 'Updating prerendering table... ';
        $DB->query("ALTER TABLE {$tableprefix}item__prerendering CHANGE COLUMN itpr_content_prerendered itpr_content_prerendered MEDIUMTEXT NULL");
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9346');
    }
    if ($old_db_version < 9348) {
        echo 'Updating sessions table... ';
        $DB->query('ALTER TABLE T_sessions CHANGE COLUMN sess_data sess_data MEDIUMBLOB DEFAULT NULL');
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9348');
    }
    if ($old_db_version < 9350) {
        echo 'Updating hitlog table... ';
        $DB->query('ALTER TABLE T_hitlog CHANGE COLUMN hit_referer_type hit_referer_type   ENUM(\'search\',\'blacklist\',\'spam\',\'referer\',\'direct\',\'self\',\'admin\') NOT NULL');
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9350');
    }
    // TODO: "If a user has permission to edit a blog, he should be able to put files in the media folder for that blog." - see http://forums.b2evolution.net/viewtopic.php?p=36417#36417
    /*
    // blueyed>> I've came up with the following, but it's too generic IMHO
    if( $old_db_version < 9300 )
    {
    	echo 'Setting automatic media perms on blogs (members can upload)... ';
    	$users = $DB->query( '
    			UPDATE T_users
    			   SET bloguser_perm_media_upload = 1
    			 WHERE bloguser_ismember = 1' );
    	echo "OK.<br />\n";
    }
    */
    // ____________________________ 2.0: ____________________________
    if ($old_db_version < 9406) {
        echo 'Updating chapter url names... ';
        $DB->query('
			ALTER TABLE T_categories
				ADD COLUMN cat_urlname VARCHAR(255) NOT NULL');
        // Create cat_urlname from cat_name:
        // TODO: Also use it for cafelog upgrade.
        load_funcs('locales/_charset.funcs.php');
        foreach ($DB->get_results('SELECT cat_ID, cat_name FROM T_categories') as $cat) {
            $cat_name = trim($cat->cat_name);
            if (strlen($cat_name)) {
                // TODO: dh> pass locale (useful for transliteration). From main blog?
                $cat_urlname = urltitle_validate('', $cat_name, $cat->cat_ID, false, 'cat_urlname', 'cat_ID', 'T_categories');
            } else {
                $cat_urlname = 'c' . $cat->cat_ID;
            }
            $DB->query('
				UPDATE T_categories
					 SET cat_urlname = ' . $DB->quote($cat_urlname) . '
				 WHERE cat_ID = ' . $cat->cat_ID);
        }
        $DB->query('
			ALTER TABLE T_categories
				ADD UNIQUE cat_urlname ( cat_urlname )');
        echo "OK.<br />\n";
        echo 'Updating Settings... ';
        $DB->query('
      UPDATE T_settings
         SET set_value = "disabled"
       WHERE set_name = "links_extrapath"
         AND set_value = 0');
        $DB->query('
      UPDATE T_settings
         SET set_value = "ymd"
       WHERE set_name = "links_extrapath"
         AND set_value <> 0');
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9406');
    }
    if ($old_db_version < 9407) {
        echo 'Moving general settings to blog settings... ';
        $DB->query('REPLACE INTO T_coll_settings( cset_coll_ID, cset_name, cset_value )
		             SELECT blog_ID, set_name, set_value
									 FROM T_blogs, T_settings
									WHERE set_name = "posts_per_page"
									   OR set_name = "what_to_show"
									   OR set_name = "archive_mode"');
        $DB->query('DELETE FROM T_settings
									WHERE set_name = "posts_per_page"
									   OR set_name = "what_to_show"
									   OR set_name = "archive_mode"');
        echo "OK.<br />\n";
        echo 'Upgrading blogs table... ';
        $query = "ALTER TABLE T_blogs\n\t\t\t\t\t\t\tDROP COLUMN blog_force_skin";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Upgrading groups table... ';
        $query = "ALTER TABLE T_groups\n\t\t\t\t\t\t\tCHANGE COLUMN grp_perm_files grp_perm_files enum('none','view','add','edit','all') NOT NULL default 'none'";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Upgrading files table... ';
        $query = "ALTER TABLE T_files\n\t\t\t\t\t\t\tCHANGE COLUMN file_root_type file_root_type enum('absolute','user','group','collection','skins') not null default 'absolute'";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Updating file types... ';
        // Only change this if it's close enough to a default install (non customized)
        $DB->query("UPDATE T_filetypes\n\t\t\t\t\t\t\t\t\t\tSET ftyp_viewtype = 'text'\n\t\t\t\t\t\t\t\t\tWHERE ftyp_ID = 12\n\t\t\t\t\t\t\t\t\t\tAND ftyp_extensions = 'php php3 php4 php5 php6'\n\t\t\t\t\t\t\t\t\t\tAND ftyp_mimetype ='application/x-httpd-php'\n\t\t\t\t\t\t\t\t\t\tAND ftyp_icon = 'php.gif'");
        echo "OK.<br />\n";
        echo 'Remove obsolete user settings... ';
        $DB->query('DELETE FROM ' . $tableprefix . 'usersettings
									WHERE uset_name = "plugins_disp_avail"');
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9407');
    }
    if ($old_db_version < 9408) {
        echo 'Creating skins table... ';
        $DB->query('CREATE TABLE T_skins__skin (
              skin_ID      int(10) unsigned      NOT NULL auto_increment,
              skin_name    varchar(32)           NOT NULL,
              skin_type    enum(\'normal\',\'feed\') NOT NULL default \'normal\',
              skin_folder  varchar(32)           NOT NULL,
              PRIMARY KEY skin_ID (skin_ID),
              UNIQUE skin_folder( skin_folder ),
              KEY skin_name( skin_name )
            )');
        echo "OK.<br />\n";
        echo 'Creating skin containers table... ';
        $DB->query('CREATE TABLE T_skins__container (
              sco_skin_ID   int(10) unsigned      NOT NULL,
              sco_name      varchar(40)           NOT NULL,
              PRIMARY KEY (sco_skin_ID, sco_name)
            )');
        echo "OK.<br />\n";
        echo 'Creating widgets table... ';
        $DB->query('CREATE TABLE T_widget (
 						wi_ID					INT(10) UNSIGNED auto_increment,
						wi_coll_ID    INT(11) UNSIGNED NOT NULL,
						wi_sco_name   VARCHAR( 40 ) NOT NULL,
						wi_order			INT(10) UNSIGNED NOT NULL,
						wi_type       ENUM( \'core\', \'plugin\' ) NOT NULL DEFAULT \'core\',
						wi_code       VARCHAR(32) NOT NULL,
						wi_params     TEXT NULL,
						PRIMARY KEY ( wi_ID ),
						UNIQUE wi_order( wi_coll_ID, wi_sco_name, wi_order )
          )');
        echo "OK.<br />\n";
        install_basic_skins(false);
        echo 'Updating blogs table... ';
        $DB->query('ALTER TABLE T_blogs
								 ALTER COLUMN blog_allowtrackbacks SET DEFAULT 0,
									DROP COLUMN blog_default_skin,
									 ADD COLUMN blog_owner_user_ID   int(11) unsigned NOT NULL default 1 AFTER blog_name,
									 ADD COLUMN blog_skin_ID INT(10) UNSIGNED NOT NULL DEFAULT 1 AFTER blog_allowusercss');
        echo "OK.<br />\n";
        install_basic_widgets($old_db_version);
        set_upgrade_checkpoint('9408');
    }
    if ($old_db_version < 9409) {
        // Upgrade the blog access types:
        echo 'Updating blogs access types... ';
        $DB->query('UPDATE T_blogs
										SET blog_access_type = "absolute"
									WHERE blog_siteurl LIKE "http://%"
									   OR blog_siteurl LIKE "https://%"');
        $DB->query('UPDATE T_blogs
										SET blog_access_type = "relative",
												blog_siteurl = CONCAT( blog_siteurl, blog_stub )
									WHERE blog_access_type = "stub"');
        db_drop_col('T_blogs', 'blog_stub');
        echo "OK.<br />\n";
        echo 'Updating columns... ';
        $DB->query("ALTER TABLE T_groups CHANGE COLUMN grp_perm_stats grp_perm_stats enum('none','user','view','edit') NOT NULL default 'none'");
        $DB->query("ALTER TABLE T_coll_user_perms CHANGE COLUMN bloguser_perm_poststatuses bloguser_perm_poststatuses set('published','deprecated','protected','private','draft','redirected') NOT NULL default ''");
        $DB->query("ALTER TABLE T_coll_group_perms CHANGE COLUMN bloggroup_perm_poststatuses bloggroup_perm_poststatuses set('published','deprecated','protected','private','draft','redirected') NOT NULL default ''");
        $DB->query("ALTER TABLE {$tableprefix}posts CHANGE COLUMN post_status post_status enum('published','deprecated','protected','private','draft','redirected') NOT NULL default 'published'");
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9409');
    }
    if ($old_db_version < 9410) {
        echo 'Updating columns... ';
        $DB->query("ALTER TABLE T_comments CHANGE COLUMN comment_status comment_status ENUM('published','deprecated','protected','private','draft','redirected') DEFAULT 'published' NOT NULL");
        $DB->query("ALTER TABLE T_sessions CHANGE COLUMN sess_data sess_data MEDIUMBLOB DEFAULT NULL");
        $DB->query("ALTER TABLE T_hitlog CHANGE COLUMN hit_referer_type hit_referer_type ENUM('search','blacklist','spam','referer','direct','self','admin') NOT NULL");
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9410');
    }
    if ($old_db_version < 9411) {
        echo 'Adding default Post Types... ';
        $DB->query("\n\t\t\tREPLACE INTO {$tableprefix}posttypes ( ptyp_ID, ptyp_name )\n\t\t\tVALUES ( 1000, 'Page' ),\n\t\t\t\t\t\t ( 2000, 'Reserved' ),\n\t\t\t\t\t\t ( 3000, 'Reserved' ),\n\t\t\t\t\t\t ( 4000, 'Reserved' ),\n\t\t\t\t\t\t ( 5000, 'Reserved' ) ");
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9411');
    }
    if ($old_db_version < 9412) {
        echo 'Adding field for post excerpts... ';
        $DB->query("ALTER TABLE {$tableprefix}posts ADD COLUMN post_excerpt  text NULL AFTER post_content");
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9412');
    }
    if ($old_db_version < 9414) {
        echo "Renaming tables...";
        $DB->query("RENAME TABLE {$tableprefix}item__prerendering TO T_items__prerendering");
        $DB->query("RENAME TABLE {$tableprefix}poststatuses TO T_items__status");
        $DB->query("RENAME TABLE {$tableprefix}posttypes TO T_items__type");
        $DB->query("RENAME TABLE {$tableprefix}posts TO T_items__item");
        echo "OK.<br />\n";
        echo "Creating Tag tables...";
        $DB->query("CREATE TABLE T_items__tag (\n\t\t      tag_ID   int(11) unsigned not null AUTO_INCREMENT,\n\t\t      tag_name varchar(50) not null,\n\t\t      primary key (tag_ID),\n\t\t      UNIQUE tag_name( tag_name )\n\t\t    )");
        $DB->query("CREATE TABLE T_items__itemtag (\n\t\t      itag_itm_ID int(11) unsigned NOT NULL,\n\t\t      itag_tag_ID int(11) unsigned NOT NULL,\n\t\t      PRIMARY KEY (itag_itm_ID, itag_tag_ID),\n\t\t      UNIQUE tagitem ( itag_tag_ID, itag_itm_ID )\n\t\t    )");
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9414');
    }
    if ($old_db_version < 9416) {
        echo "Updating blogs table...";
        $DB->query("ALTER TABLE T_blogs\n\t\t\t\t\t\t\t\t\tADD COLUMN blog_advanced_perms  TINYINT(1) NOT NULL default 0 AFTER blog_owner_user_ID,\n\t\t\t\t\t\t\t\t\tDROP COLUMN blog_staticfilename");
        $DB->query("UPDATE T_blogs\n\t\t\t\t\t\t\t\t\t  SET blog_advanced_perms = 1");
        echo "OK.<br />\n";
        echo "Additionnal blog permissions...";
        $DB->query("ALTER TABLE T_coll_user_perms\n\t\t\t\t\t\t\t\t\tADD COLUMN bloguser_perm_admin tinyint NOT NULL default 0 AFTER bloguser_perm_properties,\n\t\t\t\t\t\t\t\t\tADD COLUMN bloguser_perm_edit  ENUM('no','own','lt','le','all','redirected') NOT NULL default 'no' AFTER bloguser_perm_poststatuses");
        $DB->query("ALTER TABLE T_coll_group_perms\n\t\t\t\t\t\t\t\t\tADD COLUMN bloggroup_perm_admin tinyint NOT NULL default 0 AFTER bloggroup_perm_properties,\n\t\t\t\t\t\t\t\t\tADD COLUMN bloggroup_perm_edit  ENUM('no','own','lt','le','all','redirected') NOT NULL default 'no' AFTER bloggroup_perm_poststatuses");
        // Preserve full admin perms:
        $DB->query("UPDATE T_coll_user_perms\n\t\t\t\t\t\t\t\t\t\tSET bloguser_perm_admin = 1\n\t\t\t\t\t\t\t\t\tWHERE bloguser_perm_properties <> 0");
        $DB->query("UPDATE T_coll_group_perms\n\t\t\t\t\t\t\t\t\t\tSET bloggroup_perm_admin = 1\n\t\t\t\t\t\t\t\t\tWHERE bloggroup_perm_properties <> 0");
        // Preserve full edit perms:
        $DB->query("UPDATE T_coll_user_perms\n\t\t\t\t\t\t\t\t\t\tSET bloguser_perm_edit = 'all'");
        $DB->query("UPDATE T_coll_group_perms\n\t\t\t\t\t\t\t\t\t\tSET bloggroup_perm_edit = 'all'");
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9416');
    }
    if ($old_db_version < 9500) {
        task_begin('Normalizing columns...');
        $DB->query('ALTER TABLE T_blogs
										ALTER COLUMN blog_shortname SET DEFAULT \'\',
										ALTER COLUMN blog_tagline SET DEFAULT \'\',
										CHANGE COLUMN blog_description blog_description     varchar(250) NULL default \'\',
										ALTER COLUMN blog_siteurl SET DEFAULT \'\'');
        task_end();
        task_begin('Normalizing dates...');
        $DB->query('UPDATE T_users
										SET dateYMDhour = \'2000-01-01 00:00:00\'
									WHERE dateYMDhour = \'0000-00-00 00:00:00\'');
        $DB->query('ALTER TABLE T_users
									MODIFY COLUMN dateYMDhour DATETIME NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('UPDATE T_comments
										SET comment_date = \'2000-01-01 00:00:00\'
									WHERE comment_date = \'0000-00-00 00:00:00\'');
        $DB->query('ALTER TABLE T_comments
									MODIFY COLUMN comment_date DATETIME NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        task_end();
        task_begin('Normalizing cron jobs...');
        $DB->query('UPDATE T_cron__task
										SET ctsk_controller = REPLACE(ctsk_controller, "cron/_", "cron/jobs/_" )
									WHERE ctsk_controller LIKE "cron/_%"');
        task_end();
        task_begin('Extending comments table...');
        $DB->query('ALTER TABLE T_comments
									ADD COLUMN comment_rating     TINYINT(1) NULL DEFAULT NULL AFTER comment_content,
									ADD COLUMN comment_featured   TINYINT(1) NOT NULL DEFAULT 0 AFTER comment_rating,
									ADD COLUMN comment_nofollow   TINYINT(1) NOT NULL DEFAULT 1 AFTER comment_featured;');
        task_end();
        set_upgrade_checkpoint('9500');
    }
    if ($old_db_version < 9600) {
        // 2.2.0
        task_begin('Creating global cache table...');
        $DB->query('CREATE TABLE T_global__cache (
							      cach_name VARCHAR( 30 ) NOT NULL ,
							      cach_cache MEDIUMBLOB NULL ,
							      PRIMARY KEY ( cach_name )
							    )');
        task_end();
        task_begin('Altering posts table...');
        $DB->query('ALTER TABLE T_items__item
										MODIFY COLUMN post_datestart DATETIME NOT NULL DEFAULT \'2000-01-01 00:00:00\',
										MODIFY COLUMN post_datemodified DATETIME NOT NULL DEFAULT \'2000-01-01 00:00:00\',
										ADD COLUMN post_order    float NULL AFTER post_priority,
										ADD COLUMN post_featured tinyint(1) NOT NULL DEFAULT 0 AFTER post_order');
        $DB->query('ALTER TABLE T_items__item
										ADD INDEX post_order( post_order )');
        task_end();
        set_upgrade_checkpoint('9600');
    }
    if ($old_db_version < 9700) {
        // 2.3.2
        echo 'Creating PodCast Post Type... ';
        $DB->query("\n\t\t\tREPLACE INTO T_items__type ( ptyp_ID, ptyp_name )\n\t\t\tVALUES ( 2000, 'Podcast' )");
        echo "OK.<br />\n";
        // 2.4.0
        echo 'Adding additional group permissions... ';
        $DB->query("\n\t      ALTER TABLE T_groups\n\t\t\t\t\tADD COLUMN grp_perm_bypass_antispam         TINYINT(1)  NOT NULL DEFAULT 0        AFTER grp_perm_blogs,\n\t\t\t\t\tADD COLUMN grp_perm_xhtmlvalidation         VARCHAR(10) NOT NULL default 'always' AFTER grp_perm_bypass_antispam,\n\t\t\t\t\tADD COLUMN grp_perm_xhtmlvalidation_xmlrpc  VARCHAR(10) NOT NULL default 'always' AFTER grp_perm_xhtmlvalidation,\n\t\t\t\t\tADD COLUMN grp_perm_xhtml_css_tweaks        TINYINT(1)  NOT NULL DEFAULT 0        AFTER grp_perm_xhtmlvalidation_xmlrpc,\n      \t\tADD COLUMN grp_perm_xhtml_iframes           TINYINT(1)  NOT NULL DEFAULT 0        AFTER grp_perm_xhtml_css_tweaks,\n      \t\tADD COLUMN grp_perm_xhtml_javascript        TINYINT(1)  NOT NULL DEFAULT 0        AFTER grp_perm_xhtml_iframes,\n\t\t\t\t\tADD COLUMN grp_perm_xhtml_objects           TINYINT(1)  NOT NULL DEFAULT 0        AFTER grp_perm_xhtml_javascript ");
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9700');
    }
    if ($old_db_version < 9800) {
        // 2.5.0
        echo 'Upgrading blogs table... ';
        db_drop_col('T_blogs', 'blog_commentsexpire');
        echo "OK.<br />\n";
        echo 'Upgrading items table... ';
        $DB->query("ALTER TABLE T_items__item\n\t\t\tCHANGE COLUMN post_urltitle post_urltitle VARCHAR(210) NULL DEFAULT NULL,\n\t\t\tCHANGE COLUMN post_order    post_order DOUBLE NULL,\n\t\t\tADD COLUMN post_titletag  VARCHAR(255) NULL DEFAULT NULL AFTER post_urltitle,\n\t\t\tADD COLUMN post_double1   DOUBLE NULL COMMENT 'Custom double value 1' AFTER post_priority,\n\t\t\tADD COLUMN post_double2   DOUBLE NULL COMMENT 'Custom double value 2' AFTER post_double1,\n\t\t\tADD COLUMN post_double3   DOUBLE NULL COMMENT 'Custom double value 3' AFTER post_double2,\n\t\t\tADD COLUMN post_double4   DOUBLE NULL COMMENT 'Custom double value 4' AFTER post_double3,\n\t\t\tADD COLUMN post_double5   DOUBLE NULL COMMENT 'Custom double value 5' AFTER post_double4,\n\t\t\tADD COLUMN post_varchar1  VARCHAR(255) NULL COMMENT 'Custom varchar value 1' AFTER post_double5,\n\t\t\tADD COLUMN post_varchar2  VARCHAR(255) NULL COMMENT 'Custom varchar value 2' AFTER post_varchar1,\n\t\t\tADD COLUMN post_varchar3  VARCHAR(255) NULL COMMENT 'Custom varchar value 3' AFTER post_varchar2");
        echo "OK.<br />\n";
        echo 'Creating keyphrase table... ';
        $query = "CREATE TABLE T_track__keyphrase (\n            keyp_ID      INT UNSIGNED NOT NULL AUTO_INCREMENT,\n            keyp_phrase  VARCHAR( 255 ) NOT NULL,\n            PRIMARY KEY        ( keyp_ID ),\n            UNIQUE keyp_phrase ( keyp_phrase )\n          )";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Upgrading hitlog table... ';
        evo_flush();
        $query = "ALTER TABLE T_hitlog\n\t\t\t CHANGE COLUMN hit_ID hit_ID              INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,\n\t\t\t CHANGE COLUMN hit_datetime hit_datetime  DATETIME NOT NULL DEFAULT '2000-01-01 00:00:00',\n\t\t\t ADD COLUMN hit_keyphrase_keyp_ID         INT UNSIGNED DEFAULT NULL AFTER hit_referer_dom_ID,\n\t\t\t ADD INDEX hit_remote_addr ( hit_remote_addr ),\n\t\t\t ADD INDEX hit_sess_ID        ( hit_sess_ID )";
        $DB->query($query);
        echo "OK.<br />\n";
        echo 'Upgrading sessions table... ';
        $DB->query("ALTER TABLE T_sessions\n\t\t\tALTER COLUMN sess_lastseen SET DEFAULT '2000-01-01 00:00:00',\n\t\t\tADD COLUMN sess_hitcount  INT(10) UNSIGNED NOT NULL DEFAULT 1 AFTER sess_key,\n\t\t\tADD KEY sess_user_ID (sess_user_ID)");
        echo "OK.<br />\n";
        echo 'Creating goal tracking table... ';
        $DB->query("CREATE TABLE T_track__goal(\n\t\t\t\t\t  goal_ID int(10) unsigned NOT NULL auto_increment,\n\t\t\t\t\t  goal_name varchar(50) default NULL,\n\t\t\t\t\t  goal_key varchar(32) default NULL,\n\t\t\t\t\t  goal_redir_url varchar(255) default NULL,\n\t\t\t\t\t  goal_default_value double default NULL,\n\t\t\t\t\t  PRIMARY KEY (goal_ID),\n\t\t\t\t\t  UNIQUE KEY goal_key (goal_key)\n          )");
        $DB->query("CREATE TABLE T_track__goalhit (\n\t\t\t\t\t  ghit_ID int(10) unsigned NOT NULL auto_increment,\n\t\t\t\t\t  ghit_goal_ID    int(10) unsigned NOT NULL,\n\t\t\t\t\t  ghit_hit_ID     int(10) unsigned NOT NULL,\n\t\t\t\t\t  ghit_params     TEXT default NULL,\n\t\t\t\t\t  PRIMARY KEY  (ghit_ID),\n\t\t\t\t\t  KEY ghit_goal_ID (ghit_goal_ID),\n\t\t\t\t\t  KEY ghit_hit_ID (ghit_hit_ID)\n         )");
        echo "OK.<br />\n";
        set_upgrade_checkpoint('9800');
    }
    if ($old_db_version < 9900) {
        // 3.0 part 1
        task_begin('Updating keyphrases in hitlog table... ');
        load_class('sessions/model/_hit.class.php', 'Hit');
        // New Hit object creation was added later, to fix upgrades from very old versions.
        // We create a new temp Hit object to be able to call the Hit::extract_params_from_referer() function which was static when this upgrade block was created.
        $tempHit = new Hit();
        $sql = 'SELECT SQL_NO_CACHE hit_ID, hit_referer
  		          FROM T_hitlog
   		         WHERE hit_referer_type = "search"
		           AND hit_keyphrase_keyp_ID IS NULL';
        // this line just in case we crashed in the middle, so we restart where we stopped
        $rows = $DB->get_results($sql, OBJECT, 'get all search hits');
        foreach ($rows as $row) {
            $params = $tempHit->extract_params_from_referer($row->hit_referer);
            if (empty($params['keyphrase'])) {
                continue;
            }
            $DB->begin();
            $sql = 'SELECT keyp_ID
			          FROM T_track__keyphrase
			         WHERE keyp_phrase = ' . $DB->quote($params['keyphrase']);
            $keyp_ID = $DB->get_var($sql, 0, 0, 'Get keyphrase ID');
            if (empty($keyp_ID)) {
                $sql = 'INSERT INTO T_track__keyphrase( keyp_phrase )
				        VALUES (' . $DB->quote($params['keyphrase']) . ')';
                $DB->query($sql, 'Add new keyphrase');
                $keyp_ID = $DB->insert_id;
            }
            $DB->query('UPDATE T_hitlog
			                SET hit_keyphrase_keyp_ID = ' . $keyp_ID . '
			              WHERE hit_ID = ' . $row->hit_ID, 'Update hit');
            $DB->commit();
            echo ". \n";
        }
        task_end();
        task_begin('Upgrading widgets table... ');
        $DB->query("ALTER TABLE T_widget\n\t\t\tCHANGE COLUMN wi_order wi_order INT(10) NOT NULL");
        task_end();
        task_begin('Upgrading Files table... ');
        $DB->query("ALTER TABLE T_files\n\t\t\t\t\t\t\t\tCHANGE COLUMN file_root_type file_root_type enum('absolute','user','collection','shared','skins') not null default 'absolute'");
        task_end();
        set_upgrade_checkpoint('9900');
    }
    if ($old_db_version < 9910) {
        // 3.0 part 2
        task_begin('Upgrading Blogs table... ');
        $DB->query("ALTER TABLE T_blogs CHANGE COLUMN blog_name blog_name varchar(255) NOT NULL default ''");
        task_end();
        task_begin('Adding new Post Types...');
        $DB->query("\n\t\t\tREPLACE INTO T_items__type( ptyp_ID, ptyp_name )\n\t\t\tVALUES ( 1500, 'Intro-Main' ),\n\t\t\t\t\t\t ( 1520, 'Intro-Cat' ),\n\t\t\t\t\t\t ( 1530, 'Intro-Tag' ),\n\t\t\t\t\t\t ( 1570, 'Intro-Sub' ),\n\t\t\t\t\t\t ( 1600, 'Intro-All' ) ");
        task_end();
        task_begin('Updating User table');
        $DB->query("ALTER TABLE T_users\n\t\t\t\t\t\t\t\t\tADD COLUMN user_avatar_file_ID int(10) unsigned default NULL AFTER user_validated");
        task_end();
        task_begin('Creating table for User field definitions');
        $DB->query("CREATE TABLE T_users__fielddefs (\n\t\t\t\tufdf_ID int(10) unsigned NOT NULL,\n\t\t\t\tufdf_type char(8) NOT NULL,\n\t\t\t\tufdf_name varchar(255) collate latin1_general_ci NOT NULL,\n\t\t\t\tPRIMARY KEY  (ufdf_ID)\n\t\t\t)");
        task_end();
        task_begin('Creating default field definitions...');
        $DB->query("\n\t    INSERT INTO T_users__fielddefs (ufdf_ID, ufdf_type, ufdf_name)\n\t\t\t VALUES ( 10000, 'email',    'MSN/Live IM'),\n\t\t\t\t\t\t\t( 10100, 'word',     'Yahoo IM'),\n\t\t\t\t\t\t\t( 10200, 'word',     'AOL AIM'),\n\t\t\t\t\t\t\t( 10300, 'number',   'ICQ ID'),\n\t\t\t\t\t\t\t( 40000, 'phone',    'Skype'),\n\t\t\t\t\t\t\t( 50000, 'phone',    'Main phone'),\n\t\t\t\t\t\t\t( 50100, 'phone',    'Cell phone'),\n\t\t\t\t\t\t\t( 50200, 'phone',    'Office phone'),\n\t\t\t\t\t\t\t( 50300, 'phone',    'Home phone'),\n\t\t\t\t\t\t\t( 60000, 'phone',    'Office FAX'),\n\t\t\t\t\t\t\t( 60100, 'phone',    'Home FAX'),\n\t\t\t\t\t\t\t(100000, 'url',      'Website'),\n\t\t\t\t\t\t\t(100100, 'url',      'Blog'),\n\t\t\t\t\t\t\t(110000, 'url',      'Linkedin'),\n\t\t\t\t\t\t\t(120000, 'url',      'Twitter'),\n\t\t\t\t\t\t\t(130100, 'url',      'Facebook'),\n\t\t\t\t\t\t\t(130200, 'url',      'Myspace'),\n\t\t\t\t\t\t\t(140000, 'url',      'Flickr'),\n\t\t\t\t\t\t\t(150000, 'url',      'YouTube'),\n\t\t\t\t\t\t\t(160000, 'url',      'Digg'),\n\t\t\t\t\t\t\t(160100, 'url',      'StumbleUpon'),\n\t\t\t\t\t\t\t(200000, 'text',     'Role'),\n\t\t\t\t\t\t\t(200100, 'text',     'Company/Org.'),\n\t\t\t\t\t\t\t(200200, 'text',     'Division'),\n\t\t\t\t\t\t\t(211000, 'text',     'VAT ID'),\n\t\t\t\t\t\t\t(300000, 'text',     'Main address'),\n\t\t\t\t\t\t\t(300300, 'text',     'Home address');");
        task_end();
        task_begin('Creating table for User fields...');
        $DB->query("CREATE TABLE {$tableprefix}users_fields (\n\t\t\t\tuf_ID      int(10) unsigned NOT NULL auto_increment,\n\t\t\t  uf_user_ID int(10) unsigned NOT NULL,\n\t\t\t  uf_ufdf_ID int(10) unsigned NOT NULL,\n\t\t\t  uf_varchar varchar(255) NOT NULL,\n\t\t\t  PRIMARY KEY (uf_ID)\n\t\t\t)");
        task_end();
        set_upgrade_checkpoint('9910');
    }
    if ($old_db_version < 9920) {
        // 3.1
        task_begin('Upgrading Posts table... ');
        // This is for old posts that may have a post type of NULL which should never happen. ptyp 1 is for regular posts
        $DB->query("UPDATE T_items__item\n\t\t\t\t\t\t\t\t\t\tSET post_ptyp_ID = 1\n\t\t\t\t\t\t\t\t\tWHERE post_ptyp_ID IS NULL");
        $DB->query("ALTER TABLE T_items__item\n\t\t\t\t\t\t\tCHANGE COLUMN post_ptyp_ID post_ptyp_ID int(10) unsigned NOT NULL DEFAULT 1");
        task_end();
        task_begin('Upgrading Categories table... ');
        $DB->query("ALTER TABLE T_categories\n\t\t\tCHANGE COLUMN cat_name cat_name varchar(255) NOT NULL,\n\t\t\tCHANGE COLUMN cat_description cat_description varchar(255) NULL DEFAULT NULL");
        db_add_col('T_categories', 'cat_order', 'int(11) NULL DEFAULT NULL AFTER cat_description');
        db_add_index('T_categories', 'cat_order', 'cat_order');
        $DB->query("UPDATE T_categories\n\t\t\t\t\tSET cat_order = cat_ID");
        task_end();
        task_begin('Upgrading widgets table... ');
        db_add_col('T_widget', 'wi_enabled', 'tinyint(1) NOT NULL DEFAULT 1 AFTER wi_order');
        task_end();
    }
    if ($old_db_version < 9930) {
        // 3.1 continued
        task_begin('Updating Post Types...');
        $DB->query("\n\t\t\tREPLACE INTO T_items__type ( ptyp_ID, ptyp_name )\n\t\t\tVALUES ( 3000, 'Sidebar link' )");
        echo "OK.<br />\n";
        task_end();
        task_begin('Updating items table...');
        $DB->query("ALTER TABLE T_items__item ENGINE=innodb");
        // fp> hum... this originally was a test :)
        task_end();
        task_begin('Creating versions table...');
        $DB->query("CREATE TABLE T_items__version (\n\t            iver_itm_ID        INT UNSIGNED NOT NULL ,\n\t            iver_edit_user_ID  INT UNSIGNED NOT NULL ,\n\t            iver_edit_datetime DATETIME NOT NULL ,\n\t            iver_status        ENUM('published','deprecated','protected','private','draft','redirected') NULL ,\n\t            iver_title         TEXT NULL ,\n\t            iver_content       MEDIUMTEXT NULL ,\n\t            INDEX iver_itm_ID ( iver_itm_ID )\n\t            ) ENGINE = innodb");
        task_end();
        task_begin('Updating group permissions...');
        $DB->query("UPDATE T_groups\n\t\t\t\t\t\t\t\t\t\tSET grp_perm_xhtml_css_tweaks = 1\n\t\t\t\t\t\t\t\t\tWHERE grp_ID <= 3");
        task_end();
        set_upgrade_checkpoint('9930');
    }
    if ($old_db_version < 9940) {
        // 3.2
        task_begin('Updating hitlog table...');
        $DB->query("ALTER TABLE T_hitlog ADD COLUMN hit_serprank INT UNSIGNED DEFAULT NULL AFTER hit_keyphrase_keyp_ID");
        task_end();
        task_begin('Updating versions table...');
        $DB->query("ALTER TABLE T_items__version\n\t\t\t\t\t\t\t\tCHANGE COLUMN iver_edit_user_ID iver_edit_user_ID  INT UNSIGNED NULL");
        task_end();
    }
    if ($old_db_version < 9950) {
        // 3.3
        task_begin('Altering Blogs table... ');
        $DB->query("ALTER TABLE T_blogs CHANGE COLUMN blog_shortname blog_shortname varchar(255) default ''");
        task_end();
        task_begin('Altering default dates... ');
        $DB->query("ALTER TABLE T_links\n      ALTER COLUMN link_datecreated SET DEFAULT '2000-01-01 00:00:00',\n      ALTER COLUMN link_datemodified SET DEFAULT '2000-01-01 00:00:00'");
        $DB->query("ALTER TABLE T_cron__task\n      ALTER COLUMN ctsk_start_datetime SET DEFAULT '2000-01-01 00:00:00'");
        $DB->query("ALTER TABLE T_cron__log\n      ALTER COLUMN clog_realstart_datetime SET DEFAULT '2000-01-01 00:00:00'");
        task_end();
        task_begin('Altering Items table... ');
        $DB->query("ALTER TABLE T_items__item\n\t\t\tADD COLUMN post_metadesc VARCHAR(255) NULL DEFAULT NULL AFTER post_titletag,\n\t\t\tADD COLUMN post_metakeywords VARCHAR(255) NULL DEFAULT NULL AFTER post_metadesc,\n\t\t\tADD COLUMN post_editor_code VARCHAR(32) NULL COMMENT 'Plugin code of the editor used to edit this post' AFTER post_varchar3");
        task_end();
        task_begin('Forcing AutoP posts to html editor...');
        $DB->query('UPDATE T_items__item
											SET post_editor_code = "html"
										WHERE post_renderers = "default"
											 OR post_renderers LIKE "%b2WPAutP%"');
        task_end();
        set_upgrade_checkpoint('9950');
    }
    if ($old_db_version < 9960) {
        // 3.3
        echo "Renaming tables...";
        $DB->save_error_state();
        $DB->halt_on_error = false;
        $DB->show_errors = false;
        $DB->query("ALTER TABLE {$tableprefix}users_fields RENAME TO T_users__fields");
        $DB->restore_error_state();
        echo "OK.<br />\n";
        // fp> The following is more tricky to do with CHARACTER SET. During upgrade, we don't know what the admin actually wants.
        task_begin('Making sure all tables use desired storage ENGINE as specified in the b2evo schema...');
        foreach ($schema_queries as $table_name => $table_def) {
            if ($DB->query('SHOW TABLES LIKE \'' . $table_name . '\'') && preg_match('/\\sENGINE\\s*=\\s*([a-z]+)/is', $table_def[1], $matches)) {
                // If the table exists and has an ENGINE definition:
                echo $table_name . ':' . $matches[1] . '<br />';
                $DB->query("ALTER TABLE {$table_name} ENGINE = " . $matches[1]);
            }
        }
        task_end();
        set_upgrade_checkpoint('9960');
    }
    if ($old_db_version < 9970) {
        // 4.0 part 1
        // For create_default_currencies() and create_default_countries():
        require_once dirname(__FILE__) . '/_functions_create.php';
        task_begin('Creating table for default currencies... ');
        $DB->query('CREATE TABLE ' . $tableprefix . 'currency (
				curr_ID int(10) unsigned NOT NULL auto_increment,
				curr_code char(3) NOT NULL,
				curr_shortcut varchar(30) NOT NULL,
				curr_name varchar(40) NOT NULL,
				PRIMARY KEY curr_ID (curr_ID),
				UNIQUE curr_code (curr_code)
			) ENGINE = innodb');
        task_end();
        create_default_currencies($tableprefix . 'currency');
        task_begin('Creating table for default countries... ');
        $DB->query('CREATE TABLE ' . $tableprefix . 'country (
				ctry_ID int(10) unsigned NOT NULL auto_increment,
				ctry_code char(2) NOT NULL,
				ctry_name varchar(40) NOT NULL,
				ctry_curr_ID int(10) unsigned,
				PRIMARY KEY ctry_ID (ctry_ID),
				UNIQUE ctry_code (ctry_code)
			) ENGINE = innodb');
        task_end();
        create_default_countries($tableprefix . 'country', false);
        task_begin('Upgrading user permissions table... ');
        $DB->query("ALTER TABLE T_coll_user_perms\n\t\t\tADD COLUMN bloguser_perm_page\t\ttinyint NOT NULL default 0 AFTER bloguser_perm_media_change,\n\t\t\tADD COLUMN bloguser_perm_intro\t\ttinyint NOT NULL default 0 AFTER bloguser_perm_page,\n\t\t\tADD COLUMN bloguser_perm_podcast\ttinyint NOT NULL default 0 AFTER bloguser_perm_intro,\n\t\t\tADD COLUMN bloguser_perm_sidebar\ttinyint NOT NULL default 0 AFTER bloguser_perm_podcast");
        task_end();
        task_begin('Upgrading group permissions table... ');
        $DB->query("ALTER TABLE T_coll_group_perms\n\t\t\tADD COLUMN bloggroup_perm_page\t\ttinyint NOT NULL default 0 AFTER bloggroup_perm_media_change,\n\t\t\tADD COLUMN bloggroup_perm_intro\t\ttinyint NOT NULL default 0 AFTER bloggroup_perm_page,\n\t\t\tADD COLUMN bloggroup_perm_podcast\ttinyint NOT NULL default 0 AFTER bloggroup_perm_intro,\n\t\t\tADD COLUMN bloggroup_perm_sidebar\ttinyint NOT NULL default 0 AFTER bloggroup_perm_podcast");
        task_end();
        task_begin('Upgrading users table... ');
        $DB->query("ALTER TABLE T_users\n\t\t\tADD COLUMN user_ctry_ID int(10) unsigned NULL AFTER user_avatar_file_ID");
        task_end();
        // Creating tables for messaging module
        task_begin('Creating table for message threads... ');
        $DB->query("CREATE TABLE T_messaging__thread (\n\t\t\tthrd_ID int(10) unsigned NOT NULL auto_increment,\n\t\t\tthrd_title varchar(255) NOT NULL,\n\t\t\tthrd_datemodified datetime NOT NULL,\n\t\t\tPRIMARY KEY thrd_ID (thrd_ID)\n\t\t) ENGINE = innodb");
        task_end();
        task_begin('Creating table for messagee... ');
        $DB->query("CREATE TABLE T_messaging__message (\n\t\t\tmsg_ID int(10) unsigned NOT NULL auto_increment,\n\t\t\tmsg_author_user_ID int(10) unsigned NOT NULL,\n\t\t\tmsg_datetime datetime NOT NULL,\n\t\t\tmsg_thread_ID int(10) unsigned NOT NULL,\n\t\t\tmsg_text text NULL,\n\t\t\tPRIMARY KEY msg_ID (msg_ID)\n\t\t) ENGINE = innodb");
        task_end();
        task_begin('Creating table for message thread statuses... ');
        $DB->query("CREATE TABLE T_messaging__threadstatus (\n\t\t\ttsta_thread_ID int(10) unsigned NOT NULL,\n\t\t\ttsta_user_ID int(10) unsigned NOT NULL,\n\t\t\ttsta_first_unread_msg_ID int(10) unsigned NULL,\n\t\t\tINDEX(tsta_user_ID)\n\t\t) ENGINE = innodb");
        task_end();
        task_begin('Creating table for messaging contacts... ');
        $DB->query("CREATE TABLE T_messaging__contact (\n\t\t\tmct_from_user_ID int(10) unsigned NOT NULL,\n\t\t\tmct_to_user_ID int(10) unsigned NOT NULL,\n\t\t\tmct_blocked tinyint(1) default 0,\n\t\t\tmct_last_contact_datetime datetime NOT NULL,\n\t\t\tPRIMARY KEY mct_PK (mct_from_user_ID, mct_to_user_ID)\n\t\t) ENGINE = innodb");
        task_end();
        task_begin('Upgrading skins table... ');
        $DB->query("ALTER TABLE T_skins__skin\n\t\t\t\t\t\tMODIFY skin_type enum('normal','feed','sitemap') NOT NULL default 'normal'");
        task_end();
        task_begin('Setting skin type of sitemap skin to "sitemap"... ');
        $DB->query("UPDATE T_skins__skin\n\t\t\t\t\t\tSET skin_type = 'sitemap'\n\t\t\t\t\t\tWHERE skin_folder = '_sitemap'");
        task_end();
        // Creating table for pluggable permissions
        // This table gets created during upgrade to v0.8.9 at checkpoint 8050
        task_begin('Creating table for Group Settings... ');
        $DB->query("CREATE TABLE IF NOT EXISTS T_groups__groupsettings (\n\t\t\tgset_grp_ID INT(11) UNSIGNED NOT NULL,\n\t\t\tgset_name VARCHAR(30) NOT NULL,\n\t\t\tgset_value VARCHAR(255) NULL,\n\t\t\tPRIMARY KEY (gset_grp_ID, gset_name)\n\t\t) ENGINE = innodb");
        task_end();
        // Rename T_usersettings table to T_users__usersettings
        task_begin('Rename T_usersettings table to T_users__usersettings... ');
        $DB->query('ALTER TABLE ' . $tableprefix . 'usersettings RENAME TO T_users__usersettings');
        task_end();
        set_upgrade_checkpoint('9970');
    }
    if ($old_db_version < 9980) {
        // 4.0 part 2
        task_begin('Upgrading posts... ');
        $DB->query('
			UPDATE T_items__item
			   SET post_datestart = FROM_UNIXTIME( FLOOR(UNIX_TIMESTAMP(post_datestart)/60)*60 )
			 WHERE post_datestart > NOW()');
        db_add_col('T_items__item', 'post_excerpt_autogenerated', 'TINYINT NULL DEFAULT NULL AFTER post_excerpt');
        db_add_col('T_items__item', 'post_dateset', 'tinyint(1) NOT NULL DEFAULT 1 AFTER post_assigned_user_ID');
        task_end();
        task_begin('Upgrading countries... ');
        db_add_col($tableprefix . 'country', 'ctry_enabled', 'tinyint(1) NOT NULL DEFAULT 1 AFTER ctry_curr_ID');
        task_end();
        task_begin('Upgrading links... ');
        // Add link_position. Temporary allow NULL, set compatibility default, then do not allow NULL.
        // TODO: dh> actually, using "teaser" for the first link and "aftermore" for the rest would make more sense (and "aftermore" should get displayed with "no-more" posts anyway).
        //           Opinions? Could be heavy to transform this though..
        // fp> no, don't change past posts unexpectedly.
        db_add_col('T_links', 'link_position', "varchar(10) NULL AFTER link_title");
        $DB->query("UPDATE T_links SET link_position = 'teaser' WHERE link_position IS NULL");
        db_add_col('T_links', 'link_position', "varchar(10) NOT NULL AFTER link_title");
        // change to NOT NULL
        // Add link_order. Temporary allow NULL, use order from ID, then do not allow NULL and add UNIQUE index.
        db_add_col('T_links', 'link_order', 'int(11) unsigned NULL AFTER link_position');
        $DB->query("UPDATE T_links SET link_order = link_ID WHERE link_order IS NULL");
        db_add_col('T_links', 'link_order', 'int(11) unsigned NOT NULL AFTER link_position');
        // change to NOT NULL
        db_add_index('T_links', 'link_itm_ID_order', 'link_itm_ID, link_order', 'UNIQUE');
        task_end();
        task_begin('Upgrading sessions... ');
        $DB->query("ALTER TABLE T_sessions CHANGE COLUMN sess_ipaddress sess_ipaddress VARCHAR(39) NOT NULL DEFAULT ''");
        task_end();
        set_upgrade_checkpoint('9980');
    }
    if ($old_db_version < 9990) {
        // 4.0 part 3
        task_begin('Upgrading hitlog... ');
        db_add_col('T_hitlog', 'hit_agent_type', "ENUM('rss','robot','browser','unknown') DEFAULT 'unknown' NOT NULL AFTER hit_remote_addr");
        if (db_col_exists('T_hitlog', 'hit_agnt_ID')) {
            $DB->query('UPDATE T_hitlog, ' . $tableprefix . 'useragents
			                SET hit_agent_type = agnt_type
			              WHERE hit_agnt_ID = agnt_ID
			                AND agnt_type <> "unknown"');
            // We already have the unknown as default
            db_drop_col('T_hitlog', 'hit_agnt_ID');
        }
        $DB->query('DROP TABLE IF EXISTS ' . $tableprefix . 'useragents');
        task_end();
        set_upgrade_checkpoint('9990');
    }
    if ($old_db_version < 10000) {
        // 4.0 part 4
        // Integrate comment_secret
        task_begin('Extending Comment table... ');
        db_add_col('T_comments', 'comment_secret', 'varchar(32) NULL default NULL');
        task_end();
        // Create T_slug table and, Insert all slugs from T_items
        task_begin('Create Slugs table... ');
        $DB->query('CREATE TABLE IF NOT EXISTS T_slug (
						slug_ID int(10) unsigned NOT NULL auto_increment,
						slug_title varchar(255) NOT NULL COLLATE ascii_bin,
						slug_type char(6) NOT NULL DEFAULT "item",
						slug_itm_ID int(11) unsigned,
						PRIMARY KEY slug_ID (slug_ID),
						UNIQUE	slug_title (slug_title)
					) ENGINE = innodb');
        task_end();
        task_begin('Making sure all posts have a slug...');
        // Get posts with empty urltitle:
        $sql = 'SELECT post_ID, post_title
				      FROM T_items__item
				     WHERE post_urltitle IS NULL OR post_urltitle = ""';
        $rows = $DB->get_results($sql, OBJECT, 'Get posts with empty urltitle');
        // Create URL titles when non existent:
        foreach ($rows as $row) {
            // TODO: dh> pass locale (useful for transliteration).
            $DB->query('UPDATE T_items__item
				              SET post_urltitle = "' . urltitle_validate('', $row->post_title, 0) . '"
		                WHERE post_ID = ' . $row->post_ID, 'Set posts urltitle');
        }
        task_end();
        task_begin('Populating Slugs table... ');
        $DB->query('REPLACE INTO T_slug( slug_title, slug_type, slug_itm_ID)
		              SELECT post_urltitle, "item", post_ID
							      FROM T_items__item');
        task_end();
        task_begin('Add canonical and tiny slug IDs to post table...');
        // modify post_urltitle column -> Not allow NULL value
        db_add_col('T_items__item', 'post_urltitle', 'VARCHAR(210) NOT NULL');
        db_add_col('T_items__item', 'post_canonical_slug_ID', 'int(10) unsigned NULL default NULL after post_urltitle');
        db_add_col('T_items__item', 'post_tiny_slug_ID', 'int(10) unsigned NULL default NULL after post_canonical_slug_ID');
        task_end();
        task_begin('Upgrading posts...');
        $DB->query('UPDATE T_items__item, T_slug
			              SET post_canonical_slug_ID = slug_ID
			            WHERE CONVERT( post_urltitle USING ASCII ) COLLATE ascii_bin = slug_title');
        task_end();
        task_begin('Adding "help" slug...');
        if (db_key_exists('T_slug', 'slug_title', '"help"')) {
            echo '<strong>Warning: "help" slug already exists!</strong><br /> ';
        } else {
            $DB->query('INSERT INTO T_slug( slug_title, slug_type )
			             VALUES( "help", "help" )', 'Add "help" slug');
            task_end();
        }
        // fp> Next time we should use pluggable permissions instead.
        task_begin('Updgrading groups: Giving Administrators Group edit perms on slugs...');
        db_add_col('T_groups', 'grp_perm_slugs', "enum('none','view','edit') NOT NULL default 'none'");
        $DB->query('UPDATE T_groups
		             SET grp_perm_slugs = "edit"
		             WHERE grp_ID = 1');
        task_end();
        task_begin('Upgrading settings table... ');
        $DB->query('UPDATE T_settings
		                SET set_value = 1
		              WHERE set_name = "fm_enable_roots_user"
		                    AND set_value = 0');
        task_end();
        // New perms for comment moderation depending on status:
        task_begin('Upgrading Blog-User permissions...');
        db_add_col('T_coll_user_perms', 'bloguser_perm_draft_cmts', 'tinyint NOT NULL default 0 AFTER bloguser_perm_comments');
        db_add_col('T_coll_user_perms', 'bloguser_perm_publ_cmts', 'tinyint NOT NULL default 0 AFTER bloguser_perm_comments');
        db_add_col('T_coll_user_perms', 'bloguser_perm_depr_cmts', 'tinyint NOT NULL default 0 AFTER bloguser_perm_comments');
        if (db_col_exists('T_coll_user_perms', 'bloguser_perm_comments')) {
            // if user had perm_comments he now gets all 3 new perms also:
            $DB->query('UPDATE T_coll_user_perms
						SET bloguser_perm_draft_cmts = bloguser_perm_comments,
							bloguser_perm_publ_cmts = bloguser_perm_comments,
							bloguser_perm_depr_cmts = bloguser_perm_comments');
            db_drop_col('T_coll_user_perms', 'bloguser_perm_comments');
        }
        task_end();
        task_begin('Upgrading Blog-Group permissions...');
        db_add_col('T_coll_group_perms', 'bloggroup_perm_draft_cmts', 'tinyint NOT NULL default 0 AFTER bloggroup_perm_comments');
        db_add_col('T_coll_group_perms', 'bloggroup_perm_publ_cmts', 'tinyint NOT NULL default 0 AFTER bloggroup_perm_comments');
        db_add_col('T_coll_group_perms', 'bloggroup_perm_depr_cmts', 'tinyint NOT NULL default 0 AFTER bloggroup_perm_comments');
        if (db_col_exists('T_coll_group_perms', 'bloggroup_perm_comments')) {
            // if group had perm_comments he now gets all 3 new perms also:
            $DB->query('UPDATE T_coll_group_perms
						SET bloggroup_perm_draft_cmts = bloggroup_perm_comments,
							bloggroup_perm_publ_cmts = bloggroup_perm_comments,
							bloggroup_perm_depr_cmts = bloggroup_perm_comments');
            db_drop_col('T_coll_group_perms', 'bloggroup_perm_comments');
        }
        task_end();
        task_begin('Upgrading messaging permissions...');
        $DB->query('ALTER TABLE T_users ALTER COLUMN user_allow_msgform SET DEFAULT "2"');
        $DB->query('UPDATE T_users
					SET user_allow_msgform = 3
					WHERE user_allow_msgform = 1');
        task_end();
        task_begin('Upgrading currency table...');
        $DB->query('ALTER TABLE ' . $tableprefix . 'currency ADD COLUMN curr_enabled tinyint(1) NOT NULL DEFAULT 1 AFTER curr_name');
        task_end();
        task_begin('Upgrading default blog access type for new blogs...');
        $DB->query('ALTER TABLE T_blogs ALTER COLUMN blog_access_type SET DEFAULT "extrapath"');
        task_end();
        task_begin('Upgrading tags table...');
        $DB->query('ALTER TABLE T_items__tag CHANGE COLUMN tag_name tag_name varbinary(50) not null');
        task_end();
        // fp> I don't understand why we need to carry this out "again" but I observed the installer barking on
        // this setting missing when upgrading from older 2.x versions. I figured it would be no big deal to do it twice...
        task_begin('Makin sure usersettings table is InnoDB...');
        $DB->query('ALTER TABLE T_users__usersettings ENGINE=innodb');
        task_end();
        set_upgrade_checkpoint('10000');
    }
    if ($old_db_version < 10100) {
        // 4.1
        task_begin('Convert group permissions to pluggable permissions...');
        // asimo>This delete query needs just in case if this version of b2evo was used, before upgrade process call
        $DB->query('DELETE FROM T_groups__groupsettings
						WHERE gset_name = "perm_files" OR gset_name = "perm_options" OR gset_name = "perm_templates"');
        // Get current permission values from groups table
        $sql = 'SELECT grp_ID, grp_perm_spamblacklist, grp_perm_slugs, grp_perm_files, grp_perm_options, grp_perm_templates
				      FROM T_groups';
        $rows = $DB->get_results($sql, OBJECT, 'Get groups converted permissions');
        // Insert values into groupsettings table
        foreach ($rows as $row) {
            // "IGNORE" is needed if we already created T_groups__groupsettings during upgrade to v0.8.9 at checkpoint 8050
            $DB->query('INSERT IGNORE INTO T_groups__groupsettings( gset_grp_ID, gset_name, gset_value )
							VALUES( ' . $row->grp_ID . ', "perm_spamblacklist", "' . $row->grp_perm_spamblacklist . '" ),
								( ' . $row->grp_ID . ', "perm_slugs", "' . $row->grp_perm_slugs . '" ),
								( ' . $row->grp_ID . ', "perm_files", "' . $row->grp_perm_files . '" ),
								( ' . $row->grp_ID . ', "perm_options", "' . $row->grp_perm_options . '" ),
								( ' . $row->grp_ID . ', "perm_templates", "' . $row->grp_perm_templates . '" )');
        }
        // Drop all converted permissin colums from groups table
        db_drop_col('T_groups', 'grp_perm_spamblacklist');
        db_drop_col('T_groups', 'grp_perm_slugs');
        db_drop_col('T_groups', 'grp_perm_files');
        db_drop_col('T_groups', 'grp_perm_options');
        db_drop_col('T_groups', 'grp_perm_templates');
        task_end();
        task_begin('Upgrading users table, adding user gender...');
        db_add_col('T_users', 'user_gender', 'char(1) NULL DEFAULT NULL AFTER user_showonline');
        task_end();
        task_begin('Upgrading edit timpestamp blog-user permission...');
        db_add_col('T_coll_user_perms', 'bloguser_perm_edit_ts', 'tinyint NOT NULL default 0 AFTER bloguser_perm_delpost');
        $DB->query('UPDATE T_coll_user_perms, T_users
							SET bloguser_perm_edit_ts = 1
							WHERE bloguser_user_ID = user_ID  AND user_level > 4');
        task_end();
        task_begin('Upgrading edit timpestamp blog-group permission...');
        db_add_col('T_coll_group_perms', 'bloggroup_perm_edit_ts', 'tinyint NOT NULL default 0 AFTER bloggroup_perm_delpost');
        $DB->query('UPDATE T_coll_group_perms
							SET bloggroup_perm_edit_ts = 1
							WHERE bloggroup_group_ID = 1');
        task_end();
        task_begin('Upgrading comments table, add trash status...');
        $DB->query("ALTER TABLE T_comments MODIFY COLUMN comment_status ENUM('published','deprecated','draft', 'trash') DEFAULT 'published' NOT NULL");
        task_end();
        task_begin('Upgrading groups admin access permission...');
        $sql = 'SELECT grp_ID, grp_perm_admin
					FROM T_groups';
        $rows = $DB->get_results($sql, OBJECT, 'Get groups admin perms');
        foreach ($rows as $row) {
            switch ($row->grp_perm_admin) {
                case 'visible':
                    $value = 'normal';
                    break;
                case 'hidden':
                    $value = 'restricted';
                    break;
                default:
                    $value = 'none';
            }
            // "IGNORE" is needed if we already created T_groups__groupsettings during upgrade to v0.8.9 at checkpoint 8050
            $DB->query('INSERT IGNORE INTO T_groups__groupsettings( gset_grp_ID, gset_name, gset_value )
							VALUES( ' . $row->grp_ID . ', "perm_admin", "' . $value . '" )');
        }
        db_drop_col('T_groups', 'grp_perm_admin');
        task_end();
        task_begin('Upgrading users table, add users source...');
        db_add_col('T_users', 'user_source', 'varchar(30) NULL');
        task_end();
        task_begin('Upgrading blogs table: more granularity for comment allowing...');
        $DB->query('INSERT INTO T_coll_settings( cset_coll_ID, cset_name, cset_value )
						SELECT blog_ID, "allow_comments", "never"
							FROM T_blogs
							WHERE blog_allowcomments = "never"');
        db_drop_col('T_blogs', 'blog_allowcomments');
        task_end();
        task_begin('Upgrading blogs table: allow_rating fields...');
        $DB->query('UPDATE T_coll_settings
						SET cset_value = "any"
						WHERE cset_value = "always" AND cset_name = "allow_rating"');
        task_end();
        task_begin('Upgrading links table, add link_cmt_ID...');
        $DB->query('ALTER TABLE T_links
						MODIFY COLUMN link_itm_ID int(11) unsigned NULL,
						MODIFY COLUMN link_creator_user_ID int(11) unsigned NULL,
						MODIFY COLUMN link_lastedit_user_ID int(11) unsigned NULL,
						ADD COLUMN link_cmt_ID int(11) unsigned NULL COMMENT "Used for linking files to comments (comment attachments)" AFTER link_itm_ID');
        $DB->query('ALTER TABLE T_links
						ADD INDEX link_cmt_ID ( link_cmt_ID )');
        task_end();
        task_begin('Upgrading filetypes table...');
        // get allowed filetype ids
        $sql = 'SELECT ftyp_ID
					FROM T_filetypes
					WHERE ftyp_allowed != 0';
        $allowed_ids = implode(',', $DB->get_col($sql, 0, 'Get allowed filetypes'));
        // update table column  -- this column is about who can edit the filetype: any user, registered users or only admins.
        $DB->query('ALTER TABLE T_filetypes
						MODIFY COLUMN ftyp_allowed enum("any","registered","admin") NOT NULL default "admin"');
        // update ftyp_allowed column content
        $DB->query('UPDATE T_filetypes
						SET ftyp_allowed = "registered"
						WHERE ftyp_ID IN (' . $allowed_ids . ')');
        $DB->query('UPDATE T_filetypes
						SET ftyp_allowed = "admin"
						WHERE ftyp_ID NOT IN (' . $allowed_ids . ')');
        $DB->query('UPDATE T_filetypes
						SET ftyp_allowed = "any"
						WHERE ftyp_extensions = "gif" OR ftyp_extensions = "png" OR ftyp_extensions LIKE "%jpg%"');
        // Add m4v file type if not exists
        if (!db_key_exists('T_filetypes', 'ftyp_extensions', '"m4v"')) {
            $DB->query('INSERT INTO T_filetypes (ftyp_extensions, ftyp_name, ftyp_mimetype, ftyp_icon, ftyp_viewtype, ftyp_allowed)
				             VALUES ("m4v", "MPEG video file", "video/x-m4v", "", "browser", "registered")', 'Add "m4v" file type');
        }
        task_end();
        // The AdSense plugin needs to store quite long strings of data...
        task_begin('Upgrading collection settings table, change cset_value type...');
        $DB->query('ALTER TABLE T_coll_settings
								 MODIFY COLUMN cset_name VARCHAR(50) NOT NULL,
								 MODIFY COLUMN cset_value VARCHAR(10000) NULL');
        task_end();
        set_upgrade_checkpoint('10100');
    }
    if ($old_db_version < 10200) {
        // 4.1b
        task_begin('Creating table for a specific blog post subscriptions...');
        $DB->query("CREATE TABLE T_items__subscriptions (\n\t\t\t\t\t\tisub_item_ID  int(11) unsigned NOT NULL,\n\t\t\t\t\t\tisub_user_ID  int(11) unsigned NOT NULL,\n\t\t\t\t\t\tisub_comments tinyint(1) NOT NULL default 0 COMMENT 'The user wants to receive notifications for new comments on this post',\n\t\t\t\t\t\tPRIMARY KEY (isub_item_ID, isub_user_ID )\n\t\t\t\t\t) ENGINE = innodb");
        task_end();
        task_begin('Upgrading comments table, add subscription fields...');
        db_add_col('T_comments', 'comment_notif_status', 'ENUM("noreq","todo","started","finished") NOT NULL DEFAULT "noreq" COMMENT "Have notifications been sent for this comment? How far are we in the process?" AFTER comment_secret');
        db_add_col('T_comments', 'comment_notif_ctsk_ID', 'INT(10) unsigned NULL DEFAULT NULL COMMENT "When notifications for this comment are sent through a scheduled job, what is the job ID?" AFTER comment_notif_status');
        task_end();
        task_begin('Upgrading users table...');
        db_add_col('T_users', 'user_notify_moderation', 'tinyint(1) NOT NULL default 0 COMMENT "Notify me by email whenever a comment is awaiting moderation on one of my blogs" AFTER user_notify');
        db_add_col('T_users', 'user_unsubscribe_key', 'varchar(32) NOT NULL default "" COMMENT "A specific key, it is used when a user wants to unsubscribe from a post comments without signing in" AFTER user_notify_moderation');
        // Set unsubscribe keys for existing users with no unsubscribe key
        $sql = 'SELECT user_ID
							FROM T_users
						 WHERE user_unsubscribe_key = ""';
        $rows = $DB->get_results($sql, OBJECT, 'Get users with no unsubscribe key');
        foreach ($rows as $row) {
            $DB->query('UPDATE T_users
							SET user_unsubscribe_key = "' . generate_random_key() . '"
							WHERE user_ID = ' . $row->user_ID);
        }
        task_end();
        task_begin('Upgrading settings table... ');
        // This query was removed later, to avoid performance issue because of the smart view counting
        /*$DB->query( 'INSERT INTO T_settings (set_name, set_value)
        		VALUES ( "smart_hit_count", 1 )' );*/
        $DB->query('ALTER TABLE T_coll_settings
									CHANGE COLUMN cset_value cset_value   VARCHAR( 10000 ) NULL COMMENT "The AdSense plugin wants to store very long snippets of HTML"');
        task_end();
        // The following two upgrade task were created subsequently to "Make sure DB schema is up to date".
        // Note: These queries don't modify the correct databases
        task_begin('Upgrading users table, no notification by default...');
        $DB->query('ALTER TABLE T_users ALTER COLUMN user_notify SET DEFAULT 0');
        task_end();
        task_begin('Upgrading items table...');
        $DB->query('ALTER TABLE T_items__item CHANGE COLUMN post_priority post_priority int(11) unsigned null COMMENT "Task priority in workflow"');
        task_end();
        set_upgrade_checkpoint('10200');
    }
    if ($old_db_version < 10300) {
        // 4.2
        task_begin('Upgrading user fields...');
        $DB->query('ALTER TABLE T_users__fielddefs
									ADD COLUMN ufdf_required enum("hidden","optional","recommended","require") NOT NULL default "optional"');
        $DB->query('UPDATE T_users__fielddefs
										SET ufdf_required = "recommended"
									WHERE ufdf_name in ("Website", "Twitter", "Facebook") ');
        $DB->query("REPLACE INTO T_users__fielddefs (ufdf_ID, ufdf_type, ufdf_name, ufdf_required)\n\t\t\t \t\t\t\t\t\tVALUES (400000, 'text', 'About me', 'recommended');");
        task_end();
        task_begin('Moving data to user fields...');
        $DB->query('INSERT INTO T_users__fields( uf_user_ID, uf_ufdf_ID, uf_varchar )
								 SELECT user_ID, 10300, user_icq
									 FROM T_users
								  WHERE user_icq IS NOT NULL AND TRIM(user_icq) <> ""');
        $DB->query('INSERT INTO T_users__fields( uf_user_ID, uf_ufdf_ID, uf_varchar )
								 SELECT user_ID, 10200, user_aim
									 FROM T_users
								  WHERE user_aim IS NOT NULL AND TRIM(user_aim) <> ""');
        $DB->query('INSERT INTO T_users__fields( uf_user_ID, uf_ufdf_ID, uf_varchar )
								 SELECT user_ID, 10000, user_msn
									 FROM T_users
								  WHERE user_msn IS NOT NULL AND TRIM(user_msn) <> ""');
        $DB->query('INSERT INTO T_users__fields( uf_user_ID, uf_ufdf_ID, uf_varchar )
								 SELECT user_ID, 10100, user_yim
									 FROM T_users
								  WHERE user_yim IS NOT NULL AND TRIM(user_yim) <> ""');
        task_end();
        task_begin('Dropping obsolete user columns...');
        $DB->query('ALTER TABLE T_users
									DROP COLUMN user_icq,
									DROP COLUMN user_aim,
									DROP COLUMN user_msn,
									DROP COLUMN user_yim');
        task_end();
        // ---
        task_begin('Adding new user columns...');
        $DB->query('ALTER TABLE T_users
									ADD COLUMN user_postcode varchar(12) NULL AFTER user_ID,
									ADD COLUMN user_age_min int unsigned NULL AFTER user_postcode,
									ADD COLUMN user_age_max int unsigned NULL AFTER user_age_min');
        task_end();
        task_begin('Upgrading item table for hide teaser...');
        $DB->query('ALTER TABLE T_items__item
						ADD COLUMN post_hideteaser tinyint(1) NOT NULL DEFAULT 0 AFTER post_featured');
        $DB->query('UPDATE T_items__item
										SET post_hideteaser = 1
									WHERE post_content LIKE "%<!--noteaser-->%"');
        task_end();
        task_begin('Creating table for a specific post settings...');
        $DB->query("CREATE TABLE T_items__item_settings (\n\t\t\t\t\t\tiset_item_ID  int(10) unsigned NOT NULL,\n\t\t\t\t\t\tiset_name     varchar( 50 ) NOT NULL,\n\t\t\t\t\t\tiset_value    varchar( 2000 ) NULL,\n\t\t\t\t\t\tPRIMARY KEY ( iset_item_ID, iset_name )\n\t\t\t\t\t) ENGINE = innodb");
        task_end();
        task_begin('Adding new column to comments...');
        $DB->query('ALTER TABLE T_comments
									ADD COLUMN comment_in_reply_to_cmt_ID INT(10) unsigned NULL AFTER comment_status');
        task_end();
        task_begin('Create table for internal searches...');
        $DB->query('CREATE TABLE T_logs__internal_searches (
						isrch_ID bigint(20) NOT NULL auto_increment,
						isrch_coll_ID bigint(20) NOT NULL,
						isrch_hit_ID bigint(20) NOT NULL,
						isrch_keywords varchar(255) NOT NULL,
						PRIMARY KEY (isrch_ID)
					) ENGINE = MyISAM');
        task_end();
        task_begin('Create table for comments votes...');
        $DB->query('CREATE TABLE T_comments__votes (
						cmvt_cmt_ID  int(10) unsigned NOT NULL,
						cmvt_user_ID int(10) unsigned NOT NULL,
						cmvt_helpful TINYINT(1) NULL DEFAULT NULL,
						cmvt_spam    TINYINT(1) NULL DEFAULT NULL,
						PRIMARY KEY (cmvt_cmt_ID, cmvt_user_ID),
						KEY cmvt_cmt_ID (cmvt_cmt_ID),
						KEY cmvt_user_ID (cmvt_user_ID)
					) ENGINE = innodb');
        task_end();
        task_begin('Adding new comments columns...');
        $DB->query('ALTER TABLE T_comments
									ADD comment_helpful_addvotes INT NOT NULL DEFAULT 0 AFTER comment_nofollow ,
									ADD comment_helpful_countvotes INT UNSIGNED NOT NULL DEFAULT 0 AFTER comment_helpful_addvotes ,
									ADD comment_spam_addvotes INT NOT NULL DEFAULT 0 AFTER comment_helpful_countvotes ,
									ADD comment_spam_countvotes INT UNSIGNED NOT NULL DEFAULT 0 AFTER comment_spam_addvotes ,
									CHANGE COLUMN comment_notif_ctsk_ID comment_notif_ctsk_ID      INT(10) unsigned NULL DEFAULT NULL COMMENT "When notifications for this comment are sent through a scheduled job, what is the job ID?"');
        task_end();
        task_begin('Adding new user permission for spam voting...');
        $DB->query('ALTER TABLE T_coll_user_perms
									ADD bloguser_perm_vote_spam_cmts tinyint NOT NULL default 0 AFTER bloguser_perm_edit_ts');
        task_end();
        task_begin('Adding new group permission for spam voting...');
        $DB->query('ALTER TABLE T_coll_group_perms
									ADD bloggroup_perm_vote_spam_cmts tinyint NOT NULL default 0 AFTER bloggroup_perm_edit_ts');
        task_end();
        task_begin('Upgrading countries table...');
        $DB->query('ALTER TABLE ' . $tableprefix . 'country ADD COLUMN ctry_preferred tinyint(1) NOT NULL DEFAULT 0 AFTER ctry_enabled');
        task_end();
        $DB->query('ALTER TABLE T_items__subscriptions CHANGE COLUMN isub_comments isub_comments   tinyint(1) NOT NULL DEFAULT 0 COMMENT "The user wants to receive notifications for new comments on this post"');
        set_upgrade_checkpoint('10300');
    }
    if ($old_db_version < 10400) {
        // 4.2 part 2
        task_begin('Updating "Post by Email" settings...');
        $DB->query('UPDATE T_settings SET set_name = "eblog_autobr" WHERE set_name = "AutoBR"');
        task_end();
        if ($DB->get_var('SELECT set_value FROM T_settings WHERE set_name = "eblog_enabled"')) {
            // eblog enabled, let's create a scheduled job for it
            task_begin('Creating "Post by Email" scheduled job...');
            $start_date = form_date(date2mysql($GLOBALS['localtimenow'] + 86400), '05:00:00');
            // start tomorrow
            $DB->query('
				INSERT INTO T_cron__task ( ctsk_start_datetime, ctsk_repeat_after, ctsk_name, ctsk_controller, ctsk_params )
				VALUES ( ' . $DB->quote($start_date) . ', 86400, ' . $DB->quote(T_('Create posts by email')) . ', ' . $DB->quote('cron/jobs/_post_by_email.job.php') . ', ' . $DB->quote('N;') . ' )');
            task_end();
        }
        task_begin('Upgrading hitlog table...');
        $DB->query('ALTER TABLE T_hitlog
								ADD COLUMN hit_disp        VARCHAR(30) DEFAULT NULL AFTER hit_uri,
								ADD COLUMN hit_ctrl        VARCHAR(30) DEFAULT NULL AFTER hit_disp,
								ADD COLUMN hit_response_code     INT DEFAULT NULL AFTER hit_agent_type ');
        task_end();
        task_begin('Upgrading file types...');
        // Update ftyp_icon column
        // Previous versions used a image file name for this field,
        // but from now we should use a icon name from the file /conf/_icons.php
        $DB->query('UPDATE T_filetypes
						SET ftyp_icon = "file_image"
						WHERE ftyp_extensions IN ( "gif", "png", "jpg jpeg" )');
        $DB->query('UPDATE T_filetypes
						SET ftyp_icon = "file_document"
						WHERE ftyp_extensions = "txt"');
        $DB->query('UPDATE T_filetypes
						SET ftyp_icon = "file_www"
						WHERE ftyp_extensions = "htm html"');
        $DB->query('UPDATE T_filetypes
						SET ftyp_icon = "file_pdf"
						WHERE ftyp_extensions = "pdf"');
        $DB->query('UPDATE T_filetypes
						SET ftyp_icon = "file_doc"
						WHERE ftyp_extensions = "doc"');
        $DB->query('UPDATE T_filetypes
						SET ftyp_icon = "file_xls"
						WHERE ftyp_extensions = "xls"');
        $DB->query('UPDATE T_filetypes
						SET ftyp_icon = "file_ppt"
						WHERE ftyp_extensions = "ppt"');
        $DB->query('UPDATE T_filetypes
						SET ftyp_icon = "file_pps"
						WHERE ftyp_extensions = "pps"');
        $DB->query('UPDATE T_filetypes
						SET ftyp_icon = "file_zip"
						WHERE ftyp_extensions = "zip"');
        $DB->query('UPDATE T_filetypes
						SET ftyp_icon = "file_php"
						WHERE ftyp_extensions = "php php3 php4 php5 php6"');
        $DB->query('UPDATE T_filetypes
						SET ftyp_icon = ""
						WHERE ftyp_extensions = "css"');
        $DB->query('UPDATE T_filetypes
						SET ftyp_icon = "file_sound"
						WHERE ftyp_extensions IN ( "mp3", "m4a" )');
        $DB->query('UPDATE T_filetypes
						SET ftyp_icon = "file_video"
						WHERE ftyp_extensions IN ( "mp4", "mov", "m4v" )');
        task_end();
        set_upgrade_checkpoint('10400');
    }
    if ($old_db_version < 10500) {
        //  part 3
        task_begin('Upgrading hitlog table...');
        $DB->query("ALTER TABLE T_hitlog\n\t\t\t\t\t\t\t\tCHANGE COLUMN hit_referer_type  hit_referer_type ENUM(  'search',  'special',  'spam',  'referer',  'direct',  'self',  'admin', 'blacklist' ) NOT NULL,\n\t\t\t\t\t\t\t\tADD COLUMN hit_type ENUM('standard','rss','admin','ajax', 'service') DEFAULT 'standard' NOT NULL AFTER hit_ctrl,\n\t\t\t\t\t\t\t\tADD COLUMN hit_action VARCHAR(30) DEFAULT NULL AFTER hit_ctrl");
        $DB->query('UPDATE T_hitlog SET hit_referer_type = "special" WHERE hit_referer_type = "blacklist"');
        $DB->query('UPDATE T_hitlog SET hit_type = "admin", hit_referer_type = "direct"  WHERE hit_referer_type = "admin"');
        $DB->query("ALTER TABLE T_hitlog\n\t\t\t\t\t\t\t\tCHANGE COLUMN hit_referer_type  hit_referer_type ENUM(  'search',  'special',  'spam',  'referer',  'direct',  'self' ) NOT NULL");
        task_end();
        task_begin('Creating table for Groups of user field definitions...');
        $DB->query('CREATE TABLE T_users__fieldgroups (
				ufgp_ID int(10) unsigned NOT NULL auto_increment,
				ufgp_name varchar(255) NOT NULL,
				ufgp_order int(11) NOT NULL,
				PRIMARY KEY (ufgp_ID)
			) ENGINE = innodb');
        $DB->query('INSERT INTO T_users__fieldgroups ( ufgp_name, ufgp_order )
				VALUES ( "Instant Messaging", "1" ),
							 ( "Phone", "2" ),
							 ( "Web", "3" ),
							 ( "Organization", "4" ),
							 ( "Address", "5" ),
							 ( "Other", "6" ) ');
        task_end();
        task_begin('Upgrading user field definitions...');
        // Add new fields:
        // 		"ufdf_options" to save a values of the Option list
        // 		"ufdf_duplicated" to add a several instances
        // 		"ufdf_ufgp_ID" - Group ID
        // 		"ufdf_order" - Order number
        // 		"ufdf_suggest" - Suggest values
        $DB->query('ALTER TABLE T_users__fielddefs
						ADD ufdf_options    TEXT NOT NULL AFTER ufdf_name,
						ADD ufdf_duplicated enum("forbidden","allowed","list") NOT NULL default "allowed",
						ADD ufdf_ufgp_ID    int(10) unsigned NOT NULL AFTER ufdf_ID,
						ADD ufdf_order      int(11) NOT NULL,
						ADD ufdf_suggest    tinyint(1) NOT NULL DEFAULT 0,
						CHANGE ufdf_ID ufdf_ID int(10) UNSIGNED NOT NULL AUTO_INCREMENT');
        // Set default values of the field "ufdf_duplicated"
        $DB->query('UPDATE T_users__fielddefs
						SET ufdf_duplicated = "allowed"
						WHERE ufdf_ID IN ( 10000, 10100, 10200, 10300, 50100, 50200, 100000, 100100 )');
        // Group fields by default
        $DB->query('UPDATE T_users__fielddefs
						SET ufdf_ufgp_ID = "1"
						WHERE ufdf_ID <= 40000 ');
        $DB->query('UPDATE T_users__fielddefs
						SET ufdf_ufgp_ID = "2"
						WHERE ufdf_ID > 40000 AND ufdf_ID <= 60100');
        $DB->query('UPDATE T_users__fielddefs
						SET ufdf_ufgp_ID = "3"
						WHERE ufdf_ID > 60100 AND ufdf_ID <= 160100');
        $DB->query('UPDATE T_users__fielddefs
						SET ufdf_ufgp_ID = "4"
						WHERE ufdf_ID > 160100 AND ufdf_ID <= 211000');
        $DB->query('UPDATE T_users__fielddefs
						SET ufdf_ufgp_ID = "5"
						WHERE ufdf_ID > 211000 AND ufdf_ID <= 300300');
        $DB->query('UPDATE T_users__fielddefs
						SET ufdf_ufgp_ID = "6"
						WHERE ufdf_ID > 300300');
        // Set order field
        $userfields = $DB->get_results('SELECT ufdf_ID, ufdf_ufgp_ID
				FROM T_users__fielddefs
				ORDER BY ufdf_ufgp_ID, ufdf_ID');
        $userfield_order = 1;
        foreach ($userfields as $uf => $userfield) {
            if ($uf > 0) {
                if ($userfields[$uf - 1]->ufdf_ufgp_ID != $userfield->ufdf_ufgp_ID) {
                    // New group is starting, reset $userfield_order
                    $userfield_order = 1;
                }
            }
            $DB->query('UPDATE T_users__fielddefs
						SET ufdf_order = "' . $userfield_order . '"
						WHERE ufdf_ID = ' . $userfield->ufdf_ID);
            $userfield_order++;
        }
        // Change field type for Group 'Organization' (group_ID=4)
        $DB->query('UPDATE T_users__fielddefs
					SET ufdf_type = "word"
					WHERE ufdf_ufgp_ID = "4"');
        // Create a default additional info for administrator (user_ID=1)
        $DB->query('INSERT INTO T_users__fields ( uf_user_ID, uf_ufdf_ID, uf_varchar )
			VALUES ( 1, 200000, "Site administrator" ),
						 ( 1, 200000, "Moderator" ),
						 ( 1, 100000, "' . $baseurl . '" )');
        // Add Indexes
        $DB->query('ALTER TABLE T_users__fields
						ADD INDEX uf_ufdf_ID ( uf_ufdf_ID ),
						ADD INDEX uf_varchar ( uf_varchar ) ');
        task_end();
        task_begin('Upgrading permissions...');
        // Group permissions
        $DB->query('ALTER TABLE T_coll_group_perms
						ADD bloggroup_perm_own_cmts tinyint NOT NULL default 0 AFTER bloggroup_perm_edit_ts');
        // Set default values for Administrators & Privileged Bloggers groups
        $DB->query('UPDATE T_coll_group_perms
						SET bloggroup_perm_own_cmts = "1"
						WHERE bloggroup_group_ID IN ( 1, 2 )');
        // User permissions
        $DB->query('ALTER TABLE T_coll_user_perms
						ADD bloguser_perm_own_cmts tinyint NOT NULL default 0 AFTER bloguser_perm_edit_ts');
        task_end();
        set_upgrade_checkpoint('10500');
    }
    if ($old_db_version < 10600) {
        //  part 4
        // For create_default_regions() and create_default_subregions():
        require_once dirname(__FILE__) . '/_functions_create.php';
        task_begin('Renaming Countries table...');
        $DB->query('RENAME TABLE ' . $tableprefix . 'country TO T_regional__country');
        task_end();
        task_begin('Renaming Currencies table...');
        $DB->query('RENAME TABLE ' . $tableprefix . 'currency TO T_regional__currency');
        task_end();
        task_begin('Creating Regions table...');
        $DB->query('CREATE TABLE T_regional__region (
			rgn_ID        int(10) unsigned NOT NULL auto_increment,
			rgn_ctry_ID   int(10) unsigned NOT NULL,
			rgn_code      char(6) NOT NULL,
			rgn_name      varchar(40) NOT NULL,
			rgn_enabled   tinyint(1) NOT NULL DEFAULT 1,
			rgn_preferred tinyint(1) NOT NULL DEFAULT 0,
			PRIMARY KEY rgn_ID (rgn_ID),
			UNIQUE rgn_ctry_ID_code (rgn_ctry_ID, rgn_code)
		) ENGINE = innodb');
        task_end();
        create_default_regions();
        task_begin('Creating Sub-regions table...');
        $DB->query('CREATE TABLE T_regional__subregion (
			subrg_ID        int(10) unsigned NOT NULL auto_increment,
			subrg_rgn_ID    int(10) unsigned NOT NULL,
			subrg_code      char(6) NOT NULL,
			subrg_name      varchar(40) NOT NULL,
			subrg_enabled   tinyint(1) NOT NULL DEFAULT 1,
			subrg_preferred tinyint(1) NOT NULL DEFAULT 0,
			PRIMARY KEY subrg_ID (subrg_ID),
			UNIQUE subrg_rgn_ID_code (subrg_rgn_ID, subrg_code)
		) ENGINE = innodb');
        task_end();
        create_default_subregions();
        task_begin('Creating Cities table...');
        $DB->query('CREATE TABLE T_regional__city (
			city_ID         int(10) unsigned NOT NULL auto_increment,
			city_ctry_ID    int(10) unsigned NOT NULL,
			city_rgn_ID     int(10) unsigned NULL,
			city_subrg_ID   int(10) unsigned NULL,
			city_postcode   char(12) NOT NULL,
			city_name       varchar(40) NOT NULL,
			city_enabled    tinyint(1) NOT NULL DEFAULT 1,
			city_preferred  tinyint(1) NOT NULL DEFAULT 0,
			PRIMARY KEY city_ID (city_ID),
			INDEX city_ctry_ID_postcode ( city_ctry_ID, city_postcode ),
			INDEX city_rgn_ID_postcode ( city_rgn_ID, city_postcode ),
			INDEX city_subrg_ID_postcode ( city_subrg_ID, city_postcode )
		) ENGINE = innodb');
        task_end();
        task_begin('Update Item Settings...');
        // Admin: full rights for all blogs (look 'ma, doing a natural join! :>)
        $query = "INSERT INTO T_items__item_settings( iset_item_ID, iset_name, iset_value )\n\t\t\t\t\t\tSELECT post_ID, 'hide_teaser', post_hideteaser\n\t\t\t\t\t\t\tFROM T_items__item";
        $DB->query($query);
        db_drop_col('T_items__item', 'post_hideteaser');
        task_end();
        task_begin('Upgrading hitlog table...');
        $DB->query("ALTER TABLE T_hitlog\n\t\t\t\t\t\tADD COLUMN hit_keyphrase VARCHAR(255) DEFAULT NULL AFTER hit_keyphrase_keyp_ID");
        task_end();
        task_begin('Upgrading track__keyphrase...');
        $DB->query("ALTER TABLE T_track__keyphrase\n\t\t\t\t\t\tADD COLUMN keyp_count_refered_searches INT UNSIGNED DEFAULT 0 AFTER keyp_phrase,\n\t\t\t\t\t\tADD COLUMN keyp_count_internal_searches INT UNSIGNED DEFAULT 0 AFTER keyp_count_refered_searches");
        task_end();
        task_begin('Droping table internal searches...');
        $DB->query("DROP TABLE T_logs__internal_searches");
        task_end();
        task_begin('Upgrading users table...');
        db_add_col('T_users', 'user_rgn_ID', 'int(10) unsigned NULL AFTER user_ctry_ID');
        db_add_col('T_users', 'user_subrg_ID', 'int(10) unsigned NULL AFTER user_rgn_ID');
        db_add_col('T_users', 'user_city_ID', 'int(10) unsigned NULL AFTER user_subrg_ID');
        task_end();
        task_begin('Upgrading hitlog table...');
        $DB->query('UPDATE T_hitlog
						SET hit_type = "rss",
							hit_agent_type = "unknown"
						WHERE hit_agent_type = "rss"');
        $DB->query("ALTER TABLE T_hitlog\n\t\t\t\t\t\t\t\tCHANGE COLUMN hit_agent_type hit_agent_type ENUM('robot','browser','unknown') DEFAULT 'unknown' NOT NULL");
        task_end();
        task_begin('Creating mail log table...');
        $DB->query('CREATE TABLE ' . $tableprefix . 'mail__log (
		  emlog_ID        INT(10) UNSIGNED NOT NULL auto_increment,
		  emlog_timestamp TIMESTAMP NOT NULL,
		  emlog_to        VARCHAR(255) DEFAULT NULL,
		  emlog_success   TINYINT(1) NOT NULL DEFAULT 0,
		  emlog_subject   VARCHAR(255) DEFAULT NULL,
		  emlog_headers   TEXT DEFAULT NULL,
		  emlog_message   TEXT DEFAULT NULL,
		  PRIMARY KEY     (emlog_ID)
		) ENGINE = myisam');
        task_end();
        set_upgrade_checkpoint('10600');
    }
    if ($old_db_version < 10700) {
        // part 5
        task_begin('Upgrading user notifications settings...');
        $DB->query('INSERT INTO T_users__usersettings ( uset_user_ID, uset_name, uset_value )
						SELECT user_ID, "notify_published_comments", user_notify
							FROM T_users', 'Move notify settings from users to users_usersettings');
        $DB->query('INSERT INTO T_users__usersettings ( uset_user_ID, uset_name, uset_value )
						SELECT user_ID, "notify_comment_moderation", user_notify_moderation
							FROM T_users', 'Move notify moderation settings from users to users_usersettings');
        $DB->query('INSERT INTO T_users__usersettings ( uset_user_ID, uset_name, uset_value )
						SELECT user_ID, "enable_PM", 1
							FROM T_users
								WHERE user_allow_msgform = 1 OR user_allow_msgform = 3', 'Set enable PM on users_usersettings');
        $DB->query('INSERT INTO T_users__usersettings ( uset_user_ID, uset_name, uset_value )
						SELECT user_ID, "enable_PM", 0
							FROM T_users
								WHERE user_allow_msgform = 0 OR user_allow_msgform = 2', 'Set enable PM on users_usersettings');
        $DB->query('INSERT INTO T_users__usersettings ( uset_user_ID, uset_name, uset_value )
						SELECT user_ID, "enable_email", 1
							FROM T_users
								WHERE user_allow_msgform > 1', 'Set enable email true on users_usersettings');
        $DB->query('INSERT INTO T_users__usersettings ( uset_user_ID, uset_name, uset_value )
						SELECT user_ID, "enable_email", 0
							FROM T_users
								WHERE user_allow_msgform < 2', 'Set enable email false on users_usersettings');
        db_drop_col('T_users', 'user_notify');
        db_drop_col('T_users', 'user_notify_moderation');
        db_drop_col('T_users', 'user_allow_msgform');
        task_end();
        task_begin('Upgrading Item table...');
        db_add_col('T_items__item', 'post_ctry_ID', 'INT(10) UNSIGNED NULL');
        db_add_col('T_items__item', 'post_rgn_ID', 'INT(10) UNSIGNED NULL');
        db_add_col('T_items__item', 'post_subrg_ID', 'INT(10) UNSIGNED NULL');
        db_add_col('T_items__item', 'post_city_ID', 'INT(10) UNSIGNED NULL');
        task_end();
        task_begin('Upgrading users table...');
        db_drop_col('T_users', 'user_postcode');
        // Previously obsoleted
        db_drop_col('T_users', 'user_idmode');
        task_end();
        task_begin('Upgrading users fields table...');
        db_add_col('T_users__fielddefs', 'ufdf_bubbletip', 'varchar(2000) NULL');
        task_end();
        task_begin('Creating table for groups of messaging contacts...');
        $DB->query("CREATE TABLE IF NOT EXISTS T_messaging__contact_groups (\n\t\t\tcgr_ID      int(10) unsigned NOT NULL auto_increment,\n\t\t\tcgr_user_ID int(10) unsigned NOT NULL,\n\t\t\tcgr_name    varchar(50) NOT NULL,\n\t\t\tPRIMARY KEY cgr_ID (cgr_ID)\n\t\t) ENGINE = innodb");
        task_end();
        task_begin('Creating table for group users of messaging contacts...');
        $DB->query("CREATE TABLE T_messaging__contact_groupusers (\n\t\t\tcgu_user_ID int(10) unsigned NOT NULL,\n\t\t\tcgu_cgr_ID  int(10) unsigned NOT NULL,\n\t\t\tPRIMARY KEY cgu_PK (cgu_user_ID, cgu_cgr_ID)\n\t\t) ENGINE = innodb");
        task_end();
        task_begin('Upgrading mail log table...');
        db_add_col($tableprefix . 'mail__log', 'emlog_user_ID', 'INT(10) UNSIGNED DEFAULT NULL AFTER emlog_timestamp');
        task_end();
        set_upgrade_checkpoint('10700');
    }
    if ($old_db_version < 10800) {
        // part 6 aka between "i1-i2" and "i2"
        task_begin('Upgrading users table, add user status...');
        db_add_col('T_users', 'user_status', 'enum( "activated", "autoactivated", "closed", "deactivated", "emailchanged", "new" ) NOT NULL default "new" AFTER user_validated');
        $update_user_status_query = 'UPDATE T_users SET user_status = ';
        // check if new users must activate their account. If users are not required to activate their account, then all existing users will be considerated as activated user.
        $new_users_must_validate = $DB->get_var('SELECT set_value FROM T_settings WHERE set_name = ' . $DB->quote('newusers_mustvalidate'));
        if ($new_users_must_validate || $new_users_must_validate == NULL) {
            // newusers_mustvalidate setting is set to true, or it is not set at all. If it is not set, we know that the default value is true!
            // set activated status only for validated users
            $update_user_status_query .= $DB->quote('activated');
            $update_user_status_query .= ' WHERE user_validated = 1';
        } else {
            $update_user_status_query .= $DB->quote('autoactivated');
        }
        // set activated status for corresponding users
        $DB->query($update_user_status_query);
        db_drop_col('T_users', 'user_validated');
        task_end();
        set_upgrade_checkpoint('10800');
    }
    if ($old_db_version < 10900) {
        // part 7 aka "i3"
        task_begin('Upgrading user settings table...');
        $DB->query('INSERT INTO T_users__usersettings ( uset_user_ID, uset_name, uset_value )
						SELECT user_ID, "show_online", 0
							FROM T_users
								WHERE user_showonline = 0', 'Set show online on users_usersettings');
        $DB->query('INSERT INTO T_users__usersettings ( uset_user_ID, uset_name, uset_value )
						SELECT user_ID, "user_ip", user_ip
							FROM T_users
								WHERE user_ip IS NOT NULL', 'Set user ip on users_usersettings');
        $DB->query('INSERT INTO T_users__usersettings ( uset_user_ID, uset_name, uset_value )
						SELECT user_ID, "user_domain", user_domain
							FROM T_users
								WHERE user_domain IS NOT NULL', 'Set user domain on users_usersettings');
        $DB->query('INSERT INTO T_users__usersettings ( uset_user_ID, uset_name, uset_value )
						SELECT user_ID, "user_browser", user_browser
							FROM T_users
								WHERE user_browser IS NOT NULL', 'Set user browser on users_usersettings');
        db_drop_col('T_users', 'user_showonline');
        db_drop_col('T_users', 'user_ip');
        db_drop_col('T_users', 'user_domain');
        db_drop_col('T_users', 'user_browser');
        task_end();
        task_begin('Upgrading user activation settings...');
        // Remove all last_activation_email timestamps because we will use date instead of them
        $DB->query('DELETE FROM T_users__usersettings WHERE uset_name = "last_activation_email"');
        task_end();
        task_begin('Upgrading Users table...');
        // Update user_status column add 'failedactivation' status
        $DB->query('ALTER TABLE T_users CHANGE user_status
					user_status enum( "activated", "autoactivated", "closed", "deactivated", "emailchanged", "failedactivation", "new" ) NOT NULL default "new"');
        db_add_col('T_users', 'user_created_fromIPv4', 'int(10) unsigned NOT NULL');
        db_add_col('T_users', 'user_email_dom_ID', 'int(10) unsigned NULL');
        $DB->query('ALTER TABLE T_users CHANGE dateYMDhour user_created_datetime DATETIME NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        db_add_col('T_users', 'user_reg_ctry_ID', 'int(10) unsigned NULL AFTER user_age_max');
        db_add_col('T_users', 'user_profileupdate_ts', 'TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP');
        $DB->query('ALTER TABLE T_users ADD INDEX user_email ( user_email )');
        task_end();
        task_begin('Renaming Email log table...');
        $DB->query('RENAME TABLE ' . $tableprefix . 'mail__log TO T_email__log');
        task_end();
        task_begin('Creating email returns table...');
        $DB->query("CREATE TABLE T_email__returns (\n\t\t\t  emret_ID        INT(10) UNSIGNED NOT NULL auto_increment,\n\t\t\t  emret_address   VARCHAR(255) DEFAULT NULL,\n\t\t\t  emret_errormsg  VARCHAR(255) DEFAULT NULL,\n\t\t\t  emret_timestamp TIMESTAMP NOT NULL,\n\t\t\t  emret_headers   TEXT DEFAULT NULL,\n\t\t\t  emret_message   TEXT DEFAULT NULL,\n\t\t\t  emret_errtype   CHAR(1) NOT NULL DEFAULT 'U',\n\t\t\t  PRIMARY KEY     (emret_ID)\n\t\t\t) ENGINE = myisam");
        task_end();
        task_begin('Upgrading general settings table...');
        $DB->query('ALTER TABLE T_settings CHANGE set_value set_value VARCHAR( 5000 ) NULL');
        task_end();
        task_begin('Upgrading sessions table...');
        db_add_col('T_sessions', 'sess_device', 'VARCHAR(8) NOT NULL DEFAULT \'\'');
        task_end();
        task_begin('Creating table for Antispam IP Ranges...');
        $DB->query("CREATE TABLE T_antispam__iprange (\n\t\t\taipr_ID         int(10) unsigned NOT NULL auto_increment,\n\t\t\taipr_IPv4start  int(10) unsigned NOT NULL,\n\t\t\taipr_IPv4end    int(10) unsigned NOT NULL,\n\t\t\taipr_IP_timestamp        datetime not null DEFAULT '2000-01-01 00:00:00',\n\t\t\taipr_user_count int(10) unsigned DEFAULT 0,\n\t\t\tPRIMARY KEY aipr_ID (aipr_ID)\n\t\t) ENGINE = innodb");
        task_end();
        task_begin('Upgrading base domains table...');
        $DB->query("ALTER TABLE T_basedomains CHANGE dom_type dom_type ENUM( 'unknown', 'normal', 'searcheng', 'aggregator', 'email' ) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT 'unknown'");
        $DB->query('ALTER TABLE T_basedomains DROP INDEX dom_name');
        $DB->query('ALTER TABLE T_basedomains DROP INDEX dom_type');
        $DB->query('ALTER TABLE T_basedomains ADD UNIQUE dom_type_name ( dom_type, dom_name )');
        task_end();
        /*** Update user_email_dom_ID for all already existing users ***/
        task_begin('Upgrading users email domains...');
        $DB->begin();
        // Get the users
        $uemails_SQL = new SQL();
        $uemails_SQL->SELECT('user_ID, user_email');
        $uemails_SQL->FROM('T_users');
        $users_emails = $DB->get_assoc($uemails_SQL->get());
        if (count($users_emails) > 0) {
            // Get all email domains
            $edoms_SQL = new SQL();
            $edoms_SQL->SELECT('dom_ID, dom_name');
            $edoms_SQL->FROM('T_basedomains');
            $edoms_SQL->WHERE('dom_type = \'email\'');
            $email_domains = $DB->get_assoc($edoms_SQL->get());
            // pre_dump( $email_domains );
            foreach ($users_emails as $user_ID => $user_email) {
                if (preg_match('#@(.+)#i', strtolower($user_email), $ematch)) {
                    // Get email domain from user's email address
                    $email_domain = $ematch[1];
                    $dom_ID = array_search($email_domain, $email_domains);
                    if (!$dom_ID) {
                        // Insert new email domain
                        $DB->query('INSERT INTO T_basedomains ( dom_type, dom_name )
							VALUES ( \'email\', ' . $DB->quote($email_domain) . ' )');
                        $dom_ID = $DB->insert_id;
                        // Memorize inserted domain to prevent duplicates
                        $email_domains[$dom_ID] = $email_domain;
                        // pre_dump( $dom_ID, $email_domain );
                    }
                    // Update user_email_dom_ID
                    $DB->query('UPDATE T_users
						SET user_email_dom_ID = ' . $DB->quote($dom_ID) . '
						WHERE user_ID = ' . $DB->quote($user_ID));
                }
            }
        }
        $DB->commit();
        task_end();
        task_begin('Upgrading users fields table...');
        // Drop index before increasing a size to avoid an error about "max key length is 767 bytes"
        $DB->query('ALTER TABLE T_users__fields DROP INDEX uf_varchar');
        // Modify field size
        $DB->query('ALTER TABLE T_users__fields CHANGE uf_varchar uf_varchar VARCHAR( 10000 ) NOT NULL');
        // Add index again with limited size in 255 because of utf8 == 765
        $DB->query('ALTER TABLE T_users__fields ADD INDEX uf_varchar ( uf_varchar(255) )');
        task_end();
        task_begin('Upgrading cron tasks table...');
        $DB->query('ALTER TABLE T_cron__task CHANGE ctsk_name ctsk_name VARCHAR(255) NOT NULL');
        task_end();
        task_begin('Upgrading comments table...');
        db_add_col('T_comments', 'comment_IP_ctry_ID', 'int(10) unsigned NULL AFTER comment_author_IP');
        task_end();
        task_begin('Creating table for Blocked Email Addreses...');
        $DB->query("CREATE TABLE {$tableprefix}email__blocked (\n\t\t\temblk_ID                    INT(10) UNSIGNED NOT NULL auto_increment,\n\t\t\temblk_address               VARCHAR(255) DEFAULT NULL,\n\t\t\temblk_status                ENUM ( 'unknown', 'warning', 'suspicious1', 'suspicious2', 'suspicious3', 'prmerror', 'spammer' ) NOT NULL DEFAULT 'unknown',\n\t\t\temblk_sent_count            INT(10) UNSIGNED NOT NULL DEFAULT 0,\n\t\t\temblk_sent_last_returnerror INT(10) UNSIGNED NOT NULL DEFAULT 0,\n\t\t\temblk_prmerror_count        INT(10) UNSIGNED NOT NULL DEFAULT 0,\n\t\t\temblk_tmperror_count        INT(10) UNSIGNED NOT NULL DEFAULT 0,\n\t\t\temblk_spamerror_count       INT(10) UNSIGNED NOT NULL DEFAULT 0,\n\t\t\temblk_othererror_count      INT(10) UNSIGNED NOT NULL DEFAULT 0,\n\t\t\temblk_last_sent_ts          TIMESTAMP NULL,\n\t\t\temblk_last_error_ts         TIMESTAMP NULL,\n\t\t\tPRIMARY KEY                 (emblk_ID),\n\t\t\tUNIQUE                      emblk_address (emblk_address)\n\t\t) ENGINE = myisam");
        task_end();
        task_begin('Upgrading email log table...');
        // Get old values of emlog_success field
        $SQL = new SQL();
        $SQL->SELECT('emlog_ID');
        $SQL->FROM('T_email__log');
        $SQL->WHERE('emlog_success = 0');
        $email_failed_logs = $DB->get_col($SQL->get());
        // Change a field emlog_success to new format
        $DB->query('ALTER TABLE T_email__log CHANGE emlog_success emlog_result ENUM ( "ok", "error", "blocked" ) NOT NULL DEFAULT "ok"');
        if (!empty($email_failed_logs)) {
            // Update only the failed email logs to new values
            // Do NOT update the success email logs, because we already have a result type 'ok' as default
            $DB->query('UPDATE T_email__log
					SET emlog_result = ' . $DB->quote('error') . '
				WHERE emlog_ID IN ( ' . $DB->quote($email_failed_logs) . ' )');
        }
        task_end();
        set_upgrade_checkpoint('10900');
    }
    if ($old_db_version < 10970) {
        // part 8/a trunk aka first part of "i4"
        task_begin('Upgrading Locales table...');
        db_add_col('T_locales', 'loc_transliteration_map', 'VARCHAR(10000) NOT NULL default \'\' AFTER loc_priority');
        task_end();
        task_begin('Upgrading general settings table...');
        $DB->query('UPDATE T_settings SET set_name = ' . $DB->quote('smart_view_count') . ' WHERE set_name = ' . $DB->quote('smart_hit_count'));
        // This query below was added later to turn OFF smart view counting on upgrade from v4 to v5 for better performance
        $DB->query('DELETE FROM T_settings WHERE set_name = ' . $DB->quote('smart_view_count'));
        task_end();
        task_begin('Upgrading sessions table...');
        $DB->query("UPDATE T_sessions SET sess_lastseen = concat( '2000-01-01 ', time( sess_lastseen ) )\n\t\t\t\t\t\tWHERE date( sess_lastseen ) = '1970-01-01'");
        $DB->query("ALTER TABLE T_sessions CHANGE COLUMN sess_lastseen sess_lastseen_ts TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00' COMMENT 'User last logged activation time. Value may be off by up to 60 seconds'");
        db_add_col('T_sessions', 'sess_start_ts', "TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00' AFTER sess_hitcount");
        $DB->query('UPDATE T_sessions SET sess_start_ts = TIMESTAMPADD( SECOND, -1, sess_lastseen_ts )');
        db_drop_col('T_sessions', 'sess_hitcount');
        task_end();
        task_begin('Upgrading users table...');
        db_add_col('T_users', 'user_lastseen_ts', 'TIMESTAMP NULL AFTER user_created_datetime');
        $DB->query('UPDATE T_users SET user_lastseen_ts = ( SELECT MAX( sess_lastseen_ts ) FROM T_sessions WHERE sess_user_ID = user_ID )');
        $DB->query('UPDATE T_users SET user_profileupdate_ts = user_created_datetime WHERE user_profileupdate_ts < user_created_datetime');
        $DB->query("ALTER TABLE T_users CHANGE COLUMN user_profileupdate_ts user_profileupdate_date DATE NOT NULL DEFAULT '2000-01-01' COMMENT 'Last day when the user has updated some visible field in his profile.'");
        task_end();
        task_begin('Updating versions table...');
        db_add_col('T_items__version', 'iver_ID', 'INT UNSIGNED NOT NULL FIRST');
        $DB->query('ALTER TABLE T_items__version DROP INDEX iver_itm_ID, ADD INDEX iver_ID_itm_ID ( iver_ID , iver_itm_ID )');
        task_end();
        task_begin('Upgrading messaging contact group users...');
        db_add_foreign_key('T_messaging__contact_groupusers', 'cgu_cgr_ID', 'T_messaging__contact_groups', 'cgr_ID', 'ON DELETE CASCADE');
        task_end();
        task_begin('Creating table for a latest version of the POT file...');
        $DB->query("CREATE TABLE T_i18n_original_string (\n\t\t\tiost_ID        int(10) unsigned NOT NULL auto_increment,\n\t\t\tiost_string    varchar(10000) NOT NULL default '',\n\t\t\tiost_inpotfile tinyint(1) NOT NULL DEFAULT 0,\n\t\t\tPRIMARY KEY (iost_ID)\n\t\t) ENGINE = innodb");
        task_end();
        task_begin('Creating table for a latest versions of the PO files...');
        $DB->query("CREATE TABLE T_i18n_translated_string (\n\t\t\titst_ID       int(10) unsigned NOT NULL auto_increment,\n\t\t\titst_iost_ID  int(10) unsigned NOT NULL,\n\t\t\titst_locale   varchar(20) NOT NULL default '',\n\t\t\titst_standard varchar(10000) NOT NULL default '',\n\t\t\titst_custom   varchar(10000) NULL,\n\t\t\titst_inpofile tinyint(1) NOT NULL DEFAULT 0,\n\t\t\tPRIMARY KEY (itst_ID)\n\t\t) ENGINE = innodb DEFAULT CHARSET = utf8");
        task_end();
        task_begin('Updating Antispam IP Ranges table...');
        db_add_col('T_antispam__iprange', 'aipr_status', 'enum( \'trusted\', \'suspect\', \'blocked\' ) NULL DEFAULT NULL');
        db_add_col('T_antispam__iprange', 'aipr_block_count', 'int(10) unsigned DEFAULT 0');
        $DB->query("ALTER TABLE T_antispam__iprange CHANGE COLUMN aipr_user_count aipr_user_count int(10) unsigned DEFAULT 0");
        task_end();
        set_upgrade_checkpoint('10970');
    }
    if ($old_db_version < 10975) {
        // part 8/b trunk aka first part of "i4"
        task_begin('Creating default antispam IP ranges... ');
        $DB->query('
			INSERT INTO T_antispam__iprange ( aipr_IPv4start, aipr_IPv4end, aipr_status )
			VALUES ( ' . $DB->quote(ip2int('127.0.0.0')) . ', ' . $DB->quote(ip2int('127.0.0.255')) . ', "trusted" ),
				( ' . $DB->quote(ip2int('10.0.0.0')) . ', ' . $DB->quote(ip2int('10.255.255.255')) . ', "trusted" ),
				( ' . $DB->quote(ip2int('172.16.0.0')) . ', ' . $DB->quote(ip2int('172.31.255.255')) . ', "trusted" ),
				( ' . $DB->quote(ip2int('192.168.0.0')) . ', ' . $DB->quote(ip2int('192.168.255.255')) . ', "trusted" )
			');
        task_end();
        set_upgrade_checkpoint('10975');
    }
    if ($old_db_version < 11000) {
        // part 8/c trunk aka first part of "i4"
        task_begin('Adding new countries...');
        // IGNORE is needed for upgrades from DB version 9970 or later
        $DB->query('INSERT IGNORE INTO T_regional__country ( ctry_code, ctry_name, ctry_curr_ID ) VALUES ( \'ct\', \'Catalonia\', \'2\' )');
        task_end();
        task_begin('Upgrading message thread statuses table...');
        db_add_col('T_messaging__threadstatus', 'tsta_thread_leave_msg_ID', 'int(10) unsigned NULL DEFAULT NULL');
        task_end();
        task_begin('Upgrading Item Settings...');
        // Convert item custom fields to custom item settings ( move custom fields from T_items__item table to T_items__item_settings table )
        $query = "INSERT INTO T_items__item_settings( iset_item_ID, iset_name, iset_value ) ";
        for ($i = 1; $i <= 8; $i++) {
            // For each custom fields:
            if ($i > 1) {
                $query .= ' UNION';
            }
            $field_name = $i > 5 ? 'varchar' . ($i - 5) : 'double' . $i;
            $query .= " SELECT post_ID, 'custom_" . $field_name . "', post_" . $field_name . "\n\t\t\t\t\t\t\tFROM T_items__item WHERE post_" . $field_name . " IS NOT NULL";
        }
        $DB->query($query);
        for ($i = 1; $i <= 5; $i++) {
            // drop custom double columns from items tabe
            db_drop_col('T_items__item', 'post_double' . $i);
        }
        for ($i = 1; $i <= 3; $i++) {
            // drop custom varchar columns from items tabe
            db_drop_col('T_items__item', 'post_varchar' . $i);
        }
        // Convert post_editor_code item field to item settings
        $DB->query('INSERT INTO T_items__item_settings ( iset_item_ID, iset_name, iset_value )
						SELECT post_ID, "editor_code", post_editor_code
							FROM T_items__item
							WHERE post_editor_code IS NOT NULL');
        db_drop_col('T_items__item', 'post_editor_code');
        // Convert post_metadesc item field to item settings
        $DB->query('INSERT INTO T_items__item_settings ( iset_item_ID, iset_name, iset_value )
						SELECT post_ID, "post_metadesc", post_metadesc
							FROM T_items__item
							WHERE post_metadesc IS NOT NULL');
        db_drop_col('T_items__item', 'post_metadesc');
        // Convert and rename post_metakeywords item field to post_custom_headers item settings
        $DB->query('INSERT INTO T_items__item_settings ( iset_item_ID, iset_name, iset_value )
						SELECT post_ID, "post_custom_headers", post_metakeywords
							FROM T_items__item
							WHERE post_metakeywords IS NOT NULL');
        db_drop_col('T_items__item', 'post_metakeywords');
        task_end();
        task_begin('Upgrading items table...');
        // Drop not used column
        db_drop_col('T_items__item', 'post_commentsexpire');
        task_end();
        task_begin('Adding new video file types...');
        $ftyp = $DB->get_row('SELECT ftyp_ID, ftyp_extensions
									FROM T_filetypes
									WHERE ftyp_mimetype = "video/mp4"
									AND ftyp_extensions NOT LIKE "%f4v%"
									LIMIT 1');
        if ($ftyp) {
            // Add f4v extension to mp4 file type, if not exists
            $DB->query('UPDATE T_filetypes SET ftyp_extensions = "' . $DB->escape($ftyp->ftyp_extensions . ' f4v') . '"
							WHERE ftyp_ID = ' . $DB->quote($ftyp->ftyp_ID));
        }
        // Add flv file type if not exists
        if (!db_key_exists('T_filetypes', 'ftyp_extensions', '"flv"')) {
            $DB->query('INSERT INTO T_filetypes (ftyp_extensions, ftyp_name, ftyp_mimetype, ftyp_icon, ftyp_viewtype, ftyp_allowed)
				             VALUES ("flv", "Flash video file", "video/x-flv", "", "browser", "registered")', 'Add "flv" file type');
        }
        // Add swf file type if not exists
        if (!db_key_exists('T_filetypes', 'ftyp_extensions', '"swf"')) {
            $DB->query('INSERT INTO T_filetypes (ftyp_extensions, ftyp_name, ftyp_mimetype, ftyp_icon, ftyp_viewtype, ftyp_allowed)
				             VALUES ("swf", "Flash video file", "application/x-shockwave-flash", "", "browser", "registered")', 'Add "swf" file type');
        }
        task_end();
        task_begin('Upgrading custom item settings...');
        $DB->begin();
        // Convert latitude and longitude from custom setting to normal item settings
        // Get those blog ids where Latitude and Longitude are both set
        $result = $DB->get_col('SELECT cs_left.cset_coll_ID
									FROM T_coll_settings as cs_left
									INNER JOIN T_coll_settings as cs_right ON cs_left.cset_coll_ID = cs_right.cset_coll_ID
									WHERE cs_left.cset_name = "custom_double3" AND cs_left.cset_value = "Latitude" AND
										cs_right.cset_name = "custom_double4" AND cs_right.cset_value = "Longitude"');
        if ($result) {
            // blogs were found where Latitude and Longitude custom fields were set for google maps plugin
            // Set "Show location coordinates" on where Latitude and Longitude were set
            $query_values = '( ' . implode(', "show_location_coordinates", 1 ), ( ', $result) . ', "show_location_coordinates", 1 )';
            $DB->query('INSERT INTO T_coll_settings( cset_coll_ID, cset_name, cset_value )
							VALUES ' . $query_values);
            $coll_ids = implode(', ', $result);
            // Update latitude Item settings
            $DB->query('UPDATE T_items__item_settings SET iset_name = "latitude"
							WHERE iset_name = "custom_double3" AND iset_item_ID IN (
								SELECT post_ID FROM T_items__item
								INNER JOIN T_categories ON post_main_cat_ID = cat_ID
								WHERE cat_blog_ID IN ( ' . $coll_ids . ' )
							)');
            // Update longitude Item settings
            $DB->query('UPDATE T_items__item_settings SET iset_name = "longitude"
							WHERE iset_name = "custom_double4" AND iset_item_ID IN (
								SELECT post_ID FROM T_items__item
								INNER JOIN T_categories ON post_main_cat_ID = cat_ID
								WHERE cat_blog_ID IN ( ' . $coll_ids . ' )
							)');
            // Delete proessed latitude & longitude custom fields from collection settings
            $DB->query('DELETE FROM T_coll_settings
						WHERE ( cset_name = "custom_double3" OR cset_name = "custom_double4" ) AND
							cset_coll_ID IN ( ' . $coll_ids . ' )');
        }
        $DB->commit();
        // End convert latitude and longitude
        $DB->begin();
        // Convert custom fields
        // Delete not used custom fields
        $DB->query('DELETE FROM T_coll_settings WHERE ( cset_value IS NULL OR cset_value = "" ) AND cset_name LIKE "custom\\_%"');
        // Set custom double fields count
        $DB->query('INSERT INTO T_coll_settings( cset_coll_ID, cset_name, cset_value )
						SELECT cset_coll_ID, "count_custom_double", COUNT( cset_name )
						FROM T_coll_settings
						WHERE cset_name LIKE "custom\\_double%"
						GROUP BY cset_coll_ID');
        // Set custom varchar fields count
        $DB->query('INSERT INTO T_coll_settings( cset_coll_ID, cset_name, cset_value )
						SELECT cset_coll_ID, "count_custom_varchar", COUNT( cset_name )
						FROM T_coll_settings
						WHERE cset_name LIKE "custom\\_varchar%"
						GROUP BY cset_coll_ID');
        // Select all custom fields from all blog, to create converted field values
        $result = $DB->get_results('SELECT cset_coll_ID as coll_ID, cset_name as name, cset_value as value
										FROM T_coll_settings
										WHERE cset_name LIKE "custom\\_%"
										ORDER BY cset_coll_ID, cset_name');
        if (!empty($result)) {
            // There are custom fields in blog settings
            $convert_field_values = '';
            $reorder_field_values = '';
            $old_prefix = "";
            $old_coll_ID = "";
            foreach ($result as $row) {
                // process each custom field
                $custom_id = uniqid('');
                $prefix = substr($row->name, 7, 6) === 'double' ? 'custom_double' : 'custom_varchar';
                // replace custom_double{N} and custom_varchar{N} values with a custom_id where N is number
                $convert_field_values .= '( ' . $row->coll_ID . ', "' . $row->name . '", "' . $custom_id . '" ), ';
                // add new custom_double_{customid} and custom_varchar_{customid} entries with the old correspinding custom field values
                $convert_field_values .= '( ' . $row->coll_ID . ', "' . $prefix . '_' . $custom_id . '", "' . $row->value . '" ), ';
                // create reorder values to replace e.g. custom_double2 to custom_double1 if custom_double1 doesn't exists yet
                $index = $old_prefix == $prefix && $old_coll_ID == $row->coll_ID ? $index + 1 : 1;
                $reorder_field_values .= '( ' . $row->coll_ID . ', "' . $prefix . $index . '", "' . $custom_id . '" ), ';
                $old_prefix = $prefix;
                $old_coll_ID = $row->coll_ID;
            }
            $convert_field_values = substr($convert_field_values, 0, -2);
            $reorder_field_values = substr($reorder_field_values, 0, -2);
            // Convert custom fields in collection setting
            $DB->query('REPLACE INTO T_coll_settings( cset_coll_ID, cset_name, cset_value )
							VALUES ' . $convert_field_values);
            // Update double custom field name_ids in item settings table
            $DB->query('UPDATE T_items__item_settings SET iset_name = (
								SELECT CONCAT( "custom_double_", cset_value ) FROM T_coll_settings
									INNER JOIN T_categories ON cset_coll_ID = cat_blog_ID
									INNER JOIN T_items__item ON cat_ID = post_main_cat_ID
									WHERE cset_name = iset_name AND post_ID  = iset_item_ID )
							WHERE iset_name LIKE "custom\\_double%"');
            // Update varchar custom field name_ids in item settings table
            $DB->query('UPDATE T_items__item_settings SET iset_name = (
								SELECT CONCAT( "custom_varchar_", cset_value ) FROM T_coll_settings
									INNER JOIN T_categories ON cset_coll_ID = cat_blog_ID
									INNER JOIN T_items__item ON cat_ID = post_main_cat_ID
									WHERE cset_name = iset_name AND post_ID  = iset_item_ID )
							WHERE iset_name LIKE "custom\\_varchar%"');
            // Reorder custom fields in collection settings
            $DB->query('REPLACE INTO T_coll_settings( cset_coll_ID, cset_name, cset_value )
							VALUES ' . $reorder_field_values);
        }
        $DB->commit();
        // End convert custom fields
        task_end();
        task_begin('Convert group users permissions to pluggable permissions...');
        $DB->query('REPLACE INTO T_groups__groupsettings( gset_grp_ID, gset_name, gset_value )
						SELECT grp_ID, "perm_users", grp_perm_users
							FROM T_groups');
        db_drop_col('T_groups', 'grp_perm_users');
        task_end();
        task_begin('Update Post Types... ');
        $DB->query("REPLACE INTO T_items__type ( ptyp_ID, ptyp_name )\n\t\t\tVALUES ( 4000, 'Advertisement' )");
        task_end();
        task_begin('Update files table... ');
        db_add_col('T_files', 'file_hash', 'char(32) default NULL');
        task_end();
        task_begin('Create table for files voting...');
        $DB->query('CREATE TABLE ' . $tableprefix . 'files__vote (
				fvot_file_ID       int(11) UNSIGNED NOT NULL,
				fvot_user_ID       int(11) UNSIGNED NOT NULL,
				fvot_like          tinyint(1),
				fvot_inappropriate tinyint(1),
				fvot_spam          tinyint(1),
				primary key (fvot_file_ID, fvot_user_ID)
			) ENGINE = innodb');
        task_end();
        task_begin('Create table for users reporting...');
        $DB->query("CREATE TABLE T_users__reports (\n\t\t\turep_target_user_ID int(11) unsigned NOT NULL,\n\t\t\turep_reporter_ID    int(11) unsigned NOT NULL,\n\t\t\turep_status         enum( 'fake', 'guidelines', 'harass', 'spam', 'other' ),\n\t\t\turep_info           varchar(240),\n\t\t\turep_datetime\t\tdatetime NOT NULL,\n\t\t\tPRIMARY KEY ( urep_target_user_ID, urep_reporter_ID )\n\t\t) ENGINE = innodb");
        task_end();
        task_begin('Upgrading skins type...');
        $DB->query("ALTER TABLE T_skins__skin MODIFY COLUMN skin_type enum('normal','feed','sitemap','mobile','tablet') NOT NULL default 'normal'");
        task_end();
        task_begin('Upgrading blogs skins...');
        // Convert blog skin ID to blog settings
        $DB->query('INSERT INTO T_coll_settings( cset_coll_ID, cset_name, cset_value )
						SELECT blog_ID, "normal_skin_ID", blog_skin_ID
						FROM T_blogs');
        db_drop_col('T_blogs', 'blog_skin_ID');
        task_end();
        task_begin('Update categories table... ');
        db_add_col('T_categories', 'cat_meta', 'tinyint(1) NOT NULL DEFAULT 0');
        db_add_col('T_categories', 'cat_lock', 'tinyint(1) NOT NULL DEFAULT 0');
        task_end();
        task_begin('Plugin settings update...');
        $all_blog_ids = $DB->get_col('SELECT blog_ID FROM T_blogs');
        $plugin_ids = $DB->get_assoc('SELECT pset_plug_ID, pset_value FROM T_pluginsettings WHERE pset_name = "render_comments"');
        $insert_values = '';
        foreach ($all_blog_ids as $blog_ID) {
            foreach ($plugin_ids as $plugin_ID => $setting_value) {
                $apply_comment_rendering = $setting_value ? 'stealth' : 'never';
                $insert_values .= '( ' . $blog_ID . ', "plugin' . $plugin_ID . '_coll_apply_comment_rendering", "' . $apply_comment_rendering . '" ),';
            }
        }
        if (!empty($insert_values)) {
            $DB->query('INSERT INTO T_coll_settings( cset_coll_ID, cset_name, cset_value )
						VALUES ' . substr($insert_values, 0, strlen($insert_values) - 1));
        }
        $DB->query('DELETE FROM T_pluginsettings WHERE pset_name = "render_comments"');
        task_end();
        task_begin('Creating comment prerendering cache table...');
        $DB->query("CREATE TABLE T_comments__prerendering (\n\t\t\tcmpr_cmt_ID INT(11) UNSIGNED NOT NULL,\n\t\t\tcmpr_format ENUM('htmlbody','entityencoded','xml','text') NOT NULL,\n\t\t\tcmpr_renderers TEXT NOT NULL,\n\t\t\tcmpr_content_prerendered MEDIUMTEXT NULL,\n\t\t\tcmpr_datemodified TIMESTAMP NOT NULL,\n\t\t\tPRIMARY KEY (cmpr_cmt_ID, cmpr_format)\n\t\t) ENGINE = innodb");
        db_add_col('T_comments', 'comment_renderers', "TEXT NOT NULL AFTER comment_content");
        $DB->query('UPDATE T_comments SET comment_renderers = "default"');
        task_end();
        task_begin('Upgrading plugins table...');
        db_drop_col('T_plugins', 'plug_apply_rendering');
        task_end();
        task_begin('Upgrading Auto_P plugin...');
        $blog_settings = $DB->get_assoc('SELECT cset_coll_ID, cset_value FROM T_coll_settings WHERE cset_name = "comment_autobr"');
        $insert_values = array();
        $plugin_ids = $DB->get_col('SELECT plug_ID FROM T_plugins WHERE plug_code = "b2WPAutP"');
        foreach ($blog_settings as $blog_ID => $blog_setting_value) {
            foreach ($plugin_ids as $plugin_ID) {
                switch ($blog_setting_value) {
                    case 'never':
                        $apply_comment_rendering = 'never';
                        break;
                    case 'optional':
                        $apply_comment_rendering = 'opt-out';
                        break;
                    case 'always':
                        $apply_comment_rendering = 'stealth';
                        break;
                    default:
                        break 2;
                }
                $insert_values[] = '( ' . $blog_ID . ', "plugin' . $plugin_ID . '_coll_apply_comment_rendering", "' . $apply_comment_rendering . '" )';
            }
        }
        if (count($insert_values) > 0) {
            $DB->query('REPLACE INTO T_coll_settings( cset_coll_ID, cset_name, cset_value )
						VALUES ' . implode(',', $insert_values));
        }
        $DB->query('DELETE FROM T_coll_settings WHERE cset_name = "comment_autobr"');
        $DB->query('UPDATE T_comments SET comment_content = REPLACE( REPLACE( comment_content, "<br>\\n", "\\n" ), "<br />\\n", "\\n" )');
        task_end();
        set_upgrade_checkpoint('11000');
    }
    if ($old_db_version < 11010) {
        // part 9 trunk aka second part of "i4"
        task_begin('Upgrading post statuses...');
        $DB->query("ALTER TABLE T_items__item CHANGE COLUMN post_status post_status enum('published','community','deprecated','protected','private','review','draft','redirected') NOT NULL default 'published'");
        $DB->query("ALTER TABLE T_items__version CHANGE COLUMN iver_status iver_status ENUM('published','community','deprecated','protected','private','review','draft','redirected') NULL");
        $DB->query("ALTER TABLE T_coll_user_perms CHANGE COLUMN bloguser_perm_poststatuses bloguser_perm_poststatuses set('review','draft','private','protected','deprecated','community','published','redirected') NOT NULL default ''");
        $DB->query("ALTER TABLE T_coll_group_perms CHANGE COLUMN bloggroup_perm_poststatuses bloggroup_perm_poststatuses set('review','draft','private','protected','deprecated','community','published','redirected') NOT NULL default ''");
        task_end();
        task_begin('Upgrading groups table...');
        $pbloggers_renamed_to_moderators = $DB->query('UPDATE T_groups SET grp_name = "Moderators" WHERE grp_ID = 2 AND grp_name = "Privileged Bloggers"');
        // Update administrators and moderators users coll setting permissions with new permissions
        // Note we can change moderators permission if the group name and ID was not changed after the original install
        $moderators_condition = $pbloggers_renamed_to_moderators ? ' OR bloggroup_group_ID = 2' : '';
        $DB->query("UPDATE T_coll_group_perms SET bloggroup_perm_poststatuses = 'published,community,deprecated,protected,private,review,draft' WHERE bloggroup_group_ID = 1" . $moderators_condition);
        // Change groups name
        $DB->query('UPDATE T_groups SET grp_name = "Trusted Users" WHERE grp_ID = 3 AND grp_name = "Bloggers"');
        $DB->query('UPDATE T_groups SET grp_name = "Normal Users" WHERE grp_ID = 4 AND grp_name = "Basic Users"');
        // Get "Misbehaving/Suspect Users" group ID
        $suspect_query = 'SELECT grp_ID
						FROM T_groups
						WHERE grp_name = "Misbehaving/Suspect Users"
						ORDER BY grp_ID DESC
						LIMIT 1';
        $suspect_group_ID = $DB->get_var($suspect_query);
        if (empty($suspect_group_ID)) {
            // suspect group doesn't exists, check spammers because probably it does not exists either
            $insert_values = '( "Misbehaving/Suspect Users" )';
            // Get "Spammers/Restricted Users" group ID
            $query = 'SELECT grp_ID
					FROM T_groups
					WHERE grp_name = "Spammers/Restricted Users"
					ORDER BY grp_ID DESC
					LIMIT 1';
            $spammers_group_ID = $DB->get_var($query);
            if (empty($spammers_group_ID)) {
                $insert_values .= ', ( "Spammers/Restricted Users" )';
            }
            // Insert two new group
            $DB->query('INSERT INTO T_groups ( grp_name )
						VALUES ' . $insert_values);
            $suspect_group_ID = $DB->get_var($suspect_query);
            if ($suspect_group_ID) {
                // Set coll setting permissions for Misbehaving/Suspect Users in Forums
                $query = "\n\t\t\t\t\tINSERT INTO T_coll_group_perms( bloggroup_blog_ID, bloggroup_group_ID, bloggroup_ismember,\n\t\t\t\t\t\tbloggroup_perm_poststatuses, bloggroup_perm_delpost, bloggroup_perm_edit_ts,\n\t\t\t\t\t\tbloggroup_perm_own_cmts, bloggroup_perm_vote_spam_cmts, bloggroup_perm_draft_cmts, bloggroup_perm_publ_cmts, bloggroup_perm_depr_cmts,\n\t\t\t\t\t\tbloggroup_perm_cats, bloggroup_perm_properties,\n\t\t\t\t\t\tbloggroup_perm_media_upload, bloggroup_perm_media_browse, bloggroup_perm_media_change )\n\t\t\t\t\tSELECT blog_ID, " . $suspect_group_ID . ", 1, 'review,draft', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n\t\t\t\t\t\tFROM T_blogs WHERE blog_ID = 5 AND blog_shortname = 'Forums'";
                $DB->query($query);
            }
        }
        task_end();
        task_begin('Upgrading blogs table...');
        db_add_col('T_blogs', 'blog_type', 'ENUM( "std", "photo", "group", "forum", "manual" ) DEFAULT "std" NOT NULL');
        task_end();
        task_begin('Upgrading comment statuses...');
        $DB->query("ALTER TABLE T_comments CHANGE COLUMN comment_status comment_status ENUM('published','community','deprecated','protected','private','review','draft','trash') DEFAULT 'published' NOT NULL");
        task_end();
        task_begin('Updating collection user/group permissions...');
        db_add_col('T_coll_user_perms', 'bloguser_perm_cmtstatuses', "set('review','draft','private','protected','deprecated','community','published') NOT NULL default '' AFTER bloguser_perm_vote_spam_cmts");
        db_add_col('T_coll_user_perms', 'bloguser_perm_edit_cmt', "ENUM('no','own','anon','lt','le','all') NOT NULL default 'no' AFTER bloguser_perm_cmtstatuses");
        db_add_col('T_coll_group_perms', 'bloggroup_perm_cmtstatuses', "set('review','draft','private','protected','deprecated','community','published') NOT NULL default '' AFTER bloggroup_perm_vote_spam_cmts");
        db_add_col('T_coll_group_perms', 'bloggroup_perm_edit_cmt', "ENUM('no','own','anon','lt','le','all') NOT NULL default 'no' AFTER bloggroup_perm_cmtstatuses");
        // Add access to those comment statuses for what user had before
        $DB->query('UPDATE T_coll_user_perms
					SET bloguser_perm_cmtstatuses = ( bloguser_perm_publ_cmts * 1 ) | ( bloguser_perm_depr_cmts * 4 ) | ( bloguser_perm_draft_cmts * 64 )');
        // Add access to all cmt statuses for those users which had edit permission on all comment statuses
        $DB->query('UPDATE T_coll_user_perms
					SET bloguser_perm_cmtstatuses = "published,community,deprecated,protected,private,review,draft", bloguser_perm_edit_cmt = "all"
					WHERE bloguser_perm_publ_cmts <> 0 AND bloguser_perm_depr_cmts <> 0 AND bloguser_perm_draft_cmts <> 0');
        // Add "lower then" edit permission to those users who had permission to edit published or draft comments
        $DB->query('UPDATE T_coll_user_perms
					SET bloguser_perm_edit_cmt = "lt"
					WHERE ( bloguser_perm_cmtstatuses & 65 ) != 0 AND bloguser_perm_edit_cmt = "no"');
        // Add access to those comment statuses for what group had before
        $DB->query('UPDATE T_coll_group_perms
					SET bloggroup_perm_cmtstatuses = ( bloggroup_perm_publ_cmts * 1 ) | ( bloggroup_perm_depr_cmts * 4 ) | ( bloggroup_perm_draft_cmts * 64 )');
        // Add access to all cmt statuses for those groups which had edit permission on all comment statuses
        $DB->query('UPDATE T_coll_group_perms
					SET bloggroup_perm_cmtstatuses = "published,community,deprecated,protected,private,review,draft", bloggroup_perm_edit_cmt = "all"
					WHERE bloggroup_perm_publ_cmts <> 0 AND bloggroup_perm_depr_cmts <> 0 AND bloggroup_perm_draft_cmts <> 0');
        // Add "lower then" edit permission to those groups who had permission to edit published or draft comments
        $DB->query('UPDATE T_coll_group_perms
					SET bloggroup_perm_edit_cmt = "lt"
					WHERE ( bloggroup_perm_cmtstatuses & 65 ) != 0 AND bloggroup_perm_edit_cmt = "no"');
        db_drop_col('T_coll_user_perms', 'bloguser_perm_draft_cmts');
        db_drop_col('T_coll_user_perms', 'bloguser_perm_publ_cmts');
        db_drop_col('T_coll_user_perms', 'bloguser_perm_depr_cmts');
        db_drop_col('T_coll_group_perms', 'bloggroup_perm_draft_cmts');
        db_drop_col('T_coll_group_perms', 'bloggroup_perm_publ_cmts');
        db_drop_col('T_coll_group_perms', 'bloggroup_perm_depr_cmts');
        db_add_col('T_coll_user_perms', 'bloguser_perm_delcmts', 'tinyint NOT NULL default 0 AFTER bloguser_perm_edit_ts');
        db_add_col('T_coll_group_perms', 'bloggroup_perm_delcmts', 'tinyint NOT NULL default 0 AFTER bloggroup_perm_edit_ts');
        // GRANT delete comment perms for moderators
        $DB->query('UPDATE T_coll_group_perms
					SET bloggroup_perm_delcmts = 1
					WHERE bloggroup_perm_edit_cmt = "le" OR bloggroup_perm_edit_cmt = "all"');
        $DB->query("ALTER TABLE T_coll_user_perms CHANGE COLUMN bloguser_perm_own_cmts bloguser_perm_recycle_owncmts tinyint NOT NULL default 0");
        $DB->query("ALTER TABLE T_coll_group_perms CHANGE COLUMN bloggroup_perm_own_cmts bloggroup_perm_recycle_owncmts tinyint NOT NULL default 0");
        task_end();
        task_begin('Updating blogs settings...');
        $DB->query('UPDATE T_coll_settings SET cset_value = "blog" WHERE cset_name = "enable_goto_blog" AND cset_value = "1"');
        $DB->query('UPDATE T_coll_settings SET cset_value = "no" WHERE cset_name = "enable_goto_blog" AND cset_value = "0"');
        task_end();
        set_upgrade_checkpoint('11010');
    }
    if ($old_db_version < 11020) {
        // part 10 trunk aka third part of "i4"
        task_begin('Upgrading users table...');
        // Get all users with defined IPs
        $users_SQL = new SQL();
        $users_SQL->SELECT('user_ID, user_created_fromIPv4');
        $users_SQL->FROM('T_users');
        $users_SQL->WHERE('user_created_fromIPv4 IS NOT NULL');
        $users_SQL->WHERE_and('user_created_fromIPv4 != ' . $DB->quote(ip2int('0.0.0.0')));
        $users_SQL->WHERE_and('user_created_fromIPv4 != ' . $DB->quote(ip2int('127.0.0.1')));
        $users = $DB->get_assoc($users_SQL->get());
        // Get user's IPs from settings table
        $settings_SQL = new SQL();
        $settings_SQL->SELECT('uset_user_ID, uset_value');
        $settings_SQL->FROM('T_users__usersettings');
        $settings_SQL->WHERE('uset_name = "user_ip"');
        if (count($users) > 0) {
            // Get IPs only for users which have not IP in T_users table
            $settings_SQL->WHERE_and('uset_user_ID NOT IN (' . $DB->quote(array_keys($users)) . ')');
        }
        $settings = $DB->get_assoc($settings_SQL->get());
        if (count($users) > 0 || count($settings) > 0) {
            $users_settings_insert_sql = array();
            foreach ($users as $user_ID => $user_IP) {
                $users_settings_insert_sql[] = '( ' . $DB->quote($user_ID) . ', "created_fromIPv4", ' . $DB->quote($user_IP) . ' )';
            }
            foreach ($settings as $user_ID => $user_IP) {
                $users_settings_insert_sql[] = '( ' . $DB->quote($user_ID) . ', "created_fromIPv4", ' . $DB->quote(ip2int($user_IP)) . ' )';
            }
            // Insert IPs values into settings table
            $DB->query('INSERT INTO T_users__usersettings ( uset_user_ID, uset_name, uset_value )
				VALUES ' . implode(', ', $users_settings_insert_sql));
        }
        // Remove old IPs from settings table
        $DB->query('DELETE FROM T_users__usersettings
			WHERE uset_name = "user_ip"');
        db_drop_col('T_users', 'user_created_fromIPv4');
        task_end();
        set_upgrade_checkpoint('11020');
    }
    if ($old_db_version < 11025) {
        // part 11 trunk aka fourth part of "i4"
        task_begin('Upgrading items table...');
        $DB->query("UPDATE T_items__item SET post_datecreated = concat( '2000-01-01 ', time( post_datecreated ) )\n\t\t\t\t\t\tWHERE date( post_datecreated ) = '1970-01-01'");
        $DB->query("UPDATE T_items__item SET post_datemodified = concat( '2000-01-01 ', time( post_datemodified ) )\n\t\t\t\t\t\tWHERE date( post_datemodified ) = '1970-01-01'");
        $DB->query("ALTER TABLE T_items__item CHANGE COLUMN post_datecreated post_datecreated TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00'");
        $DB->query("ALTER TABLE T_items__item CHANGE COLUMN post_datemodified post_datemodified TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00'");
        db_add_col('T_items__item', 'post_last_touched_ts', "TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00' AFTER post_datemodified");
        $DB->query('UPDATE T_items__item SET post_last_touched_ts = post_datemodified');
        task_end();
        /*
         * ADD UPGRADES FOR i4 BRANCH __ABOVE__ IN THIS BLOCK.
         *
         * This part will be included in trunk and i4 branches
         */
        set_upgrade_checkpoint('11025');
    }
    // In some upgrade versions ( currently only in "i5" ) we would like to create profile pictures links from the user's files in the profile pictures folder
    // To be able to do that we need an up to date database version, so we will create profile pictures after the ugrade script run successfully.
    // Set this $create_profile_picture_links to true only in those upgrade block where it's required.
    $create_profile_picture_links = false;
    if ($old_db_version < 11100) {
        // part 12 trunk aka "i5"
        task_begin('Update links table...');
        db_add_col('T_links', 'link_usr_ID', 'int(11) unsigned  NULL COMMENT "Used for linking files to users (user profile picture)" AFTER link_cmt_ID');
        db_add_index('T_links', 'link_usr_ID', 'link_usr_ID');
        task_end();
        task_begin('Creating links for users profile pictures...');
        // Create links for main profile pictures
        $link_create_date = date2mysql(time());
        $DB->query('INSERT INTO T_links( link_datecreated, link_datemodified, link_usr_ID, link_file_ID, link_position, link_order )
						SELECT ' . $DB->quote($link_create_date) . ', ' . $DB->quote($link_create_date) . ', user_ID, user_avatar_file_ID, "", 1
						FROM T_users
						WHERE user_avatar_file_ID IS NOT NULL');
        // Set $create_profile_picture_links to true to create links for all files from the users profile_pictures folder
        $create_profile_picture_links = true;
        task_end();
        task_begin('Upgrading custom item settings...');
        $DB->begin();
        // Add names for custom fields
        // Select all custom fields from all blogs, to create field names
        $result = $DB->get_results('SELECT cset_coll_ID as coll_ID, cset_name as name, cset_value as value
										FROM T_coll_settings
										WHERE cset_name LIKE "custom\\_double\\_%"
										   OR cset_name LIKE "custom\\_varchar\\_%"
										ORDER BY cset_coll_ID, cset_name');
        if (!empty($result)) {
            // There are custom fields in blog settings
            $insert_field_names = '';
            foreach ($result as $row) {
                // process each custom field
                $field_guid = preg_replace('/^custom_(double|varchar)_([a-f0-9\\-]+)$/', '$2', $row->name);
                // Replace special chars/umlauts, if we can convert charsets:
                load_funcs('locales/_charset.funcs.php');
                $field_name = strtolower(preg_replace('/[^a-z0-9\\-_]+/i', '_', $row->value));
                $field_name = replace_special_chars($field_name);
                $insert_field_names .= '( ' . $row->coll_ID . ', "custom_fname_' . $field_guid . '", "' . $field_name . '" ), ';
            }
            // Insert names for custom fields in collection settings
            $DB->query('INSERT INTO T_coll_settings( cset_coll_ID, cset_name, cset_value )
							VALUES ' . substr($insert_field_names, 0, -2));
        }
        $DB->commit();
        // End adding of names for custom fields
        task_end();
        task_begin('Upgrading comments table...');
        db_add_index('T_comments', 'comment_status', 'comment_status');
        task_end();
        set_upgrade_checkpoint('11100');
    }
    if ($old_db_version < 11110) {
        // part 13 trunk aka second part of "i5"
        // Add new settings for antispam groups
        $antispam_group_settings = $DB->get_assoc('SELECT set_name, set_value
			 FROM T_settings
			WHERE set_name IN ( ' . $DB->quote(array('antispam_suspicious_group', 'antispam_trust_groups')) . ')');
        if (count($antispam_group_settings) < 2) {
            // Insert new settings only if don't exist in DB
            task_begin('Updating general settings...');
            // Set antispam suspicious group
            if (!isset($antispam_group_settings['antispam_suspicious_group'])) {
                // Insert new value, Don't rewrite value if it already defined before
                $suspect_group_SQL = new SQL();
                $suspect_group_SQL->SELECT('grp_ID');
                $suspect_group_SQL->FROM('T_groups');
                $suspect_group_SQL->WHERE('grp_name = ' . $DB->quote('Misbehaving/Suspect Users'));
                $suspect_group_ID = $DB->get_var($suspect_group_SQL->get());
                if (!empty($suspect_group_ID)) {
                    // Save setting value
                    $DB->query('INSERT INTO T_settings ( set_name, set_value ) VALUES
							( ' . $DB->quote('antispam_suspicious_group') . ', ' . $DB->quote($suspect_group_ID) . ' )');
                }
            }
            // Set antispam trust groups
            if (!isset($antispam_group_settings['antispam_trust_groups'])) {
                // Insert new value, Don't rewrite value if it already defined before
                $trust_groups = array('Administrators', 'Moderators', 'Trusted Users', 'Spammers/Restricted Users');
                $trust_groups_SQL = new SQL();
                $trust_groups_SQL->SELECT('grp_ID');
                $trust_groups_SQL->FROM('T_groups');
                $trust_groups_SQL->WHERE('grp_name IN ( ' . $DB->quote($trust_groups) . ')');
                $trust_groups_IDs = $DB->get_col($trust_groups_SQL->get());
                if (!empty($trust_groups_IDs)) {
                    // Save setting value
                    $DB->query('INSERT INTO T_settings ( set_name, set_value ) VALUES
							( ' . $DB->quote('antispam_trust_groups') . ', ' . $DB->quote(implode(',', $trust_groups_IDs)) . ' )');
                }
            }
            task_end();
        }
        set_upgrade_checkpoint('11110');
    }
    if ($old_db_version < 11200) {
        // part 14 trunk aka "i6"
        task_begin('Upgrading comments table...');
        db_add_col('T_comments', 'comment_last_touched_ts', "TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00' AFTER comment_date");
        $DB->query('UPDATE T_comments
		                SET comment_last_touched_ts = comment_date');
        task_end();
        task_begin('Convert email addresses to lowercase... ');
        $DB->query('UPDATE T_users SET user_email = LOWER( user_email )');
        $DB->query('UPDATE ' . $tableprefix . 'email__blocked SET emblk_address = LOWER( emblk_address )');
        $DB->query('UPDATE T_email__returns SET emret_address = LOWER( emret_address )');
        $DB->query('UPDATE T_email__log SET emlog_to = LOWER( emlog_to )');
        $DB->query('UPDATE T_comments
			  SET comment_author_email = LOWER( comment_author_email )
			WHERE comment_author_email IS NOT NULL');
        task_end();
        task_begin('Upgrading blogs table...');
        db_add_col('T_blogs', 'blog_order', 'int(11) NULL DEFAULT NULL');
        $DB->query('UPDATE T_blogs
		                SET blog_order = blog_ID');
        task_end();
        task_begin('Updating general settings...');
        $site_skins_enabled = $DB->get_var('SELECT set_value
			 FROM T_settings
			WHERE set_name = ' . $DB->quote('site_skins_enabled'));
        if (is_null($site_skins_enabled)) {
            // Insert new setting to disable site skins
            $DB->query('INSERT INTO T_settings ( set_name, set_value )
				VALUES ( ' . $DB->quote('site_skins_enabled') . ', ' . $DB->quote('0') . ' )');
        } elseif ($site_skins_enabled == '1') {
            // Disable site skins if it is enabled
            $DB->query('UPDATE T_settings
				  SET set_value = ' . $DB->quote('0') . '
				WHERE set_name = ' . $DB->quote('site_skins_enabled'));
        }
        task_end();
        task_begin('Upgrading blogs table...');
        db_add_col('T_blogs', 'blog_favorite', 'TINYINT(1) NOT NULL DEFAULT 1');
        task_end();
        task_begin('Upgrade table of base domains... ');
        $DB->query("ALTER TABLE T_basedomains CHANGE COLUMN dom_status dom_status ENUM('unknown','trusted','suspect','blocked') NOT NULL DEFAULT 'unknown'");
        task_end();
        task_begin('Create table for file links voting... ');
        $DB->query('CREATE TABLE ' . $tableprefix . 'links__vote (
				lvot_link_ID       int(11) UNSIGNED NOT NULL,
				lvot_user_ID       int(11) UNSIGNED NOT NULL,
				lvot_like          tinyint(1),
				lvot_inappropriate tinyint(1),
				lvot_spam          tinyint(1),
				primary key (lvot_link_ID, lvot_user_ID)
			) ENGINE = innodb');
        // Convert all file votes to link votes
        $DB->query('INSERT INTO ' . $tableprefix . 'links__vote ( lvot_link_ID, lvot_user_ID, lvot_like, lvot_inappropriate, lvot_spam )
						SELECT link_ID, fvot_user_ID, fvot_like, fvot_inappropriate, fvot_spam
						FROM ' . $tableprefix . 'files__vote
						LEFT JOIN T_links ON link_file_ID = fvot_file_ID
						WHERE link_ID IS NOT NULL');
        // Delete old file voting table
        $DB->query('DROP TABLE IF EXISTS ' . $tableprefix . 'files__vote');
        task_end();
        task_begin('Create table for goal categories... ');
        $DB->query('CREATE TABLE T_track__goalcat (
				gcat_ID     int(10) unsigned NOT NULL auto_increment,
				gcat_name   varchar(50) default NULL,
				gcat_color  char(7) default NULL,
				PRIMARY KEY (gcat_ID)
			) ENGINE = myisam');
        // Insert default goal category
        $DB->query('INSERT INTO T_track__goalcat ( gcat_name, gcat_color )
			VALUES ( ' . $DB->quote('Default') . ', ' . $DB->quote('#999999') . ' )');
        $default_goalcat_ID = $DB->insert_id;
        db_add_col('T_track__goal', 'goal_gcat_ID', 'int(10) unsigned NOT NULL DEFAULT "' . $default_goalcat_ID . '" AFTER goal_ID');
        $DB->query('ALTER TABLE T_track__goal
			CHANGE goal_gcat_ID goal_gcat_ID int(10) unsigned NOT NULL');
        task_end();
        // This task was not required, but we would like to make sure that we have future proof link_datecreated and link_datemodified fields.
        // There were previous versions, when these fields were set to '1970-01-01' because the $localtimenow was not initialized during the install script
        task_begin('Update links table...');
        $DB->query("UPDATE T_links SET link_datecreated = concat( '2000-01-01 ', time( link_datecreated ) )\n\t\t\t\t\t\tWHERE date( link_datecreated ) = '1970-01-01'");
        $DB->query("UPDATE T_links SET link_datemodified = concat( '2000-01-01 ', time( link_datemodified ) )\n\t\t\t\t\t\tWHERE date( link_datemodified ) = '1970-01-01'");
        task_end();
        task_begin('Upgrading Blogs table...');
        $DB->query('ALTER TABLE T_blogs CHANGE blog_description blog_shortdesc varchar(250) NULL default ""');
        task_end();
        task_begin('Upgrading Comments table...');
        $DB->query('ALTER TABLE T_comments
			CHANGE comment_post_ID   comment_item_ID        int(11) unsigned NOT NULL default 0,
			CHANGE comment_author_ID comment_author_user_ID int unsigned NULL default NULL');
        $DB->query('ALTER TABLE T_comments
			DROP INDEX comment_post_ID');
        $DB->query('ALTER TABLE T_comments
			ADD KEY comment_item_ID ( comment_item_ID )');
        task_end();
        task_begin('Upgrading Files table...');
        $DB->query('ALTER TABLE T_files
			DROP INDEX file,
			ADD COLUMN file_path_hash char(32) default NULL');
        // Change file path length to the max allowed value
        $DB->query("ALTER TABLE T_files CHANGE COLUMN file_path file_path VARCHAR(767) NOT NULL DEFAULT ''");
        $DB->query('UPDATE T_files SET file_path_hash = MD5( CONCAT( file_root_type, file_root_ID, file_path ) )');
        $DB->query('ALTER TABLE T_files ADD UNIQUE file_path (file_path_hash)');
        task_end();
        task_begin('Create table for email campaigns... ');
        $DB->query('CREATE TABLE T_email__campaign (
			ecmp_ID          INT NOT NULL AUTO_INCREMENT,
			ecmp_date_ts     TIMESTAMP NOT NULL DEFAULT \'2000-01-01 00:00:00\',
			ecmp_name        VARCHAR(255) NOT NULL,
			ecmp_email_title VARCHAR(255) NULL,
			ecmp_email_html  TEXT NULL,
			ecmp_email_text  TEXT NULL,
			ecmp_sent_ts     TIMESTAMP NULL,
			PRIMARY KEY      (ecmp_ID)
			) ENGINE = myisam');
        task_end();
        task_begin('Create table for email campaign send data... ');
        $DB->query('CREATE TABLE T_email__campaign_send (
			csnd_camp_ID  INT(11) UNSIGNED NOT NULL,
			csnd_user_ID  INT(11) UNSIGNED NOT NULL,
			csnd_emlog_ID INT(11) UNSIGNED NULL,
			PRIMARY KEY   csnd_PK ( csnd_camp_ID, csnd_user_ID )
			) ENGINE = myisam');
        task_end();
        task_begin('Rename table "email blocked" to "email address"... ');
        $DB->query('RENAME TABLE ' . $tableprefix . 'email__blocked TO T_email__address');
        $DB->query("ALTER TABLE T_email__address\n\t\t\tCHANGE emblk_ID                    emadr_ID                    INT(10) UNSIGNED NOT NULL auto_increment,\n\t\t\tCHANGE emblk_address               emadr_address               VARCHAR(255) DEFAULT NULL,\n\t\t\tCHANGE emblk_status                emadr_status                ENUM ( 'unknown', 'warning', 'suspicious1', 'suspicious2', 'suspicious3', 'prmerror', 'spammer' ) NOT NULL DEFAULT 'unknown',\n\t\t\tCHANGE emblk_sent_count            emadr_sent_count            INT(10) UNSIGNED NOT NULL DEFAULT 0,\n\t\t\tCHANGE emblk_sent_last_returnerror emadr_sent_last_returnerror INT(10) UNSIGNED NOT NULL DEFAULT 0,\n\t\t\tCHANGE emblk_prmerror_count        emadr_prmerror_count        INT(10) UNSIGNED NOT NULL DEFAULT 0,\n\t\t\tCHANGE emblk_tmperror_count        emadr_tmperror_count        INT(10) UNSIGNED NOT NULL DEFAULT 0,\n\t\t\tCHANGE emblk_spamerror_count       emadr_spamerror_count       INT(10) UNSIGNED NOT NULL DEFAULT 0,\n\t\t\tCHANGE emblk_othererror_count      emadr_othererror_count      INT(10) UNSIGNED NOT NULL DEFAULT 0,\n\t\t\tCHANGE emblk_last_sent_ts          emadr_last_sent_ts          TIMESTAMP NULL,\n\t\t\tCHANGE emblk_last_error_ts         emadr_last_error_ts         TIMESTAMP NULL");
        $DB->query("ALTER TABLE T_email__address\n\t\t\tADD UNIQUE emadr_address ( emadr_address )");
        $DB->query("ALTER TABLE T_email__address\n\t\t\tDROP INDEX emblk_address");
        task_end();
        // Add new email status 'redemption'
        task_begin('Upgrading table of email addresses...');
        $DB->query("ALTER TABLE T_email__address\n\t\t\tCHANGE emadr_status   emadr_status ENUM ( 'unknown', 'redemption', 'warning', 'suspicious1', 'suspicious2', 'suspicious3', 'prmerror', 'spammer' ) NOT NULL DEFAULT 'unknown'");
        task_end();
        task_begin('Upgrading blog-group permissions table...');
        db_add_col('T_coll_group_perms', 'bloggroup_can_be_assignee', 'tinyint NOT NULL default 0 AFTER bloggroup_ismember');
        $DB->query('UPDATE T_coll_group_perms
			  SET bloggroup_can_be_assignee = 1
			WHERE bloggroup_group_ID IN ( 1, 2 )');
        task_end();
        task_begin('Upgrading blog-user permissions table...');
        db_add_col('T_coll_user_perms', 'bloguser_can_be_assignee', 'tinyint NOT NULL default 0 AFTER bloguser_ismember');
        task_end();
        task_begin('Dropping obsolete columns from table Links...');
        $DB->query('ALTER TABLE T_links
									DROP COLUMN link_external_url,
									DROP COLUMN link_title,
									DROP COLUMN link_dest_itm_ID');
        task_end();
        // This task was added later to turn OFF smart view counting on upgrade from v5.0 to v5.1 for better performance
        task_begin('Turn off smart view counting...');
        $DB->query('DELETE FROM T_settings WHERE set_name = ' . $DB->quote('smart_view_count'));
        task_end();
        task_begin('Upgrading Posts table...');
        db_drop_col('T_items__item', 'post_views');
        task_end();
        task_begin('Upgrading Files table... ');
        $DB->query("ALTER TABLE T_files\n\t\t\tCHANGE COLUMN file_root_type file_root_type enum('absolute','user','collection','shared','skins','import') not null default 'absolute'");
        task_end();
        // Set flag to recreate autogenerated excerpts due to modifications on the excerpt generation
        // Note: We need to generate this in the end of the upgrade script, because the database must be up to date
        $recreate_autogenerated_excerpts = true;
        set_upgrade_checkpoint('11200');
    }
    if ($old_db_version < 11208) {
        // part 15.a trunk aka second part of "i6"
        // Note create a separate block for the hitlog upgrade because it may require very long time
        task_begin('Upgrade hitlog table...');
        $DB->query('ALTER TABLE T_hitlog
			CHANGE COLUMN hit_ID            hit_ID            INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
			CHANGE COLUMN hit_datetime      hit_datetime      TIMESTAMP NOT NULL DEFAULT \'2000-01-01 00:00:00\',
			CHANGE COLUMN hit_serprank      hit_serprank      SMALLINT UNSIGNED DEFAULT NULL,
			CHANGE COLUMN hit_blog_ID       hit_coll_ID       INT(10) UNSIGNED NULL DEFAULT NULL,
			CHANGE COLUMN hit_response_code hit_response_code SMALLINT DEFAULT NULL,
			ADD COLUMN hit_agent_ID SMALLINT UNSIGNED NULL DEFAULT NULL AFTER hit_agent_type');
        $DB->query('ALTER TABLE T_hitlog
			DROP INDEX hit_blog_ID');
        $DB->query('ALTER TABLE T_hitlog
			ADD KEY hit_coll_ID ( hit_coll_ID )');
        task_end();
        set_upgrade_checkpoint('11208');
    }
    if ($old_db_version < 11210) {
        // part 15.b trunk aka third part of "i6"
        task_begin('Updating widgets setting...');
        // Unset those widgets allow blockcache value which current settings allow blockcache but the caching is always forbidden on runtime;
        $DB->query('UPDATE T_widget
				SET wi_params = REPLACE( wi_params, \'s:16:"allow_blockcache";i:1\', \'s:16:"allow_blockcache";i:0\' )
				WHERE wi_params LIKE \'%s:16:"allow_blockcache";i:1%\' AND (
					wi_code = "user_tools" OR wi_code = "user_login" OR ( wi_code = "msg_menu_link" AND wi_params LIKE \'%s:9:"link_type";s:8:"messages"%\' )
					OR ( wi_code = "menu_link" AND ( wi_params LIKE \'%s:9:"link_type";s:5:"login"%\' OR wi_params LIKE \'%s:9:"link_type";s:8:"register"%\' ) )
					)');
        // Unset 'show_badge' setting in case of msg_menu_link widgets where the link_type is contacts
        $DB->query('UPDATE T_widget
				SET wi_params = REPLACE( wi_params, \'s:10:"show_badge";i:1\', \'s:10:"show_badge";i:0\' )
				WHERE wi_code = "msg_menu_link" AND wi_params LIKE \'%s:9:"link_type";s:8:"contacts"%\' AND wi_params LIKE \'%s:10:"show_badge";i:1%\'');
        task_end();
        task_begin('Updating files hash values...');
        $DB->query('ALTER TABLE T_files MODIFY COLUMN file_hash VARBINARY(32), MODIFY COLUMN file_path_hash VARBINARY(32)');
        $DB->query('UPDATE T_files SET file_hash = UNHEX( file_hash ), file_path_hash = UNHEX( file_path_hash )');
        $DB->query('ALTER TABLE T_files MODIFY COLUMN file_hash BINARY(16) default NULL, MODIFY COLUMN file_path_hash BINARY(16) default NULL');
        task_end();
        task_begin('Upgrading goals table...');
        $DB->query('ALTER TABLE T_track__goal
			ADD COLUMN goal_temp_redir_url varchar(255) default NULL AFTER goal_redir_url,
			ADD COLUMN goal_temp_start_ts  TIMESTAMP NULL            AFTER goal_temp_redir_url,
			ADD COLUMN goal_temp_end_ts    TIMESTAMP NULL            AFTER goal_temp_start_ts,
			ADD COLUMN goal_notes          TEXT DEFAULT NULL');
        task_end();
        set_upgrade_checkpoint('11210');
    }
    if ($old_db_version < 11220) {
        // part 16.a trunk aka fourth part of "i6"
        task_begin('Upgrading countries table...');
        $DB->query('ALTER TABLE T_regional__country
			ADD COLUMN ctry_status      enum( \'trusted\', \'suspect\', \'blocked\' ) NULL DEFAULT NULL,
			ADD COLUMN ctry_block_count int(10) unsigned DEFAULT 0');
        task_end();
        set_upgrade_checkpoint('11220');
    }
    if ($old_db_version < 11240) {
        // part 16.d trunk aka seventh part of "i6"
        task_begin('Updating general settings...');
        $DB->query('UPDATE T_settings SET
			set_name = CASE
				WHEN set_name = "user_closing_allow" THEN "account_close_enabled"
				WHEN set_name = "user_closing_intro" THEN "account_close_intro"
				WHEN set_name = "user_closing_reasons" THEN "account_close_reasons"
				WHEN set_name = "user_closing_byemsg" THEN "account_close_byemsg"
				ELSE set_name
			END');
        task_end();
        set_upgrade_checkpoint('11240');
    }
    if ($old_db_version < 11245) {
        // part 16.e trunk aka eighth part of "i6"
        task_begin('Updating Antispam IP Ranges table...');
        db_add_col('T_antispam__iprange', 'aipr_contact_email_count', 'int(10) unsigned DEFAULT 0 AFTER aipr_user_count');
        task_end();
        task_begin('Updating invalid locale settings...');
        $current_default_locale = $DB->get_var('SELECT set_value FROM T_settings WHERE set_name = "default_locale"');
        if (empty($current_default_locale)) {
            // The default locale is not set in the database, use the one from the config file
            global $default_locale;
            $current_default_locale = $default_locale;
        }
        if ($DB->get_var('SELECT loc_enabled FROM T_locales WHERE loc_locale = ' . $DB->quote($current_default_locale))) {
            // Update invalid user and collection locales to the default, but only if the default exists and it is enabled
            $DB->query('UPDATE T_users
				SET user_locale = ' . $DB->quote($current_default_locale) . '
				WHERE  user_locale NOT IN ( SELECT loc_locale FROM T_locales WHERE loc_enabled = 1 )');
            $DB->query('UPDATE T_blogs
				SET blog_locale = ' . $DB->quote($current_default_locale) . '
				WHERE  blog_locale NOT IN ( SELECT loc_locale FROM T_locales WHERE loc_enabled = 1 )');
        }
        task_end();
        set_upgrade_checkpoint('11245');
    }
    if ($old_db_version < 11250) {
        // part 16.f trunk aka ninth part of "i6"
        // Convert item content separators to new format
        load_funcs('tools/model/_dbmaintenance.funcs.php');
        dbm_convert_item_content_separators();
        set_upgrade_checkpoint('11250');
    }
    if ($old_db_version < 11255) {
        // part 16.g trunk aka tenth part of "i6"
        task_begin('Updating post types...');
        $DB->query("INSERT INTO T_items__type ( ptyp_ID, ptyp_name )\n\t\t\tVALUES ( 1400, 'Intro-Front' )");
        task_end();
        set_upgrade_checkpoint('11255');
    }
    if ($old_db_version < 11260) {
        // part 16.h trunk aka eleventh part of "i6"
        // This upgrade block updates all field collations from 'ascii_bin' to 'ascii_general_ci' except of slugs table.
        task_begin('Clean up comment emails...');
        $DB->query("UPDATE T_comments\n\t\t\t\t\t\tSET comment_author_email = CONVERT(comment_author_email USING ascii)");
        $DB->commit();
        task_end();
        task_begin('Convert the field collations from ascii_bin to ascii_general_ci... <br />');
        // fp> why would we need a transaction here?	$DB->begin();
        task_begin('- Converting skins table...');
        $DB->query("ALTER TABLE T_skins__skin\n\t\t\tMODIFY skin_type enum('normal','feed','sitemap','mobile','tablet') COLLATE ascii_general_ci NOT NULL default 'normal'");
        task_end();
        task_begin('- Converting blogs table...');
        $DB->query("ALTER TABLE T_blogs\n\t\t\tMODIFY blog_access_type    VARCHAR(10) COLLATE ascii_general_ci NOT NULL DEFAULT 'extrapath',\n\t\t\tMODIFY blog_urlname        VARCHAR(255) COLLATE ascii_general_ci NOT NULL DEFAULT 'urlname',\n\t\t\tMODIFY blog_media_location ENUM( 'default', 'subdir', 'custom', 'none' ) COLLATE ascii_general_ci DEFAULT 'default' NOT NULL,\n\t\t\tMODIFY blog_type           ENUM( 'std', 'photo', 'group', 'forum', 'manual' ) COLLATE ascii_general_ci DEFAULT 'std' NOT NULL");
        task_end();
        task_begin('- Converting blog settings table...');
        $DB->query('ALTER TABLE T_coll_settings
			MODIFY cset_name VARCHAR( 50 ) COLLATE ascii_general_ci NOT NULL');
        task_end();
        task_begin('- Converting widgets table...');
        $DB->query("ALTER TABLE {$tableprefix}widget\n\t\t\tMODIFY wi_type ENUM( 'core', 'plugin' ) COLLATE ascii_general_ci NOT NULL DEFAULT 'core',\n\t\t\tMODIFY wi_code VARCHAR(32) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting categories table...');
        $DB->query("ALTER TABLE T_categories\n\t\t\tMODIFY cat_urlname varchar(255) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting posts table...');
        $DB->query("ALTER TABLE T_items__item\n\t\t\tMODIFY post_status               enum('published','community','deprecated','protected','private','review','draft','redirected') COLLATE ascii_general_ci NOT NULL default 'published',\n\t\t\tMODIFY post_urltitle             VARCHAR(210) COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY post_notifications_status ENUM('noreq','todo','started','finished') COLLATE ascii_general_ci NOT NULL DEFAULT 'noreq',\n\t\t\tMODIFY post_comment_status       ENUM('disabled', 'open', 'closed') COLLATE ascii_general_ci NOT NULL DEFAULT 'open',\n\t\t\tMODIFY post_renderers            TEXT COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting comments table...');
        $DB->query("ALTER TABLE T_comments\n\t\t\tMODIFY comment_type         enum('comment','linkback','trackback','pingback') COLLATE ascii_general_ci NOT NULL default 'comment',\n\t\t\tMODIFY comment_status       ENUM('published','community','deprecated','protected','private','review','draft','trash') COLLATE ascii_general_ci DEFAULT 'published' NOT NULL,\n\t\t\tMODIFY comment_author_email varchar(255) COLLATE ascii_general_ci NULL,\n\t\t\tMODIFY comment_author_IP    varchar(23) COLLATE ascii_general_ci NOT NULL default '',\n\t\t\tMODIFY comment_renderers    TEXT COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY comment_secret       CHAR(32) COLLATE ascii_general_ci NULL default NULL,\n\t\t\tMODIFY comment_notif_status ENUM('noreq','todo','started','finished') COLLATE ascii_general_ci NOT NULL DEFAULT 'noreq' COMMENT 'Have notifications been sent for this comment? How far are we in the process?'");
        task_end();
        task_begin('- Converting post prerendered contents table...');
        $DB->query("ALTER TABLE T_items__prerendering\n\t\t\tMODIFY itpr_format    ENUM('htmlbody','entityencoded','xml','text') COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY itpr_renderers TEXT COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting comment prerendered contents table...');
        $DB->query("ALTER TABLE T_comments__prerendering\n\t\t\tMODIFY cmpr_format    ENUM('htmlbody','entityencoded','xml','text') COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY cmpr_renderers TEXT COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting post versions table...');
        $DB->query("ALTER TABLE T_items__version\n\t\t\tMODIFY iver_status ENUM('published','community','deprecated','protected','private','review','draft','redirected') COLLATE ascii_general_ci NULL");
        task_end();
        task_begin('- Converting post settings table...');
        $DB->query("ALTER TABLE T_items__item_settings\n\t\t\tMODIFY iset_name varchar( 50 ) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting user permissions table...');
        $DB->query("ALTER TABLE T_coll_user_perms\n\t\t\tMODIFY bloguser_perm_poststatuses set('review','draft','private','protected','deprecated','community','published','redirected') COLLATE ascii_general_ci NOT NULL default '',\n\t\t\tMODIFY bloguser_perm_edit         ENUM('no','own','lt','le','all','redirected') COLLATE ascii_general_ci NOT NULL default 'no',\n\t\t\tMODIFY bloguser_perm_cmtstatuses  set('review','draft','private','protected','deprecated','community','published') COLLATE ascii_general_ci NOT NULL default '',\n\t\t\tMODIFY bloguser_perm_edit_cmt     ENUM('no','own','anon','lt','le','all') COLLATE ascii_general_ci NOT NULL default 'no'");
        task_end();
        task_begin('- Converting group permissions table...');
        $DB->query("ALTER TABLE T_coll_group_perms\n\t\t\tMODIFY bloggroup_perm_poststatuses set('review','draft','private','protected','deprecated','community','published','redirected') COLLATE ascii_general_ci NOT NULL default '',\n\t\t\tMODIFY bloggroup_perm_edit         ENUM('no','own','lt','le','all','redirected') COLLATE ascii_general_ci NOT NULL default 'no',\n\t\t\tMODIFY bloggroup_perm_cmtstatuses  set('review','draft','private','protected','deprecated','community','published') COLLATE ascii_general_ci NOT NULL default '',\n\t\t\tMODIFY bloggroup_perm_edit_cmt     ENUM('no','own','anon','lt','le','all') COLLATE ascii_general_ci NOT NULL default 'no'");
        task_end();
        task_begin('- Converting links table...');
        $DB->query("ALTER TABLE T_links\n\t\t\tMODIFY link_position varchar(10) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting files table...');
        $DB->query("ALTER TABLE T_files\n\t\t\tMODIFY file_root_type enum('absolute','user','collection','shared','skins','import') COLLATE ascii_general_ci NOT NULL DEFAULT 'absolute'");
        task_end();
        task_begin('- Converting file types table...');
        $DB->query("ALTER TABLE T_filetypes\n\t\t\tMODIFY ftyp_extensions varchar(30) COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY ftyp_viewtype   varchar(10) COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY ftyp_allowed    enum('any','registered','admin') COLLATE ascii_general_ci NOT NULL default 'admin'");
        task_end();
        task_begin('- Converting sessions table...');
        $DB->query("ALTER TABLE T_sessions\n\t\t\tMODIFY sess_key       CHAR(32) COLLATE ascii_general_ci NULL,\n\t\t\tMODIFY sess_ipaddress VARCHAR(39) COLLATE ascii_general_ci NOT NULL DEFAULT '',\n\t\t\tMODIFY sess_device    VARCHAR(8) COLLATE ascii_general_ci NOT NULL DEFAULT ''");
        task_end();
        task_begin('- Converting domains table...');
        $DB->query("ALTER TABLE T_basedomains\n\t\t\tMODIFY dom_status ENUM('unknown','trusted','suspect','blocked') COLLATE ascii_general_ci NOT NULL DEFAULT 'unknown',\n\t\t\tMODIFY dom_type   ENUM('unknown','normal','searcheng','aggregator','email') COLLATE ascii_general_ci NOT NULL DEFAULT 'unknown'");
        task_end();
        task_begin('- Converting logs table...');
        $DB->query("ALTER TABLE T_hitlog\n\t\t\tMODIFY hit_ctrl         VARCHAR(30) COLLATE ascii_general_ci DEFAULT NULL,\n\t\t\tMODIFY hit_type         ENUM('standard','rss','admin','ajax', 'service') COLLATE ascii_general_ci DEFAULT 'standard' NOT NULL,\n\t\t\tMODIFY hit_referer_type ENUM('search','special','spam','referer','direct','self') COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY hit_remote_addr  VARCHAR(40) COLLATE ascii_general_ci DEFAULT NULL,\n\t\t\tMODIFY hit_agent_type   ENUM('robot','browser','unknown') COLLATE ascii_general_ci DEFAULT 'unknown' NOT NULL");
        task_end();
        task_begin('- Converting goal categories table...');
        $DB->query("ALTER TABLE T_track__goalcat\n\t\t\tMODIFY gcat_color  char(7) COLLATE ascii_general_ci default NULL");
        task_end();
        task_begin('- Converting groups table...');
        $DB->query("ALTER TABLE T_groups\n\t\t\tMODIFY grp_perm_blogs                  enum('user','viewall','editall') COLLATE ascii_general_ci NOT NULL default 'user',\n\t\t\tMODIFY grp_perm_xhtmlvalidation        VARCHAR(10) COLLATE ascii_general_ci NOT NULL default 'always',\n\t\t\tMODIFY grp_perm_xhtmlvalidation_xmlrpc VARCHAR(10) COLLATE ascii_general_ci NOT NULL default 'always',\n\t\t\tMODIFY grp_perm_stats                  enum('none','user','view','edit') COLLATE ascii_general_ci NOT NULL default 'none'");
        task_end();
        task_begin('- Converting group settings table...');
        $DB->query("ALTER TABLE T_groups__groupsettings\n\t\t\tMODIFY gset_name VARCHAR(30) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting settings table...');
        $DB->query("ALTER TABLE T_settings\n\t\t\tMODIFY set_name VARCHAR(30) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting cache table...');
        $DB->query("ALTER TABLE T_global__cache\n\t\t\tMODIFY cach_name VARCHAR(30) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting users table...');
        $DB->query("ALTER TABLE T_users\n\t\t\tMODIFY user_email           varchar(255) COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY user_status          enum( 'activated', 'autoactivated', 'closed', 'deactivated', 'emailchanged', 'failedactivation', 'new' ) COLLATE ascii_general_ci NOT NULL default 'new',\n\t\t\tMODIFY user_unsubscribe_key CHAR(32) COLLATE ascii_general_ci NOT NULL default '' COMMENT 'A specific key, it is used when a user wants to unsubscribe from a post comments without signing in',\n\t\t\tMODIFY user_gender          char(1) COLLATE ascii_general_ci NULL");
        task_end();
        task_begin('- Converting user fields table...');
        $DB->query("ALTER TABLE T_users__fielddefs\n\t\t\tMODIFY ufdf_type       char(8) COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY ufdf_required   enum('hidden','optional','recommended','require') COLLATE ascii_general_ci NOT NULL default 'optional',\n\t\t\tMODIFY ufdf_duplicated enum('forbidden','allowed','list') COLLATE ascii_general_ci NOT NULL default 'allowed'");
        task_end();
        task_begin('- Converting user reports table...');
        $DB->query("ALTER TABLE T_users__reports\n\t\t\tMODIFY urep_status enum( 'fake', 'guidelines', 'harass', 'spam', 'other' ) COLLATE ascii_general_ci");
        task_end();
        task_begin('- Converting locales table...');
        $DB->query("ALTER TABLE T_locales\n\t\t\tMODIFY loc_charset varchar(15) COLLATE ascii_general_ci NOT NULL default 'iso-8859-1',\n\t\t\tMODIFY loc_datefmt varchar(20) COLLATE ascii_general_ci NOT NULL default 'y-m-d',\n\t\t\tMODIFY loc_timefmt varchar(20) COLLATE ascii_general_ci NOT NULL default 'H:i:s'");
        task_end();
        task_begin('- Converting antispam table...');
        $DB->query("ALTER TABLE {$tableprefix}antispam\n\t\t\tMODIFY aspm_source enum( 'local','reported','central' ) COLLATE ascii_general_ci NOT NULL default 'reported'");
        task_end();
        task_begin('- Converting IP ranges table...');
        $DB->query("ALTER TABLE T_antispam__iprange\n\t\t\tMODIFY aipr_status enum( 'trusted', 'suspect', 'blocked' ) COLLATE ascii_general_ci NULL DEFAULT NULL");
        task_end();
        task_begin('- Converting user settings table...');
        $DB->query("ALTER TABLE T_users__usersettings\n\t\t\tMODIFY uset_name VARCHAR( 30 ) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting plugins table...');
        $DB->query("ALTER TABLE T_plugins\n\t\t\tMODIFY plug_classname VARCHAR(40) COLLATE ascii_general_ci NOT NULL default '',\n\t\t\tMODIFY plug_code      VARCHAR(32) COLLATE ascii_general_ci NULL,\n\t\t\tMODIFY plug_version   VARCHAR(42) COLLATE ascii_general_ci NOT NULL default '0',\n\t\t\tMODIFY plug_status    ENUM( 'enabled', 'disabled', 'needs_config', 'broken' ) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting plugin settings table...');
        $DB->query("ALTER TABLE T_pluginsettings\n\t\t\tMODIFY pset_name VARCHAR( 30 ) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting plugin user settings table...');
        $DB->query("ALTER TABLE T_pluginusersettings\n\t\t\tMODIFY puset_name VARCHAR( 30 ) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting plugin events table...');
        $DB->query("ALTER TABLE T_pluginevents\n\t\t\tMODIFY pevt_event VARCHAR(40) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting cron logs table...');
        $DB->query("ALTER TABLE T_cron__log\n\t\t\tMODIFY clog_status enum('started','finished','error','timeout') COLLATE ascii_general_ci not null default 'started'");
        task_end();
        task_begin('- Converting countries table...');
        $DB->query("ALTER TABLE T_regional__country\n\t\t\tMODIFY ctry_code   char(2) COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY ctry_status enum( 'trusted', 'suspect', 'blocked' ) COLLATE ascii_general_ci NULL DEFAULT NULL");
        task_end();
        task_begin('- Converting regions table...');
        $DB->query("ALTER TABLE T_regional__region\n\t\t\tMODIFY rgn_code char(6) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting subregions table...');
        $DB->query("ALTER TABLE T_regional__subregion\n\t\t\tMODIFY subrg_code char(6) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting cities table...');
        $DB->query("ALTER TABLE T_regional__city\n\t\t\tMODIFY city_postcode char(12) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting currencies table...');
        $DB->query("ALTER TABLE T_regional__currency\n\t\t\tMODIFY curr_code char(3) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting email logs table...');
        $DB->query("ALTER TABLE T_email__log\n\t\t\tMODIFY emlog_to     VARCHAR(255) COLLATE ascii_general_ci DEFAULT NULL,\n\t\t\tMODIFY emlog_result ENUM( 'ok', 'error', 'blocked' ) COLLATE ascii_general_ci NOT NULL DEFAULT 'ok'");
        task_end();
        task_begin('- Converting email returns table...');
        $DB->query("ALTER TABLE T_email__returns\n\t\t\tMODIFY emret_address   VARCHAR(255) COLLATE ascii_general_ci DEFAULT NULL,\n\t\t\tMODIFY emret_errtype   CHAR(1) COLLATE ascii_general_ci NOT NULL DEFAULT 'U'");
        task_end();
        task_begin('- Converting email addresses table...');
        $DB->query("ALTER TABLE T_email__address\n\t\t\tMODIFY emadr_address VARCHAR(255) COLLATE ascii_general_ci DEFAULT NULL,\n\t\t\tMODIFY emadr_status  ENUM( 'unknown', 'redemption', 'warning', 'suspicious1', 'suspicious2', 'suspicious3', 'prmerror', 'spammer' ) COLLATE ascii_general_ci NOT NULL DEFAULT 'unknown'");
        task_end();
        //	$DB->commit();
        task_end();
        set_upgrade_checkpoint('11260');
    }
    if ($old_db_version < 11270) {
        // part 16.i trunk aka 12th part of "i6"
        // IPv4 mapped IPv6 addresses maximum length is 45 chars: ex. ABCD:ABCD:ABCD:ABCD:ABCD:ABCD:192.168.158.190
        task_begin('Upgrading comments table...');
        $DB->query("ALTER TABLE T_comments\n\t\t\tMODIFY comment_author_IP varchar(45) COLLATE ascii_general_ci NOT NULL default ''");
        task_end();
        task_begin('Upgrading sessions table...');
        $DB->query("ALTER TABLE T_sessions\n\t\t\tMODIFY sess_ipaddress VARCHAR(45) COLLATE ascii_general_ci NOT NULL DEFAULT ''");
        task_end();
        set_upgrade_checkpoint('11270');
    }
    if ($old_db_version < 11280) {
        // part 16.j trunk aka 12th part of "i6"
        task_begin('Upgrading hit logs table...');
        $DB->query("ALTER TABLE T_hitlog\n\t\t\tMODIFY hit_remote_addr VARCHAR(45) COLLATE ascii_general_ci DEFAULT NULL");
        task_end();
        task_begin('Upgrading blogs table...');
        db_drop_col('T_blogs', 'blog_UID');
        task_end();
        set_upgrade_checkpoint('11280');
    }
    if ($old_db_version < 11285) {
        // part 16.k trunk aka 13th part of "i6"
        task_begin('Updating plugins table...');
        $DB->query('UPDATE T_plugins SET
			plug_code = CASE
				WHEN plug_classname = "generic_ping_plugin"         THEN "b2evGPing"
				WHEN plug_classname = "basic_antispam_plugin"       THEN "b2evBAspm"
				WHEN plug_classname = "flowplayer_plugin"           THEN "b2evFlwP"
				WHEN plug_classname = "html5_mediaelementjs_plugin" THEN "b2evH5MP"
				WHEN plug_classname = "html5_videojs_plugin"        THEN "b2evH5VJSP"
				ELSE plug_code
			END');
        task_end();
        set_upgrade_checkpoint('11285');
    }
    if ($old_db_version < 11286) {
        // part 16.l trunk aka 14th part of "i6"
        task_begin('Upgrade timestamp fields... ');
        $DB->query('ALTER TABLE T_email__log
			MODIFY emlog_timestamp TIMESTAMP NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_email__returns
			MODIFY emret_timestamp TIMESTAMP NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_items__prerendering
			MODIFY itpr_datemodified TIMESTAMP NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_comments__prerendering
			MODIFY cmpr_datemodified TIMESTAMP NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_users__reports
			MODIFY urep_datetime datetime NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_items__version
			MODIFY iver_edit_datetime datetime NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_messaging__thread
			MODIFY thrd_datemodified datetime NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_messaging__message
			MODIFY msg_datetime datetime NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_messaging__contact
			MODIFY mct_last_contact_datetime datetime NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        task_end();
        set_upgrade_checkpoint('11286');
    }
    if ($old_db_version < 11300) {
        // part 17 trunk aka "i7"
        task_begin('Upgrading locales table...');
        db_add_col('T_locales', 'loc_shorttimefmt', 'varchar(20) COLLATE ascii_general_ci NOT NULL default "H:i" AFTER loc_timefmt');
        task_end();
        task_begin('Creating message prerendering cache table... ');
        $DB->query('CREATE TABLE T_messaging__prerendering(
				mspr_msg_ID              INT(11) UNSIGNED NOT NULL,
				mspr_format              ENUM("htmlbody","entityencoded","xml","text") COLLATE ascii_general_ci NOT NULL,
				mspr_renderers           TEXT NOT NULL,
				mspr_content_prerendered MEDIUMTEXT NULL,
				mspr_datemodified        TIMESTAMP NOT NULL,
				PRIMARY KEY (mspr_msg_ID, mspr_format)
			) ENGINE = innodb');
        db_add_col('T_messaging__message', 'msg_renderers', 'TEXT NOT NULL');
        $DB->query('UPDATE T_messaging__message SET msg_renderers = "default"');
        task_end();
        task_begin('Upgrading categories table...');
        db_add_col('T_categories', 'cat_last_touched_ts', "TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00'");
        $DB->query('UPDATE T_categories SET cat_last_touched_ts = (
			SELECT post_last_touched_ts
			  FROM T_items__item
			       INNER JOIN T_postcats ON postcat_post_ID = post_ID
			 WHERE postcat_cat_ID = cat_ID
			 ORDER BY post_last_touched_ts DESC
			 LIMIT 1 )');
        task_end();
        task_begin('Create table for User post read status... ');
        $DB->query('CREATE TABLE T_users__postreadstatus (
			uprs_user_ID int(11) unsigned NOT NULL,
			uprs_post_ID int(11) unsigned NOT NULL,
			uprs_read_post_ts TIMESTAMP NOT NULL DEFAULT \'2000-01-01 00:00:00\',
			uprs_read_comment_ts TIMESTAMP NOT NULL DEFAULT \'2000-01-01 00:00:00\',
			PRIMARY KEY ( uprs_user_ID, uprs_post_ID )
			) ENGINE = innodb');
        task_end();
        task_begin('Create table for System log... ');
        $DB->query("CREATE TABLE T_syslog (\n\t\t\tslg_ID        INT NOT NULL AUTO_INCREMENT,\n\t\t\tslg_timestamp TIMESTAMP NOT NULL,\n\t\t\tslg_origin    ENUM('core', 'plugin') COLLATE ascii_general_ci,\n\t\t\tslg_origin_ID INT UNSIGNED NULL,\n\t\t\tslg_object    ENUM('comment', 'item', 'user') COLLATE ascii_general_ci,\n\t\t\tslg_object_ID INT UNSIGNED NOT NULL,\n\t\t\tslg_message   VARCHAR(255) NOT NULL,\n\t\t\tPRIMARY KEY   (slg_ID),\n\t\t\tINDEX         slg_object (slg_object, slg_object_ID)\n\t\t\t) ENGINE = myisam");
        task_end();
        set_upgrade_checkpoint('11300');
    }
    if ($old_db_version < 11310) {
        // part 18 trunk aka second part of "i7"
        task_begin('Upgrading cron tasks table...');
        load_funcs('cron/_cron.funcs.php');
        $DB->begin();
        $DB->query('ALTER TABLE T_cron__task
			CHANGE COLUMN ctsk_controller ctsk_key varchar(50) COLLATE ascii_general_ci NOT NULL AFTER ctsk_repeat_after,
			CHANGE COLUMN ctsk_name ctsk_name varchar(255) null COMMENT "Specific name of this task. This value is set only if this job name was modified by an admin user"');
        // Update keys from controllers
        // Important: Cron job sql query result must be converted to ascii charset since the ctsk_key is already ascii( ascii_bin collation )
        $DB->query('UPDATE T_cron__task
			INNER JOIN ( ' . cron_job_sql_query('key,ctrl') . ' ) AS temp
			       ON ctsk_key = CONVERT( temp.task_ctrl USING ascii )
			SET ctsk_key = temp.task_key');
        // Reset names to NULL if its are default
        $DB->query($sql = 'UPDATE T_cron__task
			INNER JOIN ( ' . cron_job_sql_query() . ' ) AS temp
			        ON ctsk_key = CONVERT( temp.task_key USING ascii ) AND ctsk_name = CONVERT( temp.task_name USING ' . $DB->connection_charset . ' )
			SET ctsk_name = NULL');
        $DB->commit();
        task_end();
        task_begin('Upgrade table system log... ');
        $DB->query('ALTER TABLE T_syslog
			CHANGE COLUMN slg_object slg_object ENUM(\'comment\', \'item\', \'user\', \'file\') COLLATE ascii_general_ci,
			CHANGE COLUMN slg_object_ID slg_object_ID INT UNSIGNED NULL,
			ADD    COLUMN slg_user_ID INT UNSIGNED NULL AFTER slg_timestamp,
			ADD    COLUMN slg_type ENUM(\'info\', \'warning\', \'error\', \'critical_error\') COLLATE ascii_general_ci NOT NULL DEFAULT \'info\' AFTER slg_user_ID');
        task_end();
        task_begin('Upgrade groups table... ');
        db_add_col('T_groups', 'grp_level', 'int unsigned DEFAULT 0 NOT NULL AFTER grp_name');
        $default_groups_levels = array('Administrators' => 10, 'Moderators' => 8, 'Trusted Users' => 6, 'Normal Users' => 4, 'Misbehaving/Suspect Users' => 2, 'Spammers/Restricted Users' => 1);
        // Build sql query to update group level depending on name
        $group_level_query = 'SELECT group_name, group_level FROM (';
        $first_task = true;
        foreach ($default_groups_levels as $def_group_name => $def_group_level) {
            if ($first_task) {
                $group_level_query .= 'SELECT ' . $DB->quote($def_group_name) . ' AS group_name, ' . $DB->quote($def_group_level) . ' AS group_level';
                $first_task = false;
            } else {
                $group_level_query .= ' UNION SELECT ' . $DB->quote($def_group_name) . ', ' . $DB->quote($def_group_level);
            }
        }
        $group_level_query .= ') AS inner_temp';
        // Set default levels depending on name
        $DB->query('UPDATE T_groups
			INNER JOIN ( ' . $group_level_query . ' ) AS temp
			       ON grp_name = CONVERT( temp.group_name USING ' . $DB->connection_charset . ' )
			  SET grp_level = temp.group_level');
        // Set default '4' level for all other groups
        $DB->query('UPDATE T_groups
			  SET grp_level = 4
			WHERE grp_level = 0');
        // Set default user permissions for Moderators group
        $DB->query('UPDATE T_groups__groupsettings
			  SET gset_value = "moderate"
			WHERE gset_name = "perm_users"
			  AND gset_grp_ID = (SELECT grp_ID FROM T_groups WHERE grp_name = "Moderators")');
        task_end();
        task_begin('Updating general settings...');
        $DB->query('UPDATE T_settings
				SET set_value = ' . $DB->quote('yes') . '
			WHERE set_name = ' . $DB->quote('newusers_canregister') . '
				AND set_value = ' . $DB->quote('1'));
        task_end();
        task_begin('Creating table for User invitation codes... ');
        $DB->query('CREATE TABLE T_users__invitation_code (
			ivc_ID        int(11) unsigned NOT NULL auto_increment,
			ivc_code      varchar(32) COLLATE ascii_general_ci NOT NULL,
			ivc_expire_ts TIMESTAMP NOT NULL DEFAULT \'2000-01-01 00:00:00\',
			ivc_source    varchar(30) NULL,
			ivc_grp_ID    int(4) NOT NULL,
			PRIMARY KEY ( ivc_ID ),
			UNIQUE ivc_code ( ivc_code )
		) ENGINE = innodb');
        task_end();
        task_begin('Creating table for User organizations... ');
        $DB->query('CREATE TABLE T_users__organization (
			org_ID   INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
			org_name VARCHAR(255) NOT NULL,
			org_url  VARCHAR(2000) NULL,
			PRIMARY KEY ( org_ID ),
			UNIQUE org_name ( org_name )
		) ENGINE = innodb');
        task_end();
        task_begin('Creating table for relations users with organizations... ');
        $DB->query('CREATE TABLE T_users__user_org (
			uorg_user_ID  INT(11) UNSIGNED NOT NULL,
			uorg_org_ID   INT(11) UNSIGNED NOT NULL,
			uorg_accepted TINYINT(1) DEFAULT 0,
			PRIMARY KEY ( uorg_user_ID, uorg_org_ID )
		) ENGINE = innodb');
        task_end();
        // Rename item settings:
        //   "post_custom_headers" to "metakeywords"
        //   "post_metadesc" to "metadesc"
        //   "post_expiry_delay" to "comment_expiry_delay"
        task_begin('Upgrading Item Settings...');
        $DB->query('UPDATE T_items__item_settings
				  SET iset_name = "metakeywords"
				WHERE iset_name = "post_custom_headers"');
        $DB->query('UPDATE T_items__item_settings
				  SET iset_name = "metadesc"
				WHERE iset_name = "post_metadesc"');
        $DB->query('UPDATE T_items__item_settings
				  SET iset_name = "comment_expiry_delay"
				WHERE iset_name = "post_expiry_delay"');
        task_end();
        task_begin('Upgrade table files... ');
        db_add_col('T_files', 'file_type', "enum('image', 'audio', 'other') COLLATE ascii_general_ci NULL DEFAULT NULL AFTER file_ID");
        task_end();
        task_begin('Upgrade table posts... ');
        $DB->query('ALTER TABLE T_items__item
			CHANGE post_title     post_title     VARCHAR(255) NOT NULL,
			CHANGE post_renderers post_renderers VARCHAR(255) COLLATE ascii_general_ci NOT NULL');
        task_end();
        task_begin('Upgrade table post prerendering cache... ');
        $DB->query('ALTER TABLE T_items__prerendering
			CHANGE itpr_renderers itpr_renderers VARCHAR(255) COLLATE ascii_general_ci NOT NULL');
        task_end();
        task_begin('Upgrade table post versions... ');
        $DB->query('ALTER TABLE T_items__version
			CHANGE iver_title iver_title VARCHAR(255) NULL');
        task_end();
        task_begin('Upgrade table comments... ');
        $DB->query('ALTER TABLE T_comments
			CHANGE comment_renderers comment_renderers VARCHAR(255) COLLATE ascii_general_ci NOT NULL');
        task_end();
        task_begin('Upgrade table comment prerendering cache... ');
        $DB->query('ALTER TABLE T_comments__prerendering
			CHANGE cmpr_renderers cmpr_renderers VARCHAR(255) COLLATE ascii_general_ci NOT NULL');
        task_end();
        task_begin('Upgrade table messages... ');
        $DB->query('ALTER TABLE T_messaging__message
			CHANGE msg_renderers msg_renderers VARCHAR(255) COLLATE ascii_general_ci NOT NULL');
        task_end();
        task_begin('Upgrade table message prerendering cache... ');
        $DB->query('ALTER TABLE T_messaging__prerendering
			CHANGE mspr_renderers mspr_renderers VARCHAR(255) COLLATE ascii_general_ci NOT NULL');
        task_end();
        task_begin('Upgrade table user field definitions... ');
        $DB->query('ALTER TABLE T_users__fielddefs
			CHANGE ufdf_options ufdf_options VARCHAR(255) NULL DEFAULT NULL');
        // Change emtpy ufdf_options to NULL, since it must/may be defined only in case of the list ufdf_type
        $DB->query('UPDATE T_users__fielddefs
			SET ufdf_options = NULL
			WHERE ufdf_options = "" AND ufdf_type != "list"');
        task_end();
        task_begin('Upgrade table cron tasks... ');
        $DB->query('ALTER TABLE T_cron__task
			CHANGE ctsk_params ctsk_params varchar(255)');
        task_end();
        task_begin('Upgrading users table...');
        db_add_col('T_users', 'user_salt', 'CHAR(8) NOT NULL default "" AFTER user_pass');
        task_end();
        task_begin('Updating users pass storage...');
        $DB->query('ALTER TABLE T_users MODIFY COLUMN user_pass VARBINARY(32)');
        $DB->query('UPDATE T_users SET user_pass = UNHEX( user_pass )');
        $DB->query('ALTER TABLE T_users MODIFY COLUMN user_pass BINARY(16) NOT NULL');
        task_end();
        set_upgrade_checkpoint('11310');
    }
    if ($old_db_version < 11320) {
        // part 18.a trunk aka third part of "i7"
        task_begin('Update locales to utf-8 charset...');
        db_drop_col('T_locales', 'loc_charset');
        $DB->query('UPDATE T_locales
			SET loc_name = REPLACE( loc_name, "latin1", "utf8" )
			WHERE loc_locale IN ( "en-US", "en-AU", "en-CA", "en-GB", "en-IL", "en-NZ", "en-SG" )');
        $DB->query('UPDATE T_users SET user_locale = "en-US" WHERE user_locale = "en-US-utf8"');
        $DB->query('UPDATE T_blogs SET blog_locale = "en-US" WHERE blog_locale = "en-US-utf8"');
        $DB->query('UPDATE T_items__item SET post_locale = "en-US" WHERE post_locale = "en-US-utf8"');
        $DB->query('UPDATE T_settings SET set_value = "en-US" WHERE set_name = "default_locale" AND set_value = "en-US-utf8"');
        // Check if the 'en-US-utf8' locale is enabled
        $en_us_utf8_enabled = $DB->get_var('SELECT loc_enabled FROM T_locales WHERE loc_locale = "en-US-utf8"');
        if ($en_us_utf8_enabled !== NULL) {
            // The 'en-US-utf8' was enabled we must enable the 'en-US' even if it was not enabled before because we merged the two locales into one
            $en_us_enabled = $DB->get_var('SELECT loc_enabled FROM T_locales WHERE loc_locale = "en-US"');
            if ($en_us_enabled === NULL) {
                // Update "en-US-utf8" to "en-US"
                $DB->query('UPDATE T_locales SET loc_locale = "en-US" WHERE loc_locale = "en-US-utf8"');
            } elseif ($en_us_utf8_enabled && !$en_us_enabled) {
                // Enable the "en-US" locale because it was not enabled but the "en-US-utf8" was
                $DB->query('UPDATE T_locales SET loc_enabled = 1 WHERE loc_locale = "en-US"');
            }
            if ($en_us_enabled !== NULL) {
                // Remove the "en-US-utf8" locale if the "en_US" locale is already in the database
                $DB->query('DELETE FROM T_locales WHERE loc_locale = "en-US-utf8"');
            }
        }
        task_end();
        task_begin('Upgrade table files... ');
        db_add_col('T_files', 'file_can_be_main_profile', 'TINYINT(1) NOT NULL DEFAULT 1');
        task_end();
        task_begin('Add new video file types... ');
        $video_types = array('webm' => "( 'webm', 'WebM video file', 'video/webm', 'file_video', 'browser', 'registered' )", 'ogv' => "( 'ogv', 'Ogg video file', 'video/ogg', 'file_video', 'browser', 'registered' )", 'm3u8' => "( 'm3u8', 'M3U8 video file', 'application/x-mpegurl', 'file_video', 'browser', 'registered' )");
        $SQL = new SQL();
        $SQL->SELECT('ftyp_extensions');
        $SQL->FROM('T_filetypes');
        $SQL->WHERE('ftyp_extensions LIKE "%' . implode('%" OR ftyp_extensions LIKE "%', array_keys($video_types)) . '%"');
        $existing_video_types = $DB->get_col($SQL->get());
        if (!empty($existing_video_types)) {
            // Some video types arleady exist in DB, Exclude them from inserting
            foreach ($existing_video_types as $vtype) {
                unset($video_types[$vtype]);
            }
        }
        if (count($video_types)) {
            // Insert new video file types
            $DB->query("INSERT INTO T_filetypes\n\t\t\t\t( ftyp_extensions, ftyp_name, ftyp_mimetype, ftyp_icon, ftyp_viewtype, ftyp_allowed )\n\t\t\t\tVALUES " . implode(', ', $video_types));
        }
        task_end();
        set_upgrade_checkpoint('11320');
    }
    if ($old_db_version < 11330) {
        // part 18.b trunk aka 4th part of "i7"
        task_begin('Upgrade table blogs... ');
        $DB->query('UPDATE T_blogs
			  SET blog_in_bloglist = "1"
			WHERE blog_in_bloglist > 0');
        $DB->query('ALTER TABLE T_blogs
			CHANGE blog_in_bloglist blog_in_bloglist ENUM( "public", "logged", "member", "never" ) COLLATE ascii_general_ci DEFAULT "public" NOT NULL');
        $DB->query('UPDATE T_blogs
			  SET blog_in_bloglist = "never"
			WHERE blog_in_bloglist = ""');
        task_end();
        set_upgrade_checkpoint('11330');
    }
    if ($old_db_version < 11340) {
        // part 18.c trunk aka 5th part of "i7"
        task_begin('Upgrading blogs table...');
        $DB->query("ALTER TABLE T_blogs\n\t\t\tMODIFY blog_type ENUM( 'main', 'std', 'photo', 'group', 'forum', 'manual' ) COLLATE ascii_general_ci DEFAULT 'std' NOT NULL");
        task_end();
        set_upgrade_checkpoint('11340');
    }
    if ($old_db_version < 11350) {
        // part 18.d trunk aka 6th part of "i7"
        task_begin('Update category ordering...');
        $DB->query('REPLACE INTO T_coll_settings( cset_coll_ID, cset_name, cset_value )
				SELECT blog_ID, "category_ordering", IFNULL( set_value, "alpha" )
				FROM T_blogs LEFT JOIN T_settings ON set_name = "chapter_ordering"');
        $DB->query('DELETE FROM T_settings WHERE set_name = "chapter_ordering"');
        db_add_col('T_categories', 'cat_subcat_ordering', "enum('parent', 'alpha', 'manual') COLLATE ascii_general_ci NULL DEFAULT NULL AFTER cat_order");
        task_end();
        set_upgrade_checkpoint('11350');
    }
    if ($old_db_version < 11360) {
        // part 18.e trunk aka 7th part of "i7"
        task_begin('Upgrade table posts... ');
        $DB->query('ALTER TABLE T_items__item
            CHANGE post_ptyp_ID post_ityp_ID int(10) unsigned NOT NULL DEFAULT 1');
        $DB->query('ALTER TABLE T_items__item
            DROP INDEX post_ptyp_ID');
        $DB->query('ALTER TABLE T_items__item
            ADD INDEX post_ityp_ID ( post_ityp_ID )');
        task_end();
        task_begin('Upgrade table post types... ');
        $DB->query("ALTER TABLE T_items__type\n\t\t\tCHANGE ptyp_ID   ityp_ID   INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,\n\t\t\tCHANGE ptyp_name ityp_name VARCHAR(30) NOT NULL,\n\t\t\tADD ityp_description       TEXT NULL DEFAULT NULL,\n\t\t\tADD ityp_backoffice_tab    VARCHAR(30) NULL DEFAULT NULL,\n\t\t\tADD ityp_template_name     VARCHAR(40) NULL DEFAULT NULL,\n\t\t\tADD ityp_use_title         ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'required',\n\t\t\tADD ityp_use_url           ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'optional',\n\t\t\tADD ityp_use_text          ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'optional',\n\t\t\tADD ityp_allow_html        TINYINT DEFAULT 1,\n\t\t\tADD ityp_allow_attachments TINYINT DEFAULT 1,\n\t\t\tADD ityp_use_excerpt       ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'optional',\n\t\t\tADD ityp_use_title_tag     ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'optional',\n\t\t\tADD ityp_use_meta_desc     ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'optional',\n\t\t\tADD ityp_use_meta_keywds   ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'optional',\n\t\t\tADD ityp_use_tags          ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'optional',\n\t\t\tADD ityp_allow_featured    TINYINT DEFAULT 1,\n\t\t\tADD ityp_use_country       ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'never',\n\t\t\tADD ityp_use_region        ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'never',\n\t\t\tADD ityp_use_sub_region    ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'never',\n\t\t\tADD ityp_use_city          ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'never',\n\t\t\tADD ityp_use_coordinates   ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'never',\n\t\t\tADD ityp_use_custom_fields TINYINT DEFAULT 1,\n\t\t\tADD ityp_use_comments      TINYINT DEFAULT 1,\n\t\t\tADD ityp_allow_closing_comments   TINYINT DEFAULT 1,\n\t\t\tADD ityp_allow_disabling_comments TINYINT DEFAULT 0,\n\t\t\tADD ityp_use_comment_expiration   ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'optional'");
        $DB->query('UPDATE T_items__type SET
			ityp_backoffice_tab = CASE
				WHEN ityp_ID = 1    THEN "Posts"
				WHEN ityp_ID = 1000 THEN "Pages"
				WHEN ityp_ID >= 1400 AND ityp_ID <= 1600 THEN "Intros"
				WHEN ityp_ID = 2000 THEN "Podcasts"
				WHEN ityp_ID = 3000 THEN "Sidebar links"
				WHEN ityp_ID = 4000 THEN "Advertisement"
				WHEN ityp_ID = 5000 THEN NULL
				ELSE "Posts"
			END,
			ityp_template_name = CASE
				WHEN ityp_ID = 1 OR ityp_ID = 2000 THEN "single"
				WHEN ityp_ID = 1000 THEN "page"
				ELSE NULL
			END');
        task_end();
        task_begin('Adding new post types...');
        $DB->begin();
        $new_item_types = array('manual' => array('type_ID' => 100, 'title' => 'Manual Page'), 'forum' => array('type_ID' => 200, 'title' => 'Forum Topic'));
        $item_types_insert_data = array();
        foreach ($new_item_types as $blog_type => $item_type_data) {
            $item_type_ID = $new_item_types[$blog_type]['type_ID'];
            while ($item_type_ID !== NULL) {
                // Find first free post type ID starting with 100
                $free_item_type_ID = $item_type_ID;
                $item_type_ID = $DB->get_var('SELECT ityp_ID FROM T_items__type WHERE ityp_ID = ' . $DB->quote($item_type_ID));
                if ($item_type_ID === NULL) {
                    // Use this free ID for new type
                    $item_types_insert_data[] = '( ' . $free_item_type_ID . ', ' . $DB->quote($new_item_types[$blog_type]['title']) . ', "Posts", "single", 0 )';
                    $new_item_types[$blog_type]['new_type_ID'] = $free_item_type_ID;
                    break;
                }
                $item_type_ID++;
            }
        }
        if (count($item_types_insert_data)) {
            // Insert new post types
            $DB->query('INSERT INTO T_items__type ( ityp_ID, ityp_name, ityp_backoffice_tab, ityp_template_name, ityp_allow_html )
						VALUES ' . implode(', ', $item_types_insert_data));
            // Update types of all post with "Post" type to new created (only for blogs with type 'forum' and 'manual')
            foreach ($new_item_types as $blog_type => $item_type_data) {
                $DB->query('UPDATE T_items__item
					INNER JOIN T_categories
					   ON post_main_cat_ID = cat_ID
					  AND post_ityp_ID = 1
					INNER JOIN T_blogs
					   ON cat_blog_ID = blog_ID
					  AND blog_type = ' . $DB->quote($blog_type) . '
					  SET post_ityp_ID = ' . $DB->quote($item_type_data['new_type_ID']));
            }
        }
        $DB->commit();
        task_end();
        task_begin('Upgrade table comments... ');
        $DB->query("ALTER TABLE T_comments\n\t\t\tCHANGE comment_type comment_type enum('comment','linkback','trackback','pingback','meta') COLLATE ascii_general_ci NOT NULL default 'comment'");
        task_end();
        task_begin('Creating table for custom fields of Post Types... ');
        $DB->query('CREATE TABLE T_items__type_custom_field (
			itcf_ID      INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
			itcf_ityp_ID INT(11) UNSIGNED NOT NULL,
			itcf_label   VARCHAR(255) NOT NULL,
			itcf_name    VARCHAR(255) COLLATE ascii_general_ci NOT NULL,
			itcf_type    ENUM( \'double\', \'varchar\' ) COLLATE ascii_general_ci NOT NULL,
			itcf_order   INT NULL,
			PRIMARY KEY ( itcf_ID ),
			UNIQUE itcf_ityp_ID_name( itcf_ityp_ID, itcf_name )
		) ENGINE = innodb');
        global $posttypes_perms;
        // Create post types for each blog that has at aleast one custom field
        $SQL = new SQL();
        $SQL->SELECT('*');
        $SQL->FROM('T_coll_settings');
        $SQL->WHERE('cset_name LIKE ' . $DB->quote('custom_%'));
        $SQL->ORDER_BY('cset_coll_ID');
        $setting_rows = $DB->get_results($SQL->get());
        $custom_fields = array();
        $blog_setting_delete_data = array();
        $blog_setting_item_types = array();
        if (count($setting_rows)) {
            // Initialize an array of custom fields from blog settings
            foreach ($setting_rows as $setting_row) {
                if (preg_match('/custom_(double|varchar)\\d+/', $setting_row->cset_name, $matches)) {
                    // It is a custom field
                    if (!isset($custom_fields[$setting_row->cset_coll_ID])) {
                        $custom_fields[$setting_row->cset_coll_ID] = array();
                    }
                    // Delete this blog setting
                    $blog_setting_delete_data[] = 'cset_coll_ID = ' . $DB->quote($setting_row->cset_coll_ID) . ' AND cset_name = ' . $DB->quote($setting_row->cset_name);
                    $cf_type = $matches[1];
                    $cf_key = $setting_row->cset_value;
                    $cf_label = '';
                    $cf_name = '';
                    foreach ($setting_rows as $s_row) {
                        if ($s_row->cset_name == 'custom_' . $cf_type . '_' . $cf_key) {
                            // Label
                            $cf_label = $s_row->cset_value;
                            // Delete this blog setting
                            $blog_setting_delete_data[] = 'cset_coll_ID = ' . $DB->quote($s_row->cset_coll_ID) . ' AND cset_name = ' . $DB->quote($s_row->cset_name);
                        }
                        if ($s_row->cset_name == 'custom_fname_' . $cf_key) {
                            // Name
                            $cf_name = $s_row->cset_value;
                            // Delete this blog setting
                            $blog_setting_delete_data[] = 'cset_coll_ID = ' . $DB->quote($s_row->cset_coll_ID) . ' AND cset_name = ' . $DB->quote($s_row->cset_name);
                        }
                    }
                    $custom_fields[$setting_row->cset_coll_ID][] = array('type' => $cf_type, 'key' => $cf_key, 'label' => $cf_label, 'name' => $cf_name);
                }
            }
            if (count($custom_fields)) {
                // Create post type for each blog with custom fields
                $BlogCache =& get_BlogCache();
                $itypes_insert_data = array();
                $item_type_max_ID = $DB->get_var('SELECT MAX( ityp_ID ) FROM T_items__type') + 1;
                foreach ($custom_fields as $blog_ID => $c_fields) {
                    if (!($cf_Blog = $BlogCache->get_by_ID($blog_ID, false, false))) {
                        // Skip incorrect blog ID
                        continue;
                    }
                    $itypes_insert_data[] = '( ' . $item_type_max_ID . ', ' . $DB->quote('custom_' . $cf_Blog->get('shortname')) . ', ' . '"Posts", ' . '"single", ' . $DB->quote($cf_Blog->get_setting('require_title') == 'none' ? 'never' : $cf_Blog->get_setting('require_title')) . ', ' . $DB->quote(intval($cf_Blog->get_setting('allow_html_post'))) . ', ' . $DB->quote($cf_Blog->get_setting('location_country') == 'hidden' ? 'never' : $cf_Blog->get_setting('location_country')) . ', ' . $DB->quote($cf_Blog->get_setting('location_region') == 'hidden' ? 'never' : $cf_Blog->get_setting('location_region')) . ', ' . $DB->quote($cf_Blog->get_setting('location_subregion') == 'hidden' ? 'never' : $cf_Blog->get_setting('location_subregion')) . ', ' . $DB->quote($cf_Blog->get_setting('location_city') == 'hidden' ? 'never' : $cf_Blog->get_setting('location_city')) . ', ' . $DB->quote($cf_Blog->get_setting('show_location_coordinates') ? 'optional' : 'never') . ', ' . $DB->quote(intval($cf_Blog->get_setting('disable_comments_bypost'))) . ' )';
                    // Update default post type
                    $blog_setting_item_types[$cf_Blog->ID] = $item_type_max_ID;
                    $blog_categories = $DB->get_col('SELECT cat_ID FROM T_categories WHERE cat_blog_ID = ' . $cf_Blog->ID);
                    if (count($blog_categories)) {
                        // Set new post type for each post
                        $DB->query('UPDATE T_items__item SET post_ityp_ID = ' . $item_type_max_ID . '
							WHERE post_ityp_ID = 1
							  AND post_main_cat_ID IN ( ' . implode(', ', $blog_categories) . ' )');
                        if (!empty($posttypes_perms['page'])) {
                            // Find the Pages that have at least one defined custom field:
                            $pages_SQL = new SQL();
                            $pages_SQL->SELECT('post_ID');
                            $pages_SQL->FROM('T_items__item');
                            $pages_SQL->FROM_add('INNER JOIN T_items__item_settings ON post_ID = iset_item_ID');
                            $pages_SQL->WHERE('post_main_cat_ID IN ( ' . implode(', ', $blog_categories) . ' )');
                            $pages_SQL->WHERE_and('post_ityp_ID IN ( ' . implode(', ', $posttypes_perms['page']) . ' )');
                            $pages_SQL->WHERE_and('iset_name LIKE ' . $DB->quote('custom_double_%') . ' OR iset_name LIKE ' . $DB->quote('custom_varchar_%'));
                            $pages_SQL->WHERE_and('iset_value != ""');
                            $pages_SQL->GROUP_BY('post_ID');
                            $pages_IDs = $DB->get_col($pages_SQL->get());
                            $page_type_max_ID = 0;
                            if (count($pages_IDs) > 0) {
                                // We have the Pages that have the defined custom fields
                                // Increase post type ID for new special post type for pages
                                $page_type_max_ID = $item_type_max_ID + 1;
                                $itypes_insert_data[] = '( ' . $page_type_max_ID . ', ' . $DB->quote('page_' . $cf_Blog->get('shortname')) . ', ' . '"Pages", ' . '"page", ' . $DB->quote($cf_Blog->get_setting('require_title') == 'none' ? 'never' : $cf_Blog->get_setting('require_title')) . ', ' . $DB->quote(intval($cf_Blog->get_setting('allow_html_post'))) . ', ' . $DB->quote($cf_Blog->get_setting('location_country') == 'hidden' ? 'never' : $cf_Blog->get_setting('location_country')) . ', ' . $DB->quote($cf_Blog->get_setting('location_region') == 'hidden' ? 'never' : $cf_Blog->get_setting('location_region')) . ', ' . $DB->quote($cf_Blog->get_setting('location_subregion') == 'hidden' ? 'never' : $cf_Blog->get_setting('location_subregion')) . ', ' . $DB->quote($cf_Blog->get_setting('location_city') == 'hidden' ? 'never' : $cf_Blog->get_setting('location_city')) . ', ' . $DB->quote($cf_Blog->get_setting('show_location_coordinates') ? 'optional' : 'never') . ', ' . $DB->quote(intval($cf_Blog->get_setting('disable_comments_bypost'))) . ' )';
                                foreach ($c_fields as $c_field) {
                                    // Insert custom field to get new ID
                                    $DB->query('INSERT INTO T_items__type_custom_field ( itcf_ityp_ID, itcf_label, itcf_name, itcf_type )
										VALUES ( ' . $page_type_max_ID . ', ' . $DB->quote($c_field['label']) . ', ' . $DB->quote($c_field['name']) . ', ' . $DB->quote($c_field['type']) . ' )');
                                    $itcf_ID = $DB->insert_id;
                                    // Change the UID of the item settings to the new inserted itcf_ID (ID of the custom field)
                                    $DB->query('UPDATE T_items__item_settings
											SET iset_name = ' . $DB->quote('custom_' . $c_field['type'] . '_' . $itcf_ID) . '
										WHERE iset_item_ID IN ( ' . implode(', ', $pages_IDs) . ' )
											AND iset_name = ' . $DB->quote('custom_' . $c_field['type'] . '_' . $c_field['key']));
                                }
                                // Set new post type for each page
                                $DB->query('UPDATE T_items__item SET post_ityp_ID = ' . $page_type_max_ID . '
									WHERE post_ID IN ( ' . implode(', ', $pages_IDs) . ' )');
                            }
                        }
                    }
                    // Insert custom fields for standard posts (not pages)
                    foreach ($c_fields as $c_field) {
                        // Insert custom field to get new ID
                        $DB->query('INSERT INTO T_items__type_custom_field ( itcf_ityp_ID, itcf_label, itcf_name, itcf_type )
							VALUES ( ' . $item_type_max_ID . ', ' . $DB->quote($c_field['label']) . ', ' . $DB->quote($c_field['name']) . ', ' . $DB->quote($c_field['type']) . ' )');
                        $itcf_ID = $DB->insert_id;
                        // Change the UID of the item settings to the new inserted itcf_ID (ID of the custom field)
                        $DB->query('UPDATE T_items__item_settings
								SET iset_name = ' . $DB->quote('custom_' . $c_field['type'] . '_' . $itcf_ID) . '
							WHERE iset_name = ' . $DB->quote('custom_' . $c_field['type'] . '_' . $c_field['key']));
                    }
                    // Increase post type ID for next
                    $item_type_max_ID += $page_type_max_ID > 0 ? 2 : 1;
                }
                // Insert post types
                $DB->query('INSERT INTO T_items__type ( ityp_ID, ityp_name, ityp_backoffice_tab, ityp_template_name, ityp_use_title, ityp_allow_html, ityp_use_country, ityp_use_region, ityp_use_sub_region, ityp_use_city, ityp_use_coordinates, ityp_allow_disabling_comments )
					VALUES ' . implode(', ', $itypes_insert_data));
                // Delete old blog settings from DB (custom fields)
                $blog_setting_delete_data[] = 'cset_name LIKE "count_custom_%"';
                $DB->query('DELETE FROM T_coll_settings
					WHERE ( ' . implode(') OR (', $blog_setting_delete_data) . ' )');
            }
        }
        // Update default post types
        $blogs = $DB->get_col('SELECT blog_ID FROM T_blogs');
        $sql_update_blog_settings = array();
        foreach ($blogs as $blog_ID) {
            if (isset($blog_setting_item_types[$blog_ID])) {
                // Set it from custom post type
                $current_item_type = $blog_setting_item_types[$blog_ID];
            } else {
                // Set it from first non reserved post type
                if (!isset($first_item_type)) {
                    $reserved_types = array();
                    foreach ($posttypes_perms as $r_types) {
                        $reserved_types = array_merge($reserved_types, $r_types);
                    }
                    $SQL = new SQL();
                    $SQL->SELECT('ityp_ID');
                    $SQL->FROM('T_items__type');
                    if (!empty($reserved_types)) {
                        $SQL->WHERE('ityp_ID NOT IN ( ' . implode(', ', $reserved_types) . ' )');
                    }
                    $SQL->ORDER_BY('ityp_ID');
                    $SQL->LIMIT('1');
                    $first_item_type = $DB->get_var($SQL->get());
                }
                $current_item_type = $first_item_type;
            }
            $sql_update_blog_settings[] = '( ' . $DB->quote($blog_ID) . ', "default_post_type", ' . $DB->quote($current_item_type) . ' )';
        }
        if (!empty($sql_update_blog_settings)) {
            // Execute a query to update the blog settings
            $DB->query('REPLACE INTO T_coll_settings ( cset_coll_ID, cset_name, cset_value )
				VALUES ' . implode(', ', $sql_update_blog_settings));
        }
        task_end();
        task_begin('Updating site settings... ');
        if ($DB->get_var('SELECT set_value FROM T_settings WHERE set_name = "site_color"') === NULL) {
            // Set default site color only when it is not defined yet
            $DB->query('INSERT INTO T_settings ( set_name, set_value )' . ' VALUES ( "site_color", "#ff8c0f" )');
        }
        task_end();
        set_upgrade_checkpoint('11360');
    }
    if ($old_db_version < 11370) {
        // part 18.f trunk aka 8th part of "i7"
        task_begin('Updating user settings... ');
        $DB->query('DELETE FROM T_users__usersettings WHERE uset_name = "admin_skin"');
        task_end();
        set_upgrade_checkpoint('11370');
    }
    if ($old_db_version < 11375) {
        // part 18.g trunk aka 9th part of "i7"
        task_begin('Upgrade table user field definitions... ');
        $DB->query('ALTER TABLE T_users__fielddefs
			ADD ufdf_icon_name varchar(100) COLLATE ascii_general_ci NULL');
        $DB->query('UPDATE T_users__fielddefs SET
			ufdf_icon_name = CASE
				WHEN ufdf_name = "Yahoo IM"      THEN "fa fa-yahoo"
				WHEN ufdf_name = "Skype"         THEN "fa fa-skype"
				WHEN ufdf_name = "Main phone"    THEN "fa fa-phone"
				WHEN ufdf_name = "Cell phone"    THEN "fa fa-mobile-phone"
				WHEN ufdf_name = "Office phone"  THEN "fa fa-phone"
				WHEN ufdf_name = "Home phone"    THEN "fa fa-phone"
				WHEN ufdf_name = "Office FAX"    THEN "fa fa-fax"
				WHEN ufdf_name = "Home FAX"      THEN "fa fa-fax"
				WHEN ufdf_name = "Linkedin"      THEN "fa fa-linkedin fa-x-linkedin--nudge"
				WHEN ufdf_name = "Twitter"       THEN "fa fa-twitter"
				WHEN ufdf_name = "Facebook"      THEN "fa fa-facebook"
				WHEN ufdf_name = "Flickr"        THEN "fa fa-flickr"
				WHEN ufdf_name = "YouTube"       THEN "fa fa-youtube"
				WHEN ufdf_name = "Digg"          THEN "fa fa-digg"
				WHEN ufdf_name = "StumbleUpon"   THEN "fa fa-stumbleupon"
				WHEN ufdf_name = "GitHub"        THEN "fa fa-github-alt"
				WHEN ufdf_name = "Google Plus"   THEN "fa fa-google-plus fa-x-google-plus--nudge"
				WHEN ufdf_name = "Pinterest"     THEN "fa fa-pinterest-p"
				WHEN ufdf_name = "Main address"  THEN "fa fa-building"
				WHEN ufdf_name = "Home address"  THEN "fa fa-home"
				WHEN ufdf_name = "About me"      THEN "fa fa-info-circle"
				WHEN ufdf_name = "I like"        THEN "fa fa-thumbs-o-up"
				WHEN ufdf_name = "I don\'t like" THEN "fa fa-thumbs-o-down"
				ELSE ufdf_icon_name
			END');
        task_end();
        set_upgrade_checkpoint('11375');
    }
    if ($old_db_version < 11380) {
        // part 18.h trunk aka 10th part of "i7"
        task_begin('Update links table... ');
        $DB->query('UPDATE T_links
			  SET link_position = "cover"
			WHERE link_position = "albumart"');
        task_end();
        set_upgrade_checkpoint('11380');
    }
    if ($old_db_version < 11390) {
        // part 18.i trunk aka 11th part of "i7"
        task_begin('Upgrading table of relations users with organizations... ');
        $DB->query('ALTER TABLE T_users__user_org
			ADD COLUMN uorg_role VARCHAR(255) NULL');
        task_end();
        set_upgrade_checkpoint('11390');
    }
    if ($old_db_version < 11400) {
        // part 18.j trunk aka 12th part of "i7"
        task_begin('Upgrade table user field definitions... ');
        $DB->query('ALTER TABLE T_users__fielddefs
			ADD ufdf_code varchar(20) COLLATE ascii_general_ci NULL');
        $update_user_fields = array('Micro bio' => 'microbio', 'I like' => 'ilike', 'I don\'t like' => 'idontlike', 'MSN/Live IM' => 'msnliveim', 'Yahoo IM' => 'yahooim', 'AOL AIM' => 'aolaim', 'ICQ ID' => 'icqid', 'Skype' => 'skype', 'Main phone' => 'mainphone', 'Cell phone' => 'cellphone', 'Office phone' => 'officephone', 'Home phone' => 'homephone', 'Office FAX' => 'officefax', 'Home FAX' => 'homefax', 'Twitter' => 'twitter', 'Facebook' => 'facebook', 'Google Plus' => 'googleplus', 'Linkedin' => 'linkedin', 'GitHub' => 'github', 'Website' => 'website', 'Blog' => 'blog', 'Myspace' => 'myspace', 'Flickr' => 'flickr', 'YouTube' => 'youtube', 'Digg' => 'digg', 'StumbleUpon' => 'stumbleupon', 'Pinterest' => 'pinterest', 'Role' => 'role', 'Organization' => 'organization', 'Division' => 'division', 'VAT ID' => 'vatid', 'Main address' => 'mainaddress', 'Home address' => 'homeaddress');
        foreach ($update_user_fields as $update_user_field_name => $update_user_field_code) {
            $DB->query('UPDATE T_users__fielddefs
				  SET ufdf_code = ' . $DB->quote($update_user_field_code) . '
				WHERE ufdf_name = ' . $DB->quote($update_user_field_name) . '
				LIMIT 1');
            // limit by 1 in order to update only first record to avoid the duplicate codes
        }
        // Update codes for all other unknown fields
        $DB->query('UPDATE T_users__fielddefs
				SET ufdf_code = CONCAT( "code_", ufdf_ID )
			WHERE ufdf_code IS NULL');
        // Make code field unique
        $DB->query('ALTER TABLE T_users__fielddefs
			MODIFY ufdf_code varchar(20) COLLATE ascii_general_ci UNIQUE NOT NULL');
        task_end();
        /*
         * ADD UPGRADES FOR i7 BRANCH __ABOVE__ IN THIS BLOCK.
         *
         * This part will be included in trunk and i7 branches
         */
        set_upgrade_checkpoint('11400');
    }
    if ($old_db_version < 11410) {
        // part 18.k trunk aka 13th part of "i7"
        task_begin('Upgrading skin names... ');
        $DB->query('UPDATE T_skins__skin 
							 SET skin_folder = CASE
									WHEN skin_folder = "bootstrap"        THEN "bootstrap_blog_skin"
									WHEN skin_folder = "bootstrap_main"   THEN "bootstrap_main_skin"
									WHEN skin_folder = "bootstrap_manual" THEN "bootstrap_manual_skin"
									ELSE skin_folder
			END');
        task_end();
        /*
         * ADD UPGRADES FOR i7 BRANCH __ABOVE__ IN THIS BLOCK.
         *
         * This part will be included in trunk and i7 branches
         */
        set_upgrade_checkpoint('11410');
    }
    if ($old_db_version < 11420) {
        // part 18.l trunk aka 14th part of "i7"
        // This upgrade block restores all field collations that may have been broken by the back-office DB convert tool
        // to 'ascii_bin' and 'ascii_general_ci'
        task_begin('Updating hit log keyphrases table...');
        $DB->query('ALTER TABLE T_track__keyphrase
			MODIFY keyp_phrase  VARCHAR( 255 ) COLLATE utf8_bin NOT NULL');
        task_end();
        task_begin('Check and normalize the ASCII charsets/collations... <br />');
        task_begin('- Converting skins table...');
        $DB->query("ALTER TABLE T_skins__skin\n\t\t\tMODIFY skin_type enum('normal','feed','sitemap','mobile','tablet') COLLATE ascii_general_ci NOT NULL default 'normal'");
        task_end();
        task_begin('- Converting blogs table...');
        $DB->query("ALTER TABLE T_blogs\n\t\t\tMODIFY blog_access_type    VARCHAR(10) COLLATE ascii_general_ci NOT NULL DEFAULT 'extrapath',\n\t\t\tMODIFY blog_urlname        VARCHAR(255) COLLATE ascii_general_ci NOT NULL DEFAULT 'urlname',\n\t\t\tMODIFY blog_in_bloglist    ENUM( 'public', 'logged', 'member', 'never' ) COLLATE ascii_general_ci DEFAULT 'public' NOT NULL,\n\t\t\tMODIFY blog_media_location ENUM( 'default', 'subdir', 'custom', 'none' ) COLLATE ascii_general_ci DEFAULT 'default' NOT NULL,\n\t\t\tMODIFY blog_type           ENUM( 'main', 'std', 'photo', 'group', 'forum', 'manual' ) COLLATE ascii_general_ci DEFAULT 'std' NOT NULL");
        task_end();
        task_begin('- Converting blog settings table...');
        $DB->query('ALTER TABLE T_coll_settings
			MODIFY cset_name VARCHAR( 50 ) COLLATE ascii_general_ci NOT NULL');
        task_end();
        task_begin('- Converting widgets table...');
        $DB->query("ALTER TABLE {$tableprefix}widget\n\t\t\tMODIFY wi_type ENUM( 'core', 'plugin' ) COLLATE ascii_general_ci NOT NULL DEFAULT 'core',\n\t\t\tMODIFY wi_code VARCHAR(32) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting categories table...');
        $DB->query("ALTER TABLE T_categories\n\t\t\tMODIFY cat_urlname varchar(255) COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY cat_subcat_ordering enum('parent', 'alpha', 'manual') COLLATE ascii_general_ci NULL DEFAULT NULL");
        task_end();
        task_begin('- Converting posts table...');
        $DB->query("ALTER TABLE T_items__item\n\t\t\tMODIFY post_status               enum('published','community','deprecated','protected','private','review','draft','redirected') COLLATE ascii_general_ci NOT NULL default 'published',\n\t\t\tMODIFY post_urltitle             VARCHAR(210) COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY post_notifications_status ENUM('noreq','todo','started','finished') COLLATE ascii_general_ci NOT NULL DEFAULT 'noreq',\n\t\t\tMODIFY post_comment_status       ENUM('disabled', 'open', 'closed') COLLATE ascii_general_ci NOT NULL DEFAULT 'open',\n\t\t\tMODIFY post_renderers            VARCHAR(255) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting comments table...');
        $DB->query("ALTER TABLE T_comments\n\t\t\tMODIFY comment_type         enum('comment','linkback','trackback','pingback','meta') COLLATE ascii_general_ci NOT NULL default 'comment',\n\t\t\tMODIFY comment_status       ENUM('published','community','deprecated','protected','private','review','draft','trash') COLLATE ascii_general_ci DEFAULT 'published' NOT NULL,\n\t\t\tMODIFY comment_author_email varchar(255) COLLATE ascii_general_ci NULL,\n\t\t\tMODIFY comment_author_IP    varchar(45) COLLATE ascii_general_ci NOT NULL default '',\n\t\t\tMODIFY comment_renderers    VARCHAR(255) COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY comment_secret       CHAR(32) COLLATE ascii_general_ci NULL default NULL,\n\t\t\tMODIFY comment_notif_status ENUM('noreq','todo','started','finished') COLLATE ascii_general_ci NOT NULL DEFAULT 'noreq' COMMENT 'Have notifications been sent for this comment? How far are we in the process?'");
        task_end();
        task_begin('- Converting post prerendered contents table...');
        $DB->query("ALTER TABLE T_items__prerendering\n\t\t\tMODIFY itpr_format    ENUM('htmlbody','entityencoded','xml','text') COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY itpr_renderers VARCHAR(255) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting comment prerendered contents table...');
        $DB->query("ALTER TABLE T_comments__prerendering\n\t\t\tMODIFY cmpr_format    ENUM('htmlbody','entityencoded','xml','text') COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY cmpr_renderers VARCHAR(255) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting post versions table...');
        $DB->query("ALTER TABLE T_items__version\n\t\t\tMODIFY iver_status ENUM('published','community','deprecated','protected','private','review','draft','redirected') COLLATE ascii_general_ci NULL");
        task_end();
        task_begin('- Converting post types table...');
        $DB->query("ALTER TABLE T_items__type\n\t\t\tMODIFY ityp_use_title              ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'required',\n\t\t\tMODIFY ityp_use_url                ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'optional',\n\t\t\tMODIFY ityp_use_text               ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'optional',\n\t\t\tMODIFY ityp_use_excerpt            ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'optional',\n\t\t\tMODIFY ityp_use_title_tag          ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'optional',\n\t\t\tMODIFY ityp_use_meta_desc          ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'optional',\n\t\t\tMODIFY ityp_use_meta_keywds        ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'optional',\n\t\t\tMODIFY ityp_use_tags               ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'optional',\n\t\t\tMODIFY ityp_use_country            ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'never',\n\t\t\tMODIFY ityp_use_region             ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'never',\n\t\t\tMODIFY ityp_use_sub_region         ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'never',\n\t\t\tMODIFY ityp_use_city               ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'never',\n\t\t\tMODIFY ityp_use_coordinates        ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'never',\n\t\t\tMODIFY ityp_use_comment_expiration ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'optional'");
        task_end();
        task_begin('- Converting post types custom fields table...');
        $DB->query("ALTER TABLE T_items__type_custom_field\n\t\t\tMODIFY itcf_name VARCHAR(255) COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY itcf_type ENUM( 'double', 'varchar' ) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting post settings table...');
        $DB->query("ALTER TABLE T_items__item_settings\n\t\t\tMODIFY iset_name varchar( 50 ) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting user permissions table...');
        $DB->query("ALTER TABLE T_coll_user_perms\n\t\t\tMODIFY bloguser_perm_poststatuses set('review','draft','private','protected','deprecated','community','published','redirected') COLLATE ascii_general_ci NOT NULL default '',\n\t\t\tMODIFY bloguser_perm_edit         ENUM('no','own','lt','le','all','redirected') COLLATE ascii_general_ci NOT NULL default 'no',\n\t\t\tMODIFY bloguser_perm_cmtstatuses  set('review','draft','private','protected','deprecated','community','published') COLLATE ascii_general_ci NOT NULL default '',\n\t\t\tMODIFY bloguser_perm_edit_cmt     ENUM('no','own','anon','lt','le','all') COLLATE ascii_general_ci NOT NULL default 'no'");
        task_end();
        task_begin('- Converting group permissions table...');
        $DB->query("ALTER TABLE T_coll_group_perms\n\t\t\tMODIFY bloggroup_perm_poststatuses set('review','draft','private','protected','deprecated','community','published','redirected') COLLATE ascii_general_ci NOT NULL default '',\n\t\t\tMODIFY bloggroup_perm_edit         ENUM('no','own','lt','le','all','redirected') COLLATE ascii_general_ci NOT NULL default 'no',\n\t\t\tMODIFY bloggroup_perm_cmtstatuses  set('review','draft','private','protected','deprecated','community','published') COLLATE ascii_general_ci NOT NULL default '',\n\t\t\tMODIFY bloggroup_perm_edit_cmt     ENUM('no','own','anon','lt','le','all') COLLATE ascii_general_ci NOT NULL default 'no'");
        task_end();
        task_begin('- Converting links table...');
        $DB->query("ALTER TABLE T_links\n\t\t\tMODIFY link_position varchar(10) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting files table...');
        $DB->query("ALTER TABLE T_files\n\t\t\tMODIFY file_type      enum('image', 'audio', 'other') COLLATE ascii_general_ci NULL DEFAULT NULL,\n\t\t\tMODIFY file_root_type enum('absolute','user','collection','shared','skins','import') COLLATE ascii_general_ci NOT NULL DEFAULT 'absolute'");
        task_end();
        task_begin('- Converting file types table...');
        $DB->query("ALTER TABLE T_filetypes\n\t\t\tMODIFY ftyp_extensions varchar(30) COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY ftyp_viewtype   varchar(10) COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY ftyp_allowed    enum('any','registered','admin') COLLATE ascii_general_ci NOT NULL default 'admin'");
        task_end();
        task_begin('- Converting messages table...');
        $DB->query("ALTER TABLE T_messaging__message\n\t\t\tMODIFY msg_renderers VARCHAR(255) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting message prerendering contents table...');
        $DB->query("ALTER TABLE T_messaging__prerendering\n\t\t\tMODIFY mspr_format    ENUM('htmlbody','entityencoded','xml','text') COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY mspr_renderers VARCHAR(255) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting sessions table...');
        $DB->query("ALTER TABLE T_sessions\n\t\t\tMODIFY sess_key       CHAR(32) COLLATE ascii_general_ci NULL,\n\t\t\tMODIFY sess_ipaddress VARCHAR(45) COLLATE ascii_general_ci NOT NULL DEFAULT '',\n\t\t\tMODIFY sess_device    VARCHAR(8) COLLATE ascii_general_ci NOT NULL DEFAULT ''");
        task_end();
        task_begin('- Converting domains table...');
        $DB->query("ALTER TABLE T_basedomains\n\t\t\tMODIFY dom_status ENUM('unknown','trusted','suspect','blocked') COLLATE ascii_general_ci NOT NULL DEFAULT 'unknown',\n\t\t\tMODIFY dom_type   ENUM('unknown','normal','searcheng','aggregator','email') COLLATE ascii_general_ci NOT NULL DEFAULT 'unknown'");
        task_end();
        task_begin('- Converting logs table...');
        $DB->query("ALTER TABLE T_hitlog\n\t\t\tMODIFY hit_ctrl         VARCHAR(30) COLLATE ascii_general_ci DEFAULT NULL,\n\t\t\tMODIFY hit_type         ENUM('standard','rss','admin','ajax', 'service') COLLATE ascii_general_ci DEFAULT 'standard' NOT NULL,\n\t\t\tMODIFY hit_referer_type ENUM('search','special','spam','referer','direct','self') COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY hit_remote_addr  VARCHAR(45) COLLATE ascii_general_ci DEFAULT NULL,\n\t\t\tMODIFY hit_agent_type   ENUM('robot','browser','unknown') COLLATE ascii_general_ci DEFAULT 'unknown' NOT NULL");
        task_end();
        task_begin('- Converting goal categories table...');
        $DB->query("ALTER TABLE T_track__goalcat\n\t\t\tMODIFY gcat_color  char(7) COLLATE ascii_general_ci default NULL");
        task_end();
        task_begin('- Converting groups table...');
        $DB->query("ALTER TABLE T_groups\n\t\t\tMODIFY grp_perm_blogs                  enum('user','viewall','editall') COLLATE ascii_general_ci NOT NULL default 'user',\n\t\t\tMODIFY grp_perm_xhtmlvalidation        VARCHAR(10) COLLATE ascii_general_ci NOT NULL default 'always',\n\t\t\tMODIFY grp_perm_xhtmlvalidation_xmlrpc VARCHAR(10) COLLATE ascii_general_ci NOT NULL default 'always',\n\t\t\tMODIFY grp_perm_stats                  enum('none','user','view','edit') COLLATE ascii_general_ci NOT NULL default 'none'");
        task_end();
        task_begin('- Converting group settings table...');
        $DB->query("ALTER TABLE T_groups__groupsettings\n\t\t\tMODIFY gset_name VARCHAR(30) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting settings table...');
        $DB->query("ALTER TABLE T_settings\n\t\t\tMODIFY set_name VARCHAR(30) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting cache table...');
        $DB->query("ALTER TABLE T_global__cache\n\t\t\tMODIFY cach_name VARCHAR(30) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting users table...');
        $DB->query("ALTER TABLE T_users\n\t\t\tMODIFY user_email           varchar(255) COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY user_status          enum( 'activated', 'autoactivated', 'closed', 'deactivated', 'emailchanged', 'failedactivation', 'new' ) COLLATE ascii_general_ci NOT NULL default 'new',\n\t\t\tMODIFY user_unsubscribe_key CHAR(32) COLLATE ascii_general_ci NOT NULL default '' COMMENT 'A specific key, it is used when a user wants to unsubscribe from a post comments without signing in',\n\t\t\tMODIFY user_gender          char(1) COLLATE ascii_general_ci NULL");
        task_end();
        task_begin('- Converting user fields table...');
        $DB->query("ALTER TABLE T_users__fielddefs\n\t\t\tMODIFY ufdf_type       char(8) COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY ufdf_required   enum('hidden','optional','recommended','require') COLLATE ascii_general_ci NOT NULL default 'optional',\n\t\t\tMODIFY ufdf_duplicated enum('forbidden','allowed','list') COLLATE ascii_general_ci NOT NULL default 'allowed',\n\t\t\tMODIFY ufdf_icon_name  varchar(100) COLLATE ascii_general_ci NULL,\n\t\t\tMODIFY ufdf_code       varchar(20) COLLATE ascii_general_ci UNIQUE NOT NULL");
        task_end();
        task_begin('- Converting user reports table...');
        $DB->query("ALTER TABLE T_users__reports\n\t\t\tMODIFY urep_status enum( 'fake', 'guidelines', 'harass', 'spam', 'other' ) COLLATE ascii_general_ci");
        task_end();
        task_begin('- Converting user invitation codes table...');
        $DB->query("ALTER TABLE T_users__invitation_code\n\t\t\tMODIFY ivc_code varchar(32) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting locales table...');
        $DB->query("ALTER TABLE T_locales\n\t\t\tMODIFY loc_datefmt varchar(20) COLLATE ascii_general_ci NOT NULL default 'y-m-d',\n\t\t\tMODIFY loc_timefmt varchar(20) COLLATE ascii_general_ci NOT NULL default 'H:i:s',\n\t\t\tMODIFY loc_shorttimefmt varchar(20) COLLATE ascii_general_ci NOT NULL default 'H:i'");
        task_end();
        task_begin('- Converting antispam table...');
        $DB->query("ALTER TABLE {$tableprefix}antispam\n\t\t\tMODIFY aspm_source enum( 'local','reported','central' ) COLLATE ascii_general_ci NOT NULL default 'reported'");
        task_end();
        task_begin('- Converting IP ranges table...');
        $DB->query("ALTER TABLE T_antispam__iprange\n\t\t\tMODIFY aipr_status enum( 'trusted', 'suspect', 'blocked' ) COLLATE ascii_general_ci NULL DEFAULT NULL");
        task_end();
        task_begin('- Converting user settings table...');
        $DB->query("ALTER TABLE T_users__usersettings\n\t\t\tMODIFY uset_name VARCHAR( 30 ) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting plugins table...');
        $DB->query("ALTER TABLE T_plugins\n\t\t\tMODIFY plug_classname VARCHAR(40) COLLATE ascii_general_ci NOT NULL default '',\n\t\t\tMODIFY plug_code      VARCHAR(32) COLLATE ascii_general_ci NULL,\n\t\t\tMODIFY plug_version   VARCHAR(42) COLLATE ascii_general_ci NOT NULL default '0',\n\t\t\tMODIFY plug_status    ENUM( 'enabled', 'disabled', 'needs_config', 'broken' ) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting plugin settings table...');
        $DB->query("ALTER TABLE T_pluginsettings\n\t\t\tMODIFY pset_name VARCHAR( 30 ) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting plugin user settings table...');
        $DB->query("ALTER TABLE T_pluginusersettings\n\t\t\tMODIFY puset_name VARCHAR( 30 ) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting plugin events table...');
        $DB->query("ALTER TABLE T_pluginevents\n\t\t\tMODIFY pevt_event VARCHAR(40) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting cron tasks table...');
        $DB->query("ALTER TABLE T_cron__task\n\t\t\tMODIFY ctsk_key varchar(50) COLLATE ascii_general_ci not null");
        task_end();
        task_begin('- Converting cron logs table...');
        $DB->query("ALTER TABLE T_cron__log\n\t\t\tMODIFY clog_status enum('started','finished','error','timeout') COLLATE ascii_general_ci not null default 'started'");
        task_end();
        task_begin('- Converting countries table...');
        $DB->query("ALTER TABLE T_regional__country\n\t\t\tMODIFY ctry_code   char(2) COLLATE ascii_general_ci NOT NULL,\n\t\t\tMODIFY ctry_status enum( 'trusted', 'suspect', 'blocked' ) COLLATE ascii_general_ci NULL DEFAULT NULL");
        task_end();
        task_begin('- Converting regions table...');
        $DB->query("ALTER TABLE T_regional__region\n\t\t\tMODIFY rgn_code char(6) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting subregions table...');
        $DB->query("ALTER TABLE T_regional__subregion\n\t\t\tMODIFY subrg_code char(6) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting cities table...');
        $DB->query("ALTER TABLE T_regional__city\n\t\t\tMODIFY city_postcode char(12) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting currencies table...');
        $DB->query("ALTER TABLE T_regional__currency\n\t\t\tMODIFY curr_code char(3) COLLATE ascii_general_ci NOT NULL");
        task_end();
        task_begin('- Converting slugs table...');
        $DB->query("ALTER TABLE T_slug\n\t\t\tMODIFY slug_title varchar(255) COLLATE ascii_bin NOT NULL,\n\t\t\tMODIFY slug_type\tchar(6) COLLATE ascii_bin NOT NULL DEFAULT 'item'");
        task_end();
        task_begin('- Converting email logs table...');
        $DB->query("ALTER TABLE T_email__log\n\t\t\tMODIFY emlog_to     VARCHAR(255) COLLATE ascii_general_ci DEFAULT NULL,\n\t\t\tMODIFY emlog_result ENUM( 'ok', 'error', 'blocked' ) COLLATE ascii_general_ci NOT NULL DEFAULT 'ok'");
        task_end();
        task_begin('- Converting email returns table...');
        $DB->query("ALTER TABLE T_email__returns\n\t\t\tMODIFY emret_address   VARCHAR(255) COLLATE ascii_general_ci DEFAULT NULL,\n\t\t\tMODIFY emret_errtype   CHAR(1) COLLATE ascii_general_ci NOT NULL DEFAULT 'U'");
        task_end();
        task_begin('- Converting email addresses table...');
        $DB->query("ALTER TABLE T_email__address\n\t\t\tMODIFY emadr_address VARCHAR(255) COLLATE ascii_general_ci DEFAULT NULL,\n\t\t\tMODIFY emadr_status  ENUM( 'unknown', 'redemption', 'warning', 'suspicious1', 'suspicious2', 'suspicious3', 'prmerror', 'spammer' ) COLLATE ascii_general_ci NOT NULL DEFAULT 'unknown'");
        task_end();
        task_begin('- Converting system log table...');
        $DB->query("ALTER TABLE T_syslog\n\t\t\tMODIFY slg_type   ENUM('info', 'warning', 'error', 'critical_error') COLLATE ascii_general_ci NOT NULL DEFAULT 'info',\n\t\t\tMODIFY slg_origin ENUM('core', 'plugin') COLLATE ascii_general_ci,\n\t\t\tMODIFY slg_object ENUM('comment', 'item', 'user', 'file') COLLATE ascii_general_ci");
        task_end();
        task_end();
        set_upgrade_checkpoint('11420');
    }
    if ($old_db_version < 11430) {
        // part 18.m trunk aka 15th part of "i7"
        task_begin('Upgrading tags table...');
        // Get all tags that contain not ascii chars, because some mysql versions cannot convert them correctly to utf8_bin
        $not_ascii_tags = $DB->get_results('SELECT *
			 FROM T_items__tag
			WHERE tag_name NOT REGEXP "^[A-Za-z0-9_\\-\\s]+$"');
        foreach ($not_ascii_tags as $not_ascii_tag) {
            // Replace each not ascii char with "_" in tag name in order to avoid error on below table upgrading
            $ascii_tag_name = preg_replace('/[^A-Za-z0-9_\\-\\s]/', '_', $not_ascii_tag->tag_name);
            $ascii_tag_name = str_replace('__', '_', $ascii_tag_name);
            if ($ascii_tag_name == $not_ascii_tag->tag_name) {
                // Skip this tag name because it doesn't contain not ascii chars really
                continue;
            }
            // Check tag name for uniqueness
            $c = 1;
            $new_tag_name = $ascii_tag_name;
            while ($DB->get_var('SELECT tag_ID
				 FROM T_items__tag
				WHERE tag_name = ' . $DB->quote($new_tag_name))) {
                $new_tag_name = $ascii_tag_name . $c;
                $c++;
            }
            // Update tag name to new value without not ascii chars
            $DB->query('UPDATE T_items__tag
				  SET tag_name = ' . $DB->quote($new_tag_name) . '
				WHERE tag_ID = ' . $not_ascii_tag->tag_ID);
        }
        // Remove the empty tags
        $empty_tag_IDs = $DB->get_col('SELECT tag_ID FROM T_items__tag
			WHERE tag_name = ""');
        if (!empty($empty_tag_IDs)) {
            $DB->query('DELETE FROM T_items__tag
				WHERE tag_ID IN ( ' . $DB->quote($empty_tag_IDs) . ' ) ');
            $DB->query('DELETE FROM T_items__itemtag
				WHERE itag_tag_ID IN ( ' . $DB->quote($empty_tag_IDs) . ' ) ');
        }
        // Upgrade field "tag_name" from varbinary to varchar utf8_bin
        $DB->query('ALTER TABLE T_items__tag
			MODIFY tag_name VARCHAR(50) COLLATE utf8_bin NOT NULL');
        // Allow multiple special char variations for each tag
        task_end();
        task_begin('Upgrading collection user/group permissions tables...');
        $DB->query("ALTER TABLE T_coll_user_perms\n\t\t\tMODIFY bloguser_perm_edit ENUM('no','own','lt','le','all') COLLATE ascii_general_ci NOT NULL default 'no'");
        $DB->query("ALTER TABLE T_coll_group_perms\n\t\t\tMODIFY bloggroup_perm_edit ENUM('no','own','lt','le','all') COLLATE ascii_general_ci NOT NULL default 'no'");
        task_end();
        // fp> Note: do NOT put back and "add upgrades" comment here. The comment is OUTSIDE of the block now!
        set_upgrade_checkpoint('11430');
    }
    if ($old_db_version < 11440) {
        // part 18.n trunk aka 16th part of "i7"
        task_begin('Upgrading base domains table...');
        $DB->query("ALTER TABLE T_basedomains\n\t\t\tMODIFY dom_name VARCHAR(250) COLLATE utf8_bin NOT NULL DEFAULT ''");
        task_end();
        set_upgrade_checkpoint('11440');
    }
    if ($old_db_version < 11450) {
        // part 18.o trunk aka 17th part of "i7"
        task_begin('Upgrading blog-group permissions table...');
        $DB->query("ALTER TABLE T_coll_group_perms\n\t\t\tADD COLUMN bloggroup_perm_item_type ENUM('standard','restricted','admin') COLLATE ascii_general_ci NOT NULL default 'standard' AFTER bloggroup_perm_poststatuses,\n\t\t\tDROP COLUMN bloggroup_perm_page,\n\t\t\tDROP COLUMN bloggroup_perm_intro,\n\t\t\tDROP COLUMN bloggroup_perm_podcast,\n\t\t\tDROP COLUMN bloggroup_perm_sidebar");
        task_end();
        task_begin('Upgrading blog-user permissions table...');
        $DB->query("ALTER TABLE T_coll_user_perms\n\t\t\tADD COLUMN bloguser_perm_item_type ENUM('standard','restricted','admin') COLLATE ascii_general_ci NOT NULL default 'standard' AFTER bloguser_perm_poststatuses,\n\t\t\tDROP COLUMN bloguser_perm_page,\n\t\t\tDROP COLUMN bloguser_perm_intro,\n\t\t\tDROP COLUMN bloguser_perm_podcast,\n\t\t\tDROP COLUMN bloguser_perm_sidebar");
        task_end();
        task_begin('Upgrade post types table... ');
        $DB->query("ALTER TABLE T_items__type\n\t\t\tADD COLUMN ityp_perm_level ENUM( 'standard', 'restricted', 'admin' ) COLLATE ascii_general_ci NOT NULL default 'standard'");
        task_end();
        set_upgrade_checkpoint('11450');
    }
    if ($old_db_version < 11460) {
        // part 18.p trunk aka 18th part of "i7"
        task_begin('Creating table for PostType-to-Collection relationships...');
        $DB->query("CREATE TABLE T_items__type_coll (\n\t\t\titc_ityp_ID int(11) unsigned NOT NULL,\n\t\t\titc_coll_ID int(11) unsigned NOT NULL,\n\t\t\tPRIMARY KEY (itc_ityp_ID, itc_coll_ID),\n\t\t\tUNIQUE itemtypecoll ( itc_ityp_ID, itc_coll_ID )\n\t\t) ENGINE = innodb");
        task_end();
        task_begin('Updating collection permissions... ');
        $DB->query('UPDATE T_coll_group_perms
			  SET bloggroup_perm_item_type = "restricted"
			WHERE bloggroup_perm_item_type = "standard"');
        $DB->query('UPDATE T_coll_user_perms
			  SET bloguser_perm_item_type = "restricted"
			WHERE bloguser_perm_item_type = "standard"');
        task_end();
        task_begin('Updating post types table... ');
        $DB->query('UPDATE T_items__type SET
			ityp_perm_level = CASE
				WHEN ityp_ID = "1"    THEN "standard"
				WHEN ityp_ID = "100"  THEN "standard"
				WHEN ityp_ID = "200"  THEN "standard"
				WHEN ityp_ID = "1000" THEN "restricted"
				WHEN ityp_ID = "1400" THEN "restricted"
				WHEN ityp_ID = "1500" THEN "restricted"
				WHEN ityp_ID = "1520" THEN "restricted"
				WHEN ityp_ID = "1530" THEN "restricted"
				WHEN ityp_ID = "1570" THEN "restricted"
				WHEN ityp_ID = "1600" THEN "restricted"
				WHEN ityp_ID = "2000" THEN "standard"
				WHEN ityp_ID = "3000" THEN "admin"
				WHEN ityp_ID = "4000" THEN "admin"
				ELSE ityp_perm_level
			END');
        task_end();
        set_upgrade_checkpoint('11460');
    }
    if ($old_db_version < 11470) {
        // part 18.r trunk aka 19th part of "i7"
        task_begin('Updating widgets table... ');
        // Disable all widgets of Menu container for all "Main" collections
        $DB->query('UPDATE ' . $tableprefix . 'widget
			INNER JOIN T_blogs ON blog_ID = wi_coll_ID AND blog_type = "main"
			  SET wi_enabled = 0
			WHERE wi_sco_name = "Menu"');
        task_end();
        set_upgrade_checkpoint('11470');
    }
    if ($old_db_version < 11480) {
        // part 18.s trunk aka 20th part of "i7"
        task_begin('Updating table for PostType-to-Collection relationships... ');
        // Get all collections:
        $collections_SQL = new SQL();
        $collections_SQL->SELECT('blog_ID, blog_type');
        $collections_SQL->FROM('T_blogs');
        $collections = $DB->get_assoc($collections_SQL->get());
        // Get all post types:
        $posttypes_SQL = new SQL();
        $posttypes_SQL->SELECT('ityp_ID');
        $posttypes_SQL->FROM('T_items__type');
        $posttypes = $DB->get_col($posttypes_SQL->get());
        // Enable post types for the collections:
        $posttypes_collections = array();
        foreach ($collections as $collection_ID => $collection_type) {
            switch ($collection_type) {
                // Set what post types should not be enabled depending on the collection type:
                case 'main':
                case 'photo':
                    $skip_posttypes = array(100, 200, 2000, 5000);
                    break;
                case 'forum':
                    $skip_posttypes = array(1, 100, 2000, 5000);
                    break;
                case 'manual':
                    $skip_posttypes = array(1, 200, 2000, 5000);
                    break;
                default:
                    // 'std'
                    $skip_posttypes = array(100, 200, 5000);
                    break;
            }
            foreach ($posttypes as $posttype_ID) {
                if (in_array($posttype_ID, $skip_posttypes)) {
                    // Skip(Don't enable) this post type for the collection:
                    continue;
                }
                $posttypes_collections[] = '( ' . $posttype_ID . ', ' . $collection_ID . ' )';
            }
        }
        if (count($posttypes_collections)) {
            // Update the relationships only when at least one is required:
            $DB->query('REPLACE INTO T_items__type_coll
				( itc_ityp_ID, itc_coll_ID )
				VALUES ' . implode(', ', $posttypes_collections));
        }
        task_end();
        set_upgrade_checkpoint('11480');
    }
    if ($old_db_version < 11482) {
        // v6.6.3
        task_begin('Updating default post types for forums and manual collections... ');
        $item_types = array('manual' => array('ID' => 100, 'name' => 'Manual Page'), 'forum' => array('ID' => 200, 'name' => 'Forum Topic'));
        $update_default_type_sql = array();
        foreach ($item_types as $collection_type => $item_type) {
            // Try to find an item type by ID or name:
            $item_type_ID = $DB->get_var('SELECT ityp_ID
				 FROM T_items__type
				WHERE ityp_ID = ' . $item_type['ID'] . '
				   OR ityp_name = ' . $DB->quote($item_type['name']));
            if (empty($item_type_ID)) {
                // Item type is not found in DB, Skip it:
                continue;
            }
            // Get all collections with type:
            $type_collection_IDs = $DB->get_col('SELECT blog_ID
				 FROM T_blogs
				WHERE blog_type = ' . $DB->quote($collection_type));
            foreach ($type_collection_IDs as $type_collection_ID) {
                $update_default_type_sql[] = '( ' . $type_collection_ID . ', "default_post_type", ' . $DB->quote($item_type_ID) . ' )';
            }
        }
        if (count($update_default_type_sql) > 0) {
            // Update default post types of collections:
            $DB->query('REPLACE INTO T_coll_settings ( cset_coll_ID, cset_name, cset_value )
				VALUES ' . implode(',', $update_default_type_sql));
        }
        task_end();
        set_upgrade_checkpoint('11482');
    }
    if ($old_db_version < 11483) {
        // v6.6.4
        task_begin('Updating general settings...');
        $DB->query('UPDATE T_settings
				SET set_value = ' . $DB->quote('no') . '
			WHERE set_name = ' . $DB->quote('newusers_canregister') . '
				AND set_value = ' . $DB->quote('0'));
        task_end();
        task_begin('Updating user settings...');
        $DB->query('ALTER TABLE T_users__usersettings CHANGE COLUMN uset_name uset_name VARCHAR( 50 ) COLLATE ascii_general_ci NOT NULL');
        $DB->query('ALTER TABLE T_pluginusersettings CHANGE COLUMN puset_name puset_name VARCHAR( 50 ) COLLATE ascii_general_ci NOT NULL');
        task_end();
        set_upgrade_checkpoint('11483');
    }
    if ($old_db_version < 11484) {
        // part 2 of v6.6.4
        task_begin('Upgrade table item types... ');
        $DB->query("ALTER TABLE T_items__type\n\t\t\tADD ityp_use_parent ENUM( 'required', 'optional', 'never' ) COLLATE ascii_general_ci DEFAULT 'never' AFTER ityp_use_url");
        task_end();
        set_upgrade_checkpoint('11484');
    }
    if ($old_db_version < 11485) {
        // v6.6.6
        task_begin('Upgrade table item types... ');
        $DB->query('ALTER TABLE T_items__type
			ADD ityp_allow_breaks TINYINT DEFAULT 1 AFTER ityp_allow_html');
        $DB->query('UPDATE T_items__type
			SET ityp_allow_breaks = 0,
			    ityp_allow_featured = 0
			WHERE ityp_ID >= 1400
			  AND ityp_ID <= 1600');
        task_end();
        set_upgrade_checkpoint('11485');
    }
    if ($old_db_version < 11486) {
        // part 2 of v6.6.6
        task_begin('Upgrade timestamp fields... ');
        $DB->query('ALTER TABLE T_email__log
			MODIFY emlog_timestamp TIMESTAMP NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_email__returns
			MODIFY emret_timestamp TIMESTAMP NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_syslog
			MODIFY slg_timestamp TIMESTAMP NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_items__prerendering
			MODIFY itpr_datemodified TIMESTAMP NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_comments__prerendering
			MODIFY cmpr_datemodified TIMESTAMP NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_messaging__prerendering
			MODIFY mspr_datemodified TIMESTAMP NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_users__reports
			MODIFY urep_datetime datetime NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_items__version
			MODIFY iver_edit_datetime datetime NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_messaging__thread
			MODIFY thrd_datemodified datetime NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_messaging__message
			MODIFY msg_datetime datetime NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        $DB->query('ALTER TABLE T_messaging__contact
			MODIFY mct_last_contact_datetime datetime NOT NULL DEFAULT \'2000-01-01 00:00:00\'');
        task_end();
        // set_upgrade_checkpoint( '11486' );
    }
    /*
     * ADD UPGRADES __ABOVE__ IN A NEW UPGRADE BLOCK.
     *
     * YOU MUST USE:
     * task_begin( 'Descriptive text about action...' );
     * task_end();
     *
     * ALL DB CHANGES MUST BE EXPLICITLY CARRIED OUT. DO NOT RELY ON SCHEMA UPDATES!
     * Schema updates do not survive after several incremental changes.
     *
     * NOTE: every change that gets done here, should bump {@link $new_db_version} (by 100).
     */
    // Execute general upgrade tasks.
    // These tasks needs to be called after every upgrade process, except if they were already executed but the upgrade was not finished because of the max execution time check.
    if (param('exec_general_tasks', 'boolean', 1)) {
        // We haven't executed these general tasks yet:
        // Update modules own b2evo tables
        echo "Calling modules for individual upgrades...<br>\n";
        evo_flush();
        modules_call_method('upgrade_b2evo_tables');
        // Just in case, make sure the db schema version is up to date at the end.
        if ($old_db_version != $new_db_version) {
            // Update DB schema version to $new_db_version
            set_upgrade_checkpoint($new_db_version);
        }
        // We're going to need some environment in order to init caches and create profile picture links...
        if (!is_object($Settings)) {
            // create Settings object
            load_class('settings/model/_generalsettings.class.php', 'GeneralSettings');
            $Settings = new GeneralSettings();
        }
        if (!is_object($Plugins)) {
            // create Plugins object
            load_class('plugins/model/_plugins.class.php', 'Plugins');
            $Plugins = new Plugins();
        }
        // Init Caches:
        load_funcs('tools/model/_system.funcs.php');
        system_init_caches(true, $old_db_version <= 11410);
        // Only force enabling the caches if we upgrade from a version older or equal to 11410 (6.4.2-beta)
        // note: the above outputs messages
        // Check/Repair Caches:
        task_begin('Checking &amp; repairing caches...');
        load_funcs('tools/model/_system.funcs.php');
        // Check all cache folders if exist and work properly. Try to repair cache folders if they aren't ready for operation.
        $check_cache_messages = system_check_caches(true);
        if (is_array($check_cache_messages) && count($check_cache_messages)) {
            // Display errors of the cache checking
            foreach ($check_cache_messages as $check_cache_message) {
                echo '<br /><span class="text-danger"><evo:error>' . $check_cache_message . '</evo:error></span>';
            }
            echo '<br />';
        }
        task_end();
        // Check if profile picture links should be recreated. It won't be executed in each upgrade, but only in those cases when it is required.
        // This requires an up to date database, and also $Plugins and $GeneralSettings objects must be initialized before this.
        // Note: Check $create_profile_picture_links intialization and usage above to get more information.
        if ($create_profile_picture_links) {
            // Create links for all files from the users profile_pictures folder
            task_begin('Creating profile picture links...');
            create_profile_picture_links();
            task_end();
        }
        // Invalidate all page caches after every upgrade.
        // A new version of b2evolution may not use the same links to access special pages.
        // We want to play it safe here so that people don't think that upgrading broke their blog!
        task_begin('Invalidating all page caches to make sure they don\'t contain old action links...');
        invalidate_pagecaches();
        task_end();
        // Reload plugins after every upgrade, to detect even those changes on plugins which didn't require db modifications
        task_begin('Reloading installed plugins to make sure their config is up to date...');
        $Plugins_admin =& get_Plugins_admin();
        $Plugins_admin->reload_plugins();
        task_end();
        // This has to be at the end because plugin install may fail if the DB schema is not current (matching Plugins class).
        // Only new default plugins will be installed, based on $old_db_version.
        // dh> NOTE: if this fails (e.g. fatal error in one of the plugins), it will not get repeated
        task_begin('Installing new default plugins (if any)...');
        install_basic_plugins($old_db_version);
        task_end();
        // Create default cron jobs (this can be done at each upgrade):
        echo "Checking if some default cron jobs need to be installed...<br/>\n";
        evo_flush();
        require_once dirname(__FILE__) . '/_functions_create.php';
        create_default_jobs(true);
        // "Time running low" test: Check if the upgrade script elapsed time is close to the max execution time.
        // Note: This should not really happen except the case when many plugins must be installed.
        task_begin('Checking timing of upgrade...');
        $elapsed_time = time() - $script_start_time;
        $max_exe_time = ini_get('max_execution_time');
        if ($max_exe_time && $elapsed_time > $max_exe_time - 20) {
            // Max exe time not disabled and we're recahing the end
            // URL to continue the upgrade process from install folder
            $recreate_excerpts = $recreate_autogenerated_excerpts ? '&amp;recreate_excerpts=1' : '';
            $upgrade_continue_url = $baseurl . 'install/index.php?locale=' . $locale . '&amp;action=' . $upgrade_action . '&amp;exec_general_tasks=0' . $recreate_excerpts;
            echo 'We are reaching the time limit for this script. Please click <a href="' . $upgrade_continue_url . '">continue</a>...';
            // Dirty temporary solution:
            exit(0);
        }
        task_end();
    }
    if ($recreate_autogenerated_excerpts) {
        if (!is_object($Settings)) {
            // create Settings object
            load_class('settings/model/_generalsettings.class.php', 'GeneralSettings');
            $Settings = new GeneralSettings();
        }
        if (!is_object($Plugins)) {
            // create Plugins object
            load_class('plugins/model/_plugins.class.php', 'Plugins');
            $Plugins = new Plugins();
        }
        task_begin('Recreate autogenerated post excerpts...');
        $upgrade_continue_url = $baseurl . 'install/index.php?locale=' . $locale . '&amp;action=' . $upgrade_action . '&amp;exec_general_tasks=0&amp;recreate_excerpts=1';
        $all_excerpt = param('all_excerpt', 'integer', 0);
        recreate_autogenerated_excerpts($upgrade_continue_url, $all_excerpt == 0);
        task_end();
    }
    // Update the progress bar status
    update_install_progress_bar();
    /*
     * -----------------------------------------------
     * Check to make sure the DB schema is up to date:
     * -----------------------------------------------
     */
    echo "Starting to check DB...<br/>\n";
    evo_flush();
    $upgrade_db_deltas = array();
    // This holds changes to make, if any (just all queries)
    global $debug;
    foreach ($schema_queries as $table => $query_info) {
        // For each table in the schema, check diffs...
        if ($debug) {
            echo '<br />Checking table: ' . $table . ': ';
        }
        $updates = db_delta($query_info[1], array('drop_column', 'drop_index'), false, true);
        if (empty($updates)) {
            if ($debug) {
                echo 'ok';
            }
        } else {
            if ($debug) {
                echo 'NEEDS UPDATE!';
            }
            foreach ($updates as $table => $queries) {
                foreach ($queries as $qinfo) {
                    foreach ($qinfo['queries'] as $query) {
                        // subqueries for this query (usually one, but may include required other queries)
                        $upgrade_db_deltas[] = $query;
                    }
                }
            }
        }
    }
    if ($debug) {
        echo '<br />';
    }
    if (empty($upgrade_db_deltas)) {
        // no upgrades needed:
        echo '<p>' . T_('The database schema is up to date.') . '</p>';
    } else {
        // Upgrades are needed:
        $confirmed_db_upgrade = param('confirmed', 'integer', 0);
        // force confirmation
        $upgrade_db_deltas_confirm_md5 = param('upgrade_db_deltas_confirm_md5', 'string', '');
        if (!$confirmed_db_upgrade) {
            if (!empty($upgrade_db_deltas_confirm_md5)) {
                // received confirmation from form
                if ($upgrade_db_deltas_confirm_md5 != md5(implode('', $upgrade_db_deltas))) {
                    // unlikely to happen
                    echo '<p class="text-danger"><evo:error>' . T_('The DB schema has been changed since confirmation.') . '</evo:error></p>';
                } else {
                    $confirmed_db_upgrade = true;
                }
            }
        }
        if (!$confirmed_db_upgrade) {
            global $action, $form_action;
            load_class('_core/ui/forms/_form.class.php', 'Form');
            if (!empty($form_action)) {
                $Form = new Form($form_action, '', 'post');
            } else {
                $Form = new Form(NULL, '', 'post');
            }
            $Form->begin_form('fform', T_('Upgrade database'));
            $Form->begin_fieldset();
            $Form->hidden('upgrade_db_deltas_confirm_md5', md5(implode('', $upgrade_db_deltas)));
            $Form->hidden('action', $action);
            $Form->hidden('locale', $locale);
            echo '<p>' . T_('The version number is correct, but we have detected changes in the database schema. This can happen if you\'ve been using development versions directly off GitHub...') . '</p>';
            echo '<p>' . T_('The following database changes will be carried out. If you are not sure what this means, it will probably be alright.') . '</p>';
            echo '<ul>';
            foreach ($upgrade_db_deltas as $l_delta) {
                #echo '<li><code>'.nl2br($l_delta).'</code></li>';
                echo '<li><pre>' . str_replace("\t", '  ', $l_delta) . '</pre></li>';
            }
            echo '</ul>';
            $Form->submit(array('', T_('Try to Repair/Upgrade database now!'), 'btn-warning'));
            $Form->end_form();
            return 'need-fix';
        }
        // Alter DB to match DB schema:
        install_make_db_schema_current(true);
    }
    // Force MySQL strict mode
    $DB->query('SET sql_mode = "TRADITIONAL"', 'Force MySQL "strict" mode (and make sure server is not configured with a weird incompatible mode)');
    track_step('upgrade-success');
    return true;
}
 /**
  * Get the main Chapter.
  *
  * @return Chapter
  */
 function &get_main_Chapter()
 {
     if (is_null($this->main_Chapter)) {
         $ChapterCache =& get_ChapterCache();
         /**
          * @var Chapter
          */
         $this->main_Chapter =& $ChapterCache->get_by_ID($this->main_cat_ID, false);
         if (empty($this->main_Chapter)) {
             // If main chapter is broken we should get it from one of extra chapters
             $chapters = $this->get_Chapters();
             foreach ($chapters as $Chapter) {
                 if (!empty($Chapter)) {
                     // We have found a valid Chapter...
                     $this->main_Chapter =& $Chapter;
                     $this->main_cat_ID = $Chapter->ID;
                     break;
                 }
             }
         }
         if (empty($this->main_Chapter)) {
             // If we still don't have a valid Chapter, display clean error and die().
             global $admin_url, $Blog, $blog;
             if (empty($Blog)) {
                 if (!empty($blog)) {
                     $BlogCache =& get_BlogCache();
                     $Blog =& $BlogCache->get_by_ID($blog, false);
                 }
             }
             $url_to_edit_post = $admin_url . '?ctrl=items&amp;action=edit&amp;p=' . $this->ID;
             if (!empty($Blog)) {
                 $url_to_edit_post .= '&amp;blog=' . $Blog->ID;
                 if (is_admin_page()) {
                     // Try to set a main category
                     $default_cat_ID = $Blog->get_setting('default_cat_ID');
                     if (!empty($default_cat_ID)) {
                         // If default category is set
                         $this->main_cat_ID = $default_cat_ID;
                         $this->main_Chapter =& $ChapterCache->get_by_ID($this->main_cat_ID, false);
                     } else {
                         // Set from first chapter of the blog
                         $ChapterCache->clear();
                         $ChapterCache->load_subset($Blog->ID);
                         if ($Chapter =& $ChapterCache->get_next()) {
                             $this->main_cat_ID = $Chapter->ID;
                             $this->main_Chapter =& $Chapter;
                         }
                     }
                 }
             }
             $message = sprintf('Item with ID <a %s>%s</a> has an invalid main category ID %s.', 'href="' . $url_to_edit_post . '"', $this->ID, $this->main_cat_ID);
             if (empty($Blog)) {
                 // No blog defined
                 $message .= ' In addition we cannot fallback to the default category because no valid blog ID has been specified.';
             }
             if (empty($this->main_Chapter)) {
                 // Main chapter is not defined, because blog doesn't have the default cat ID and even blog doesn't have any categories
                 debug_die($message);
             } else {
                 // Main chapter is defined, we can show the page
                 global $Messages;
                 $Messages->add($message);
             }
         }
     }
     return $this->main_Chapter;
 }
 /**
  * Generate a title for the current list, depending on its filtering params
  *
  * @todo cleanup some displays
  * @todo implement HMS part of YMDHMS
  *
  * @return array List of titles to display, which are escaped for HTML display
  *               (dh> only checked this for 'authors'/?authors=, where the output was not escaped)
  */
 function get_filter_titles($ignore = array(), $params = array())
 {
     global $month, $disp_detail;
     $params = array_merge(array('category_text' => T_('Category') . ': ', 'categories_text' => T_('Categories') . ': ', 'categories_nor_text' => T_('All but '), 'tag_text' => T_('Tag') . ': ', 'tags_text' => T_('Tags') . ': ', 'author_text' => T_('Author') . ': ', 'authors_text' => T_('Authors') . ': ', 'authors_nor_text' => T_('All authors except') . ': ', 'visibility_text' => T_('Visibility') . ': ', 'keyword_text' => T_('Keyword') . ': ', 'keywords_text' => T_('Keywords') . ': ', 'keywords_exact_text' => T_('Exact match') . ' ', 'status_text' => T_('Status') . ': ', 'statuses_text' => T_('Statuses') . ': ', 'archives_text' => T_('Archives for') . ': ', 'assignes_text' => T_('Assigned to') . ': ', 'group_mask' => '$group_title$$filter_items$', 'filter_mask' => '"$filter_name$"', 'filter_mask_nogroup' => '"$filter_name$"', 'before_items' => '', 'after_items' => '', 'separator_and' => ' ' . T_('and') . ' ', 'separator_or' => ' ' . T_('or') . ' ', 'separator_nor' => ' ' . T_('or') . ' ', 'separator_comma' => ', ', 'display_category' => true, 'display_archive' => true, 'display_keyword' => true, 'display_tag' => true, 'display_author' => true, 'display_assignee' => true, 'display_locale' => true, 'display_status' => true, 'display_visibility' => true, 'display_time' => true, 'display_limit' => true), $params);
     if (empty($this->filters)) {
         // Filters have no been set before, we'll use the default filterset:
         // echo ' setting default filterset ';
         $this->set_filters($this->default_filters);
     }
     $title_array = array();
     if ($this->single_post) {
         // We have requested a specific post:
         // Should be in first position
         $Item =& $this->get_by_idx(0);
         if (is_null($Item)) {
             $title_array[] = T_('Invalid request');
         } else {
             $title_array[] = $Item->get_titletag();
         }
         return $title_array;
     }
     // Check if the filter mask has an icon to clear the filter item
     $clear_icon = strpos($params['filter_mask'], '$clear_icon$') !== false;
     $filter_classes = array('green');
     $filter_class_i = 0;
     if (strpos($params['filter_mask'], '$filter_class$') !== false) {
         // Initialize array with available classes for filter items
         $filter_classes = array('green', 'yellow', 'orange', 'red', 'magenta', 'blue');
     }
     // CATEGORIES:
     if ($params['display_category']) {
         if (!empty($this->filters['cat_array'])) {
             // We have requested specific categories...
             $cat_names = array();
             $ChapterCache =& get_ChapterCache();
             $catsel_param = get_param('catsel');
             foreach ($this->filters['cat_array'] as $cat_ID) {
                 if (($tmp_Chapter =& $ChapterCache->get_by_ID($cat_ID, false)) !== false) {
                     // It is almost never meaningful to die over an invalid cat when generating title
                     $cat_clear_url = regenerate_url((empty($catsel_param) ? 'cat=' : 'catsel=') . $cat_ID);
                     if ($disp_detail == 'posts-subcat' || $disp_detail == 'posts-cat') {
                         // Remove category url from $ReqPath when we use the cat url instead of cat ID
                         $cat_clear_url = str_replace('/' . $tmp_Chapter->get_url_path(), '', $cat_clear_url);
                     }
                     $cat_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', $cat_clear_url) : '';
                     $cat_names[] = str_replace(array('$group_title$', '$filter_name$', '$clear_icon$', '$filter_class$'), array($params['category_text'], $tmp_Chapter->name, $cat_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask']);
                 }
             }
             $filter_class_i++;
             if ($this->filters['cat_modifier'] == '*') {
                 // Categories with "AND" condition
                 $cat_names_string = implode($params['separator_and'], $cat_names);
             } elseif ($this->filters['cat_modifier'] == '-') {
                 // Categories with "NOR" condition
                 $cat_names_string = implode($params['separator_nor'], $cat_names);
             } else {
                 // Categories with "OR" condition
                 $cat_names_string = implode($params['separator_or'], $cat_names);
             }
             if (!empty($cat_names_string)) {
                 if ($this->filters['cat_modifier'] == '-') {
                     // Categories with "NOR" condition
                     $cat_names_string = $params['categories_nor_text'] . $cat_names_string;
                     $params['category_text'] = $params['categories_text'];
                 }
                 $title_array['cats'] = str_replace(array('$group_title$', '$filter_items$'), count($this->filters['cat_array']) > 1 ? array($params['categories_text'], $params['before_items'] . $cat_names_string . $params['after_items']) : array($params['category_text'], $cat_names_string), $params['group_mask']);
             }
         }
     }
     // ARCHIVE TIMESLOT:
     if ($params['display_archive']) {
         if (!empty($this->filters['ymdhms'])) {
             // We have asked for a specific timeframe:
             $my_year = substr($this->filters['ymdhms'], 0, 4);
             if (strlen($this->filters['ymdhms']) > 4) {
                 // We have requested a month too:
                 $my_month = T_($month[substr($this->filters['ymdhms'], 4, 2)]);
             } else {
                 $my_month = '';
             }
             // Requested a day?
             $my_day = substr($this->filters['ymdhms'], 6, 2);
             $arch = $my_month . ' ' . $my_year;
             if (!empty($my_day)) {
                 // We also want to display a day
                 $arch .= ', ' . $my_day;
             }
             if (!empty($this->filters['week']) || $this->filters['week'] === 0) {
                 // We also want to display a week number
                 $arch .= ', ' . T_('week') . ' ' . $this->filters['week'];
             }
             $filter_class_i = $filter_class_i > count($filter_classes) - 1 ? 0 : $filter_class_i;
             $arch_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', regenerate_url($this->param_prefix . 'm')) : '';
             $arch = str_replace(array('$group_title$', '$filter_name$', '$clear_icon$', '$filter_class$'), array($params['archives_text'], $arch, $arch_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask']);
             $title_array['ymdhms'] = str_replace(array('$group_title$', '$filter_items$'), array($params['archives_text'], $arch), $params['group_mask']);
             $filter_class_i++;
         }
     }
     // KEYWORDS:
     if ($params['display_keyword']) {
         if (!empty($this->filters['keywords'])) {
             if ($this->filters['phrase'] == 'OR' || $this->filters['phrase'] == 'AND') {
                 // Search by each keyword
                 $keywords = trim(preg_replace('/("|, *)/', ' ', $this->filters['keywords']));
                 $keywords = explode(' ', $keywords);
             } else {
                 // Exact match (Single keyword)
                 $keywords = array($this->filters['keywords']);
             }
             $filter_class_i = $filter_class_i > count($filter_classes) - 1 ? 0 : $filter_class_i;
             $keyword_names = array();
             foreach ($keywords as $keyword) {
                 $word_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', regenerate_url($this->param_prefix . 's=' . $keyword)) : '';
                 $keyword_names[] = str_replace(array('$group_title$', '$filter_name$', '$clear_icon$', '$filter_class$'), array($params['keyword_text'], $keyword, $word_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask']);
             }
             $filter_class_i++;
             $keywords = ($this->filters['exact'] ? $params['keywords_exact_text'] : '') . implode($this->filters['phrase'] == 'OR' ? $params['separator_or'] : $params['separator_and'], $keyword_names);
             $title_array[] = str_replace(array('$group_title$', '$filter_items$'), count($keyword_names) > 1 ? array($params['keywords_text'], $params['before_items'] . $keywords . $params['after_items']) : array($params['keyword_text'], $keywords), $params['group_mask']);
         }
     }
     // TAGS:
     if ($params['display_tag']) {
         if (!empty($this->filters['tags'])) {
             $tags = explode(',', $this->filters['tags']);
             $tag_names = array();
             $filter_class_i = $filter_class_i > count($filter_classes) - 1 ? 0 : $filter_class_i;
             foreach ($tags as $tag) {
                 $tag_clear_url = regenerate_url($this->param_prefix . 'tag=' . $tag);
                 if ($disp_detail == 'posts-tag') {
                     // Remove tag url from $ReqPath when we use tag url instead of tag ID
                     $tag_clear_url = str_replace('/' . $tag . ':', '', $tag_clear_url);
                 }
                 $tag_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', $tag_clear_url) : '';
                 $tag_names[] = str_replace(array('$group_title$', '$filter_name$', '$clear_icon$', '$filter_class$'), array($params['tag_text'], $tag, $tag_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask']);
             }
             $filter_class_i++;
             $tags = implode($params['separator_comma'], $tag_names);
             $title_array[] = str_replace(array('$group_title$', '$filter_items$'), count($tag_names) > 1 ? array($params['tags_text'], $params['before_items'] . $tags . $params['after_items']) : array($params['tag_text'], $tags), $params['group_mask']);
         }
     }
     // AUTHORS:
     if ($params['display_author']) {
         if (!empty($this->filters['authors']) || !empty($this->filters['authors_login'])) {
             $authors = trim($this->filters['authors'] . ',' . get_users_IDs_by_logins($this->filters['authors_login']), ',');
             $exclude_authors = false;
             if (substr($authors, 0, 1) == '-') {
                 // Authors are excluded
                 $authors = substr($authors, 1);
                 $exclude_authors = true;
             }
             $authors = preg_split('~\\s*,\\s*~', $authors, -1, PREG_SPLIT_NO_EMPTY);
             $author_names = array();
             if ($authors) {
                 $UserCache =& get_UserCache();
                 $filter_class_i = $filter_class_i > count($filter_classes) - 1 ? 0 : $filter_class_i;
                 foreach ($authors as $author_ID) {
                     if ($tmp_User = $UserCache->get_by_ID($author_ID, false, false)) {
                         $user_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', regenerate_url($this->param_prefix . 'author=' . $author_ID)) : '';
                         $author_names[] = str_replace(array('$group_title$', '$filter_name$', '$clear_icon$', '$filter_class$'), array($params['author_text'], $tmp_User->get('login'), $user_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask']);
                     }
                 }
                 $filter_class_i++;
             }
             if (count($author_names) > 0) {
                 // Display info of filter by authors
                 if ($exclude_authors) {
                     // Exclude authors
                     $author_names_string = $params['authors_nor_text'] . implode($params['separator_nor'], $author_names);
                 } else {
                     // Filter by authors
                     $author_names_string = implode($params['separator_comma'], $author_names);
                 }
                 $title_array[] = str_replace(array('$group_title$', '$filter_items$'), count($author_names) > 1 ? array($params['authors_text'], $params['before_items'] . $author_names_string . $params['after_items']) : array($params['author_text'], $author_names_string), $params['group_mask']);
             }
         }
     }
     // ASSIGNEES:
     if ($params['display_assignee']) {
         if (!empty($this->filters['assignees']) || !empty($this->filters['assignees_login'])) {
             $filter_class_i = $filter_class_i > count($filter_classes) - 1 ? 0 : $filter_class_i;
             if ($this->filters['assignees'] == '-') {
                 $user_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', regenerate_url($this->param_prefix . 'assgn')) : '';
                 $title_array[] = str_replace(array('$filter_name$', '$clear_icon$', '$filter_class$'), array(T_('Not assigned'), $user_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask_nogroup']);
             } else {
                 $assignees = trim($this->filters['assignees'] . ',' . get_users_IDs_by_logins($this->filters['assignees_login']), ',');
                 $assignees = preg_split('~\\s*,\\s*~', $assignees, -1, PREG_SPLIT_NO_EMPTY);
                 $assignees_names = array();
                 if ($assignees) {
                     $UserCache =& get_UserCache();
                     foreach ($assignees as $user_ID) {
                         if ($tmp_User =& $UserCache->get_by_ID($user_ID, false, false)) {
                             $user_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', regenerate_url($this->param_prefix . 'assgn=' . $user_ID)) : '';
                             $assignees_names[] = str_replace(array('$group_title$', '$filter_name$', '$clear_icon$', '$filter_class$'), array($params['assignes_text'], $tmp_User->get_identity_link(array('link_text' => 'name')), $user_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask']);
                         }
                     }
                 }
                 $title_array[] = str_replace(array('$group_title$', '$filter_items$'), count($assignees_names) > 1 ? array($params['assignes_text'], $params['before_items'] . implode($params['separator_comma'], $assignees_names) . $params['after_items']) : array($params['assignes_text'], implode($params['separator_comma'], $assignees_names)), $params['group_mask']);
             }
             $filter_class_i++;
         }
     }
     // LOCALE:
     if ($params['display_locale']) {
         if ($this->filters['lc'] != 'all') {
             $filter_class_i = $filter_class_i > count($filter_classes) - 1 ? 0 : $filter_class_i;
             $user_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', regenerate_url($this->param_prefix . 'lc')) : '';
             $loc = str_replace(array('$group_title$', '$filter_name$', '$clear_icon$', '$filter_class$'), array(T_('Locale') . ': ', $this->filters['lc'], $user_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask']);
             $title_array[] = str_replace(array('$group_title$', '$filter_items$'), array(T_('Locale') . ': ', $loc), $params['group_mask']);
             $filter_class_i++;
         }
     }
     // EXTRA STATUSES:
     if ($params['display_status']) {
         if (!empty($this->filters['statuses'])) {
             $filter_class_i = $filter_class_i > count($filter_classes) - 1 ? 0 : $filter_class_i;
             if ($this->filters['statuses'] == '-') {
                 $status_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', regenerate_url($this->param_prefix . 'status=-')) : '';
                 $title_array[] = str_replace(array('$filter_name$', '$clear_icon$', '$filter_class$'), array(T_('Without status'), $status_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask_nogroup']);
             } else {
                 $status_IDs = explode(',', $this->filters['statuses']);
                 $ItemStatusCache =& get_ItemStatusCache();
                 $statuses = array();
                 foreach ($status_IDs as $status_ID) {
                     if ($ItemStatus =& $ItemStatusCache->get_by_ID($status_ID)) {
                         $status_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', regenerate_url($this->param_prefix . 'status=' . $status_ID)) : '';
                         $statuses[] = str_replace(array('$group_title$', '$filter_name$', '$clear_icon$', '$filter_class$'), array($params['status_text'], $ItemStatus->get_name(), $status_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask']);
                     }
                 }
                 $title_array[] = str_replace(array('$group_title$', '$filter_items$'), count($statuses) > 1 ? array($params['statuses_text'], $params['before_items'] . implode($params['separator_comma'], $statuses) . $params['after_items']) : array($params['status_text'], implode($params['separator_comma'], $statuses)), $params['group_mask']);
             }
             $filter_class_i++;
         }
     }
     // VISIBILITY (SHOW STATUSES):
     if ($params['display_visibility']) {
         if (!in_array('visibility', $ignore)) {
             $post_statuses = get_visibility_statuses();
             if (count($this->filters['visibility_array']) != count($post_statuses)) {
                 // Display it only when visibility filter is changed
                 $status_titles = array();
                 $filter_class_i = $filter_class_i > count($filter_classes) - 1 ? 0 : $filter_class_i;
                 foreach ($this->filters['visibility_array'] as $status) {
                     $vis_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', regenerate_url($this->param_prefix . 'show_statuses=' . $status)) : '';
                     $status_titles[] = str_replace(array('$group_title$', '$filter_name$', '$clear_icon$', '$filter_class$'), array($params['visibility_text'], $post_statuses[$status], $vis_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask']);
                 }
                 $filter_class_i++;
                 $title_array[] = str_replace(array('$group_title$', '$filter_items$'), count($status_titles) > 1 ? array($params['visibility_text'], $params['before_items'] . implode($params['separator_comma'], $status_titles) . $params['after_items']) : array($params['visibility_text'], implode($params['separator_comma'], $status_titles)), $params['group_mask']);
             }
         }
     }
     if ($params['display_time']) {
         // START AT:
         if (!empty($this->filters['ymdhms_min']) || !empty($this->filters['ts_min'])) {
             $filter_class_i = $filter_class_i > count($filter_classes) - 1 ? 0 : $filter_class_i;
             if (!empty($this->filters['ymdhms_min'])) {
                 $time_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', regenerate_url($this->param_prefix . 'dstart')) : '';
                 $title_array['ts_min'] = str_replace(array('$group_title$', '$filter_name$', '$clear_icon$', '$filter_class$'), array(T_('Start at') . ': ', date2mysql($this->filters['ymdhms_min']), $time_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask']);
             } else {
                 if ($this->filters['ts_min'] == 'now') {
                     $time_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', regenerate_url($this->param_prefix . 'show_future')) : '';
                     $title_array['ts_min'] = str_replace(array('$filter_name$', '$clear_icon$', '$filter_class$'), array(T_('Hide past'), $time_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask_nogroup']);
                 } else {
                     $time_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', regenerate_url($this->param_prefix . 'show_future')) : '';
                     $title_array['ts_min'] = str_replace(array('$group_title$', '$filter_name$', '$clear_icon$', '$filter_class$'), array(T_('Start at') . ': ', date2mysql($this->filters['ts_min']), $time_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask']);
                 }
             }
             $filter_class_i++;
         }
         // STOP AT:
         if (!empty($this->filters['ymdhms_max']) || !empty($this->filters['ts_max'])) {
             $filter_class_i = $filter_class_i > count($filter_classes) - 1 ? 0 : $filter_class_i;
             if (!empty($this->filters['ymdhms_max'])) {
                 $time_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', regenerate_url($this->param_prefix . 'dstop')) : '';
                 $title_array['ts_max'] = str_replace(array('$group_title$', '$filter_name$', '$clear_icon$', '$filter_class$'), array(T_('Stop at') . ': ', date2mysql($this->filters['ymdhms_max']), $time_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask']);
             } else {
                 if ($this->filters['ts_max'] == 'now') {
                     if (!in_array('hide_future', $ignore)) {
                         $time_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', regenerate_url($this->param_prefix . 'show_past')) : '';
                         $title_array['ts_max'] = str_replace(array('$filter_name$', '$clear_icon$', '$filter_class$'), array(T_('Hide future'), $time_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask_nogroup']);
                     }
                 } else {
                     $time_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', regenerate_url($this->param_prefix . 'show_past')) : '';
                     $title_array['ts_max'] = str_replace(array('$group_title$', '$filter_name$', '$clear_icon$', '$filter_class$'), array(T_('Stop at') . ': ', date2mysql($this->filters['ts_max']), $time_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask']);
                 }
             }
             $filter_class_i++;
         }
     }
     // LIMIT TO:
     if ($params['display_limit']) {
         if ($this->single_post) {
             // Single post: no paging required!
         } elseif (!empty($this->filters['ymdhms'])) {
             // no restriction if we request a month... some permalinks may point to the archive!
         } elseif ($this->filters['unit'] == 'posts' || $this->filters['unit'] == 'all') {
             // We're going to page, so there's no real limit here...
         } elseif ($this->filters['unit'] == 'days') {
             // We are going to limit to x days:
             // echo 'LIMIT DAYS ';
             $filter_class_i = $filter_class_i > count($filter_classes) - 1 ? 0 : $filter_class_i;
             if (empty($this->filters['ymdhms_min'])) {
                 // We have no start date, we'll display the last x days:
                 if (!empty($this->filters['keywords']) || !empty($this->filters['cat_array']) || !empty($this->filters['authors'])) {
                     // We are in DAYS mode but we can't restrict on these! (TODO: ?)
                 } else {
                     // We are going to limit to LAST x days:
                     // TODO: rename 'posts' to 'limit'
                     $unit_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', regenerate_url($this->param_prefix . 'unit')) : '';
                     $title_array['posts'] = str_replace(array('$filter_name$', '$clear_icon$', '$filter_class$'), array(sprintf(T_('Limited to last %d days'), $this->limit), $unit_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask_nogroup']);
                 }
             } else {
                 // We have a start date, we'll display x days starting from that point:
                 $unit_clear_icon = $clear_icon ? action_icon(T_('Remove this filter'), 'remove', regenerate_url($this->param_prefix . 'unit')) : '';
                 $title_array['posts'] = str_replace(array('$filter_name$', '$clear_icon$', '$filter_class$'), array(sprintf(T_('Limited to %d days'), $this->limit), $unit_clear_icon, $filter_classes[$filter_class_i]), $params['filter_mask_nogroup']);
             }
             $filter_class_i++;
         } else {
             debug_die('Unhandled LIMITING mode in ItemList:' . $this->filters['unit'] . ' (paged mode is obsolete)');
         }
     }
     return $title_array;
 }
Exemple #29
0
 /**
  * Get colors for page elements that can't be controlled by CSS (charts)
  */
 function get_color($what)
 {
     switch ($what) {
         case 'payload_background':
             return 'f1f6f8';
             break;
     }
     debug_die('unknown color');
 }
Exemple #30
0
 /**
  * Get the path (and name) of a {@link File} relative to the {@link Filelist::$_FileRoot::$ads_path}.
  *
  * @param string
  * @return string
  */
 function rdfs_relto_root_from_adfs($adfs_path)
 {
     // Check that the file is inside root:
     if (substr($adfs_path, 0, strlen($this->_FileRoot->ads_path)) != $this->_FileRoot->ads_path) {
         debug_die('rdfs_relto_root_from_adfs: Path is NOT inside of root!');
     }
     // Return only the relative part:
     return substr($adfs_path, strlen($this->_FileRoot->ads_path));
 }