Пример #1
0
function xthreads_forumdisplay_thread()
{
    global $thread, $threadfields, $threadfield_cache, $foruminfo;
    // make threadfields array
    $threadfields = array();
    foreach ($threadfield_cache as $k => &$v) {
        xthreads_get_xta_cache($v, $GLOBALS['tids']);
        $threadfields[$k] =& $thread['xthreads_' . $k];
        xthreads_sanitize_disp($threadfields[$k], $v, !xthreads_empty($thread['username']) ? $thread['username'] : $thread['threadusername']);
    }
    // evaluate group separator
    if ($foruminfo['xthreads_grouping']) {
        static $threadcount = 0;
        static $nulldone = false;
        global $templates;
        if ($thread['sticky'] == 0 && !$nulldone) {
            $nulldone = true;
            $nulls = (count($GLOBALS['threadcache']) - $threadcount) % $foruminfo['xthreads_grouping'];
            if ($nulls) {
                $excess = $nulls;
                $nulls = $foruminfo['xthreads_grouping'] - $nulls;
                $GLOBALS['nullthreads'] = '';
                while ($nulls--) {
                    $bgcolor = alt_trow();
                    // TODO: this may be problematic
                    eval('$GLOBALS[\'nullthreads\'] .= "' . $templates->get('forumdisplay_thread_null') . '";');
                }
            }
        }
        // reset counter on sticky/normal sep
        if ($thread['sticky'] == 0 && $GLOBALS['shownormalsep']) {
            $nulls = $threadcount % $foruminfo['xthreads_grouping'];
            if ($nulls) {
                $excess = $nulls;
                $nulls = $foruminfo['xthreads_grouping'] - $nulls;
                while ($nulls--) {
                    $bgcolor = alt_trow();
                    eval('$GLOBALS[\'threads\'] .= "' . $templates->get('forumdisplay_thread_null') . '";');
                }
            }
            $threadcount = 0;
        }
        if ($threadcount && $threadcount % $foruminfo['xthreads_grouping'] == 0) {
            eval('$GLOBALS[\'threads\'] .= "' . $templates->get('forumdisplay_group_sep') . '";');
        }
        ++$threadcount;
    }
}
Пример #2
0
 function xthreads_admin_forumedit_hook_sorter(&$args)
 {
     global $lang;
     static $done = false;
     if ($done || $args['title'] != $lang->default_view_options) {
         return;
     }
     $done = true;
     global $view_options, $default_sort_by, $form, $forum_data;
     if (count($view_options) != 3) {
         return;
     }
     // back out if things seem a little odd
     // add our custom sortby options here
     if ($GLOBALS['mybb']->version_code >= 1500) {
         $default_sort_by['prefix'] = $lang->xthreads_sort_ext_prefix;
     }
     $default_sort_by['icon'] = $lang->xthreads_sort_ext_icon;
     $default_sort_by['lastposter'] = $lang->xthreads_sort_ext_lastposter;
     $default_sort_by['numratings'] = $lang->xthreads_sort_ext_numratings;
     $default_sort_by['attachmentcount'] = $lang->xthreads_sort_ext_attachmentcount;
     $threadfield_cache = xthreads_gettfcache($forum_data['fid'] ? $forum_data['fid'] : -1);
     if (!empty($threadfield_cache)) {
         //$changed = false;
         foreach ($threadfield_cache as &$tf) {
             if ($tf['inputtype'] == XTHREADS_INPUT_TEXTAREA || !xthreads_empty($tf['multival'])) {
                 continue;
             }
             if (!$lang->xthreads_sort_threadfield_prefix) {
                 $lang->load('xthreads');
             }
             //$changed = true;
             $itemname = $lang->xthreads_sort_threadfield_prefix . $tf['title'];
             if ($tf['inputtype'] == XTHREADS_INPUT_FILE) {
                 foreach (array('filename', 'filesize', 'uploadtime', 'updatetime', 'downloads') as $tfan) {
                     $langvar = 'xthreads_sort_' . $tfan;
                     $default_sort_by['tfa_' . $tfan . '_' . $tf['field']] = $itemname . ' [' . $lang->{$langvar} . ']';
                 }
             } else {
                 $default_sort_by['tf_' . $tf['field']] = $itemname;
             }
         }
     }
     //if(!$changed) return;
     // regenerate stuff
     $view_options[1] = $lang->default_sort_by . "<br />\n" . $form->generate_select_box('defaultsortby', $default_sort_by, $forum_data['defaultsortby'], array('checked' => $forum_data['defaultsortby'], 'id' => 'defaultsortby'));
     $args['content'] = '<div class="forum_settings_bit">' . implode('</div><div class="forum_settings_bit">', $view_options) . '</div>';
 }
