[geeklog-cvs] geeklog: Ported plugin upload (part of Matt's GSoC project) over...
geeklog-cvs at lists.geeklog.net
geeklog-cvs at lists.geeklog.net
Sun Oct 5 09:35:57 EDT 2008
details: http://project.geeklog.net/cgi-bin/hgweb.cgi/rev/527b34a8095b
changeset: 6426:527b34a8095b
user: Dirk Haun <dirk at haun-online.de>
date: Sun Oct 05 15:35:41 2008 +0200
description:
Ported plugin upload (part of Matt's GSoC project) over from the gsoc-2008 repository
diffstat:
3 files changed, 312 insertions(+), 14 deletions(-)
language/english.php | 24 +++
language/english_utf-8.php | 24 +++
public_html/admin/plugins.php | 278 +++++++++++++++++++++++++++++++++++++++--
diffs (truncated from 392 to 300 lines):
diff -r 8a105009ba6e -r 527b34a8095b language/english.php
--- a/language/english.php Sun Oct 05 00:26:16 2008 +0200
+++ b/language/english.php Sun Oct 05 15:35:41 2008 +0200
@@ -1023,7 +1023,24 @@
35 => 'Edit',
36 => 'Code',
37 => 'Data',
- 38 => 'Update!'
+ 38 => 'Update!',
+ 39 => 'Upload a plugin',
+ 40 => 'You can upload a plugin archive (.tar.gz, .tgz, .zip) directly here:',
+ 41 => 'Upload',
+
+ // to match the PHP error constants,
+ // http://www.php.net/manual/en/features.file-upload.errors.php
+ // TBD: move to a separate $LANG array
+ 99 => 'An unknown error occured',
+ 100 => 'Ok.',
+ 101 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini.',
+ 102 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.',
+ 103 => 'The uploaded file was only partially uploaded.',
+ 104 => 'No file was uploaded.',
+ 105 => '(undefined error)',
+ 106 => 'Missing a temporary folder.',
+ 107 => 'Failed to write file to disk.',
+ 108 => 'File upload stopped by extension.'
);
###############################################################################
@@ -1182,7 +1199,10 @@
94 => 'Backup Failed: Filesize less than 1kb',
95 => 'There was an error.',
96 => 'Sorry, you do not have access to the configuration administration page. Please note that all attempts to access unauthorized features are logged.',
- 97 => 'Not all required fields have been passed validation - default custom membership message'
+ 97 => 'Not all required fields have been passed validation - default custom membership message',
+ 98 => 'The plugin was successfully uploaded.',
+ 99 => 'The plugin already exists.',
+ 100 => 'The plugin file you uploaded was not a GZip or Zip compressed archive.'
);
###############################################################################
diff -r 8a105009ba6e -r 527b34a8095b language/english_utf-8.php
--- a/language/english_utf-8.php Sun Oct 05 00:26:16 2008 +0200
+++ b/language/english_utf-8.php Sun Oct 05 15:35:41 2008 +0200
@@ -1023,7 +1023,24 @@
35 => 'Edit',
36 => 'Code',
37 => 'Data',
- 38 => 'Update!'
+ 38 => 'Update!',
+ 39 => 'Upload a plugin',
+ 40 => 'You can upload a plugin archive (.tar.gz, .tgz, .zip) directly here:',
+ 41 => 'Upload',
+
+ // to match the PHP error constants,
+ // http://www.php.net/manual/en/features.file-upload.errors.php
+ // TBD: move to a separate $LANG array
+ 99 => 'An unknown error occured',
+ 100 => 'Ok.',
+ 101 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini.',
+ 102 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.',
+ 103 => 'The uploaded file was only partially uploaded.',
+ 104 => 'No file was uploaded.',
+ 105 => '(undefined error)',
+ 106 => 'Missing a temporary folder.',
+ 107 => 'Failed to write file to disk.',
+ 108 => 'File upload stopped by extension.'
);
###############################################################################
@@ -1182,7 +1199,10 @@
94 => 'Backup Failed: Filesize less than 1kb',
95 => 'There was an error.',
96 => 'Sorry, you do not have access to the configuration administration page. Please note that all attempts to access unauthorized features are logged.',
- 97 => 'Not all required fields have been passed validation - default custom membership message'
+ 97 => 'Not all required fields have been passed validation - default custom membership message',
+ 98 => 'The plugin was successfully uploaded.',
+ 99 => 'The plugin already exists.',
+ 100 => 'The plugin file you uploaded was not a GZip or Zip compressed archive.'
);
###############################################################################
diff -r 8a105009ba6e -r 527b34a8095b public_html/admin/plugins.php
--- a/public_html/admin/plugins.php Sun Oct 05 00:26:16 2008 +0200
+++ b/public_html/admin/plugins.php Sun Oct 05 15:35:41 2008 +0200
@@ -14,6 +14,7 @@
// | Mark Limburg - mlimburg AT users DOT sourceforge DOT net |
// | Jason Whittenburg - jwhitten AT securitygeeks DOT com |
// | Dirk Haun - dirk AT haun-online DOT de |
+// | Matt West - matt AT mattdanger DOT net |
// +---------------------------------------------------------------------------+
// | |
// | This program is free software; you can redistribute it and/or |
@@ -42,10 +43,10 @@
// the data being passed in a POST operation
// echo COM_debug($_POST);
-// Number of plugins to list per page
-// We use 25 here instead of the 50 entries in other lists to leave room
-// for the list of uninstalled plugins.
-define ('PLUGINS_PER_PAGE', 25);
+// define upload error codes introduced in later PHP versions
+if (!defined('UPLOAD_ERR_NO_TMP_DIR')) { define('UPLOAD_ERR_NO_TMP_DIR', 6); }
+if (!defined('UPLOAD_ERR_CANT_WRITE')) { define('UPLOAD_ERR_CANT_WRITE', 7); }
+if (!defined('UPLOAD_ERR_EXTENSION')) { define('UPLOAD_ERR_EXTENSION', 8); }
$display = '';
@@ -433,6 +434,264 @@
return $retval;
}
+/**
+ * Check if an error occured while uploading a file
+ *
+ * @param array $mFile $_FILE['uploaded_file']
+ * @return mixed Returns the error string if an error occured,
+ * returns false if no error occured
+ *
+ */
+function plugin_getUploadError($mFile)
+{
+ global $LANG32;
+
+ $retval = '';
+
+ if (isset($mFile['error']) && ($mFile['error'] !== UPLOAD_ERR_OK)) { // If an error occured while uploading the file.
+
+ if ($mFile['error'] > UPLOAD_ERR_EXTENSION) { // If the error code isn't known
+
+ $retval = $LANG32[99]; // Unknown error
+
+ } else {
+
+ $retval = $LANG32[$mFile['error'] + 100]; // Print the error
+
+ }
+
+ } else { // If no upload error occurred
+
+ $retval = false;
+
+ }
+
+ return $retval;
+}
+
+/**
+* Check if uploads are possible
+*
+* @return boolean true: uploads possible; false: not possible
+*
+*/
+function plugin_upload_enabled()
+{
+ global $_CONF;
+
+ // If 'file_uploads' is enabled in php.ini
+ // and the plugin directories are writable by the web server.
+ $upload_enabled = (ini_get('file_uploads')
+ && is_writable($_CONF['path'] . 'plugins/')
+ && is_writable($_CONF['path_html'])
+ && is_writable($_CONF['path_html'] . 'admin/plugins/'))
+ ? true
+ : false;
+
+ return $upload_enabled;
+}
+
+/**
+* Display upload form
+*
+* @return string HTML for the upload form
+*
+*/
+function plugin_show_uploadform($token)
+{
+ global $_CONF, $LANG28, $LANG32;
+
+ $retval = '';
+
+ $retval .= COM_startBlock($LANG32[39], '',
+ COM_getBlockTemplate('_admin_block', 'header'));
+
+ // Show the upload form
+ $retval .= '<p>' . $LANG32[40] . '</p>' . LB
+ . '<form name="plugins_upload" action="' . $_CONF['site_admin_url'] . '/plugins.php" method="post" enctype="multipart/form-data">' . LB
+ . '<div>' . $LANG28[29] . ': '
+ . '<input type="file" dir="ltr" name="plugin" size="40"' . XHTML
+ . '> ' . LB
+ . '<input type="submit" name="upload" value="' . $LANG32[41] . '"'
+ . XHTML . '>' . LB
+ . '<input type="hidden" name="' . CSRF_TOKEN . '" value="' . $token
+ . '"' . XHTML . '>' . '</div>' . LB . '</form>' . LB;
+
+ $retval .= COM_endBlock(COM_getBlockTemplate('_admin_block', 'footer'));
+
+ return $retval;
+}
+
+/**
+* Handle uploaded plugin
+*
+* @return string HTML: redirect or main plugin screen + error message
+*
+*/
+function plugin_upload()
+{
+ global $_CONF;
+
+ $retval = '';
+
+ // Check if a plugin file was uploaded
+ $upload_success = false;
+ if (isset($_FILES['plugin'])) {
+
+ // If an error occured while uploading the file.
+ $error_msg = plugin_getUploadError($_FILES['plugin']);
+ if (!empty($error_msg)) {
+
+ $retval .= plugin_main($error_msg);
+
+ } else {
+
+ $plugin_file = $_CONF['path_data'] . $_FILES['plugin']['name']; // Name the plugin file
+
+ if ($_FILES['plugin']['type'] == 'application/zip') {
+
+ // Zip
+ require_once 'Archive/Zip.php'; // import Archive_Zip library
+ $archive = new Archive_Zip($_FILES['plugin']['tmp_name']); // Use PEAR's Archive_Zip to extract the package
+
+ } else {
+
+ // Tarball
+ require_once 'Archive/Tar.php'; // import Archive_Tar library
+ $archive = new Archive_Tar($_FILES['plugin']['tmp_name']); // Use PEAR's Archive_Tar to extract the package
+
+ }
+ $tmp = $archive->listContent(); // Grab the contents of the tarball to see what the plugin name is
+ $dirname = preg_replace('/\/.*$/', '', $tmp[0]['filename']);
+
+ if (empty($dirname)) { // If $dirname is blank it's probably because the user uploaded a non Tarball file.
+
+ $retval = COM_refresh($_CONF['site_admin_url'] . '/plugins.php?msg=100');
+
+ } else if (file_exists($_CONF['path'] . 'plugins/' . $dirname)) { // If plugin directory already exists
+
+ $retval = COM_refresh($_CONF['site_admin_url'] . '/plugins.php?msg=99');
+
+ } else {
+
+ /**
+ * Install the plugin
+ * This doesn't work if the public_html & public_html/admin/plugins directories aren't 777
+ */
+
+ // Extract the tarball to data so we can get the $pi_name name from admin/install.php
+ if ($_FILES['plugin']['type'] == 'application/zip') {
+
+ // Zip
+ $archive->extract(array('add_path' => $_CONF['path'] . 'data/',
+ 'by_name' => $dirname . '/admin/install.php'));
+
+ } else {
+
+ // Tarball
+ $archive->extractList(array($dirname . '/admin/install.php'), $_CONF['path'] . 'data/');
+
+ }
+ $plugin_inst = $_CONF['path'] . 'data/' . $dirname . '/admin/install.php';
+ $fhandle = fopen($plugin_inst, 'r');
+ $fdata = fread($fhandle, filesize($plugin_inst));
+ fclose($fhandle);
+
+ // Remove the plugin from data/
+ require_once 'System.php';
+ @System::rm('-rf ' . $_CONF['path'] . 'data/' . $dirname);
+
+ /**
+ * One time I wanted to install a muffler on my car and
+ * needed to match up the outside diameter of the car's
+ * exhaust pipe to the inside diameter of the muffler.
+ * Unfortunately, when I went to the auto parts store they
+ * didn't have a coupling adapter that would perfectly
+ * match the two pipes, only a bunch of smaller adapters.
+ * I ended up using about 4 small adapters to step down
+ * one size at a time to the size of the muffler's input.
+ *
+ * It's kind of like this regular expression:
+ *
+ */
+ $fdata = preg_replace('/\n/', '', $fdata);
+ $fdata = preg_replace('/ /', '', $fdata);
+ $pi_name = preg_replace('/^.*\$pi\_name=\'/', '', $fdata);
+ $pi_name = preg_replace('/\'.*$/', '', $pi_name);
+
+ // Some plugins don't have $pi_name set in their install.php file,
+ // This means our regex won't work and we should just use $dirname
+ if (preg_match('/\<\?php/', $pi_name) || preg_match('/--/', $pi_name)) {
More information about the geeklog-cvs
mailing list