示例#1
0
function do_upload_xtattachment($attachment, &$tf, $update_attachment = 0, $tid = 0, $timestamp = TIME_NOW)
{
    global $db, $mybb, $lang;
    $posthash = $db->escape_string($mybb->input['posthash']);
    $tid = (int) $tid;
    // may be possible for this to be null, if so, change to 0
    $path = $mybb->settings['uploadspath'] . '/xthreads_ul/';
    if (!$lang->xthreads_threadfield_attacherror) {
        $lang->load('xthreads');
    }
    if (is_array($attachment)) {
        if (isset($attachment['error']) && $attachment['error']) {
            if ($attachment['error'] == 2) {
                return array('error' => $lang->sprintf($lang->xthreads_xtaerr_error_attachsize, get_friendly_size($tf['filemaxsize'])));
            } elseif ($attachment['error'] >= 1 && $attachment['error'] <= 7) {
                $langvar = 'error_uploadfailed_php' . $attachment['error'];
                $langstr = $lang->{$langvar};
            } else {
                $langstr = $lang->sprintf($lang->error_uploadfailed_phpx, $attachment['error']);
            }
            return array('error' => $lang->error_uploadfailed . $lang->error_uploadfailed_detail . $langstr);
        }
        if (!is_uploaded_file($attachment['tmp_name']) || empty($attachment['tmp_name'])) {
            return array('error' => $lang->error_uploadfailed . $lang->error_uploadfailed_php4);
        }
        $file_size = $attachment['size'];
        // @filesize($attachment['tmp_name'])
        $attachment['name'] = strtr($attachment['name'], array('/' => '', "" => ''));
        if ($error = xthreads_validate_attachment($attachment, $tf)) {
            @unlink($attachment['tmp_name']);
            return array('error' => $error);
        }
        $movefunc = 'move_uploaded_file';
    } elseif ($mybb->usergroup['cancp'] == 1 && substr($attachment, 0, 7) == 'file://') {
        // admin file move
        $filename = strtr(substr($attachment, 7), array('/' => '', DIRECTORY_SEPARATOR => '', "" => ''));
        $file = $path . 'admindrop/' . $filename;
        if (xthreads_empty($filename) || !file_exists($file)) {
            return array('error' => $lang->sprintf($lang->xthreads_xtaerr_admindrop_not_found, htmlspecialchars_uni($filename), htmlspecialchars_uni($file)));
        }
        if (!is_writable($file)) {
            return array('error' => $lang->sprintf($lang->xthreads_xtaerr_admindrop_file_unwritable, htmlspecialchars_uni($filename)));
        }
        if (strtolower($file) == 'index.html') {
            return array('error' => $lang->xthreads_xtaerr_admindrop_index_error);
        }
        $attachment = array('name' => $filename, 'tmp_name' => $file, 'size' => @filesize($file));
        unset($file, $filename);
        if ($error = xthreads_validate_attachment($attachment, $tf)) {
            return array('error' => $error);
        }
        $file_size = $attachment['size'];
        $movefunc = 'rename';
    } else {
        // fetch URL
        if (!empty($tf['filemagic'])) {
            $magic =& $tf['filemagic'];
        } else {
            $magic = array();
        }
        $attachment = xthreads_fetch_url($attachment, $tf['filemaxsize'], $tf['fileexts'], $magic);
        db_ping($db);
        if ($attachment['error']) {
            return array('error' => $attachment['error']);
        }
        $file_size = $attachment['size'];
        if (xthreads_empty($attachment['name']) || $file_size < 1) {
            return array('error' => $lang->error_uploadfailed);
        }
        $attachment['name'] = strtr($attachment['name'], array('/' => '', "" => ''));
        $movefunc = 'rename';
    }
    if ($tf['fileimage']) {
        $img_dimensions = @getimagesize($attachment['tmp_name']);
        if (empty($img_dimensions) || !in_array($img_dimensions[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG))) {
            @unlink($attachment['tmp_name']);
            return array('error' => $lang->error_attachtype);
        }
        if (preg_match('~^([0-9]+)x([0-9]+)(\\|([0-9]+)x([0-9]+))?$~', $tf['fileimage'], $match)) {
            // check if image exceeds max/min dimensions
            if ($img_dimensions[0] < $match[1] || $img_dimensions[1] < $match[2] || $match[3] && ($img_dimensions[0] > $match[4] || $img_dimensions[1] > $match[5])) {
                @unlink($attachment['tmp_name']);
                return array('error' => $lang->sprintf($lang->xthreads_xtaerr_error_imgdims, $img_dimensions[0], $img_dimensions[1]));
            }
        }
        /*
        // convert WBMP -> PNG (saves space, bandwidth and works with MyBB's thumbnail generator)
        // unfortunately, although this is nice, we have a problem of filetype checking etc...
        if($img_dimensions[2] == IMAGETYPE_WBMP) {
        	if(function_exists('imagecreatefromwbmp') && $img = @imagecreatefromwbmp($attachment['tmp_name'])) {
        		@unlink($attachment['tmp_name']);
        		@imagepng($img, $attachment['tmp_name'], 6); // use zlib's recommended compression level
        		imgdestroy($img);
        		unset($img);
        		// double check that we have a file
        		if(!file_exists($attachment['tmp_name']))
        			return array('error' => $lang->error_attachtype); // get user to upload a non-WBMP file, lol
        		// change extension + update filesize, do MIME as well
        		if(strtolower(substr($attachment['name'], -5)) == '.wbmp')
        			$attachment['name'] = substr($attachment['name'], 0, -5).'.png';
        		$file_size = @filesize($attachment['tmp_name']);
        		if(strtolower($attachment['type']) == 'image/wbmp')
        			$attachment['type'] = 'image/png';
        		// update type too
        		$img_dimensions[2] = IMAGETYPE_PNG;
        	}
        	else {
        		// can't do much, error out
        		@unlink($attachment['tmp_name']);
        		return array('error' => $lang->error_attachtype);
        	}
        }
        */
        // we won't actually bother checking MIME types - not a big issue anyway
    }
    if (!XTHREADS_UPLOAD_LARGEFILE_SIZE || $file_size < XTHREADS_UPLOAD_LARGEFILE_SIZE) {
        @set_time_limit(30);
        // as md5_file may take a while
        $md5_start = time();
        $file_md5 = @md5_file($attachment['tmp_name'], true);
        if (strlen($file_md5) == 32) {
            // perhaps not PHP5
            $file_md5 = pack('H*', $file_md5);
        }
        if (time() - $md5_start > 2) {
            // ping DB if process took longer than 2 secs
            db_ping($db);
        }
        unset($md5_start);
    }
    if ($update_attachment) {
        $prevattach = $db->fetch_array($db->simple_select('xtattachments', 'aid,attachname,indir,md5hash', 'aid=' . (int) $update_attachment));
        if (!$prevattach['aid']) {
            $update_attachment = false;
        }
    }
    /* else {
    		// Check if attachment already uploaded
    		// TODO: this is actually a little problematic - perhaps verify that this is attached to this field (or maybe rely on checks in xt_updatehooks file)
    		if(isset($file_md5))
    			$md5check = ' OR md5hash='.xthreads_db_escape_binary($file_md5);
    		else
    			$md5check = '';
    		$prevattach = $db->fetch_array($db->simple_select('xtattachments', 'aid', 'filename="'.$db->escape_string($attachment['name']).'" AND (md5hash IS NULL'.$md5check.') AND filesize='.$file_size.' AND (posthash="'.$posthash.'" OR (tid='.$tid.' AND tid!=0))'));
    		if($prevattach['aid']) {
    			@unlink($attachment['tmp_name']);
    			// TODO: maybe return aid instead?
    			return array('error' => $lang->error_alreadyuploaded);
    		}
    	} */
    // We won't use MyBB's nice monthly directories, instead, we'll use a more confusing system based on the timestamps
    // note, one month = 2592000 seconds, so if we split up by 1mil, it'll be approx 11.5 days
    // If safe_mode is enabled, don't attempt to use the monthly directories as it won't work
    if (ini_get('safe_mode') == 1 || strtolower(ini_get('safe_mode')) == 'on') {
        $month_dir = '';
    } else {
        $month_dir = 'ts_' . floor(TIME_NOW / 1000000) . '/';
        if (!@is_dir($path . $month_dir)) {
            @mkdir($path . $month_dir);
            // Still doesn't exist - oh well, throw it in the main directory
            if (@is_dir($path . $month_dir)) {
                // write index file
                if ($index = fopen($path . $month_dir . 'index.html', 'w')) {
                    fwrite($index, '<html><body></body></html>');
                    fclose($index);
                    @my_chmod($path . $month_dir . 'index.html', 0644);
                }
                @my_chmod($path . $month_dir, 0755);
            } else {
                $month_dir = '';
            }
        }
    }
    // All seems to be good, lets move the attachment!
    $basename = substr(md5(uniqid(mt_rand(), true) . substr($mybb->post_code, 16)), 12, 8) . '_' . preg_replace('~[^a-zA-Z0-9_\\-%]~', '', str_replace(array(' ', '.', '+'), '_', $attachment['name'])) . '.upload';
    $filename = 'file_' . ($prevattach['aid'] ? $prevattach['aid'] : 't' . TIME_NOW) . '_' . $basename;
    @ignore_user_abort(true);
    // don't let the user break this integrity between file system and DB
    if (isset($GLOBALS['xtfurl_tmpfiles'])) {
        // if using url fetch, remove this from list of temp files
        unset($GLOBALS['xtfurl_tmpfiles'][$attachment['tmp_name']]);
    }
    while (!@$movefunc($attachment['tmp_name'], $path . $month_dir . $filename)) {
        if ($month_dir) {
            // try doing it again without the month_dir
            $month_dir = '';
        } else {
            // failed
            @ignore_user_abort(false);
            return array('error' => $lang->error_uploadfailed . $lang->error_uploadfailed_detail . $lang->error_uploadfailed_movefailed);
        }
    }
    // Lets just double check that it exists
    if (!file_exists($path . $month_dir . $filename)) {
        @ignore_user_abort(false);
        return array('error' => $lang->error_uploadfailed . $lang->error_uploadfailed_detail . $lang->error_uploadfailed_lost);
    }
    // Generate the array for the insert_query
    $attacharray = array('posthash' => $posthash, 'tid' => $tid, 'uid' => (int) $mybb->user['uid'], 'field' => $tf['field'], 'filename' => strval($attachment['name']), 'uploadmime' => strval($attachment['type']), 'filesize' => $file_size, 'attachname' => $basename, 'indir' => $month_dir, 'downloads' => 0, 'uploadtime' => $timestamp, 'updatetime' => $timestamp);
    if (isset($file_md5)) {
        $attacharray['md5hash'] = new xthreads_db_binary_value($file_md5);
    } else {
        $attacharray['md5hash'] = null;
    }
    if (!empty($img_dimensions)) {
        $origdimarray = array('w' => $img_dimensions[0], 'h' => $img_dimensions[1], 'type' => $img_dimensions[2]);
        $attacharray['thumbs'] = serialize(array('orig' => $origdimarray));
    }
    if ($update_attachment) {
        unset($attacharray['downloads'], $attacharray['uploadtime']);
        //$attacharray['updatetime'] = TIME_NOW;
        xthreads_db_update('xtattachments', $attacharray, 'aid=' . $prevattach['aid']);
        $attacharray['aid'] = $prevattach['aid'];
        // and finally, delete old attachment
        xthreads_rm_attach_fs($prevattach);
        $new_file = $path . $month_dir . $filename;
    } else {
        $attacharray['aid'] = xthreads_db_insert('xtattachments', $attacharray);
        // now that we have the aid, move the file
        $new_file = $path . $month_dir . 'file_' . $attacharray['aid'] . '_' . $basename;
        @rename($path . $month_dir . $filename, $new_file);
        if (!file_exists($new_file)) {
            // oh dear, all our work for nothing...
            @unlink($path . $month_dir . $filename);
            $db->delete_query('xtattachments', 'aid=' . $attacharray['aid']);
            @ignore_user_abort(false);
            return array('error' => $lang->error_uploadfailed . $lang->error_uploadfailed_detail . $lang->error_uploadfailed_lost);
        }
    }
    @my_chmod($new_file, '0644');
    @ignore_user_abort(false);
    if (!empty($img_dimensions) && !empty($tf['fileimgthumbs'])) {
        // generate thumbnails
        $attacharray['thumbs'] = xthreads_build_thumbnail($tf['fileimgthumbs'], $attacharray['aid'], $tf['field'], $new_file, $path, $month_dir, $img_dimensions);
        $attacharray['thumbs']['orig'] = $origdimarray;
        $attacharray['thumbs'] = serialize($attacharray['thumbs']);
    }
    return $attacharray;
}
示例#2
0
function xthreads_admin_rebuildthumbs()
{
    global $mybb, $db;
    if ($mybb->request_method == 'post') {
        if (isset($mybb->input['do_rebuildxtathumbs'])) {
            $page = (int) $mybb->input['page'];
            if ($page < 1) {
                $page = 1;
            }
            $perpage = (int) $mybb->input['xtathumbs'];
            if (!$perpage) {
                $perpage = 500;
            }
            global $lang;
            if (!$lang->xthreads_rebuildxtathumbs_nofields) {
                $lang->load('xthreads');
            }
            $thumbfields = xthreads_admin_getthumbfields();
            if (empty($thumbfields)) {
                flash_message($lang->xthreads_rebuildxtathumbs_nofields, 'error');
                admin_redirect(xthreads_admin_url('tools', 'recount_rebuild'));
                return;
            }
            $where = 'field IN ("' . implode('","', array_keys($thumbfields)) . '")';
            //  AND tid!=0
            $num_xta = $db->fetch_field($db->simple_select('xtattachments', 'count(*) as n', $where), 'n');
            @set_time_limit(1800);
            require_once MYBB_ROOT . 'inc/xthreads/xt_upload.php';
            require_once MYBB_ROOT . 'inc/xthreads/xt_updatehooks.php';
            include_once MYBB_ROOT . 'cache/xthreads_evalcache.php';
            // for thumbnail code
            $xtadir = $mybb->settings['uploadspath'] . '/xthreads_ul/';
            if ($xtadir[0] != '/') {
                $xtadir = '../' . $xtadir;
            }
            // TODO: perhaps check for absolute Windows paths as well?  but then, who uses Windows on a production server? :>
            $query = $db->simple_select('xtattachments', '*', $where, array('order_by' => 'aid', 'limit' => $perpage, 'limit_start' => ($page - 1) * $perpage));
            while ($xta = $db->fetch_array($query)) {
                // remove thumbs, then rebuild
                $name = xthreads_get_attach_path($xta);
                // unfortunately, we still need $xtadir
                if ($thumbs = @glob(substr($name, 0, -6) . '*.thumb')) {
                    foreach ($thumbs as &$thumb) {
                        @unlink($xtadir . $xta['indir'] . basename($thumb));
                    }
                }
                $thumb = xthreads_build_thumbnail($thumbfields[$xta['field']], $xta['aid'], $xta['field'], $name, $xtadir, $xta['indir']);
                // TODO: perhaps check for errors? but then, what to do?
            }
            $db->free_result($query);
            ++$page;
            check_proceed($num_xta, $page * $perpage, $page, $perpage, 'xtathumbs', 'do_rebuildxtathumbs', $lang->xthreads_rebuildxtathumbs_done);
        }
    } else {
        $GLOBALS['plugins']->add_hook('admin_formcontainer_end', 'xthreads_admin_rebuildthumbs_show');
    }
}