Пример #3
0
function xthreads_fetch_url_write(&$fetcher, &$data)
{
    $len = strlen($data);
    global $xtfurl_datalen, $xtfurl_magicchecked, $xtfurl_ret;
    // check extension
    if (!$xtfurl_datalen) {
        // firstly, do we have an extension?  if not, maybe try guess one from the content-type
        if (!xthreads_empty($xtfurl_ret['type']) && !$xtfurl_ret['name_disposition'] && strpos($xtfurl_ret['name'], '.') === false) {
            // we'll only try a few common ones
            switch (strtolower($xtfurl_ret['type'])) {
                case 'text/html':
                case 'text/xhtml+xml':
                    $xtfurl_ret['name'] .= '.html';
                    break;
                case 'image/jpeg':
                case 'image/jpg':
                    $xtfurl_ret['name'] .= '.jpg';
                    break;
                case 'image/gif':
                    $xtfurl_ret['name'] .= '.gif';
                    break;
                case 'image/png':
                    $xtfurl_ret['name'] .= '.png';
                    break;
                case 'image/bmp':
                    $xtfurl_ret['name'] .= '.bmp';
                    break;
                case 'image/svg+xml':
                    $xtfurl_ret['name'] .= '.svg';
                    break;
                case 'image/tiff':
                    $xtfurl_ret['name'] .= '.tiff';
                    break;
                case 'image/x-icon':
                    $xtfurl_ret['name'] .= '.ico';
                    break;
                case 'text/xml':
                    $xtfurl_ret['name'] .= '.xml';
                    break;
                case 'text/plain':
                    $xtfurl_ret['name'] .= '.txt';
                    break;
                case 'text/css':
                    $xtfurl_ret['name'] .= '.css';
                    break;
                case 'text/javascript':
                case 'application/javascript':
                case 'application/x-javascript':
                    $xtfurl_ret['name'] .= '.js';
                    break;
            }
        }
        if (!xthreads_fetch_url_validext($xtfurl_ret['name'], $GLOBALS['xtfurl_exts'])) {
            $xtfurl_magicchecked = 'invalid';
            // dirty, but works...
            return false;
        }
    }
    $xtfurl_datalen += $len;
    if ($GLOBALS['xtfurl_max_size'] && $xtfurl_datalen > $GLOBALS['xtfurl_max_size']) {
        $xtfurl_ret['size'] = $xtfurl_datalen;
        return false;
    }
    if (!$xtfurl_magicchecked && !empty($GLOBALS['xtfurl_validmagic'])) {
        global $xtfurl_databuf;
        if ($xtfurl_datalen >= 255) {
            // check magic
            $xtfurl_databuf .= substr($data, 0, 255 - $xtfurl_datalen + $len);
            if (!xthreads_fetch_url_validmagic($xtfurl_databuf, $GLOBALS['xtfurl_validmagic'])) {
                $xtfurl_magicchecked = 'invalid';
                return false;
            }
            $xtfurl_magicchecked = true;
        } else {
            $xtfurl_databuf .= $data;
        }
    }
    fwrite($GLOBALS['xtfurl_fp'], $data);
    return true;
}
Пример #4
0
function xthreads_sanitize_disp(&$s, &$tfinfo, $mename = null, $noextra = false)
{
    $evalfunc = 'xthreads_evalcache_' . $tfinfo['field'];
    if (!$noextra) {
        // this "hack" stops this function being totally independent of the outside world :(
        global $threadfields_x;
        if (!isset($threadfields_x)) {
            $threadfields_x = array();
        }
        $sx =& $threadfields_x[$tfinfo['field']];
    }
    // otherwise, let the following line dummy the variable
    $sx = array('title' => htmlspecialchars_uni($tfinfo['title']), 'desc' => htmlspecialchars_uni($tfinfo['desc']), 'num_values' => 1, 'num_values_friendly' => my_number_format(1), 'raw_value' => $s);
    $dispfmt = 'dispformat';
    if (!xthreads_user_in_groups($tfinfo['viewable_gids'])) {
        $dispfmt = 'unviewableval';
    }
    if ($tfinfo['inputtype'] == XTHREADS_INPUT_FILE || $tfinfo['inputtype'] == XTHREADS_INPUT_FILE_URL && !preg_match('~^[a-z]+\\://~i', $s)) {
        global $xta_cache, $mybb;
        // attached file
        if (!$s) {
            $s = array('value' => $evalfunc('blankval'));
            xthreads_sanitize_disp_set_blankthumbs($s, $tfinfo);
            return;
        }
        if (xthreads_empty($tfinfo['multival'])) {
            xthreads_sanitize_disp_set_xta_fields($s, $s, $tfinfo, $dispfmt, $evalfunc);
            $sx['value'] =& $s['value'];
        } else {
            $aids = explode(',', $s);
            $s = array('total_downloads' => 0, 'total_filesize' => 0, 'updatetime' => 0, 'uploadtime' => 0, 'value' => '', 'num_files' => 0);
            $sx['items'] = $sx['value'] = array();
            $comma = '';
            foreach ($aids as $aid) {
                $xta =& $sx['items'][];
                xthreads_sanitize_disp_set_xta_fields($xta, $aid, $tfinfo, 'dispitemformat', $evalfunc);
                if (!$xta['aid']) {
                    continue;
                }
                $sx['value'][] = $xta['value'];
                $s['total_downloads'] += $xta['downloads'];
                $s['total_filesize'] += $xta['filesize'];
                $s['uploadtime'] = max($xta['uploadtime'], $s['uploadtime']);
                ++$s['num_files'];
                $s['value'] .= $comma . $xta['value'];
                $comma = $tfinfo['multival'];
            }
            $s['total_downloads_friendly'] = my_number_format($s['total_downloads']);
            $s['total_filesize_friendly'] = get_friendly_size($s['total_filesize']);
            $s['upload_time'] = my_date($mybb->settings['timeformat'], $s['uploadtime']);
            $s['upload_date'] = my_date($mybb->settings['dateformat'], $s['uploadtime']);
            $s['value'] = $evalfunc($dispfmt, array('VALUE' => $s['value']));
            $sx['num_values'] = $s['num_files'];
            $sx['num_values_friendly'] = $s['num_files_friendly'] = my_number_format($s['num_files']);
        }
    } else {
        if ($s === '' || $s === null) {
            $sx['num_values'] = 0;
            $sx['num_values_friendly'] = my_number_format(0);
            $s = $evalfunc('blankval');
            return;
        }
        if (!xthreads_empty($tfinfo['multival'])) {
            // we _could_ optimise this out if the final $dispformat never actually refers to {VALUE}, but this is perhaps an unlikely situation, and we don't know whether the dispitemformat has some special eval'd code we should run
            $vals = explode("\n", str_replace("\r", '', $s));
            $i = 0;
            $sx['value'] = array();
            foreach ($vals as &$v) {
                xthreads_sanitize_disp_field($v, $tfinfo, 'dispitemformat', $mename);
                $sx['value'][$i++] = $v;
            }
            $sx['num_values'] = $i;
            $sx['num_values_friendly'] = my_number_format($i);
            $s = implode($tfinfo['multival'], $vals);
            $s = $evalfunc($dispfmt, array('VALUE' => $s));
        } else {
            xthreads_sanitize_disp_field($s, $tfinfo, $dispfmt, $mename);
            $sx['value'] =& $s;
        }
    }
}
Пример #5
0
function xthreads_upload_attachments()
{
    global $xta_cache, $threadfield_cache, $mybb, $db, $lang, $fid;
    // only ever execute this function once per page
    static $done = false;
    if ($done) {
        return;
    }
    $done = true;
    if (!$fid) {
        if ($GLOBALS['forum']['fid']) {
            $fid = $GLOBALS['forum']['fid'];
        } elseif ($GLOBALS['foruminfo']['fid']) {
            $fid = $GLOBALS['foruminfo']['fid'];
        } elseif ($mybb->input['pid']) {
            // editpost - not good to trust user input, but should be fine
            $post = get_post((int) $mybb->input['pid']);
            if ($post['pid']) {
                $fid = $post['fid'];
            }
        } elseif ($mybb->input['fid']) {
            // newthread
            $fid = (int) $mybb->input['fid'];
        }
        // we _should_ now have an fid
    }
    if (!isset($threadfield_cache)) {
        $threadfield_cache = xthreads_gettfcache($fid);
    }
    // remove uneditable fields
    xthreads_filter_tfeditable($threadfield_cache, $fid);
    // NOTE: modifies the global tfcache!
    if (empty($threadfield_cache)) {
        return;
    }
    if (!is_array($xta_cache)) {
        $xta_cache = array();
    }
    // first, run through to see if we have already uploaded some attachments
    // this code totally relies on the posthash being unique...
    if ($GLOBALS['thread']['tid']) {
        $attachwhere = 'tid=' . (int) $GLOBALS['thread']['tid'];
    } else {
        $attachwhere = 'posthash="' . $db->escape_string($mybb->input['posthash']) . '"';
    }
    $query = $db->simple_select('xtattachments', '*', $attachwhere);
    $attach_fields = array();
    while ($attach = $db->fetch_array($query)) {
        $xta_cache[$attach['aid']] = $attach;
        $attach_fields[$attach['field']][] = $attach['aid'];
    }
    $db->free_result($query);
    @ignore_user_abort(true);
    $errors = array();
    $xta_remove = $threadfield_updates = array();
    foreach ($threadfield_cache as $k => &$v) {
        if ($v['inputtype'] != XTHREADS_INPUT_FILE && $v['inputtype'] != XTHREADS_INPUT_FILE_URL) {
            continue;
        }
        $aid =& $mybb->input['xthreads_' . $k];
        if ($v['inputtype'] != XTHREADS_INPUT_FILE_URL || is_numeric($mybb->input['xthreads_' . $k])) {
            $singleval = xthreads_empty($v['multival']);
            // now, we're ignoring what the user sends us, totally...
            if ($attach_fields[$k]) {
                if ($singleval) {
                    $aid = (int) reset($attach_fields[$k]);
                } else {
                    $aid = array_unique(array_map('intval', $attach_fields[$k]));
                    // re-ordering support
                    if (is_array($mybb->input['xtaorder'])) {
                        $aid_order = array_unique(array_map('intval', $mybb->input['xtaorder']));
                        if (count($aid) == count($aid_order) && $aid != $aid_order && !count(array_diff($aid, $aid_order))) {
                            $aid = $aid_order;
                            $threadfield_updates[$k] = implode(',', $aid);
                        }
                    }
                    $aid = array_combine($aid, $aid);
                }
            } else {
                $aid = 0;
            }
        }
        // handle file upload
        $ul = null;
        if ($singleval) {
            if (!empty($_FILES['xthreads_' . $k]) && !xthreads_empty($_FILES['xthreads_' . $k]['name']) && is_string($_FILES['xthreads_' . $k]['name'])) {
                $ul = $_FILES['xthreads_' . $k];
            } elseif ($v['inputtype'] == XTHREADS_INPUT_FILE && XTHREADS_ALLOW_URL_FETCH && !xthreads_empty($mybb->input['xtaurl_' . $k])) {
                // the preg_match is just a basic prelim check - the real URL checking is done later; we need this prelim check to stop it erroring out on the defalt "http://" string
                if (preg_match('~^[a-z0-9\\-]+\\://[^/?#]+(?:/.*)?$~', $mybb->input['xtaurl_' . $k])) {
                    $ul = $mybb->input['xtaurl_' . $k];
                }
            }
            !isset($ul) or $ul = array($ul);
        } else {
            $ul = array();
            if (is_array($mybb->input['xtaurl_' . $k])) {
                $input_urls = $mybb->input['xtaurl_' . $k];
                $input_key_match = true;
                // if URL input is an array, we'll match with equivalent file input keys
            } else {
                $input_urls = explode("\n", str_replace("\r", '', $mybb->input['xtaurl_' . $k]));
                $input_key_match = false;
            }
            if (!empty($_FILES['xthreads_' . $k]) && is_array($_FILES['xthreads_' . $k])) {
                foreach ($_FILES['xthreads_' . $k]['name'] as $file_k => $filename) {
                    if (!xthreads_empty($filename)) {
                        $file_v = array();
                        // why does PHP does this and make our life difficult?
                        foreach ($_FILES['xthreads_' . $k] as $fvkey => $fvval) {
                            $file_v[$fvkey] = $fvval[$file_k];
                        }
                        if ($input_key_match && is_numeric($file_k) || preg_match('~^aid\\d+$~', $file_k)) {
                            $ul[$file_k] = $file_v;
                        } else {
                            $ul[] = $file_v;
                        }
                    }
                }
            }
            if ($v['inputtype'] == XTHREADS_INPUT_FILE && XTHREADS_ALLOW_URL_FETCH && !empty($input_urls) && is_array($input_urls)) {
                foreach ($input_urls as $url_k => $url_v) {
                    $url_v = trim($url_v);
                    if (preg_match('~^[a-z0-9\\-]+\\://[a-z0-9_\\-@:.]+(?:/.*)?$~', $url_v)) {
                        if ($input_key_match && is_numeric($url_k) || preg_match('~^aid\\d+$~', $url_k)) {
                            isset($ul[$url_k]) or $ul[$url_k] = $url_v;
                        } else {
                            $ul[] = $url_v;
                        }
                    }
                }
            }
        }
        unset($mybb->input['xtaurl_' . $k], $_FILES['xthreads_' . $k]);
        // remove files from list first (so we can properly measure the correct final number of attachments when uploading)
        // fix the threadfield_updates array later on
        if ($singleval) {
            if (empty($ul) && $mybb->input['xtarm_' . $k] && $v['editable'] != XTHREADS_EDITABLE_REQ) {
                // user wants to remove attachment
                $xta_remove[$aid] = $aid;
                $aid = 0;
            }
        } elseif (!empty($mybb->input['xtarm_' . $k]) && is_array($mybb->input['xtarm_' . $k])) {
            foreach ($mybb->input['xtarm_' . $k] as $rm_aid => $rm_confirm) {
                if (!$rm_confirm) {
                    continue;
                }
                // double-check they really do want to remove this
                $xta_remove[$rm_aid] = $rm_aid;
                unset($aid[$rm_aid]);
            }
        }
        // upload new stuff
        if (!empty($ul)) {
            require_once MYBB_ROOT . 'inc/xthreads/xt_upload.php';
            $update_aid = is_array($aid) ? 0 : $aid;
            $failed_urls = array();
            // list of any URLs that failed to fetch
            foreach ($ul as $ul_key => $ul_file) {
                // hard limit number of files to at least 20
                if (!$singleval && is_array($aid)) {
                    // hard limit
                    if (strlen(implode(',', $aid)) >= 245) {
                        if (!$lang->xthreads_xtaerr_error_attachhardlimit) {
                            $lang->load('xthreads');
                        }
                        $errors[] = $lang->sprintf($lang->xthreads_xtaerr_error_attachhardlimit, htmlspecialchars_uni($v['title']));
                        break;
                    }
                    // admin defined limit
                    if ($v['multival_limit'] && count($aid) >= $v['multival_limit']) {
                        if (!$lang->xthreads_xtaerr_error_attachnumlimit) {
                            $lang->load('xthreads');
                        }
                        $errors[] = $lang->sprintf($lang->xthreads_xtaerr_error_attachnumlimit, $v['multival_limit'], htmlspecialchars_uni($v['title']));
                        break;
                    }
                }
                // allow updating a specific attachment in a multi-field thing
                $update_aid2 = $update_aid;
                if (!$update_aid2 && is_array($aid) && substr($ul_key, 0, 3) == 'aid') {
                    $update_aid2 = (int) substr($ul_key, 3);
                    if (!in_array($update_aid2, $aid)) {
                        $update_aid2 = 0;
                    }
                }
                $attachedfile = upload_xtattachment($ul_file, $v, $mybb->user['uid'], $update_aid2, $GLOBALS['thread']['tid']);
                if ($attachedfile['error']) {
                    if (!$lang->xthreads_threadfield_attacherror) {
                        $lang->load('xthreads');
                    }
                    $errors[] = $lang->sprintf($lang->xthreads_threadfield_attacherror, htmlspecialchars_uni($v['title']), $attachedfile['error']);
                    if (is_string($ul_file)) {
                        $failed_urls[] = $ul_file;
                    }
                } else {
                    //unset($attachedfile['posthash'], $attachedfile['tid'], $attachedfile['downloads']);
                    $xta_cache[$attachedfile['aid']] = $attachedfile;
                    if ($singleval) {
                        unset($mybb->input['xtarm_' . $k]);
                        // since successful upload, don't tick remove box
                        $aid = $attachedfile['aid'];
                    } else {
                        if (is_array($mybb->input['xtarm_' . $k])) {
                            unset($mybb->input['xtarm_' . $k][$attachedfile['aid']]);
                        }
                        is_array($aid) or $aid = array();
                        // if no aid already set, it will be 0, so turn into array if necessary
                        $aid[$attachedfile['aid']] = $attachedfile['aid'];
                    }
                    // if we were going to remove this file, don't
                    if (isset($xta_remove[$attachedfile['aid']])) {
                        unset($xta_remove[$attachedfile['aid']]);
                    }
                    if ($attachedfile['aid'] != $update_aid2) {
                        // adding a new attachment
                        $threadfield_updates[$k] = $singleval ? $aid : true;
                    }
                }
            }
            // list failed URLs in textboxes
            if (!empty($failed_urls)) {
                $mybb->input['xtaurl_' . $k] = implode("\n", $failed_urls);
                unset($failed_urls);
            }
        }
        // fix threadfield update if removing an item and not already done
        if (!empty($xta_remove) && !isset($threadfield_updates[$k])) {
            $threadfield_updates[$k] = $singleval ? 0 : true;
        }
        // fix placeholder value
        if ($threadfield_updates[$k] === true) {
            $threadfield_updates[$k] = implode(',', $aid);
        }
        unset($aid);
    }
    if (!empty($xta_remove)) {
        $db->delete_query('xtattachments', 'aid IN (' . implode(',', $xta_remove) . ')');
        foreach ($xta_remove as $aid) {
            xthreads_rm_attach_fs($xta_cache[$aid]);
        }
    }
    $is_editing = $GLOBALS['current_page'] == 'editpost.php';
    // if editing post, also commit change to thread field immediately (waiting for user to submit is unreliable)
    if (($is_editing || $GLOBALS['thread']['tid'] && $GLOBALS['current_page'] == 'newthread.php') && !empty($threadfield_updates)) {
        xthreads_db_update_replace('threadfields_data', $threadfield_updates, 'tid', $GLOBALS['thread']['tid']);
    }
    @ignore_user_abort(false);
    if (!empty($errors)) {
        global $plugins;
        $is_mybb_18 = $mybb->version_code >= 1700;
        // MyBB 1.4 - 1.5
        // and MyBB 1.6 is inconsistent (does different things on newthread/editpost)...
        if ($mybb->version_code < 1600 || $is_editing) {
            // can't find a better way to check other than to check version numbers
            global $theme, $templates;
            $errstr = '<li>' . implode('</li><li>', $errors) . '</li>';
            if ($is_editing && $is_mybb_18) {
                // special workaround for MyBB 1.8
                $GLOBALS['xt_attach_errors'] =& $errstr;
                $templates->cache['__xt_orig_error_attacherror'] = $templates->cache['error_attacherror'];
                function xthreads_upload_attachments_error()
                {
                    global $theme, $templates, $attacherror, $mybb, $lang, $fid;
                    if ($attacherror) {
                        return;
                    }
                    // already handled by template cache hack
                    $attachedfile = array('error' => '<ul>' . $GLOBALS['xt_attach_errors'] . '</ul>');
                    eval('$attacherror = "' . $templates->get('__xt_orig_error_attacherror') . '";');
                }
                $plugins->add_hook('editpost_action_start', 'xthreads_upload_attachments_error');
            } else {
                $attachedfile = array('error' => '<ul>' . $errstr . '</ul>');
                eval('$GLOBALS[\'attacherror\'] .= "' . $templates->get('error_attacherror') . '";');
            }
            // if there's going to be a MyBB attachment error, and it's not been evaluated yet, shove it in the template to force it through - safe since this function is guaranteed to run only once
            $templates->cache['error_attacherror'] = str_replace('{$attachedfile[\'error\']}', '<ul>' . strtr($errstr, array('\\' => '\\\\', '$' => '\\$', '{' => '\\{', '}' => '\\}')) . '<li>{$attachedfile[\'error\']}</li></ul>', $templates->cache['error_attacherror']);
        } elseif ($is_mybb_18) {
            // for MyBB 1.8
            $GLOBALS['xt_attach_errors'] =& $errors;
            function xthreads_upload_attachments_error()
            {
                if (empty($GLOBALS['errors'])) {
                    $GLOBALS['errors'] =& $GLOBALS['xt_attach_errors'];
                } else {
                    $GLOBALS['errors'] = array_merge($GLOBALS['errors'], $GLOBALS['xt_attach_errors']);
                }
            }
            $plugins->add_hook('newthread_start', 'xthreads_upload_attachments_error');
        } else {
            // for MyBB 1.6
            if (empty($GLOBALS['errors'])) {
                $GLOBALS['errors'] =& $errors;
            } else {
                $GLOBALS['errors'] = array_merge($GLOBALS['errors'], $errors);
            }
        }
        $mybb->input['action'] = $is_editing ? 'editpost' : 'newthread';
        // block the preview, since a failed upload can stuff it up
        // lower priority to go before inputdisp function (contention, the function checks for 'previewpost')
        $plugins->add_hook('newthread_start', 'xthreads_newthread_ulattach_blockpreview', 5);
        $plugins->add_hook('editpost_start', 'xthreads_editthread_ulattach_blockpreview', 5);
    }
}
Пример #6
0
function threadfields_add_edit_handler(&$tf, $update)
{
    global $mybb, $page, $lang, $db, $plugins, $sub_tabs;
    global $form;
    if ($update) {
        $title = $lang->edit_threadfield;
    } else {
        $title = $lang->add_threadfield;
    }
    $props = xthreads_threadfields_props();
    if ($mybb->request_method == 'post') {
        foreach ($props as $field => &$prop) {
            if ($field == 'field') {
                $field = 'newfield';
            }
            // cause you can't "continue" in a switch statement, lol...
            if ($field == 'forums' || $field == 'editable_gids' || $field == 'viewable_gids' || $field == 'filemaxsize' || $field == 'multival') {
                continue;
            }
            if ($prop['datatype'] == 'string') {
                $mybb->input[$field] = trim($mybb->input[$field]);
            } else {
                $mybb->input[$field] = (int) $mybb->input[$field];
            }
        }
        $mybb->input['textmask'] = str_replace("", '', $mybb->input['textmask']);
        $mybb->input['filemaxsize'] = xthreads_size_to_bytes($mybb->input['filemaxsize']);
        $mybb->input['fileimage_mindim'] = strtolower(trim($mybb->input['fileimage_mindim']));
        $mybb->input['fileimage_maxdim'] = strtolower(trim($mybb->input['fileimage_maxdim']));
        if (!xthreads_empty($mybb->input['formatmap'])) {
            $fm = array();
            $fms = str_replace("{\n}", "\r", str_replace("\r", '', $mybb->input['formatmap']));
            foreach (explode("\n", $fms) as $map) {
                $map = str_replace("\r", "\n", $map);
                $p = strpos($map, '{|}');
                if (!$p) {
                    continue;
                }
                // can't be zero index either - blank display format used for that
                $fmkey = substr($map, 0, $p);
                if (isset($fm[$fmkey])) {
                    $errors[] = $lang->sprintf($lang->error_dup_formatmap, htmlspecialchars_uni($fmkey));
                    unset($fm);
                    break;
                }
                $fm[$fmkey] = substr($map, $p + 3);
            }
            if (isset($fm)) {
                $mybb->input['formatmap'] = serialize($fm);
            }
        }
        if (is_array($mybb->input['forums'])) {
            $mybb->input['forums'] = implode(',', array_unique(array_map('intval', array_map('trim', $mybb->input['forums']))));
            if (empty($mybb->input['forums'])) {
                $mybb->input['forums'] = '';
            }
        } else {
            $mybb->input['forums'] = trim($mybb->input['forums']);
            if ($mybb->input['forums']) {
                $mybb->input['forums'] = implode(',', array_unique(array_map('intval', array_map('trim', explode(',', $mybb->input['forums'])))));
            }
            if (!$mybb->input['forums']) {
                $mybb->input['forums'] = '';
            }
        }
        if ($mybb->input['editable'] == '99') {
            if (is_array($mybb->input['editable_gids'])) {
                $mybb->input['editable_gids'] = implode(',', array_unique(array_map('intval', array_map('trim', $mybb->input['editable_gids']))));
                if (empty($mybb->input['editable_gids'])) {
                    $mybb->input['editable_gids'] = '';
                }
            } else {
                $mybb->input['editable_gids'] = trim($mybb->input['editable_gids']);
                if ($mybb->input['editable_gids']) {
                    $mybb->input['editable_gids'] = implode(',', array_unique(array_map('intval', array_map('trim', explode(',', $mybb->input['editable_gids'])))));
                }
                if (!$mybb->input['editable_gids']) {
                    $mybb->input['editable_gids'] = '';
                }
            }
            if ($mybb->input['editable_gids']) {
                $mybb->input['editable'] = 0;
            } else {
                $mybb->input['editable'] = XTHREADS_EDITABLE_NONE;
            }
            // no group ids selected
        } else {
            $mybb->input['editable'] = min_max((int) $mybb->input['editable'], XTHREADS_EDITABLE_ALL, XTHREADS_EDITABLE_NONE);
            $mybb->input['editable_gids'] = '';
        }
        $mybb->input['hidefield'] = 0;
        foreach (array('input' => XTHREADS_HIDE_INPUT, 'thread' => XTHREADS_HIDE_THREAD) as $k => $v) {
            if ($mybb->input['hidefield_' . $k]) {
                $mybb->input['hidefield'] |= $v;
            }
        }
        if (!xthreads_empty($mybb->input['editable_values'])) {
            $ev = array();
            $evs = str_replace("{\n}", "\r", str_replace("\r", '', $mybb->input['editable_values']));
            foreach (explode("\n", $evs) as $editable_value) {
                $editable_value = str_replace("\r", "\n", $editable_value);
                $p = strpos($editable_value, '{|}');
                if ($p === false) {
                    continue;
                }
                $evkey = substr($editable_value, 0, $p);
                if (isset($ev[$evkey])) {
                    $errors[] = $lang->sprintf($lang->error_dup_editable_value, htmlspecialchars_uni($evkey));
                    unset($ev);
                    break;
                }
                $ev[$evkey] = array_unique(array_map('intval', explode(',', substr($editable_value, $p + 3))));
                // remove '0' element
                if (($zerorm = array_search(0, $ev[$evkey])) !== false) {
                    unset($ev[$evkey][$zerorm]);
                }
            }
            if (isset($ev)) {
                $mybb->input['editable_values'] = serialize($ev);
            }
        }
        if (is_array($mybb->input['viewable_gids'])) {
            $mybb->input['viewable_gids'] = implode(',', array_unique(array_map('intval', array_map('trim', $mybb->input['viewable_gids']))));
            if (empty($mybb->input['viewable_gids'])) {
                $mybb->input['viewable_gids'] = '';
            }
        } else {
            $mybb->input['viewable_gids'] = trim($mybb->input['viewable_gids']);
            if ($mybb->input['viewable_gids']) {
                $mybb->input['viewable_gids'] = implode(',', array_unique(array_map('intval', array_map('trim', explode(',', $mybb->input['viewable_gids'])))));
            }
            if (!$mybb->input['viewable_gids']) {
                $mybb->input['viewable_gids'] = '';
            }
        }
        $mybb->input['sanitize'] = min_max((int) $mybb->input['sanitize'], XTHREADS_SANITIZE_HTML, XTHREADS_SANITIZE_NONE);
        //if($mybb->input['sanitize'] == XTHREADS_SANITIZE_PARSER) {
        $parser_opts = array('parser_nl2br' => XTHREADS_SANITIZE_PARSER_NL2BR, 'parser_nobadw' => XTHREADS_SANITIZE_PARSER_NOBADW, 'parser_html' => XTHREADS_SANITIZE_PARSER_HTML, 'parser_mycode' => XTHREADS_SANITIZE_PARSER_MYCODE, 'parser_mycodeimg' => XTHREADS_SANITIZE_PARSER_MYCODEIMG, 'parser_mycodevid' => XTHREADS_SANITIZE_PARSER_VIDEOCODE, 'parser_smilies' => XTHREADS_SANITIZE_PARSER_SMILIES);
        foreach ($parser_opts as $opt => $n) {
            if ($mybb->input[$opt]) {
                $mybb->input['sanitize'] |= $n;
            }
        }
        //}
        $mybb->input['inputtype'] = min_max((int) $mybb->input['inputtype'], XTHREADS_INPUT_TEXT, XTHREADS_INPUT_FILE_URL);
        if (xthreads_empty($mybb->input['title'])) {
            $errors[] = $lang->error_missing_title;
        }
        if (xthreads_empty($mybb->input['newfield'])) {
            $errors[] = $lang->error_missing_field;
        }
        if (!xthreads_empty($mybb->input['textmask'])) {
            // test for bad regex
            xthreads_catch_errorhandler();
            @preg_match('~' . str_replace('~', '\\~', $mybb->input['textmask']) . '~si', 'testvalue');
            restore_error_handler();
            if (!empty($GLOBALS['_previous_error'])) {
                $errmsg =& $GLOBALS['_previous_error'][1];
                if (substr($errmsg, 0, 12) == 'preg_match()') {
                    $p = strpos($errmsg, ':', 12);
                    if ($p) {
                        $errmsg = trim(substr($errmsg, $p + 1));
                    } else {
                        $errmsg = trim(substr($errmsg, 12));
                    }
                    $errors[] = $lang->sprintf($lang->error_bad_textmask, $errmsg);
                }
            }
        }
        switch ($mybb->input['inputtype']) {
            case XTHREADS_INPUT_SELECT:
            case XTHREADS_INPUT_RADIO:
            case XTHREADS_INPUT_CHECKBOX:
                $mybb->input['sanitize'] = $mybb->input['inputtype'] == XTHREADS_INPUT_SELECT ? XTHREADS_SANITIZE_HTML : XTHREADS_SANITIZE_NONE;
                $mybb->input['textmask'] = '';
                // must have value defined
                if (xthreads_empty($mybb->input['vallist'])) {
                    $errors[] = $lang->error_require_valllist;
                }
                break;
            case XTHREADS_INPUT_TEXTAREA:
            case XTHREADS_INPUT_FILE:
            case XTHREADS_INPUT_FILE_URL:
                $mybb->input['allowfilter'] = 0;
                $mybb->input['vallist'] = '';
                break;
            case XTHREADS_INPUT_TEXT:
                $mybb->input['vallist'] = '';
        }
        if ($mybb->input['multival_enable'] || $mybb->input['inputtype'] == XTHREADS_INPUT_CHECKBOX) {
            if (xthreads_empty($mybb->input['multival'])) {
                $errors[] = $lang->error_require_multival_delimiter;
            }
            // force textual datatype
            if ($mybb->input['datatype'] !== XTHREADS_DATATYPE_TEXT) {
                $mybb->input['datatype'] = XTHREADS_DATATYPE_TEXT;
            }
        } else {
            $mybb->input['multival'] = '';
        }
        if ($mybb->input['use_formhtml']) {
            if (xthreads_empty($mybb->input['formhtml'])) {
                $errors[] = $lang->error_require_formhtml;
            }
        } else {
            $mybb->input['formhtml'] = '';
        }
        if ($mybb->input['datatype'] !== XTHREADS_DATATYPE_TEXT) {
            // verify value list if applicable
            /* if($mybb->input['inputtype'] == XTHREADS_INPUT_SELECT || $mybb->input['inputtype'] == XTHREADS_INPUT_RADIO) {
            				// maybe we won't do this...
            			} */
            $mybb->input['datatype'] = min_max($mybb->input['datatype'], XTHREADS_DATATYPE_TEXT, XTHREADS_DATATYPE_FLOAT);
        }
        $mybb->input['fileimage'] = '';
        if ($mybb->input['filereqimg']) {
            if ($mybb->input['fileimage_mindim'] && !preg_match('~^[0-9]+x[0-9]+$~', $mybb->input['fileimage_mindim'])) {
                $errors[] = $lang->error_invalid_min_dims;
            }
            if ($mybb->input['fileimage_maxdim'] && !preg_match('~^[0-9]+x[0-9]+$~', $mybb->input['fileimage_maxdim'])) {
                $errors[] = $lang->error_invalid_max_dims;
            }
            if ($mybb->input['fileimage_mindim']) {
                $mybb->input['fileimage'] = $mybb->input['fileimage_mindim'];
            } else {
                $mybb->input['fileimage'] = '0x0';
            }
            if ($mybb->input['fileimage_maxdim']) {
                $mybb->input['fileimage'] .= '|' . $mybb->input['fileimage_maxdim'];
            }
        }
        //if($mybb->input['fileimgthumbs']) {
        // TODO: verify format
        //if(!preg_match('~^[0-9]+x[0-9]+(\\|[0-9]+x[0-9]+)*$~', $mybb->input['fileimgthumbs']))
        //	$errors[] = $lang->error_invalid_thumb_dims;
        //}
        if ($update) {
            // check that sent field name is valid
            // and whilst we're here, check for bad conversions (eg file -> textbox)
            $oldfield = $db->fetch_array($db->simple_select('threadfields', '*', 'field="' . $db->escape_string($mybb->input['field']) . '"'));
            if (empty($oldfield)) {
                $errors[] = $lang->error_bad_old_field;
            } else {
                switch ($oldfield['inputtype']) {
                    case XTHREADS_INPUT_FILE:
                    case XTHREADS_INPUT_FILE_URL:
                        if ($oldfield['inputtype'] != $mybb->input['inputtype']) {
                            $errors['error_invalid_inputtype'] = $lang->error_invalid_inputtype;
                        }
                        break;
                    default:
                        if ($mybb->input['inputtype'] == XTHREADS_INPUT_FILE || $mybb->input['inputtype'] == XTHREADS_INPUT_FILE_URL) {
                            $errors['error_invalid_inputtype'] = $lang->error_invalid_inputtype;
                        }
                }
            }
        }
        if (!xthreads_empty($mybb->input['newfield'])) {
            if ($mybb->input['newfield'] == 'tid') {
                $errors[] = $lang->error_field_name_tid;
            } elseif (strlen($mybb->input['newfield']) > 50) {
                $errors[] = $lang->error_field_name_too_long;
            } elseif (!preg_match('~^[a-zA-Z0-9_]+$~', $mybb->input['newfield'])) {
                $errors[] = $lang->error_field_name_invalid;
            } elseif (isset($mybb->input['newfield'][2]) && $mybb->input['newfield'][0] == '_' && $mybb->input['newfield'][1] == '_') {
                // don't allow fields starting with "__" (reserved for special use)
                // in hindsight, special uses (eg filters) really should've used something like '~' so we don't need to do this, but it's too late now
                $errors[] = $lang->error_field_name_reserved;
            } elseif (!$update || $mybb->input['field'] != $mybb->input['newfield']) {
                $ftest = $db->fetch_field($db->simple_select('threadfields', 'field', 'field="' . $db->escape_string($mybb->input['newfield']) . '"'), 'field');
                if (!xthreads_empty($ftest)) {
                    $errors[] = $lang->error_field_name_in_use;
                }
            }
        }
        // check for syntax errors in conditionals
        // this is a bit tricky because we need the cache function to build the conditional for checking
        if ($update) {
            $test_tf = array_merge($oldfield, $mybb->input);
        } else {
            $test_tf = $mybb->input;
        }
        xthreads_buildtfcache_parseitem($test_tf);
        // test for bad conditional syntax
        foreach (array('defaultval', 'blankval', 'inputformat', 'inputvalidate', 'dispformat', 'dispitemformat', 'unviewableval', 'formhtml', 'formhtml_item') as $condcheck) {
            if ($test_tf[$condcheck] && !xthreads_check_evalstr($test_tf[$condcheck])) {
                if ($condcheck == 'formhtml_item') {
                    $condcheck = 'formhtml';
                }
                $tflangkey = 'threadfields_' . $condcheck;
                $errors[] = $lang->sprintf($lang->error_bad_conditional, $lang->{$tflangkey});
            }
        }
        if (!xthreads_empty($test_tf['formatmap'])) {
            foreach ($test_tf['formatmap'] as &$fm) {
                if ($fm && !xthreads_check_evalstr($fm)) {
                    $errors[] = $lang->sprintf($lang->error_bad_conditional, $lang->threadfields_formatmap);
                    break;
                }
            }
        }
        if (!xthreads_empty($test_tf['fileimgthumbs'])) {
            foreach ($test_tf['fileimgthumbs'] as $thumb => $chain) {
                if ($chain) {
                    if (!xthreads_check_evalstr('".$img->' . $chain . '."')) {
                        $errors[] = $lang->sprintf($lang->error_bad_conditional, $lang->threadfields_fileimgthumbs);
                        break;
                    }
                }
            }
        }
        if (!$errors) {
            $new_tf = array();
            foreach (array_keys($props) as $field) {
                if ($field == 'field') {
                    $new_tf[$field] = $db->escape_string($mybb->input['newfield']);
                } else {
                    $new_tf[$field] = $db->escape_string($mybb->input[$field]);
                }
            }
            if ($mybb->input['inputtype'] == XTHREADS_INPUT_FILE) {
                if (xthreads_empty($mybb->input['multival'])) {
                    $fieldtype = xthreads_db_fielddef('int', null, true) . ' not null default 0';
                } else {
                    $fieldtype = 'varchar(255) not null default ""';
                }
                // we'll stick a hard limit of 25 files
            } elseif ($mybb->input['inputtype'] == XTHREADS_INPUT_FILE_URL) {
                $fieldtype = 'varchar(255) not null default ""';
            } else {
                switch ($new_tf['datatype']) {
                    case XTHREADS_DATATYPE_INT:
                    case XTHREADS_DATATYPE_UINT:
                        $fieldtype = xthreads_db_fielddef('int', null, $new_tf['datatype'] == XTHREADS_DATATYPE_UINT) . ' default null';
                        break;
                    case XTHREADS_DATATYPE_BIGINT:
                    case XTHREADS_DATATYPE_BIGUINT:
                        $fieldtype = xthreads_db_fielddef('bigint', null, $new_tf['datatype'] == XTHREADS_DATATYPE_BIGUINT) . ' default null';
                        break;
                    case XTHREADS_DATATYPE_FLOAT:
                        $fieldtype = 'double default null';
                        break;
                    default:
                        switch ($mybb->input['inputtype']) {
                            case XTHREADS_INPUT_TEXTAREA:
                                $fieldtype = 'text not null';
                                break;
                            case XTHREADS_INPUT_SELECT:
                            case XTHREADS_INPUT_RADIO:
                                if ($new_tf['multival'] === '' || $mybb->input['inputtype'] == XTHREADS_INPUT_RADIO) {
                                    $fieldtype = 'varchar(255) not null default ""';
                                    $using_long_varchar = false;
                                    break;
                                }
                            default:
                                if ($new_tf['allowfilter']) {
                                    // initially, try 1024 chars
                                    $fieldtype = 'varchar(1024) not null default ""';
                                    $using_long_varchar = true;
                                } else {
                                    $fieldtype = 'text not null';
                                }
                        }
                }
            }
            if ($update) {
                $plugins->run_hooks('admin_config_threadfields_edit_commit');
                $db->update_query('threadfields', $new_tf, 'field="' . $db->escape_string($mybb->input['field']) . '"');
                $alterations = array();
                // TODO: perhaps only run this query if necessary
                //if($mybb->input['field'] != $mybb->input['newfield'])
                $alterfield_base = 'CHANGE `' . $db->escape_string($mybb->input['field']) . '` `' . $new_tf['field'] . '` ';
                $alterations['field'] = $alterfield_base . $fieldtype;
                if ((bool) $new_tf['allowfilter'] != (bool) $oldfield['allowfilter']) {
                    if ($new_tf['allowfilter']) {
                        $alterations['addkey'] = 'ADD KEY `' . $new_tf['field'] . '` (`' . $new_tf['field'] . '`)';
                    } else {
                        $alterations['dropkey'] = 'DROP KEY `' . $db->escape_string($mybb->input['field']) . '`';
                    }
                } elseif ($new_tf['allowfilter'] && $mybb->input['field'] != $mybb->input['newfield']) {
                    // change key name - only way to do this in MySQL appears to be recreating the key...
                    $alterations['dropkey'] = 'DROP KEY `' . $db->escape_string($mybb->input['field']) . '`';
                    $alterations['addkey'] = 'ADD KEY `' . $new_tf['field'] . '` (`' . $new_tf['field'] . '`)';
                }
                if (!empty($alterations)) {
                    $qry_base = 'ALTER TABLE `' . $db->table_prefix . 'threadfields_data` ';
                    if ($using_long_varchar) {
                        if (!$db->write_query($qry_base . implode(', ', $alterations), true)) {
                            $alterations['field'] = $alterfield_base . str_replace('varchar(1024)', 'varchar(255)', $fieldtype);
                            $db->write_query($qry_base . implode(', ', $alterations));
                        }
                    } else {
                        $db->write_query($qry_base . implode(', ', $alterations));
                    }
                    if ($mybb->input['field'] != $mybb->input['newfield'] && ($new_tf['inputtype'] == XTHREADS_INPUT_FILE || $new_tf['inputtype'] == XTHREADS_INPUT_FILE_URL)) {
                        // need to update xtattachments table too!
                        $db->update_query('xtattachments', array('field' => $new_tf['field']), 'field="' . $db->escape_string($mybb->input['field']) . '"');
                    }
                }
            } else {
                $plugins->run_hooks('admin_config_threadfields_add_commit');
                $db->insert_query('threadfields', $new_tf);
                $addkey = '';
                if ($new_tf['allowfilter']) {
                    $addkey .= ', ADD KEY (`' . $new_tf['field'] . '`)';
                }
                $qry_base = 'ALTER TABLE `' . $db->table_prefix . 'threadfields_data` ADD COLUMN `' . $new_tf['field'] . '` ';
                if ($using_long_varchar) {
                    if (!$db->write_query($qry_base . $fieldtype . $addkey, true)) {
                        $db->write_query($qry_base . str_replace('varchar(1024)', 'varchar(255)', $fieldtype) . $addkey);
                    }
                } else {
                    $db->write_query($qry_base . $fieldtype . $addkey);
                }
            }
            // Log admin action
            log_admin_action($new_tf['field'], htmlspecialchars_uni($mybb->input['title']));
            xthreads_buildtfcache();
            if ($update) {
                flash_message($lang->success_updated_threadfield, 'success');
            } else {
                flash_message($lang->success_added_threadfield, 'success');
            }
            admin_redirect(xthreads_admin_url('config', 'threadfields'));
        }
    }
    $page->add_breadcrumb_item($title);
    $page->output_header($lang->custom_threadfields . ' - ' . $title);
    echo '<noscript>';
    $page->output_alert($lang->threadfields_enable_js);
    echo '</noscript>';
    if (!$update) {
        $page->output_nav_tabs($sub_tabs, 'threadfields_add');
    }
    if ($update) {
        $form = new Form(xthreads_admin_url('config', 'threadfields') . '&amp;action=edit&amp;field=' . urlencode($tf['field']), 'post');
    } else {
        $form = new Form(xthreads_admin_url('config', 'threadfields&amp;action=add'), 'post');
    }
    if ($errors) {
        $page->output_inline_error($errors);
        $GLOBALS['data'] =& $mybb->input;
    } else {
        $GLOBALS['data'] =& $tf;
    }
    global $data;
    global $form_container;
    $form_container = new FormContainer($title);
    $form_container->output_row($lang->threadfields_title . ' <em>*</em>', $lang->threadfields_title_desc, $form->generate_text_box('title', $data['title'], array('id' => 'title')), 'title');
    if (isset($data['newfield'])) {
        $key =& $data['newfield'];
    } else {
        $key =& $data['field'];
    }
    $form_container->output_row($lang->threadfields_name . ' <em>*</em>', $lang->threadfields_name_desc, $form->generate_text_box('newfield', $key, array('id' => 'newfield')), 'newfield');
    if ($data['forums'] && !is_array($data['forums'])) {
        $data['forums'] = array_map('intval', array_map('trim', explode(',', $data['forums'])));
    }
    $form_container->output_row($lang->threadfields_forums, $lang->threadfields_forums_desc, $form->generate_forum_select('forums[]', $data['forums'], array('multiple' => true, 'size' => 5)), 'forums');
    $hidefield_boxes = '';
    foreach (array('input' => XTHREADS_HIDE_INPUT, 'thread' => XTHREADS_HIDE_THREAD) as $k => $v) {
        $l = 'threadfields_hidefield_' . $k;
        $ld = 'threadfields_hidefield_' . $k . '_desc';
        $hidefield_boxes .= $form->generate_check_box('hidefield_' . $k, '1', $lang->{$l}, array('checked' => (bool) ($data['hidefield'] & $v))) . '<div style="margin-left: 2.25em;" class="description">' . $lang->{$ld} . '</div>';
    }
    $form_container->output_row($lang->threadfields_hidefield, $lang->threadfields_hidefield_desc, $hidefield_boxes, 'hidefield');
    $inputtypes = array(XTHREADS_INPUT_TEXT => $lang->threadfields_inputtype_text, XTHREADS_INPUT_TEXTAREA => $lang->threadfields_inputtype_textarea, XTHREADS_INPUT_SELECT => $lang->threadfields_inputtype_select, XTHREADS_INPUT_RADIO => $lang->threadfields_inputtype_radio, XTHREADS_INPUT_CHECKBOX => $lang->threadfields_inputtype_checkbox, XTHREADS_INPUT_FILE => $lang->threadfields_inputtype_file);
    if ($update) {
        // disable some conversions as they are not possible
        if (isset($errors['error_invalid_inputtype'])) {
            // but if invalid type is supplied, don't lock the user in either
            $inputtype = $oldfield['inputtype'];
        } else {
            $inputtype = $data['inputtype'];
        }
        if ($inputtype == XTHREADS_INPUT_FILE || $inputtype == XTHREADS_INPUT_FILE_URL) {
            foreach ($inputtypes as $k => &$v) {
                if ($k != $inputtype) {
                    unset($inputtypes[$k]);
                }
            }
        } else {
            unset($inputtypes[XTHREADS_INPUT_FILE], $inputtypes[XTHREADS_INPUT_FILE_URL]);
        }
    }
    // TODO: weird issue where inputtype isn't being set...
    if (!ini_get('file_uploads')) {
        $lang->threadfields_file_name_info .= '<div style="color: red; font-style: italic;">' . $lang->threadfields_file_upload_disabled_warning . '</div>';
    }
    make_form_row('inputtype', 'select_box', $inputtypes, '<div id="inputtype_file_explain" style="font-size: 0.95em; margin-top: 1em;">' . $lang->threadfields_file_name_info . '</div>');
    make_form_row('disporder', 'text_box');
    $form_container->end();
    unset($GLOBALS['form_container']);
    global $form_container;
    $form_container = new FormContainer($lang->threadfields_cat_input);
    if ($data['editable_gids'] && !is_array($data['editable_gids'])) {
        $data['editable_gids'] = array_map('intval', array_map('trim', explode(',', $data['editable_gids'])));
    }
    if (!empty($data['editable_gids'])) {
        $data['editable'] = 99;
    }
    make_form_row('editable', 'select_box', array(XTHREADS_EDITABLE_ALL => $lang->threadfields_editable_everyone, XTHREADS_EDITABLE_REQ => $lang->threadfields_editable_requied, XTHREADS_EDITABLE_MOD => $lang->threadfields_editable_mod, XTHREADS_EDITABLE_ADMIN => $lang->threadfields_editable_admin, XTHREADS_EDITABLE_NONE => $lang->threadfields_editable_none, 99 => $lang->threadfields_editable_bygroup));
    $form_container->output_row($lang->threadfields_editable_gids, $lang->threadfields_editable_gids_desc, xt_generate_group_select('editable_gids[]', $data['editable_gids'], array('multiple' => true, 'size' => 5)), 'editable_gids', array(), array('id' => 'row_editable_gids'));
    make_form_row('maxlen', 'text_box');
    make_form_row('vallist', 'text_area');
    make_form_row('fileexts', 'text_box');
    if (!is_int(2147483648)) {
        // detect 32-bit PHP
        $lang->threadfields_filemaxsize_desc .= $lang->threadfields_filemaxsize_desc_2gbwarn;
    }
    // PHP upload limits
    $upload_max_filesize = @ini_get('upload_max_filesize');
    $post_max_size = @ini_get('post_max_size');
    // TODO: maybe also pull in [ file_uploads, max_file_uploads, max_input_time ] ?
    if ($upload_max_filesize || $post_max_size) {
        $lang->threadfields_filemaxsize_desc .= '<br /><br />' . $lang->threadfields_filemaxsize_desc_phplimit;
        if (!$lang->limit_upload_max_filesize) {
            $lang->load('config_attachment_types');
        }
        if ($upload_max_filesize) {
            $lang->threadfields_filemaxsize_desc .= '<br />' . $lang->sprintf($lang->limit_upload_max_filesize, $upload_max_filesize);
        }
        if ($post_max_size) {
            $lang->threadfields_filemaxsize_desc .= '<br />' . $lang->sprintf($lang->limit_post_max_size, $post_max_size);
        }
    }
    make_form_row('filemaxsize', 'text_box');
    make_form_row('filemagic', 'text_box');
    $data['filereqimg'] = $data['fileimage'] ? 1 : 0;
    if (!function_exists('imagecreate')) {
        $lang->threadfields_filereqimg_desc .= $lang->threadfields_filereqimg_desc_nogd;
    }
    make_form_row('filereqimg', 'yes_no_radio');
    unset($data['filereqimg']);
    $data['fileimage_mindim'] = $data['fileimage_maxdim'] = '';
    if ($data['fileimage']) {
        list($min, $max) = explode('|', $data['fileimage']);
        if ($min === '0x0') {
            $min = '';
        }
        $data['fileimage_mindim'] = $min;
        $data['fileimage_maxdim'] = $max;
    }
    make_form_row('fileimage_mindim', 'text_box');
    make_form_row('fileimage_maxdim', 'text_box');
    unset($data['fileimage_mindim'], $data['fileimage_maxdim']);
    make_form_row('fileimgthumbs', 'text_box');
    $data['multival_enable'] = $data['multival'] !== '' ? 1 : 0;
    make_form_row('multival_enable', 'yes_no_radio');
    unset($data['multival_enable']);
    make_form_row('multival_limit', 'text_box');
    make_form_row('textmask', 'text_box');
    make_form_row('inputformat', 'text_area', array('style' => 'font-family: monospace'));
    make_form_row('inputvalidate', 'text_area', array('style' => 'font-family: monospace'));
    if (!is_array($data['editable_values'])) {
        $ev = @unserialize($data['editable_values']);
        if (is_array($ev)) {
            $data['editable_values'] =& $ev;
        }
    }
    if (is_array($data['editable_values'])) {
        $evtxt = '';
        foreach ($data['editable_values'] as $k => &$v) {
            // don't need to htmlspecialchar - it'll be done for us
            $evtxt .= str_replace("\n", "{\n}", $k) . '{|}' . implode(',', $v) . "\n";
        }
        $data['editable_values'] =& $evtxt;
    }
    make_form_row('editable_values', 'text_area', array('style' => 'font-family: monospace'));
    $form_container->end();
    unset($GLOBALS['form_container']);
    global $form_container;
    $form_container = new FormContainer($lang->threadfields_cat_inputfield);
    make_form_row('desc', 'text_box');
    make_form_row('defaultval', 'text_area', array('style' => 'font-family: monospace'));
    make_form_row('fieldwidth', 'text_box');
    make_form_row('fieldheight', 'text_box');
    make_form_row('tabstop', 'yes_no_radio');
    $data['use_formhtml'] = $data['formhtml'] !== '' ? 1 : 0;
    make_form_row('use_formhtml', 'yes_no_radio');
    unset($data['use_formhtml']);
    $lang->threadfields_formhtml .= ' <em>*</em>';
    make_form_row('formhtml', 'text_area', array('style' => 'font-family: monospace'));
    $form_container->end();
    unset($GLOBALS['form_container']);
    global $form_container;
    $form_container = new FormContainer($lang->threadfields_cat_output);
    $sanitize = $data['sanitize'];
    $data['sanitize'] &= XTHREADS_SANITIZE_MASK;
    make_form_row('sanitize', 'select_box', array(XTHREADS_SANITIZE_HTML => $lang->threadfields_sanitize_plain, XTHREADS_SANITIZE_HTML_NL => $lang->threadfields_sanitize_plain_nl, XTHREADS_SANITIZE_PARSER => $lang->threadfields_sanitize_mycode, XTHREADS_SANITIZE_NONE => $lang->threadfields_sanitize_none));
    $parser_opts = array('parser_nl2br' => $sanitize & XTHREADS_SANITIZE_PARSER_NL2BR, 'parser_nobadw' => $sanitize & XTHREADS_SANITIZE_PARSER_NOBADW, 'parser_html' => $sanitize & XTHREADS_SANITIZE_PARSER_HTML, 'parser_mycode' => $sanitize & XTHREADS_SANITIZE_PARSER_MYCODE, 'parser_mycodeimg' => $sanitize & XTHREADS_SANITIZE_PARSER_MYCODEIMG, 'parser_mycodevid' => $sanitize & XTHREADS_SANITIZE_PARSER_VIDEOCODE, 'parser_smilies' => $sanitize & XTHREADS_SANITIZE_PARSER_SMILIES);
    if ($mybb->version_code < 1600) {
        unset($parser_opts['parser_mycodevid']);
    }
    $parser_opts_str = '';
    foreach ($parser_opts as $opt => $checked) {
        $langstr = 'threadfields_sanitize_' . $opt;
        $parser_opts_str .= '<div style="display: block;">' . $form->generate_check_box($opt, 1, $lang->{$langstr}, array('checked' => $checked ? 1 : 0)) . '</div>';
    }
    $form_container->output_row($lang->threadfields_sanitize_parser, $lang->threadfields_sanitize_parser_desc, $parser_opts_str, 'sanitize_parser', array(), array('id' => 'parser_opts'));
    make_form_row('blankval', 'text_area', array('style' => 'font-family: monospace'));
    make_form_row('dispformat', 'text_area', array('style' => 'font-family: monospace'));
    $lang->threadfields_multival .= ' <em>*</em>';
    make_form_row('multival', 'text_box');
    $lang->threadfields_multival = substr($lang->threadfields_multival, 0, -11);
    make_form_row('dispitemformat', 'text_area', array('style' => 'font-family: monospace'));
    if (!is_array($data['formatmap'])) {
        $fm = @unserialize($data['formatmap']);
        if (is_array($fm)) {
            $data['formatmap'] =& $fm;
        }
    }
    if (is_array($data['formatmap'])) {
        $fmtxt = '';
        foreach ($data['formatmap'] as $k => &$v) {
            // don't need to htmlspecialchar - it'll be done for us
            $fmtxt .= str_replace("\n", "{\n}", $k . '{|}' . $v) . "\n";
        }
        $data['formatmap'] =& $fmtxt;
    }
    make_form_row('formatmap', 'text_area', array('style' => 'font-family: monospace'));
    if ($data['viewable_gids'] && !is_array($data['viewable_gids'])) {
        $data['viewable_gids'] = array_map('intval', array_map('trim', explode(',', $data['viewable_gids'])));
    }
    $form_container->output_row($lang->threadfields_viewable_gids, $lang->threadfields_viewable_gids_desc, xt_generate_group_select('viewable_gids[]', $data['viewable_gids'], array('multiple' => true, 'size' => 5, 'id' => 'viewable_gids')), 'viewable_gids', array(), array('id' => 'row_viewable_gids'));
    make_form_row('unviewableval', 'text_area', array('style' => 'font-family: monospace'));
    $form_container->end();
    unset($GLOBALS['form_container']);
    // this will currently be empty if a file input is chosen...
    global $form_container;
    $form_container = new FormContainer($lang->threadfields_cat_misc);
    make_form_row('allowfilter', 'select_box', array(XTHREADS_FILTER_NONE => $lang->threadfields_filter_none, XTHREADS_FILTER_EXACT => $lang->threadfields_filter_exact, XTHREADS_FILTER_PREFIX => $lang->threadfields_filter_prefix, XTHREADS_FILTER_ANYWHERE => $lang->threadfields_filter_anywhere, XTHREADS_FILTER_WILDCARD => $lang->threadfields_filter_wildcard));
    make_form_row('datatype', 'select_box', array(XTHREADS_DATATYPE_TEXT => $lang->threadfields_datatype_text, XTHREADS_DATATYPE_INT => $lang->threadfields_datatype_int, XTHREADS_DATATYPE_UINT => $lang->threadfields_datatype_uint, XTHREADS_DATATYPE_BIGINT => $lang->threadfields_datatype_bigint, XTHREADS_DATATYPE_BIGUINT => $lang->threadfields_datatype_biguint, XTHREADS_DATATYPE_FLOAT => $lang->threadfields_datatype_float));
    $form_container->end();
    unset($GLOBALS['form_container']);
    if ($update) {
        $buttons[] = $form->generate_submit_button($lang->update_threadfield);
    } else {
        $buttons[] = $form->generate_submit_button($lang->add_threadfield);
    }
    $form->output_submit_wrapper($buttons);
    $form->end();
    ?>
<script type="text/javascript">
<!--
	var xt_inited = false;
	function xt_visi(o,v) {
		document.getElementById(o).style.display = (v ? '':'none');
	}
	document.getElementById('sanitize').onchange = function() {
		xt_visi('parser_opts', this.options[this.selectedIndex].value == "<?php 
    echo XTHREADS_SANITIZE_PARSER;
    ?>
" && document.getElementById('row_sanitize').style.display != 'none');
	};
	
	function xt_multival_enable() {
		var si = parseInt(document.getElementById('inputtype').options[document.getElementById('inputtype').selectedIndex].value);
		var checkboxIn = (si == <?php 
    echo XTHREADS_INPUT_CHECKBOX;
    ?>
);
		var pureFileIn = (si == <?php 
    echo XTHREADS_INPUT_FILE;
    ?>
);
		var fileIn = (pureFileIn || si == <?php 
    echo XTHREADS_INPUT_FILE_URL;
    ?>
);
		e = checkboxIn; // forced
		
		var datatypeText = (document.getElementById('datatype').options[document.getElementById('datatype').selectedIndex].value == "<?php 
    echo XTHREADS_DATATYPE_TEXT;
    ?>
");
		xt_visi('row_multival_enable', checkboxIn || ((
			si != <?php 
    echo XTHREADS_INPUT_RADIO;
    ?>
 && (datatypeText || pureFileIn)
		)));
		
		if(!e) e = (document.getElementById('multival_enable_yes').checked && document.getElementById('row_multival_enable').style.display != 'none');
		xt_visi('row_multival', e);
		xt_visi('row_multival_limit', e);
		xt_visi('row_dispitemformat', e);
		datatypeVisible = (!e && !checkboxIn && !fileIn);
		xt_visi('row_datatype', datatypeVisible);
		
		// hide some sanitise options (if browser supports it)
		var sanitizeOptShow = ((datatypeVisible && !datatypeText) ? 'none' : '');
		for(i in document.getElementById('sanitize').options) {
			var optItem = document.getElementById('sanitize').options[i];
			if(!optItem) continue; // fix IE6 bug
			if(optItem.value == "<?php 
    echo XTHREADS_SANITIZE_HTML_NL;
    ?>
" || optItem.value == "<?php 
    echo XTHREADS_SANITIZE_NONE;
    ?>
") {
				// our target
				if(sanitizeOptShow == 'none' && document.getElementById('sanitize').selectedIndex == i)
					document.getElementById('sanitize').selectedIndex = 0;
				optItem.style.display = sanitizeOptShow;
			}
		}
		
		dispfmt_obj = document.getElementById('dispformat');
		fileVal = "<a href=\"{URL}\">{FILENAME}</a>";
		nonFileVal = "{VALUE}";
		if(pureFileIn) {
			if(e) {
				if(document.getElementById('dispitemformat').value == nonFileVal) {
					if(dispfmt_obj.value == nonFileVal)
						document.getElementById('dispitemformat').value = fileVal;
					else {
						// swap dispformat <-> dispitemformat
						document.getElementById('dispitemformat').value = dispfmt_obj.value;
						dispfmt_obj.value = nonFileVal;
					}
				}
				if(dispfmt_obj.value == fileVal)
					dispfmt_obj.value = nonFileVal;
			} else {
				if(dispfmt_obj.value == nonFileVal) {
					dispfmt_obj.value = fileVal;
					if(document.getElementById('dispitemformat').value != nonFileVal) {
						// maybe swap?
						var DIFval = document.getElementById('dispitemformat').value.toUpperCase();
						if((function(s){
							for(i in s)
								if(DIFval.indexOf("{"+s[i]+"}") > -1)
									return true;
							return false;
						})(
							["DOWNLOADS","DOWNLOADS_FRIENDLY","FILENAME","UPLOADMIME","URL","FILESIZE","FILESIZE_FRIENDLY","MD5HASH","UPLOADTIME","UPLOAD_TIME","UPLOAD_DATE","UPDATETIME","UPDATE_TIME","UPDATE_DATE","THUMBS","DIMS","MODIFIED"]
						)) {
							dispfmt_obj.value = document.getElementById('dispitemformat').value;
							document.getElementById('dispitemformat').value = nonFileVal;
						}
					}
				}
				if(document.getElementById('dispitemformat').value == fileVal)
					document.getElementById('dispitemformat').value = nonFileVal;
			}
		} else {
			if(document.getElementById('dispitemformat').value == fileVal)
				document.getElementById('dispitemformat').value = nonFileVal;
			if(dispfmt_obj.value == fileVal)
				dispfmt_obj.value = nonFileVal;
		}
	}
	document.getElementById('multival_enable_yes').onclick = xt_multival_enable;
	document.getElementById('multival_enable_no').onclick = xt_multival_enable;
	
	(document.getElementById('use_formhtml_yes').onclick = document.getElementById('use_formhtml_no').onclick = xt_use_formhtml = function() {
		xt_visi('row_formhtml', document.getElementById('use_formhtml_yes').checked);
		xt_visi('formhtml_desc_js', true);
	})();
	
	function xt_filereqimg() {
		var e = (document.getElementById('filereqimg_yes').checked && document.getElementById('row_filereqimg').style.display != 'none');
		xt_visi('row_fileimage_mindim', e);
		xt_visi('row_fileimage_maxdim', e);
		xt_visi('row_fileimgthumbs', e);
	}
	document.getElementById('filereqimg_yes').onclick = xt_filereqimg;
	document.getElementById('filereqimg_no').onclick = xt_filereqimg;
	
	
	(document.getElementById('inputtype').onchange = function() {
		var si = parseInt(this.options[this.selectedIndex].value);
		
		var pureFileIn = (si == <?php 
    echo XTHREADS_INPUT_FILE;
    ?>
);
		var fileIn = (pureFileIn || si == <?php 
    echo XTHREADS_INPUT_FILE_URL;
    ?>
);
		var radioIn = (si == <?php 
    echo XTHREADS_INPUT_RADIO;
    ?>
);
		var checkboxIn = (si == <?php 
    echo XTHREADS_INPUT_CHECKBOX;
    ?>
);
		var selectBoxIn = (si == <?php 
    echo XTHREADS_INPUT_SELECT;
    ?>
);
		var selectIn = (selectBoxIn || radioIn || checkboxIn);
		var textAreaIn = (si == <?php 
    echo XTHREADS_INPUT_TEXTAREA;
    ?>
);
		var textIn = (textAreaIn || si == <?php 
    echo XTHREADS_INPUT_TEXT;
    ?>
);
		xt_visi('row_sanitize', !fileIn && !selectIn);
		document.getElementById('sanitize').onchange();
		
		xt_visi('inputtype_file_explain', pureFileIn);
		
		xt_visi('row_allowfilter', !fileIn && !textAreaIn);
		xt_visi('row_formatmap', !fileIn);
		xt_visi('row_editable_values', !fileIn);
		xt_visi('row_defaultval', !pureFileIn);
		
		xt_visi('row_textmask', textIn);
		xt_visi('row_inputformat', !fileIn);
		xt_visi('row_maxlen', textIn);
		xt_visi('row_fieldwidth', textIn || fileIn || selectBoxIn);
		xt_visi('row_fieldheight', textAreaIn || selectBoxIn);
		
		xt_visi('row_vallist', selectIn);
		
		//xt_visi('row_datatype', !checkboxIn && !fileIn);
		//xt_visi('row_multival_enable', !checkboxIn && !radioIn && !fileIn);
		xt_multival_enable();
		
		xt_visi('row_filemagic', pureFileIn);
		xt_visi('row_fileexts', pureFileIn);
		xt_visi('row_filemaxsize', pureFileIn);
		xt_visi('row_filereqimg', pureFileIn);
		xt_filereqimg();
		
		if(textAreaIn) {
			if(document.getElementById('sanitize').options[document.getElementById('sanitize').selectedIndex].value == "<?php 
    echo XTHREADS_SANITIZE_HTML;
    ?>
")
				document.getElementById('sanitize').selectedIndex++;
		} else if(textIn) {
			if(document.getElementById('sanitize').options[document.getElementById('sanitize').selectedIndex].value == "<?php 
    echo XTHREADS_SANITIZE_HTML_NL;
    ?>
")
				document.getElementById('sanitize').selectedIndex--;
		}
		
		var setFormhtml = true;
		if(document.getElementById('use_formhtml_yes').checked) {
			if(!xt_inited)
				setFormhtml = (document.getElementById("formhtml").value == "");
			else
				setFormhtml = confirm("<?php 
    echo xt_js_str_escape($lang->threadfields_formhtml_js_reset_warning);
    ?>
");
			if(setFormhtml) {
				document.getElementById('use_formhtml_no').checked = true;
			}
			xt_use_formhtml();
		}
		switch(si) {
			<?php 
    foreach (array(XTHREADS_INPUT_TEXTAREA, XTHREADS_INPUT_SELECT, XTHREADS_INPUT_CHECKBOX, XTHREADS_INPUT_RADIO, XTHREADS_INPUT_FILE, XTHREADS_INPUT_TEXT) as $inputtype) {
        $formhtml_info = xthreads_default_threadfields_formhtml($inputtype);
        $formhtml_desc = '';
        foreach ($formhtml_info[1] as $fhvar) {
            $langvar = 'threadfields_formhtml_desc_' . strtolower($fhvar);
            $formhtml_desc .= '<li><code>{' . $fhvar . '}</code>: ' . $lang->{$langvar} . '</li>';
        }
        echo '
				case ' . $inputtype . ':
					if(setFormhtml) document.getElementById("formhtml").value = "' . xt_js_str_escape($formhtml_info[0]) . '";
					document.getElementById("formhtml_desc_ul_js").innerHTML = "' . xt_js_str_escape($formhtml_desc) . '";
					break;';
    }
    ?>
		}
	}).apply(document.getElementById('inputtype'));
	
	(document.getElementById('datatype').onchange = function() {
		//var isText = this.options[this.selectedIndex].value == "<?php 
    echo XTHREADS_DATATYPE_TEXT;
    ?>
";
		//xt_visi('row_multival_enable', isText);
		xt_multival_enable();
	}).apply(document.getElementById('datatype'));
	
	(document.getElementById('editable').onchange = function() {
		xt_visi('row_editable_gids', this.options[this.selectedIndex].value == "99");
	}).apply(document.getElementById('editable'));
	
	(document.getElementById('viewable_gids').onchange = function() {
		var e=false;
		var o=document.getElementById('viewable_gids').options;
		for(i=0; i<o.length; i++)
			if(e = o[i].selected) // no, I do mean =, not ==
				break;
		xt_visi('row_unviewableval', e);
	}).apply(document.getElementById('viewable_gids'));
	
	<?php 
    $textmask_types = array('anything' => '^.*$', 'digit' => '^\\d+$', 'alphadigit' => '^[a-z0-9]+$', 'number' => '^(-?)([0-9]*)(?:\\.(\\d*))?(?:e([+-]?\\d*))?$', 'date' => '^(0?[1-9]|[12]\\d|3[01])/(0?[1-9]|1[012])/((?:19|20)\\d\\d)$', 'date_us' => '^(0?[1-9]|1[012])/(0?[1-9]|[12]\\d|3[01])/((?:19|20)\\d\\d)$', 'uri' => '^([^:/?#]+)\\:((//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?)$', 'url' => '^([a-z0-9]+)\\://([^/?#]+)(/([^\\r\\n"<>#?]*)(\\?([^\\r\\n"<>#]*))?(#([^\\r\\n"<>]*))?)?$', 'httpurl' => '^(https?)\\://([^/?#]+)(/([^\\r\\n"<>#?]*)(\\?([^\\r\\n"<>#]*))?(#([^\\r\\n"<>]*))?)?$', 'email' => '^(.+)@([a-z0-9_.\\-]+)$', 'emailr' => '^([^ "(),:;<>@\\[\\\\\\]]+)@([a-z0-9_.\\-]+)$', 'css' => '^[a-z0-9_\\- ]+$', 'color' => '^[a-z\\-]+|#?[0-9a-f]{6}$');
    ?>
	document.getElementById('textmask').parentNode.innerHTML =
			'<select name="textmask_select" id="textmask_select">' +
<?php 
    foreach ($textmask_types as $type => &$mask) {
        $langvar = 'threadfields_textmask_' . $type;
        echo '			\'<option value="', $type, '">', $lang->{$langvar}, '</option>\' +
';
    }
    ?>
			'<option value="custom">'+<?php 
    echo "'", $lang->threadfields_textmask_custom, "'";
    ?>
+'</option>' +
			'</select> ' + document.getElementById('textmask').parentNode.innerHTML + '<div id="textmask_select_descriptions" style="font-size: smaller; padding-top: 0.5em;">' +
<?php 
    foreach ($textmask_types as $type => &$mask) {
        $langvar = 'threadfields_textmask_' . $type . '_desc';
        if (property_exists($lang, $langvar)) {
            echo '			\'<div id="textmask_selector_desc_', $type, '" style="display: none;">', xt_js_str_escape($lang->{$langvar}), '</div>\' +
';
        }
    }
    ?>
			'</div>';
	var textmaskMapping = {
<?php 
    $comma = '';
    foreach ($textmask_types as $type => &$mask) {
        echo $comma, '		', $type, ': "', xt_js_str_escape($mask), '"';
        if (!$comma) {
            $comma = ',
';
        }
    }
    ?>

	};
	// determine which option to be selected by default
	(function() {
		// we can only index by number, and as we're a little lazy, create a name -> index map
		var textmaskSelectOpts = document.getElementById('textmask_select').options;
		var textmaskSelectMap = {};
		for(i=0; i<textmaskSelectOpts.length; i++) {
			textmaskSelectMap[textmaskSelectOpts[i].value] = i;
		}
		
		var mask = document.getElementById('textmask').value;
		for(var maskName in textmaskMapping) {
			if(mask == textmaskMapping[maskName]) {
				document.getElementById('textmask_select').selectedIndex = textmaskSelectMap[maskName];
				textmaskSelectUpdated();
				return;
			}
		}
		document.getElementById('textmask_select').selectedIndex = textmaskSelectMap["custom"];
	})();
	document.getElementById('textmask_select').onchange = function() {
		var maskName = this.options[this.selectedIndex].value;
		if(textmaskMapping[maskName])
			document.getElementById('textmask').value = textmaskMapping[maskName];
		textmaskSelectUpdated();
	};
	document.getElementById('textmask_select').onkeypress = document.getElementById('textmask_select').onkeydown = document.getElementById('textmask_select').onkeyup = function(e) {
		document.getElementById('textmask_select').onchange();
		return true;
	};
	function textmaskSelectUpdated() {
		var maskName = document.getElementById('textmask_select').options[document.getElementById('textmask_select').selectedIndex].value;
		var d = (maskName != "custom");
		document.getElementById('textmask').readOnly = d;
		document.getElementById('textmask').tabIndex = (d?'-1':''); // note, this is non-standard
		document.getElementById('textmask').style.background = (d ? "#F0F0F0":"");
		document.getElementById('textmask').style.color = (d ? "#808080":"");
		
		var o = document.getElementById('textmask_select_descriptions').childNodes;
		for(i=0; i<o.length; i++) {
			if(o[i].id == "textmask_selector_desc_"+maskName)
				o[i].style.display = "";
			else
				o[i].style.display = "none";
		}
	}
	document.getElementById('textmask').onfocus = function() {
		if(this.readOnly)
			document.getElementById('textmask_select').focus();
	};
	xt_inited = true;
//-->
</script>
<script type="text/javascript" src="jscripts/xtofedit.js?xtver=<?php 
    echo XTHREADS_VERSION;
    ?>
"></script>
<script type="text/javascript">
<!--
xtOFEditorLang.confirmFormSubmit = "<?php 
    echo $lang->xthreads_js_confirm_form_submit;
    ?>
";
xtOFEditorLang.windowTitle = "<?php 
    echo $lang->xthreads_js_edit_value;
    ?>
";
xtOFEditorLang.saveButton = "<?php 
    echo $lang->xthreads_js_save_changes;
    ?>
";
xtOFEditorLang.closeSaveChanges = "<?php 
    echo $lang->xthreads_js_close_save_changes;
    ?>
";

var fmtMapEditor = new xtOFEditor();
fmtMapEditor.src = document.getElementById('formatmap');
fmtMapEditor.loadFunc = function(s) {
	var a = s.replace(/\r/g, "").replace(/\{\n\}/g, "\r").split("\n");
	var data = [];
	for(var i=0; i<a.length; i++) {
		a[i] = a[i].replace(/\r/g, "\n");
		var p = a[i].indexOf("{|}");
		if(p < 0) continue;
		data.push([ a[i].substring(0, p), a[i].substring(p+3) ]);
	}
	return data;
};
fmtMapEditor.saveFunc = function(a) {
	var ret = "";
	for(var i=0; i<a.length; i++) {
		ret += a[i].join("{|}").replace(/\n/g, "{\n}") + "\n";
	}
	return ret;
};
fmtMapEditor.fields = [
	{title: "<?php 
    echo $lang->xthreads_js_formatmap_from;
    ?>
", width: '45%', elemFunc: fmtMapEditor.textAreaFunc},
	{title: "<?php 
    echo $lang->xthreads_js_formatmap_to;
    ?>
", width: '55%', elemFunc: fmtMapEditor.textAreaFunc}
];

fmtMapEditor.copyStyles=true;
fmtMapEditor.init();

var editValEditor = new xtOFEditor();
editValEditor.src = document.getElementById('editable_values');
editValEditor.loadFunc = function(s) {
	var a = s.replace(/\r/g, "").replace(/\{\n\}/g, "\r").split("\n");
	var data = [];
	for(var i=0; i<a.length; i++) {
		a[i] = a[i].replace(/\r/g, "\n");
		var p = a[i].indexOf("{|}");
		if(p < 0) continue;
		data.push([ a[i].substring(0, p), a[i].substring(p+3).split(",") ]);
	}
	return data;
};
editValEditor.saveFunc = function(a) {
	var ret = "";
	for(var i=0; i<a.length; i++) {
		ret += a[i][0].replace(/\n/g, "{\n}") + "{|}" + a[i][1].join(",") + "\n";
	}
	return ret;
};
editValEditor.fields = [
	{title: "<?php 
    echo $lang->xthreads_js_formatmap_from;
    ?>
", width: '50%', elemFunc: editValEditor.textAreaFunc},
	{title: "<?php 
    echo $lang->xthreads_js_editable_values_groups;
    ?>
", width: '50%', elemFunc: function(c) {
		var o = appendNewChild(c, "select");
		o.multiple = true;
		o.size = 3;
		o.style.width = '100%';
		o.innerHTML = '<?php 
    foreach ($GLOBALS['cache']->read('usergroups') as $group) {
        echo '<option value="' . $group['gid'] . '">' . xt_js_str_escape(htmlspecialchars_uni(strip_tags($group['title']))) . '</option>';
    }
    ?>
';
		return o;
	}}
];

editValEditor.copyStyles=true;
editValEditor.init();

//-->
</script><?php 
    $page->output_footer();
}
Пример #7
0
 static function _processHttpHeader_parse(&$header)
 {
     $header = trim($header);
     $p = strpos($header, ':');
     if (!$p) {
         // look for HTTP/1.1 type header
         if (strtoupper(substr($header, 0, 5)) == 'HTTP/') {
             if (preg_match('~^HTTP/[0-9.]+ (\\d+) (.*)$~i', $header, $match)) {
                 return array('retcode' => array((int) $match[1], trim($match[2])));
             }
         }
         return null;
     }
     $hdata = trim(substr($header, $p + 1));
     switch (strtolower(substr($header, 0, $p))) {
         case 'content-length':
             $size = (int) $hdata;
             if ($size || $hdata === '0') {
                 return array('size' => $size);
             }
             break;
         case 'content-disposition':
             foreach (explode(';', $hdata) as $disp) {
                 $disp = trim($disp);
                 if (strtolower(substr($disp, 0, 9)) == 'filename=') {
                     $tmp = substr($disp, 9);
                     if (!xthreads_empty($tmp)) {
                         if ($tmp[0] == '"' && $tmp[strlen($tmp) - 1] == '"') {
                             $tmp = substr($tmp, 1, -1);
                         }
                         return array('name' => trim(str_replace("", '', $tmp)));
                     }
                 }
             }
             break;
         case 'content-type':
             return array('type' => $hdata);
             break;
     }
     return null;
 }
Пример #8
0
function xthreads_sanitize_eval(&$s, $fields = array(), $evalvarname = null)
{
    if (xthreads_empty($s)) {
        $s = '';
        return;
    }
    // the following won't work properly with array indexes which have non-alphanumeric and underscore chars; also, it won't do ${var} syntax
    // also, damn PHP's magic quotes for preg_replace - but it does assist with backslash fun!!!
    $s = preg_replace_callback('~\\{\\\\\\$([a-zA-Z_][a-zA-Z_0-9]*)((?:-\\>|\\[)[^}]+?)?\\}~', function ($m) {
        return '{$GLOBALS[\'' . $m[1] . '\']' . _xthreads_phptpl_expr_parse2($m[2]) . '}';
    }, preg_replace(array('~\\{\\\\\\$forumurl\\\\\\$\\}~i', '~\\{\\\\\\$forumurl\\?\\}~i', '~\\{\\\\\\$threadurl\\\\\\$\\}~i', '~\\{\\\\\\$threadurl\\?\\}~i'), array('{$GLOBALS[\'forumurl\']}', '{$GLOBALS[\'forumurl_q\']}', '{$GLOBALS[\'threadurl\']}', '{$GLOBALS[\'threadurl_q\']}'), strtr($s, array('\\' => '\\\\', '$' => '\\$', '"' => '\\"'))));
    // replace conditionals
    xthreads_phptpl_parsetpl($s, $fields, $evalvarname);
    // replace value tokens at the end
    if (!empty($fields)) {
        $s = xthreads_phptpl_parse_fields($s, $fields, true);
    }
}
Пример #9
0
    function xthreads_moderation_custom_do(&$tids, $editstr)
    {
        if (!$editstr) {
            return;
        }
        $edits = array();
        // caching stuff
        static $threadfields = null;
        if (!isset($threadfields)) {
            $threadfields = xthreads_gettfcache();
        }
        // grab all threadfields
        require_once MYBB_ROOT . 'inc/xthreads/xt_phptpl_lib.php';
        foreach (explode("\n", str_replace("{\n}", "\r", str_replace("\r", '', $editstr))) as $editline) {
            $editline = trim(str_replace("\r", "\n", $editline));
            list($n, $v) = explode('=', $editline, 2);
            if (!isset($v)) {
                continue;
            }
            // don't allow editing of file fields
            if (!isset($threadfields[$n]) || $threadfields[$n]['inputtype'] == XTHREADS_INPUT_FILE) {
                continue;
            }
            // we don't do much validation here as we trust admins, right?
            // this is just a prelim check (speed optimisation) - we'll need to check this again after evaluating conditionals
            $upperv = strtoupper($v);
            if (($upperv === '' || $upperv == 'NULL' || $upperv == 'NUL') && $threadfields[$n]['datatype'] != XTHREADS_DATATYPE_TEXT) {
                $edits[$n] = null;
            } else {
                $edits[$n] = $v;
                xthreads_sanitize_eval($edits[$n], array('VALUE' => null, 'TID' => null));
            }
        }
        if (empty($edits)) {
            return;
        }
        $modfields = array_keys($edits);
        global $db;
        $query = $db->query('
			SELECT t.tid, tfd.`' . implode('`, tfd.`', $modfields) . '`
			FROM ' . TABLE_PREFIX . 'threads t
			LEFT JOIN ' . TABLE_PREFIX . 'threadfields_data tfd ON t.tid=tfd.tid
			WHERE t.tid IN (' . implode(',', $tids) . ')
		');
        //$query = $db->simple_select('threadfields_data', 'tid,`'.implode('`,`', $modfields).'`', 'tid IN ('.implode(',', $tids).')');
        while ($thread = $db->fetch_array($query)) {
            $updates = array();
            foreach ($edits as $n => $v) {
                if ($v !== null) {
                    // TODO: allowing conditionals direct access to multivals?
                    $v = trim(eval_str($v, array('VALUE' => $thread[$n], 'TID' => $thread['tid'])));
                    if ($threadfields[$n]['datatype'] != XTHREADS_DATATYPE_TEXT) {
                        $upperv = strtoupper($v);
                        if ($upperv == '' || $upperv == 'NULL' || $upperv == 'NUL') {
                            $v = null;
                        }
                        // TODO: intval/floatval here?
                    }
                }
                if ($v !== $thread[$n]) {
                    // we'll do some basic validation for multival fields
                    if (!xthreads_empty($threadfields[$n]['multival'])) {
                        $d = "\n";
                        if ($threadfields[$n]['inputtype'] == XTHREADS_INPUT_TEXT) {
                            $d = ',';
                        }
                        $v = array_unique(array_map('trim', explode($d, str_replace("\r", '', $v))));
                        foreach ($v as $key => &$val) {
                            if (xthreads_empty($val)) {
                                unset($v[$key]);
                            }
                        }
                        $v = implode($d, $v);
                    }
                    $updates[$n] = $v;
                }
            }
            if (!empty($updates)) {
                xthreads_db_update_replace('threadfields_data', $updates, 'tid', $thread['tid']);
            }
        }
        $db->free_result($query);
    }
Пример #10
0
function xthreads_wol_patch(&$a)
{
    global $lang, $thread_fid_map;
    global $forums, $threads, $posts, $attachments;
    $langargs = array();
    $user_activity =& $a['user_activity'];
    $activity = $user_activity['activity'];
    switch ($user_activity['activity']) {
        case 'announcements':
        case 'forumdisplay':
        case 'newthread':
            $fid = $user_activity['fid'];
            $langargs = array(get_forum_link($fid), $forums[$fid]);
            // TODO: special forumdisplay linkto string?
            break;
        case 'attachment':
            $tid = $posts[$attachments[$user_activity['aid']]];
            $fid = $thread_fid_map[$tid];
            $langargs = array($user_activity['aid'], $threads[$tid], get_thread_link($tid));
            break;
        case 'showpost':
            $activity = 'showthread';
        case 'newreply':
            if ($user_activity['pid']) {
                $user_activity['tid'] = $posts[$user_activity['pid']];
            }
            // fall through
        // fall through
        case 'showthread':
            $fid = $thread_fid_map[$user_activity['tid']];
            $langargs = array(get_thread_link($user_activity['tid']), $threads[$user_activity['tid']], '');
            break;
            //case 'editpost': -
            //case 'newpoll':
            //case 'editpoll':
            //case 'showresults':
            //case 'vote':
            //case 'ratethread': -
            //case 'report':
            //case 'sendthread':
            /*
            case 'xtattachment':
            	$a['location_name'] = $lang->sprintf($lang->xthreads_downloading_attachment, htmlspecialchars_uni($user_activity['location']), htmlspecialchars_uni($user_activity['filenamename']));
            	// TODO: allow custom for this too
            	return;
            */
    }
    if (!$fid) {
        return;
    }
    global $forumcache;
    if (!is_array($forumcache)) {
        $forumcache = $GLOBALS['cache']->read('forums');
    }
    $wolstr =& $forumcache[$fid]['xthreads_wol_' . $activity];
    if (!xthreads_empty($wolstr)) {
        if (empty($langargs)) {
            $a['location_name'] = $wolstr;
        } else {
            array_unshift($langargs, $wolstr);
            $a['location_name'] = call_user_func_array(array($lang, 'sprintf'), $langargs);
        }
    }
}