<?php
/*======================================================================*\
|| #################################################################### ||
|| # vBulletin 4.0.5
|| # ---------------------------------------------------------------- # ||
|| # Copyright ©2000-2010 vBulletin Solutions Inc. All Rights Reserved. ||
|| # This file may not be redistributed in whole or significant part. # ||
|| # ---------------- VBULLETIN IS NOT FREE SOFTWARE ---------------- # ||
|| # http://www.vbulletin.com | http://www.vbulletin.com/license.html # ||
|| #################################################################### ||
\*======================================================================*/
if (!isset($GLOBALS['vbulletin']->db))
{
exit;
}
/**
* Single attachment display class
*
* @package vBulletin
* @version $Revision: 37230 $
* @date $Date: 2010-05-28 11:50:59 -0700 (Fri, 28 May 2010) $
*
*/
class vB_Attachment_Display_Single_Library
{
/**
* Singleton emulation
*
*/
private static $instance = null;
/**
* Select library
*
* @param vB_Registry Instance of the vBulletin data registry object - expected to have the database object as one of its $this->db member.
* @param integer Unique id of this contenttype (forum post, blog entry, etc)
* @param boolean Display thumbnail
* @param integer Unique id of this item attachment.attachmentid
*
* @return object
*/
public static function &fetch_library(&$registry, $contenttypeid, $thumbnail, $attachmentid)
{
if (self::$instance)
{
return self::$instance;
}
require_once(DIR . '/includes/class_bootstrap_framework.php');
require_once(DIR . '/vb/types.php');
vB_Bootstrap_Framework::init();
$types = vB_Types::instance();
$attachmentinfo = array();
if (!$contenttypeid)
{
// Send the contenttypeid into fetch_library to avoid this query!
$contentinfo = $registry->db->query_first_slave("
SELECT a.contenttypeid
FROM " . TABLE_PREFIX . "attachment AS a
WHERE a.attachmentid = $attachmentid
");
$contenttypeid = $contentinfo['contenttypeid'];
}
if (!($contenttypeid = $types->getContentTypeID($contenttypeid)))
{
return false;
}
$package = $types->getContentTypePackage($contenttypeid);
$class = $types->getContentTypeClass($contenttypeid);
$selectclass = "vB_Attachment_Display_Single_{$package}_{$class}";
include_once(DIR . '/packages/' . strtolower($package) . '/attach/' . strtolower($class) . '.php');
if (class_exists($selectclass))
{
self::$instance = new $selectclass($registry, $attachmentid, $thumbnail);
}
else
{
return false;
}
return self::$instance;
}
}
/**
* Abstracted Attachment display class
*
* @package vBulletin
* @version $Revision: 37230 $
* @date $Date: 2010-05-28 11:50:59 -0700 (Fri, 28 May 2010) $
*
* @abstract
*/
abstract class vB_Attachment_Display_Single
{
/**
* Main data registry
*
* @var vB_Registry
*/
protected $registry = null;
/**
* Attachmentid
*
* @var Integer
*/
protected $attachmentid = 0;
/**
* Display thumbnail
*
* @var bool
*/
protected $thumbnail = false;
/**
* Attachment information
*
* @var Array
*/
protected $attachmentinfo = array();
/**
* Browsing information for WOL
*
* @var Array
*/
protected $browsinginfo = array();
/**
* Constructor
*
* @param vB_Registry Instance of the vBulletin data registry object - expected to have the database object as one of its $this->db member.
* @param integer Unique id of this item attachment.attachmentid
* @param boolean Display thumbnail
*
* @return void
*/
public function __construct(&$registry, $attachmentid, $thumbnail, $attachmentid_2 = false)
{
$this->registry =& $registry;
$this->attachmentid = $attachmentid ? $attachmentid : $attachmentid_2;
$this->thumbnail = $thumbnail;
}
/**
* Return attachmentinfo array
*
* @return array
*/
public function fetch_attachmentinfo()
{
return $this->attachmentinfo;
}
/**
* Return information used in session update to modify the session table for WOL
*
* @return array
*/
public function fetch_browsinginfo()
{
return $this->browsinginfo;
}
/**
* Verify permissions of a single attachment
*
* @return bool
*/
abstract public function verify_attachment();
/**
* Verify permissions of a single attachment
*
* @return bool
*/
protected function verify_attachment_specific($contenttype, $selectsql = array(), $joinsql = array(), $wheresql = array())
{
require_once(DIR . '/includes/class_bootstrap_framework.php');
require_once(DIR . '/vb/types.php');
vB_Bootstrap_Framework::init();
$types = vB_Types::instance();
$contenttypeid = intval($types->getContentTypeID($contenttype));
$hook_query_fields = $hook_query_joins = $hook_query_where = '';
($hook = vBulletinHook::fetch_hook('attachment_start')) ? eval($hook) : false;
$selectfields = array(
"a.userid, a.attachmentid, a.state, a.contentid, a.filename",
"fd.userid as uploader, fd.extension, fd.filedataid",
$this->thumbnail ? "fd.thumbnail_dateline AS dateline, fd.thumbnail_filesize AS filesize" : "fd.dateline, fd.filesize",
"at.extension, at.mimetype",
);
if ($selectsql)
{
$selectfields = array_merge($selectfields, $selectsql);
}
$joinfields = array(
"INNER JOIN " . TABLE_PREFIX . "filedata AS fd ON (a.filedataid = fd.filedataid)",
"LEFT JOIN " . TABLE_PREFIX . "attachmenttype AS at ON (at.extension = fd.extension)",
);
if ($joinsql)
{
$joinfields = array_merge($joinfields, $joinsql);
}
$wherefields = array(
"a.attachmentid = " . intval($this->attachmentid),
"a.contenttypeid = " . intval($contenttypeid),
);
if ($wheresql)
{
$wherefields = array_merge($wherefields , $wheresql);
}
if (!($this->attachmentinfo = $this->registry->db->query_first_slave("
SELECT
" . implode(",\r\n", $selectfields) . "
$hook_query_fields
FROM " . TABLE_PREFIX . "attachment AS a
" . implode("\r\n", $joinfields) . "
$hook_query_joins
WHERE " . implode(" AND ", $wherefields) . "
$hook_query_where
")))
{
return false;
}
else
{
return true;
}
}
}
/**
* Multiple attachment display class
*
* @package vBulletin
* @version $Revision: 37230 $
* @date $Date: 2010-05-28 11:50:59 -0700 (Fri, 28 May 2010) $
*
*/
class vB_Attachment_Display_Multiple
{
/**
* Main data registry
*
* @var vB_Registry
*/
protected $registry = null;
/**
* Content Type classes
*
* @var Array
*/
protected $contentref = array();
/**
*
*
* @var boolean
*/
public $usable = true;
/**
* Constructor
* Sets registry
*
* @param vB_Registry
*
* @return void
*/
public function __construct(&$registry)
{
$this->registry =& $registry;
if (!is_subclass_of($this, 'vB_Attachment_Display_Multiple'))
{
require_once(DIR . "/includes/class_bootstrap_framework.php");
vB_Bootstrap_Framework::init();
$indexed_types = array();
$collection = new vB_Collection_ContentType();
$collection->filterAttachable(true);
foreach ($collection AS $type)
{
$value['package'] = $type->getPackageClass();
$value['class'] = $type->getClass();
$indexed_types[$type->getID()] = $value;
}
foreach ($indexed_types AS $contenttypeid => $content)
{
$selectclass = "vB_Attachment_Display_Multiple_{$content['package']}_{$content['class']}";
//we check if the class exists, but also don't want warnings if the content file exists.
$include_file = DIR . '/packages/' . strtolower($content['package']) . '/attach/' . strtolower($content['class']) . '.php';
if (!file_exists($include_file))
{
continue;
}
include_once($include_file);
if (!class_exists($selectclass))
{
continue;
}
$this->contentref["$contenttypeid"] = new $selectclass($this->registry, $contenttypeid);
if (!$this->contentref["$contenttypeid"]->usable)
{
unset($this->contentref["$contenttypeid"]);
}
}
}
}
/**
* Fetches the aggregate results of an attachment query
*
* @param string SQL WHERE criteria
* @param boolean Return the total count and filesize instead of a list of attachments
* @param integer Offset to return results from
* @param integer Number of attachments to return - 0 to disable
* @param string SQL order by
* @param string SQL sort order
*
* @return array
*/
public function fetch_results($criteria, $countonly = false, $start = 0, $limit = 25, $orderby = 'displayorder', $sortorder = 'DESC')
{
$unionsql = array();
$classes = array();
$this->criteria = $criteria;
if (!$countonly)
{
$selectfieldssql = array(
'a.attachmentid',
'a.contenttypeid',
'a.displayorder',
);
switch($orderby)
{
case 'filesize':
$selectfieldssql[] = "fd.filesize";
break;
case 'state':
case 'dateline':
case 'filename':
case 'counter':
$selectfieldssql[] = "a.$orderby";
break;
case 'username':
$selectfieldssql[] = "user.username";
break;
}
$selectfields = implode(', ', $selectfieldssql);
}
else
{
$selectfields = "COUNT(*) AS count, SUM(fd.filesize) AS sum";
}
foreach ($this->contentref AS $contentref)
{
$unionsql[] = $contentref->fetch_sql_ids($criteria, $selectfields);
}
$sql = array(
"(" . implode(") UNION ALL (", $unionsql) . ")"
);
if (!$countonly)
{
$sql[] = "ORDER BY $orderby $sortorder";
if ($limit)
{
$sql[] = "LIMIT $start, $limit";
}
}
$results = $this->registry->db->query_read_slave(implode("\r\n", $sql));
if ($countonly)
{
$attachdata = $this->registry->db->query_first("
SELECT SUM(filesize) AS sum
FROM
(
SELECT DISTINCT fd.filedataid, fd.filesize
FROM " . TABLE_PREFIX . "attachment AS a
INNER JOIN " . TABLE_PREFIX . "filedata AS fd ON (fd.filedataid = a.filedataid)
WHERE
$criteria
) AS x
");
$count = 0;
$sum = 0;
// simulate query_first
while ($result = $this->registry->db->fetch_array($results))
{
$count += $result['count'];
$sum += $result['sum'];
}
return array('count' => $count, 'sum' => $sum, 'uniquesum' => $attachdata['sum']);
}
else
{
$bycontent = $byorder = array();
while ($result = $this->registry->db->fetch_array($results))
{
$bycontent["$result[contenttypeid]"]["$result[attachmentid]"] = $result['attachmentid'];
$byorder["$result[attachmentid]"] = 1;
}
foreach ($bycontent AS $contenttypeid => $attachmentids)
{
$attachments = $this->contentref["$contenttypeid"]->fetch_sql($attachmentids);
while ($attach = $this->registry->db->fetch_array($attachments))
{
$byorder["$attach[attachmentid]"] = $attach;
}
}
return $byorder;
}
}
protected function fetch_sql_specific($attachmentids, $selectsql = array(), $joinsql = array())
{
$selectfields = array(
"fd.filesize AS size, fd.thumbnail_filesize, IF(fd.thumbnail_filesize > 0, 1, 0) AS hasthumbnail, fd.filesize, fd.thumbnail_dateline, fd.thumbnail_width, fd.thumbnail_height",
"a.filename, a.counter, a.userid, a.attachmentid, a.dateline, a.contenttypeid, a.contentid, IF(a.contentid = 0, 1, 0) AS inprogress, a.state, a.caption",
);
if ($selectsql)
{
$selectfields = array_merge($selectfields, $selectsql);
}
$attachments = $this->registry->db->query_read_slave("
SELECT
" . implode(",\r\n", $selectfields) . "
FROM " . TABLE_PREFIX . "attachment AS a
INNER JOIN " . TABLE_PREFIX . "filedata AS fd ON (a.filedataid = fd.filedataid)
" . (!empty($joinsql) ? implode("\r\n", $joinsql) : "") . "
WHERE
a.attachmentid IN (" . implode(", ", $attachmentids) . ")
");
return $attachments;
}
protected function fetch_sql_ids_specific($contenttypeid, $criteria, $selectfields, $subwheresql = array(), $joinsql = array())
{
if (empty($subwheresql))
{
$subwheresql[] = "a.contentid <> 0";
}
$wheresql = array(
"a.contenttypeid = $contenttypeid",
"
(
(
a.contentid = 0
AND
a.userid = {$this->registry->userinfo['userid']}
)
OR
(
" . implode(" AND ", $subwheresql) . "
)
)
",
);
if ($criteria)
{
$wheresql[] = $criteria;
}
return "
SELECT
$selectfields
FROM " . TABLE_PREFIX . "attachment AS a
INNER JOIN " . TABLE_PREFIX . "filedata AS fd ON (a.filedataid = fd.filedataid)
LEFT JOIN " . TABLE_PREFIX . "attachmenttype AS at ON (at.extension = fd.extension)
" . (!empty($joinsql) ? implode("\r\n", $joinsql) : "") . "
WHERE
" . implode(" AND ", $wheresql) . "
";
}
/**
* Return content specific template for displaying results in aggregate view
*
* @param array Attachment information
*
* @return string
*/
public function process_attachment($attachment, $showthumbs = false)
{
global $show;
$show['moderated'] = ($attachment['state'] == 'moderation');
$attachment['filename'] = htmlspecialchars_uni($attachment['filename']);
$attachment['counter'] = vb_number_format($attachment['counter']);
$attachment['size'] = vb_number_format($attachment['size'], 1, true);
$attachment['postdate'] = vbdate($this->registry->options['dateformat'], $attachment['dateline'], true);
$attachment['posttime'] = vbdate($this->registry->options['timeformat'], $attachment['dateline']);
$attachment['attachmentextension'] = strtolower(file_extension($attachment['filename']));
$result = $this->contentref["$attachment[contenttypeid]"]->process_attachment_template($attachment, $showthumbs);
if ($show['candelete'] OR $show['canmoderate'])
{
$show['inlinemod'] = true;
}
return $result;
}
/**
* Return content specific url to the owner (post, entry) of an attachment
*
* @param array Content information
* @param string Prefix for url if we don't have "http(s)"
*
* @return string
*/
public function fetch_content_url($contentinfo, $prefix = null)
{
$url = $this->contentref["$contentinfo[contenttypeid]"]->fetch_content_url_instance($contentinfo);
if ($prefix AND !preg_match('#^https?://#si', $url))
{
return $prefix . $url;
}
return $url;
}
}
// #######################################################################
// ############################# STORAGE #################################
// #######################################################################
/**
* Attachment Storage class
*
* @package vBulletin
* @version $Revision: 37230 $
* @date $Date: 2010-05-28 11:50:59 -0700 (Fri, 28 May 2010) $
*
*/
class vB_Attachment_Store_Library
{
/**
* Singleton emulation
*
*/
private static $instance = null;
/**
* Select library
*
* @return object
*/
public static function &fetch_library(&$registry, $contenttypeid, $categoryid, $values)
{
if (self::$instance)
{
return self::$instance;
}
require_once(DIR . '/includes/class_bootstrap_framework.php');
require_once(DIR . '/vb/types.php');
vB_Bootstrap_Framework::init();
$types = vB_Types::instance();
if (!($contenttypeid = $types->getContentTypeID($contenttypeid)))
{
return false;
}
$package = $types->getContentTypePackage($contenttypeid);
$class = $types->getContentTypeClass($contenttypeid);
$selectclass = "vB_Attachment_Store_{$package}_{$class}";
include_once(DIR . '/packages/' . strtolower($package) . '/attach/' . strtolower($class) . '.php');
if (class_exists($selectclass))
{
self::$instance = new $selectclass($registry, $contenttypeid, $categoryid, $values);
}
else
{
exit;
return false;
}
return self::$instance;
}
}
/**
* Abstracted Attachment storage class
*
* @package vBulletin
* @version $Revision: 37230 $
* @date $Date: 2010-05-28 11:50:59 -0700 (Fri, 28 May 2010) $
*
* @abstract
*/
abstract class vB_Attachment_Store
{
/**
* Main data registry
*
* @var vB_Registry
*/
protected $registry = null;
/**
* Array of information specific to this contenttype, needed for permisson checks, etc
*
* @var array
*/
protected $values = array();
/**
* contentypeid of this object
*
* @var integer
*/
private $contenttypeid = 0;
/**
* contentid of the attachment owner
*
* @var integer
*/
protected $contentid = 0;
/**
* Username of content owner
*
* @var string
*/
protected $content_owner = '';
/**
* Attachment count of this content object
*
* @var integer
*/
protected $attachcount = 0;
/**
* Override the vboption for thumbnails
*
* @var boolean
*/
public $forcethumbnail = false;
/**
* Upload errors
*
* @var array
*/
public $errors = array();
/**
* Userinfo of owner of content
*
* @var array
*/
public $userinfo = array();
/**
* Constructor
* Sets registry
*
* @return void
*/
public function __construct(&$registry, $contenttypeid, $categoryid, $values)
{
$this->registry =& $registry;
$this->values = $values;
$this->userinfo = $this->registry->userinfo;
$this->contenttypeid = $contenttypeid;
$this->categoryid = $categoryid;
}
/**
* Verify permissions
*
* @return bool
*/
abstract protected function verify_permissions();
/**
* Verify amount of attachments has not exceed maximum number based on permissions
* - defaulting to 'Post' type permissions, but can be overidden by subclasses
*
* @param array Attachment information
*
* @return bool true if we are under the limit
*/
protected function verify_max_attachments($attachment)
{
global $vbphrase;
if ($this->registry->options['attachlimit'] AND $this->attachcount > $this->registry->options['attachlimit'])
{
$error = construct_phrase($vbphrase['you_may_only_attach_x_files_per_post'], $this->registry->options['attachlimit']);
$this->errors[] = array(
'filename' => is_array($attachment) ? $attachment['name'] : $attachment,
'error' => $error
);
return false;
}
return true;
}
/**
* Count new and pre-existing attachments
*
* @return bool
*/
public function fetch_attachcount()
{
$currentattaches = $this->registry->db->query_first("
SELECT COUNT(*) AS count
FROM " . TABLE_PREFIX . "attachment
WHERE
posthash = '" . $this->registry->db->escape_string($this->values['posthash']) . "'
AND
contenttypeid = " . $this->contenttypeid . "
" . ($this->contentid ? " AND contentid = 0 " : "") . "
");
$this->attachcount = $currentattaches['count'];
if ($this->contentid)
{
$currentattaches = $this->registry->db->query_first("
SELECT COUNT(*) AS count
FROM " . TABLE_PREFIX . "attachment
WHERE
contentid = " . $this->contentid . "
AND
contenttypeid = " . $this->contenttypeid . "
");
$this->attachcount += $currentattaches['count'];
$show['postowner'] = true;
}
else
{
$show['postowner'] = false;
}
return true;
}
/**
* Fetch new and pre-existing attachments
*
* @return object
*/
public function fetch_attachments()
{
$attachments = $this->registry->db->query_read(
($this->contentid ? "(" : "") .
"SELECT
a.contentid, a.dateline, a.filename, a.attachmentid, a.userid, a.displayorder,
fd.filesize, IF(fd.thumbnail_filesize > 0, 1, 0) AS hasthumbnail, fd.filedataid, fd.userid AS fuserid, fd.extension,
fd.width, fd.height, fd.thumbnail_width, fd.thumbnail_height, fd.thumbnail_dateline
FROM " . TABLE_PREFIX . "attachment AS a
INNER JOIN " . TABLE_PREFIX . "filedata AS fd ON (a.filedataid = fd.filedataid)
WHERE
a.posthash = '" . $this->registry->db->escape_string($this->values['posthash']) . "'
AND
a.contenttypeid = " . intval($this->contenttypeid) . "
" . ($this->contentid ? ") UNION (" : "") . "
" . ($this->contentid ? "
SELECT
a.contentid, a.dateline, a.filename, a.attachmentid, a.userid, a.displayorder,
fd.filesize, IF(fd.thumbnail_filesize > 0, 1, 0) AS hasthumbnail, fd.filedataid, fd.userid AS fuserid, fd.extension,
fd.width, fd.height, fd.thumbnail_width, fd.thumbnail_height, fd.thumbnail_dateline
FROM " . TABLE_PREFIX . "attachment AS a
INNER JOIN " . TABLE_PREFIX . "filedata AS fd ON (a.filedataid = fd.filedataid)
WHERE
a.contentid = " . intval($this->contentid) . "
AND
a.contenttypeid = " . intval($this->contenttypeid) . "
)
" : "") . "
ORDER BY displayorder
");
return $attachments;
}
public function delete($ids)
{
if (!empty($ids))
{
$attachdata =& datamanager_init('Attachment', $this->registry, ERRTYPE_STANDARD, 'attachment');
$attachids = array_map('intval', array_keys($ids));
$condition = array(
"a.attachmentid IN (" . implode(", ", $attachids) . ")",
"a.contenttypeid = " . intval($this->contenttypeid),
);
if ($this->contentid)
{
$condition[] = "(a.contentid = " . intval($this->contentid) . " OR a.posthash = '" . $this->registry->db->escape_string($this->values['posthash']) . "')";
}
else
{
$condition[] = "a.posthash = '" . $this->registry->db->escape_string($this->values['posthash']) . "'";
}
$attachdata->condition = implode(" AND ", $condition);
$attachdata->delete(true, false);
unset($attachdata);
}
}
public function upload($files, $urls, $filedata, $imageonly = false)
{
$errors = array();
require_once(DIR . '/includes/class_upload.php');
require_once(DIR . '/includes/class_image.php');
// check for any funny business
$filecount = 1;
if (!empty($files['tmp_name']))
{
foreach ($files['tmp_name'] AS $filename)
{
if (!empty($filename))
{
if ($filecount > $this->registry->options['attachboxcount'])
{
@unlink($filename);
}
$filecount++;
}
}
}
// Move any urls into the attachment array if we allow url upload
if ($this->registry->options['attachurlcount'])
{
$urlcount = 1;
foreach ($urls AS $url)
{
if (!empty($url) AND $urlcount <= $this->registry->options['attachurlcount'])
{
$index = count($files['name']);
$files['name']["$index"] = $url;
$files['url']["$index"] = true;
$urlcount++;
}
}
}
if (!empty($filedata))
{
foreach($filedata AS $filedataid)
{
$index = count($files['name']);
$files['name']["$index"] = 'filedata';
$files['filedataid']["$index"] = $filedataid;
}
}
//$this->attachcount = 0;
$ids = array();
$uploadsum = count($files['name']);
for ($x = 0; $x < $uploadsum; $x++)
{
if (!$files['name']["$x"])
{
if ($files['tmp_name']["$x"])
{
@unlink($files['tmp_name']["$x"]);
}
continue;
}
$attachdata =& $this->fetch_attachdm();
$upload = new vB_Upload_Attachment($this->registry);
$upload->contenttypeid = $this->contenttypeid;
$image =& vB_Image::fetch_library($this->registry);
$upload->userinfo = $this->userinfo;
$upload->data =& $attachdata;
$upload->image =& $image;
if ($uploadsum > 1)
{
$upload->emptyfile = false;
}
if ($files['filedataid']["$x"])
{
if (!($filedatainfo = $this->registry->db->query_first_slave("
SELECT
acu.filedataid, acu.filename, fd.filehash, fd.filesize, fd.extension
FROM " . TABLE_PREFIX . "attachmentcategoryuser AS acu
INNER JOIN " . TABLE_PREFIX . "filedata AS fd ON (acu.filedataid = fd.filedataid)
WHERE
acu.filedataid = " . intval($files['filedataid']["$x"]) . "
AND
acu.userid = " . $this->registry->userinfo['userid'] . "
")))
{
$this->errors[] = array(
'filename' => "",
'error' => fetch_error('invalid_filedataid_x', $files['filedataid']["$x"])
);
continue;
}
$attachment = array(
'filedataid' => $files['filedataid']["$x"],
'name' => $filedatainfo['filename'],
'filehash' => $filedatainfo['filehash'],
'filesize' => $filedatainfo['filesize'],
'extension' => $filedatainfo['extension'],
'filename' => $filedatainfo['filename']
);
}
else if ($files['url']["$x"])
{
$attachment = $files['name']["$x"];
}
else
{
$attachment = array(
'name' => $files['name']["$x"],
'tmp_name' => $files['tmp_name']["$x"],
'error' => $files['error']["$x"],
'size' => $files['size']["$x"],
'utf8_name' => $files['utf8_names']
);
}
$this->attachcount++;
$ids[] = $this->process_upload($upload, $attachment, $imageonly);
}
return implode(',', $ids);
}
protected function &fetch_attachdm()
{
// here we call the attach/file data combined dm
$attachdata =& datamanager_init('AttachmentFiledata', $this->registry, ERRTYPE_ARRAY, 'attachment');
$attachdata->set('contenttypeid', $this->contenttypeid);
$attachdata->set('posthash', $this->values['posthash']);
$attachdata->set_info('contentid', $this->contentid);
$attachdata->set_info('categoryid', $this->categoryid);
$attachdata->set('state', 'visible');
return $attachdata;
}
protected function process_upload($upload, $attachment, $imageonly = false)
{
// first verify maximum number of attachments has not been reached
if (!$this->verify_max_attachments($attachment))
{
return false;
}
// process the upload
if (!($attachmentid = $upload->process_upload($attachment, $this->forcethumbnail, $imageonly)))
{
$this->attachcount--;
}
// add any upload errors to the error array
if ($error = $upload->fetch_error())
{
$this->errors[] = array(
'filename' => is_array($attachment) ? $attachment['name'] : $attachment,
'error' => $error,
);
}
return $attachmentid;
}
}
/**
* Class for initiating proper subclass to extende attachment DM operations
*
* @package vBulletin
* @version $Revision: 37230 $
* @date $Date: 2010-05-28 11:50:59 -0700 (Fri, 28 May 2010) $
*
*/
class vB_Attachment_Dm_Library
{
/**
* Select library
*
* @param vB_Registry Instance of the vBulletin data registry object - expected to have the database object as one of its $this->db member.
* @param integer Unique id of this contenttype (forum post, blog entry, etc)
*
* @return object
*/
public static function &fetch_library(&$registry, $contenttypeid)
{
static $instance;
if (!$instance["$contenttypeid"])
{
require_once(DIR . '/includes/class_bootstrap_framework.php');
require_once(DIR . '/vb/types.php');
vB_Bootstrap_Framework::init();
$types = vB_Types::instance();
if (!($contenttypeid = $types->getContentTypeID($contenttypeid)))
{
return false;
}
$package = $types->getContentTypePackage($contenttypeid);
$class = $types->getContentTypeClass($contenttypeid);
$selectclass = "vB_Attachment_Dm_{$package}_{$class}";
include_once(DIR . '/packages/' . strtolower($package) . '/attach/' . strtolower($class) . '.php');
if (class_exists($selectclass))
{
$instance["$contenttypeid"] = new $selectclass($registry, $contenttypeid);
}
else
{
return false;
}
}
return $instance["$contenttypeid"];
}
}
/**
* Abstract class for attachment dm operation across content types
*
* @package vBulletin
* @version $Revision: 37230 $
* @date $Date: 2010-05-28 11:50:59 -0700 (Fri, 28 May 2010) $
*
*/
abstract class vB_Attachment_Dm
{
/**
* Main data registry
*
* @var vB_Registry
*/
protected $registry = null;
/**
* Lists of data
*
* @var Array
*/
protected $lists = array();
/**
* Constructor - checks that the registry object has been passed correctly.
*
* @param vB_Registry Instance of the vBulletin data registry object - expected to have the database object as one of its $this->db member.
*/
public function __construct(&$registry, $contenttypeid)
{
$this->registry =& $registry;
$this->contenttypeid = $contenttypeid;
}
/**
* post save function - extend if the contenttype needs to do anything
*
* @param
*/
public function post_save_each()
{
return true;
}
/**
* pre_delete function - extend if the contenttype needs to do anything
*
* @param array list of deleted attachment ids that belong to a specific
*/
public function pre_delete($list)
{
return true;
}
/**
* post_delete function - extend if the contenttype needs to do anything
*
* @param array list of deleted attachment ids that belong to a specific
*/
public function post_delete()
{
return true;
}
/**
* pre_unapprove function - extend if the contenttype needs to do anything
*
* @param array list of unapproved attachment ids that belong to a specific
*/
public function pre_unapprove($list)
{
return true;
}
/**
* post_unapprove function - extend if the contenttype needs to do anything
*
* @param array list of unapproved attachment ids that belong to a specific
*/
public function post_unapprove()
{
return true;
}
/**
* pre_approve function - extend if the contenttype needs to do anything
*
* @param array list of approved attachment ids that belong to a specific
*/
public function pre_approve($list)
{
return true;
}
/**
* post_approve function - extend if the contenttype needs to do anything
*
* @param array list of approved attachment ids that belong to a specific
*/
public function post_approve()
{
return true;
}
}
class vB_Attachment_Upload_Displaybit_Library
{
/**
* Singleton emulation
*
*/
private static $instance = null;
/**
* Select library
*
* @return object
*/
public static function &fetch_library(&$registry, $contenttypeid)
{
if (self::$instance)
{
return self::$instance;
}
require_once(DIR . '/includes/class_bootstrap_framework.php');
require_once(DIR . '/vb/types.php');
vB_Bootstrap_Framework::init();
$types = vB_Types::instance();
if (!($contenttypeid = $types->getContentTypeID($contenttypeid)))
{
return false;
}
$package = $types->getContentTypePackage($contenttypeid);
$class = $types->getContentTypeClass($contenttypeid);
$selectclass = "vB_Attachment_Upload_Displaybit_{$package}_{$class}";
include_once(DIR . '/packages/' . strtolower($package) . '/attach/' . strtolower($class) . '.php');
if (class_exists($selectclass))
{
self::$instance = new $selectclass($registry, $contenttypeid);
}
else
{
return false;
}
return self::$instance;
}
}
/**
* Abstract class for updating the display of the calling window during uploads
*
* @package vBulletin
* @version $Revision: 37230 $
* @date $Date: 2010-05-28 11:50:59 -0700 (Fri, 28 May 2010) $
*
*/
abstract class vB_Attachment_Upload_Displaybit
{
/**
* Main data registry
*
* @var vB_Registry
*/
protected $registry = null;
/**
* Constructor - checks that the registry object has been passed correctly.
*
* @param vB_Registry Instance of the vBulletin data registry object - expected to have the database object as one of its $this->db member.
*/
public function __construct(&$registry)
{
$this->registry =& $registry;
}
/**
* Parses the appropriate template for contenttype that is to be updated on the calling window during an upload
*
* @param array Attachment information
* @param array Values array pertaining to contenttype
* @param boolean Disable template comments
*
* @return string
*/
abstract public function process_display_template($attach, $values = array(), $disablecomment = false);
/**
*
*
* @param array Attachment information
* @param boolean Add window.opener to call
*
* @return string
*/
public function construct_attachment_add_js($attachment, $addopener = false)
{
$attachment['extension'] = strtolower(file_extension($attachment['filename']));
$attachment['filename'] = htmlspecialchars_uni($attachment['filename']);
return ($addopener ? "window.opener." : "") . "vB_Attachments.add($attachment[attachmentid], \"" . addslashes(str_replace(array("\r", "\n"), '', $attachment['html'])) . "\", '" . addslashes_js($attachment['filename']) . "', '" . addslashes_js($attachment['filesize']) . "', '$stylevar[imgdir_attach]/$attachment[extension].gif');\n";
}
}
/**
* Class for common attachment tasks that are content agnostic
*
* @package vBulletin
* @version $Revision: 37230 $
* @date $Date: 2010-05-28 11:50:59 -0700 (Fri, 28 May 2010) $
*
*/
class vB_Attach_Display_Content
{
/**
* Main data registry
*
* @var vB_Registry
*/
protected $registry = null;
/**
* Contenttype id
*
* @var integer
*/
protected $contenttypeid = 0;
/**
* Constructor - checks that the registry object has been passed correctly.
*
* @param vB_Registry Instance of the vBulletin data registry object - expected to have the database object as one of its $this->db member.
* @param string Contenttype
*/
public function __construct(&$registry, $contenttype)
{
$this->registry =& $registry;
require_once(DIR . '/includes/class_bootstrap_framework.php');
vB_Bootstrap_Framework::init();
$this->contenttypeid = vB_Types::instance()->getContentTypeID($contenttype);
}
/**
* Fetches the contenttypeid
*
* @return integer
*/
public function fetch_contenttypeid()
{
return $this->contenttypeid;
}
/**
* Fetches a list of attachments for display on edit or preview
*
* @param string Posthash of this edit/add
* @param integer Start time of this edit/add
* @param array Combined existing and new attachments belonging to this content
* @param integer id of attachments owner
* @param string Content specific values that need to be passed on to the attachment form
* @param string $editorid of the message editor on the page that launched the asset manager
* @param integer Number of fetched attachments, set by this function
* @param mixed Who can view an attachment with no contentid (in progress), other than vbulletin->userinfo
*
* @return string
*/
public function fetch_edit_attachments(&$posthash, &$poststarttime, &$postattach, $contentid, $values, $editorid, &$attachcount, $users = null)
{
global $show;
require_once(DIR . '/includes/functions_file.php');
$inimaxattach = fetch_max_upload_size();
$maxattachsize = vb_number_format($inimaxattach, 1, true);
$attachcount = 0;
$attachment_js = '';
if (!$posthash OR !$poststarttime)
{
$poststarttime = TIMENOW;
$posthash = md5($poststarttime . $this->registry->userinfo['userid'] . $this->registry->userinfo['salt']);
}
if (empty($postattach))
{
$postattach = $this->fetch_postattach($posthash, $contentid, $users);
}
if (!empty($postattach))
{
$attachdisplaylib =& vB_Attachment_Upload_Displaybit_Library::fetch_library($this->registry, $this->contenttypeid);
foreach($postattach AS $attachmentid => $attach)
{
$attachcount++;
$attach['html'] = $attachdisplaylib->process_display_template($attach, $values);
$attachments .= $attach['html'];
$show['attachmentlist'] = true;
$attachment_js .= $attachdisplaylib->construct_attachment_add_js($attach);
}
}
$templater = vB_Template::create('newpost_attachment');
$templater->register('attachments', $attachments);
$templater->register('attachment_js', $attachment_js);
$templater->register('editorid', $editorid);
$templater->register('posthash', $posthash);
$templater->register('contentid', $contentid);
$templater->register('poststarttime', $poststarttime);
$templater->register('attachuserid', $this->registry->userinfo['userid']);
$templater->register('contenttypeid', $this->contenttypeid);
$templater->register('values', $values);
return $templater->render();
}
/**
* Constructor - checks that the registry object has been passed correctly.
*
* @param string Posthash of this edit/add
* @param integer id of attachments owner
* @param mixed Who can view an attachment with no contentid (in progress), other than vbulletin->userinfo
*
* @return array
*/
public function fetch_postattach($posthash = 0, $contentid = 0, $users = null)
{
// if we were passed no information, simply return an empty array
// to avoid a nasty database error
if (empty($posthash) AND empty($contentid))
{
return array();
}
if (!$users)
{
$users = array($this->registry->userinfo['userid']);
}
else
{
if (is_array($users))
{
$temp = array_map("intval", $users);
$users = $temp;
}
else if ($userid = intval($users))
{
$users = array($userid);
}
$users[] = $this->registry->userinfo['userid'];
}
$union = array();
if ($contentid)
{
if (is_array($contentid))
{
$sql = "a.contentid IN (" . implode(",", $contentid) . ")";
}
else
{
$sql = "a.contentid = " . intval($contentid);
}
$union[] = "
SELECT
fd.thumbnail_dateline, fd.filesize, IF(fd.thumbnail_filesize > 0, 1, 0) AS hasthumbnail, fd.thumbnail_filesize,
a.dateline, a.state, a.attachmentid, a.counter, a.contentid, a.filename, a.userid, a.settings, a.displayorder,
at.contenttypes
FROM " . TABLE_PREFIX . "attachment AS a
INNER JOIN " . TABLE_PREFIX . "filedata AS fd ON (fd.filedataid = a.filedataid)
LEFT JOIN " . TABLE_PREFIX . "attachmenttype AS at ON (at.extension = fd.extension)
WHERE
$sql
AND
a.contenttypeid = " . $this->contenttypeid . "
";
}
if ($posthash)
{
$union[] = "
SELECT
fd.thumbnail_dateline, fd.filesize, IF(fd.thumbnail_filesize > 0, 1, 0) AS hasthumbnail, fd.thumbnail_filesize,
a.dateline, a.state, a.attachmentid, a.counter, a.contentid, a.filename, a.userid, a.settings, a.displayorder,
at.contenttypes
FROM " . TABLE_PREFIX . "attachment AS a
INNER JOIN " . TABLE_PREFIX . "filedata AS fd ON (fd.filedataid = a.filedataid)
LEFT JOIN " . TABLE_PREFIX . "attachmenttype AS at ON (at.extension = fd.extension)
WHERE
a.posthash = '" . $this->registry->db->escape_string($posthash) . "'
AND
a.userid IN (" . implode(',', $users) . ")
AND
a.contenttypeid = " . $this->contenttypeid . "
";
}
if (count($union) > 1)
{
$unionsql = array(
"(" . implode(") UNION ALL (", $union) . ")",
"ORDER BY displayorder",
);
}
else
{
$unionsql = array(
$union[0],
"ORDER BY a.contentid, a.displayorder",
);
}
$postattach = array();
$attachments = $this->registry->db->query_read_slave(implode("\r\n", $unionsql));
while ($attachment = $this->registry->db->fetch_array($attachments))
{
$content = @unserialize($attachment['contenttypes']);
$attachment['newwindow'] = $content[$this->contenttypeid]['n'];
if (is_array($contentid))
{
$postattach["$attachment[contentid]"]["$attachment[attachmentid]"] = $attachment;
}
else
{
$postattach["$attachment[attachmentid]"] = $attachment;
}
}
return $postattach;
}
/**
* Constructor - checks that the registry object has been passed correctly.
*
* @param array Information about the content that owns these attachments
* @param array List of attachments belonging to the specifed post
* @param boolean Display download count
* @param boolean View has permissions to download attachments
* @param boolean Viewer has permission to get attachments
* @param boolean Viewer has permission to set thumbnails
*
* @return void
*/
function process_attachments(&$post, &$attachments, $hidecounter = false, $canmod = false, $canget = true, $canseethumb = true, $linkonly = false)
{
global $show, $vbphrase;
if (!empty($attachments))
{
$show['modattachmentlink'] = ($canmod OR $post['userid'] == $this->registry->userinfo['userid']);
$show['attachments'] = true;
$show['moderatedattachment'] = $show['thumbnailattachment'] = $show['otherattachment'] = false;
$show['imageattachment'] = $show['imageattachmentlink'] = false;
$attachcount = sizeof($attachments);
$thumbcount = 0;
if (!$this->registry->options['viewattachedimages'])
{
$showimagesprev = $this->registry->userinfo['showimages'];
$this->registry->userinfo['showimages'] = false;
}
foreach ($attachments AS $attachmentid => $attachment)
{
if ($attachment['thumbnail_filesize'] == $attachment['filesize'])
{
// This is an image that is already thumbnail sized..
$attachment['hasthumbnail'] = 0;
$attachment['forceimage'] = $this->registry->userinfo['showimages'];
}
else if (!$canseethumb)
{
$attachment['hasthumbnail'] = 0;
}
$show['newwindow'] = $attachment['newwindow'];
$attachment['filename'] = fetch_censored_text(htmlspecialchars_uni($attachment['filename']));
$attachment['attachmentextension'] = strtolower(file_extension($attachment['filename']));
$attachment['filesize'] = vb_number_format($attachment['filesize'], 1, true);
if (vB_Template_Runtime::fetchStyleVar('dirmark'))
{
$attachment['filename'] .= vB_Template_Runtime::fetchStyleVar('dirmark');
}
($hook = vBulletinHook::fetch_hook('postbit_attachment')) ? eval($hook) : false;
if ($attachment['state'] == 'visible')
{
if ($hidecounter)
{
$attachment['counter'] = $vbphrase['n_a'];
$show['views'] = false;
}
else
{
$show['views'] = true;
}
$lightbox_extensions = array('gif', 'jpg', 'jpeg', 'jpe', 'png', 'bmp');
$ext = $linkonly ? null : $attachment['attachmentextension'];
switch($ext)
{
case 'gif':
case 'jpg':
case 'jpeg':
case 'jpe':
case 'png':
case 'bmp':
case 'tiff':
case 'tif':
case 'psd':
case 'pdf':
if (!$this->registry->userinfo['showimages'])
{
// Special case for PDF - don't list it as an 'image'
if ($attachment['attachmentextension'] == 'pdf')
{
$templater = vB_Template::create('postbit_attachment');
$templater->register('attachment', $attachment);
$post['otherattachments'] .= $templater->render();
$show['otherattachment'] = true;
}
else
{
$templater = vB_Template::create('postbit_attachment');
$templater->register('attachment', $attachment);
$post['imageattachmentlinks'] .= $templater->render();
$show['imageattachmentlink'] = true;
}
}
else if ($this->registry->options['viewattachedimages'] == 1)
{
if ($attachment['hasthumbnail'])
{
$thumbcount++;
if ($this->registry->options['attachrow'] AND $thumbcount >= $this->registry->options['attachrow'])
{
$thumbcount = 0;
$show['br'] = true;
}
else
{
$show['br'] = false;
}
$show['cangetattachment'] = ($canget AND in_array($attachment['attachmentextension'], $lightbox_extensions));
$templater = vB_Template::create('postbit_attachmentthumbnail');
$templater->register('attachment', $attachment);
$post['thumbnailattachments'] .= $templater->render();
$show['thumbnailattachment'] = true;
}
else if (!in_array($attachment['attachmentextension'], array('tiff', 'tif', 'psd', 'pdf')) AND $attachment['forceimage'])
{
$templater = vB_Template::create('postbit_attachmentimage');
$templater->register('attachment', $attachment);
$post['imageattachments'] .= $templater->render();
$show['imageattachment'] = true;
}
else
{
// Special case for PDF - don't list it as an 'image'
if ($attachment['attachmentextension'] == 'pdf')
{
$templater = vB_Template::create('postbit_attachment');
$templater->register('attachment', $attachment);
$post['otherattachments'] .= $templater->render();
$show['otherattachment'] = true;
}
else
{
$templater = vB_Template::create('postbit_attachment');
$templater->register('attachment', $attachment);
$post['imageattachmentlinks'] .= $templater->render();
$show['imageattachmentlink'] = true;
}
}
}
else if (!in_array($attachment['attachmentextension'], array('tiff', 'tif', 'psd', 'pdf')) AND ($this->registry->options['viewattachedimages'] == 3 OR ($this->registry->options['viewattachedimages'] == 2 AND $attachcount == 1)))
{
$templater = vB_Template::create('postbit_attachmentimage');
$templater->register('attachment', $attachment);
$post['imageattachments'] .= $templater->render();
$show['imageattachment'] = true;
}
else
{
$templater = vB_Template::create('postbit_attachment');
$templater->register('attachment', $attachment);
$post['imageattachmentlinks'] .= $templater->render();
$show['imageattachmentlink'] = true;
}
break;
default:
$templater = vB_Template::create('postbit_attachment');
$templater->register('attachment', $attachment);
$post['otherattachments'] .= $templater->render();
$show['otherattachment'] = true;
}
}
else
{
$templater = vB_Template::create('postbit_attachment');
$templater->register('attachment', $attachment);
$post['moderatedattachments'] .= $templater->render();
$show['moderatedattachment'] = true;
}
}
if (!$this->registry->options['viewattachedimages'])
{
$this->registry->userinfo['showimages'] = $showimagesprev;
}
}
else
{
$show['attachments'] = false;
}
}
}
/*======================================================================*\
|| ####################################################################
|| # CVS: $RCSfile$ - $Revision: 37230 $
|| ####################################################################
\*======================================================================*/