+<?php
+class NP_Medium extends NucleusPlugin
+{
+ private $skin = '';
+
+ public $type = '';
+
+ public $collection = '';
+ public $description = '';
+ public $filter = '';
+ public $message = '';
+
+ public $amount = 0;
+ public $media = array();
+ public $offset = 0;
+ public $prev = 0;
+ public $next = 0;
+
+ public function getName()
+ {
+ return 'Medium';
+ }
+
+ public function getAuthor()
+ {
+ return 'Sakamoto Takashi';
+ }
+
+ public function getURL()
+ {
+ return '';
+ }
+
+ public function getVersion()
+ {
+ return '0.9(beta)';
+ }
+
+ public function getMinNucleusVersion()
+ {
+ return '400';
+ }
+
+ public function getDescription()
+ {
+ return _MEDIUM_DESC;
+ }
+
+ public function supportsFeature($what)
+ {
+ return ( $what == 'SqlTablePrefix' );
+ }
+
+ public function getEventList()
+ {
+ return array('AdminPrePageHead', 'AdminTemplateExtraFields');
+ }
+
+ public function init()
+ {
+ // include translation file for this plugin
+ if ( file_exists($this->getDirectory() . 'locales/' . i18n::get_current_locale() . '.' . i18n::get_current_charset() . '.php') )
+ {
+ include_once($this->getDirectory() . 'locales/' . i18n::get_current_locale() . '.' . i18n::get_current_charset() . '.php');
+ }
+ else
+ {
+ include_once($this->getDirectory() . 'locales/en_Latn_US.UTF-8.php');
+ }
+ return;
+ }
+
+ public function install()
+ {
+ $this->createOption('collectionlist_head', 'NP_MEDIUM_COLLECTIONLIST_HEAD', 'textarea',
+ "<label for=\"media_collection\">"
+ . "<%text(_MEDIA_COLLECTION_LABEL)%>"
+ . "</label>"
+ . "<select name=\"collection\" id=\"media_collection\">\n");
+
+ $this->createOption('collectionlist_body', 'NP_MEDIUM_COLLECTIONLIST_BODY', 'textarea',
+ "<option value=\"<%name%>\" <%selected%>>"
+ . "<%desc%>"
+ . "</option>\n");
+
+ $this->createOption('collectionlist_foot', 'NP_MEDIUM_COLLECTIONLIST_FOOT', 'textarea',
+ "</select>\n");
+
+ $this->createOption('medialist_head', 'NP_MEDIUM_MEDIALIST_HEAD', 'textarea',
+ "<table frame=\"box\" rules=\"frame\" sumary=\"<%text(Media List)%>\">\n"
+ . "<caption><%text(_MEDIA_COLLECTION_LABEL)%> <%description%></caption>\n"
+ . "<thead>\n"
+ . "<tr>\n"
+ . "<th><%text(_MEDIA_MODIFIED)%></th>\n"
+ . "<th><%text(_MEDIA_FILENAME)%></th>\n"
+ . "<th><%text(_MEDIA_DIMENSIONS)%></th>\n"
+ . "</tr>\n"
+ . "</thead>\n"
+ . "<tbody>\n");
+
+ $this->createOption('medialist_body_image', 'NP_MEDIUM_MEDIALIST_BODY_IMAGE', 'textarea',
+ "<tr>\n"
+ . "<td><%timestamp%></td>\n"
+ . "<td>\n"
+ . "<a href=\"<%mediumurl%>\" onclick=\"medium.chooseImage('<%collection%>', '<%filename%>', <%width%>, <%height%>);\" title=\"<%filename%>\">\n"
+ . "<%shortfilename%>\n"
+ . "</a>\n"
+ . "(\n"
+ . "<a href=\"<%mediumurl%>\" onclick=\"window.open(this.href); return false;\" title=\"<%text(_MEDIA_VIEW_TT%>\">\n"
+ . "<%text(_MEDIA_VIEW)%>\n"
+ . "</a>\n"
+ . ")\n"
+ . "</td>\n"
+ . "<td><%width%> x <%height%></td>\n"
+ . "</tr>\n");
+
+ $this->createOption('medialist_body_other', 'NP_MEDIUM_MEDIALIST_BODY_OTHER', 'textarea',
+ "<tr>\n"
+ . "<td><%timestamp%></td>\n"
+ . "<td>\n"
+ . "<a href=\"<%mediumurl%>\" onclick=\"medium.chooseOther('<%collection%>', '<%filename%>');\" title=\"<%filename%>\">\n"
+ . "<%shortfilename%>\n"
+ . "</a>\n"
+ . "</td>\n"
+ . "<td><%size%> KB</td>\n"
+ . "</tr>\n");
+
+ $this->createOption('medialist_foot', 'NP_MEDIUM_MEDIALIST_FOOT', 'textarea',
+ "</tbody>\n"
+ . "</table>\n");
+
+ $this->createOption('medialist_blank', 'NP_MEDIUM_MEDIALIST_BLANK', 'textarea',
+ "<p>Nothing</p>\n");
+
+ return;
+ }
+
+ public function event_AdminPrePageHead($data)
+ {
+ global $CONF;
+
+ if ( !in_array($data['action'], array('createitem', 'itemedit')) )
+ {
+ return;
+ }
+
+ $data['extrahead'] .= "<script type=\"text/javascript\" src=\"{$CONF['PluginURL']}/medium/scripts/medium.js\"></script>\n"
+ . "<script type=\"text/javascript\">\n"
+ . " medium.url = '{$CONF['ActionURL']}?action=plugin&name=medium';\n"
+ . '</script>'."\n";
+
+ return;
+ }
+
+ public function doAction($type)
+ {
+ global $CONF, $DIR_MEDIA, $manager, $member;
+
+ /*
+ * defines how much media items will be shown per page. You can override this
+ * in config.php if you like. (changing it in config.php instead of here will
+ * allow your settings to be kept even after a Nucleus upgrade)
+ */
+ $CONF['MediaPerPage'] = 10;
+
+ /* include all classes */
+ if ( !class_exists('Media', FALSE) )
+ {
+ include_libs('MEDIA.php', FALSE, FALSE);
+ }
+
+ /* include all classes */
+ if ( !class_exists('BaseActions', FALSE) )
+ {
+ include_libs('BaseActions.php', FALSE, FALSE);
+ }
+
+ if ( !class_exists('MediumActions', FALSE) )
+ {
+ include($this->getDirectory() . 'MediumActions.php');
+ }
+
+ /* get skin object */
+ $skinid = $CONF['AdminSkin'];
+ if ( !Skin::existsID($skinid) )
+ {
+ echo _ERROR_SKIN;
+ exit;
+ }
+ $this->skin = new Skin($skinid, 'MediumActions', 'MediumSkin');
+
+ /* user needs to be logged in to use this */
+ if ( !$member->isLoggedIn() )
+ {
+ $this->login();
+ exit;
+ }
+
+ /* check if member is on at least one teamlist */
+ $query = 'SELECT * FROM %s WHERE tmember=%d;';
+ $query = sprintf($query, sql_table('team'), $member->getID());
+ $teams = DB::getResult($query);
+ if ( $teams->rowCount() == 0 && !$member->isAdmin() )
+ {
+ $this->error(_ERROR_DISALLOWEDUPLOAD);
+ return;
+ }
+
+ /* avoid directory travarsal and accessing invalid directory */
+ $this->collection = requestVar('collection');
+ $this->description = $this->collection;
+ if ( !$this->collection || $this->collection == $member->getID()
+ || !@is_dir("{$DIR_MEDIA}{$this->collection}") )
+ {
+ $this->collection = $member->getID();
+ $this->description = PRIVATE_COLLECTION;
+ }
+ else if ( !Media::isValidCollection($this->collection) )
+ {
+ $this->error(_ERROR_DISALLOWED);
+ return;
+ }
+
+ /* check type */
+ if ( !in_array($type, array('select', 'choose', 'upload')) )
+ {
+ $type = 'select';
+ }
+
+ /* check ticket */
+ $needless_to_check = array('select', 'choose');
+ if ( !in_array($type, $needless_to_check) )
+ {
+ if ( !$manager->checkTicket() )
+ {
+ $this->error(_ERROR_BADTICKET);
+ return;
+ }
+ }
+
+ /* processing */
+ switch ( $type )
+ {
+ case 'choose':
+ if ( !$member->isAdmin() && !$CONF['AllowUpload'] )
+ {
+ $this->error(_ERROR_DISALLOWED);
+ return;
+ }
+ $this->choose();
+ break;
+ case 'upload':
+ if ( !$member->isAdmin() && !$CONF['AllowUpload'] )
+ {
+ $this->error(_ERROR_DISALLOWED);
+ return;
+ }
+ $this->upload();
+ break;
+ case 'select':
+ default:
+ $this->select();
+ break;
+ }
+ exit;
+ }
+
+ private function select()
+ {
+ global $CONF;
+
+ $this->type = 'select';
+ $this->filter = requestVar('filter');
+
+ $media = Media::getMediaListByCollection($this->collection, $this->filter);
+
+ $this->amount = count($media);
+ $this->offset = intRequestVar('offset');
+
+ if ( $this->amount > 0 )
+ {
+ if ( ($this->offset + $CONF['MediaPerPage']) >= $this->amount )
+ {
+ $this->offset = $this->amount - $CONF['MediaPerPage'];
+ }
+
+ if ( $this->offset < 0 )
+ {
+ $this->offset = 0;
+ }
+
+ $start = $this->offset;
+ $end = $this->offset + $CONF['MediaPerPage'];
+ $next = $end;
+ $prev = $start - $CONF['MediaPerPage'];
+
+ if ( $prev < 0 )
+ {
+ $prev = 0;
+ }
+
+ if ( $end > $this->amount )
+ {
+ $end = $this->amount;
+ }
+
+ if ( $start > 0 )
+ {
+ $this->prev = $prev;
+ }
+
+ if ( $end < $this->amount )
+ {
+ $this->next = $next;
+ }
+
+ for( $index = $start; $index < $end; $index++ )
+ {
+ $this->media[] = $media[$index];
+ }
+
+ unset($media);
+ }
+
+ $this->skin->parse('fileparse', $this->getDirectory() . 'skins/select.skn');
+ return;
+ }
+
+ private function choose()
+ {
+ $this->type = 'choose';
+ $this->skin->parse('fileparse', $this->getDirectory() . 'skins/choose.skn');
+ }
+
+ private function upload()
+ {
+ global $CONF;
+
+ $this->type = 'upload';
+
+ $uploadInfo = postFileInfo('uploadfile');
+
+ $filename = $uploadInfo['name'];
+ $filetype = $uploadInfo['type'];
+ $filesize = $uploadInfo['size'];
+ $filetempname = $uploadInfo['tmp_name'];
+ $fileerror = (integer) $uploadInfo['error'];
+
+ switch ( $fileerror )
+ {
+ // include error code for debugging
+ // (see http://www.php.net/manual/en/features.file-upload.errors.php)
+ case 0: // = UPLOAD_ERR_OK
+ break;
+ case 1: // = UPLOAD_ERR_INI_SIZE
+ case 2: // = UPLOAD_ERR_FORM_SIZE
+ $this->error(_ERROR_FILE_TOO_BIG);
+ return;
+ case 3: // = UPLOAD_ERR_PARTIAL
+ case 4: // = UPLOAD_ERR_NO_FILE
+ case 6: // = UPLOAD_ERR_NO_TMP_DIR
+ case 7: // = UPLOAD_ERR_CANT_WRITE
+ default:
+ $this->error(_ERROR_BADREQUEST . ' (' . $fileerror . ')');
+ return;
+ }
+
+ if ( $filesize > $CONF['MaxUploadSize'] )
+ {
+ $this->error(_ERROR_FILE_TOO_BIG);
+ return;
+ }
+
+ // check file type against allowed types
+ $ok = 0;
+ $allowedtypes = preg_split('#,#', $CONF['AllowedTypes']);
+ foreach ( $allowedtypes as $type )
+ {
+ if ( preg_match("#.{$type}$#i", $filename) )
+ {
+ $ok = 1;
+ }
+ }
+ if ( !$ok )
+ {
+ $this->error(_ERROR_BADFILETYPE);
+ return;
+ }
+
+ if ( !is_uploaded_file($filetempname) )
+ {
+ $this->error(_ERROR_BADREQUEST);
+ return;
+ }
+ // prefix filename with current date (YYYY-MM-DD-)
+ // this to avoid nameclashes
+ if ( $CONF['MediaPrefix'] )
+ {
+ $filename = i18n::formatted_datetime("%Y%m%d-", time()) . $filename;
+ }
+
+ $res = Media::addMediaObject($this->collection, $filetempname, $filename);
+
+ if ( $res != '' )
+ {
+ $this->error($res);
+ return;
+ }
+
+ $this->select();
+ return;
+ }
+
+ private function login()
+ {
+ $this->type = 'login';
+ $this->skin->parse('fileparse', $this->getDirectory() . 'skins/login.skn');
+ return;
+ }
+
+ private function error($msg)
+ {
+ $this->type = 'error';
+ $this->message = $msg;
+ $this->skin->parse('fileparse', $this->getDirectory() . 'skins/error.skn');
+ return;
+ }
+}