summaryrefslogtreecommitdiffstats
path: root/apps/shorty/lib
diff options
context:
space:
mode:
Diffstat (limited to 'apps/shorty/lib')
-rw-r--r--apps/shorty/lib/backend.php286
-rw-r--r--apps/shorty/lib/exception.php162
-rw-r--r--apps/shorty/lib/hooks.php64
-rw-r--r--apps/shorty/lib/l10n.php93
-rw-r--r--apps/shorty/lib/meta.php213
-rw-r--r--apps/shorty/lib/query.php57
-rw-r--r--apps/shorty/lib/tools.php235
-rw-r--r--apps/shorty/lib/type.php291
8 files changed, 1401 insertions, 0 deletions
diff --git a/apps/shorty/lib/backend.php b/apps/shorty/lib/backend.php
new file mode 100644
index 00000000000..aa6c58b4490
--- /dev/null
+++ b/apps/shorty/lib/backend.php
@@ -0,0 +1,286 @@
+<?php
+/**
+* @package shorty an ownCloud url shortener plugin
+* @category internet
+* @author Christian Reiner
+* @copyright 2011-2012 Christian Reiner <foss@christian-reiner.info>
+* @license GNU Affero General Public license (AGPL)
+* @link information
+* @link repository https://svn.christian-reiner.info/svn/app/oc/shorty
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the license, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.
+* If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * @file lib/backend.php
+ * Routines to use remote (online) shortening services as backends in a local workflow
+ * @author Christian Reiner
+ */
+
+/**
+ * @class OC_Shorty_Backend
+ * @brief Library to register urls using backends, typically remote (online) url shortening services
+ * @access public
+ * @author Christian Reiner
+ */
+class OC_Shorty_Backend
+{
+ /**
+ * @method OC_Shorty_Backend::registerUrl
+ * @brief Wrapper function around the specific backend routines
+ * @param id (string) Internal shorty id used to reference a shorty upon usage.
+ * @returns (string) The shortened url as generated by a specific backend.
+ * @throws OC_Shorty_Exception taking over the explaining of the failure from the specific backend
+ * @access public
+ * @author Christian Reiner
+ */
+ static function registerUrl ( $id )
+ {
+ try
+ {
+ // construct the $relay, the url to be called to reach THIS service (ownclouds shorty plugin)
+ $relay = OC_Shorty_Tools::relayUrl ( $id );
+ // call backend specific work horse
+ switch ( $type=OCP\Config::getUserValue(OCP\User::getUser(),'shorty','backend-type','none') )
+ {
+ default: return OC_Shorty_Backend::registerUrl_default ( $id, $relay );
+ case 'static': return OC_Shorty_Backend::registerUrl_static ( $id, $relay );
+ case 'bitly': return OC_Shorty_Backend::registerUrl_bitly ( $id, $relay );
+ case 'cligs': return OC_Shorty_Backend::registerUrl_cligs ( $id, $relay );
+ case 'google': return OC_Shorty_Backend::registerUrl_google ( $id, $relay );
+ case 'isgd': return OC_Shorty_Backend::registerUrl_isgd ( $id, $relay );
+ case 'tinyurl': return OC_Shorty_Backend::registerUrl_tinyurl ( $id, $relay );
+ case 'tinycc': return OC_Shorty_Backend::registerUrl_tinycc ( $id, $relay );
+ } // switch
+ } // try
+ catch (OC_Shorty_Exception $e)
+ {
+ throw $e;
+ } // catch
+ catch (Exception $e)
+ {
+ throw new OC_Shorty_Exception ( "Failed to register url '%s' at '%s' backend", array($relay,$type) );
+ } // catch
+ } // OC_Shorty_Backend::registerUrl
+
+ /**
+ * @method OC_Shorty_Backend::registerUrl_default
+ * @brief Pseudo-registers a given local relay url
+ * @param id (string)
+ * @param relay (url)
+ * @returns validated and pseudo-registered relay
+ * @access public
+ * @author Chrisian Reiner
+ */
+ static function registerUrl_default ( $id, $relay )
+ {
+ return OC_Shorty_Type::validate ( $relay, OC_Shorty_Type::URL );
+ } // OC_Shorty_Backend::registerUrl_default
+
+ /**
+ * @method OC_Shorty_Backend::registerUrl_static
+ * @brief Registers a given local relay url as local static shorty
+ * @param id (string)
+ * @param relay (url)
+ * @returns registered and validated relay url
+ * @access public
+ * @author Chrisian Reiner
+ */
+ static function registerUrl_static ( $id, $relay )
+ {
+ if ( (FALSE===($base=trim ( OCP\Config::getAppValue('shorty','backend-static-base',FALSE))))
+ ||(empty($base)) )
+ throw new OC_Shorty_Exception ( 'No base url defined for the static backend' );
+ return OC_Shorty_Type::validate ( $base.$id, OC_Shorty_Type::URL );
+ } // OC_Shorty_Backend::registerUrl_static
+
+ /**
+ * @method OC_Shorty_Backend::registerUrl_bitly
+ * @brief Registers a given local relay url at the bit.ly shortening service
+ * @param id (string)
+ * @param relay (url)
+ * @returns registered and validated relay url
+ * @access public
+ * @author Chrisian Reiner
+ */
+ static function registerUrl_bitly ( $id, $relay )
+ {
+ $bitly_api_user = OCP\Config::getUserValue(OCP\User::getUser(),'shorty','backend-bitly-user','');
+ $bitly_api_key = OCP\Config::getUserValue(OCP\User::getUser(),'shorty','backend-bitly-key', '');
+ if ( ! $bitly_api_key || ! $bitly_api_user )
+ throw new OC_Shorty_Exception ( 'No API user or key configured' );
+ $curl = curl_init ( );
+ curl_setopt ( $curl, CURLOPT_URL, 'https://api-ssl.bit.ly/shorten' );
+ curl_setopt ( $curl, CURLOPT_SSL_VERIFYHOST, TRUE );
+ curl_setopt ( $curl, CURLOPT_POST, TRUE );
+ curl_setopt ( $curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json') );
+ curl_setopt ( $curl, CURLOPT_POSTFIELDS, json_encode(array('version'=>'2.0.1',
+ 'longUrl'=>$relay,
+ 'format'=>'json',
+ 'login'=>$bitly_api_user,
+ 'apiKey'=>$bitly_api_key) ) );
+ curl_setopt ( $curl, CURLOPT_RETURNTRANSFER, TRUE );
+ if ( (FALSE===($reply=curl_exec($curl)))
+ ||(NULL===($payload=json_decode($reply)))
+ ||(!is_object($payload))
+ ||(!property_exists($payload,'id')) )
+ {
+ throw new OC_Shorty_Exception ( "Failed to register url at backend 'static'" );
+ }
+ curl_close ( $curl );
+ return OC_Shorty_Type::validate ( $payload->id, OC_Shorty_Type::URL );
+ } // OC_Shorty_Backend::registerUrl_bitly
+
+ /**
+ * @method OC_Shorty_Backend::registerUrl_cligs
+ * @brief Registers a given local relay url at the cli.gs shortening service
+ * @param id (string)
+ * @param relay (url)
+ * @returns registered and validated relay url
+ * @access public
+ * @author Chrisian Reiner
+ */
+ static function registerUrl_cligs ( $id, $relay )
+ {
+ $curl = curl_init ( );
+ curl_setopt ( $curl, CURLOPT_URL, sprintf('http://cli.gs/api/v2/cligs/create?url=%s&appid=owncloud_shorty&test=1', urlencode(trim($relay))) );
+ curl_setopt ( $curl, CURLOPT_RETURNTRANSFER, TRUE );
+ if ( (FALSE===($reply=curl_exec($curl)))
+ ||( ! preg_match( '/^(.+)$/', $reply, $match )) )
+ {
+ throw new OC_Shorty_Exception ( "Failed to register url at backend 'cli.gs'" );
+ }
+ curl_close ( $curl );
+ return OC_Shorty_Type::validate ( $match[1], OC_Shorty_Type::URL );
+ } // OC_Shorty_Backend::registerUrl_cligs
+
+ /**
+ * @method OC_Shorty_Backend::registerUrl_isgd
+ * @brief Registers a given local relay url at the is.gd shortening service
+ * @param id (string)
+ * @param relay (url)
+ * @returns registered and validated relay url
+ * @access public
+ * @author Chrisian Reiner
+ */
+ static function registerUrl_isgd ( $id, $relay )
+ {
+ $curl = curl_init ( );
+ curl_setopt ( $curl, CURLOPT_URL, sprintf('http://is.gd/create.php?format=simple&url=%s', urlencode(trim($relay))) );
+ curl_setopt ( $curl, CURLOPT_RETURNTRANSFER, TRUE );
+ if ( (FALSE===($reply=curl_exec($curl)))
+ ||( ! preg_match( '/^(.+)$/', $reply, $match )) )
+ {
+ throw new OC_Shorty_Exception ( "Failed to register url at backend 'is.gd'" );
+ }
+ curl_close ( $curl );
+ return OC_Shorty_Type::validate ( $match[1], OC_Shorty_Type::URL );
+ } // OC_Shorty_Backend::registerUrl_isgd
+
+ /**
+ * @method OC_Shorty_Backend::registerUrl_google
+ * @brief Registers a given local relay url at the google shortening service
+ * @param id (string)
+ * @param relay (url)
+ * @returns registered and validated relay url
+ * @access public
+ * @author Chrisian Reiner
+ */
+ static function registerUrl_google ( $id, $relay )
+ {
+ $api_key = OCP\Config::getUserValue(OCP\User::getUser(),'shorty','backend-google-key','');
+ if ( ! $api_key )
+ throw new OC_Shorty_Exception ( 'No goo.gl API key configured' );
+ $curl = curl_init ( );
+ curl_setopt ( $curl, CURLOPT_URL, 'https://www.googleapis.com/urlshortener/v1/url' );
+ curl_setopt ( $curl, CURLOPT_SSL_VERIFYHOST, TRUE );
+ curl_setopt ( $curl, CURLOPT_POST, TRUE );
+ curl_setopt ( $curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json') );
+ curl_setopt ( $curl, CURLOPT_POSTFIELDS, json_encode(array('longUrl'=>$relay,
+ 'key'=>$api_key) ) );
+ curl_setopt ( $curl, CURLOPT_RETURNTRANSFER, TRUE );
+ if ( (FALSE===($reply=curl_exec($curl)))
+ ||(NULL===($payload=json_decode($reply)))
+ ||(!is_object($payload))
+ ||(!property_exists($payload,'id')) )
+ {
+ throw new OC_Shorty_Exception ( "Failed to register url at backend 'goo.gl'" );
+ }
+ curl_close ( $curl );
+ return OC_Shorty_Type::validate ( $payload->id, OC_Shorty_Type::URL );
+ } // OC_Shorty_Backend::registerUrl_google
+
+ /**
+ * @method OC_Shorty_Backend::registerUrl_tinycc
+ * @brief Registers a given local relay url at the tiny.cc shortening service
+ * @param id (string)
+ * @param relay (url)
+ * @returns registered and validated relay url
+ * @access public
+ * @author Chrisian Reiner
+ */
+ static function registerUrl_tinycc ( $id, $relay )
+ {
+ $api_user = OCP\Config::getUserValue(OCP\User::getUser(),'shorty','backend-tinycc-user','');
+ $api_key = OCP\Config::getUserValue(OCP\User::getUser(),'shorty','backend-tinycc-key','');
+ if ( ! $api_key || ! $api_user )
+ throw new OC_Shorty_Exception ( 'No goo.gl API key configured' );
+ $curl = curl_init ( );
+ curl_setopt ( $curl, CURLOPT_URL, 'http://tiny.cc/?c=shorten' );
+ curl_setopt ( $curl, CURLOPT_SSL_VERIFYHOST, TRUE );
+ curl_setopt ( $curl, CURLOPT_POST, TRUE );
+ curl_setopt ( $curl, CURLOPT_HEADER, TRUE );
+ curl_setopt ( $curl, CURLOPT_POSTFIELDS, array('longUrl'=>$relay,
+ 'version'=>'2.0.3',
+ 'format'=>'json',
+ 'login'=>$api_user,
+ 'apiKey'=>$api_key) );
+ curl_setopt ( $curl, CURLOPT_RETURNTRANSFER, TRUE );
+ if ( (FALSE===($reply=curl_exec($curl)))
+ ||(NULL===($payload=json_decode($reply)))
+ ||(!is_object($payload))
+ ||(!property_exists($payload,'id')) )
+ {
+ throw new OC_Shorty_Exception ( "Failed to register url at backend 'tiny.cc'" );
+ }
+ curl_close ( $curl );
+ return OC_Shorty_Type::validate ( $payload->id, OC_Shorty_Type::URL );
+ } // OC_Shorty_Backend::registerUrl_google
+
+ /**
+ * @method OC_Shorty_Backend::registerUrl_tinyurl
+ * @brief Registers a given local relay url at the tinyURL shortening service
+ * @param id (string)
+ * @param relay (url)
+ * @returns registered and validated relay url
+ * @access public
+ * @author Chrisian Reiner
+ */
+ static function registerUrl_tinyurl ( $id, $relay )
+ {
+ $curl = curl_init ( );
+ curl_setopt ( $curl, CURLOPT_URL, sprintf('http://tinyurl.com/api-create.php?url=%s', urlencode(trim($relay))) );
+ curl_setopt ( $curl, CURLOPT_RETURNTRANSFER, TRUE );
+ if ( (FALSE===($reply=curl_exec($curl)))
+ ||( ! preg_match( '/^(.+)$/', $reply, $match )) )
+ {
+ throw new OC_Shorty_Exception ( "Failed to register url at backend 'tinyUrl'" );
+ }
+ curl_close ( $curl );
+ return OC_Shorty_Type::validate ( $match[1], OC_Shorty_Type::URL );
+ } // OC_Shorty_Backend::registerUrl_tinyurl
+
+} // class OC_Shorty_Backend
diff --git a/apps/shorty/lib/exception.php b/apps/shorty/lib/exception.php
new file mode 100644
index 00000000000..daeb9d10a9c
--- /dev/null
+++ b/apps/shorty/lib/exception.php
@@ -0,0 +1,162 @@
+<?php
+/**
+* @package shorty an ownCloud url shortener plugin
+* @category internet
+* @author Christian Reiner
+* @copyright 2011-2012 Christian Reiner <foss@christian-reiner.info>
+* @license GNU Affero General Public license (AGPL)
+* @link information
+* @link repository https://svn.christian-reiner.info/svn/app/oc/shorty
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the license, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.
+* If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * @file lib/exception.php
+ * Application specific exception class
+ * @author Christian Reiner
+ */
+
+/**
+ * @class OC_Shorty_Exception
+ * @brief Application specific exception class
+ * @access public
+ * @author Christian Reiner
+ */
+class OC_Shorty_Exception extends Exception
+{
+ protected $phrase = '';
+ protected $param = array ( );
+
+ /**
+ * @method OC_Shorty_Exception::__construct
+ * @brief: Constructs an exception based on a phrase and a set of parameters
+ * @param phrase (string) Human readable message that should be translatable
+ * @param param (array) Set of parameters to be used as sprintf arguments to fill the phrase
+ * @access public
+ * @author Christian Reiner
+ */
+ public function __construct ( $phrase, $param=array() )
+ {
+ if ( is_array($param) )
+ $this->param = $param;
+ else $this->param = array($param);
+ $this->phrase = $phrase;
+// $this->message = vsprintf ( $phrase, $this->params );
+ Exception::__construct ( vsprintf($phrase,$this->param), 1 );
+ }
+
+ /**
+ * @method OC_Shorty_Exception::getTranslation
+ * @brief: Returns the translated message of the exception
+ * @returns (string) Translated message including the filled in set of arguments
+ * @access public
+ * @author Christian Reiner
+ */
+ public function getTranslation ( )
+ {
+ return OC_Shorty_L10n::t ( $this->phrase, $this->param );
+ }
+
+ /**
+ * @method OC_Shorty_Exception::JSONerror
+ * @brief Calls OCP\JSON::error with a pretty formated version of an exception
+ * @param e (exception) an exception object holding information
+ * @returns (json) OCP\JSON::error
+ * @access public
+ * @author Christian Reiner
+ */
+ static function JSONerror ( $e )
+ {
+ $title = OC_Shorty_L10n::t("Exception");
+ switch ( get_class($e) )
+ {
+ case 'OC_Shorty_Exception':
+ $message = $e->getTranslation();
+ break;
+ case 'PDOException':
+ $message = sprintf ( OC_Shorty_L10n::t( "%s\nMessage(code): %s (%s)\nFile(line): %s (%s)\nInfo: %%s",
+ OC_Shorty_L10n::t("Exception (%s)", get_class($e)),
+ htmlspecialchars($e->getMessage()),
+ htmlspecialchars($e->getCode()),
+ htmlspecialchars($e->getFile()),
+ htmlspecialchars($e->getLine()) ),
+ (method_exists($e,'errorInfo') ? trim($e->errorInfo()) : '-/-') );
+ break;
+ default:
+ if ( is_a($e,'Exception') )
+ $message = OC_Shorty_L10n::t("Unexpected type of exception caught: %s", get_class($e));
+ else $message = OC_Shorty_L10n::t("Unknown object of type caught: %s", get_class($e));
+ } // switch
+ // swallow any accidential output generated by php notices and stuff to preserve a clean JSON reply structure
+ $output = trim ( OC_Shorty_Tools::ob_control(FALSE) );
+ if ( $output )
+ {
+ $message = "! Swallowing accidential output from ajax routines ! \n"
+ ."Please fix this ! Here is the first line: \n"
+ .substr ( $output, 0, strpos($output,"\n") );
+ OCP\Util::writeLog( 'shorty', $message, OC_Log::WARN );
+ } // output
+ // return a clean JSON error
+ return OCP\JSON::error ( array ( 'title' => $title,
+ 'message' => sprintf("%s: %s", $title, $message) ) );
+ } // function error
+} // class OC_Shorty_Exception
+
+/**
+ * @class OC_Shorty_HttpException
+ * @brief Application specific exception class: protocol layer
+ * @access public
+ * @author Christian Reiner
+ */
+class OC_Shorty_HttpException extends OC_Shorty_Exception
+{
+
+ /**
+ * @method OC_Shorty_HttpException::__construct
+ * @brief: Constructs an exception based on a phrase and a set of parameters
+ * @param status (integer) Http status code
+ * @access public
+ * @author Christian Reiner
+ */
+ public function __construct ( $status )
+ {
+ if ( is_numeric($status)
+ && array_key_exists($status,OC_Shorty_Type::$HTTPCODE) )
+ {
+ $status = intval($status);
+ $phrase = OC_Shorty_Type::$HTTPCODE[$status];
+ }
+ else
+ {
+ $status = 400;
+ $phrase = OC_Shorty_Type::$HTTPCODE[400]; // "Bad Request"
+ } // switch
+
+ // return http status code to client (browser)
+ if ( ! headers_sent() )
+ {
+ header ( sprintf("HTTP/1.0 %s %s",$status,$phrase) );
+ }
+ $tmpl = new OCP\Template("shorty", "tmpl_http_status", "guest");
+ $tmpl->assign("explanation", OC_Shorty_L10n::t($phrase));
+ $tmpl->printPage();
+ exit;
+ } // function __construct
+
+} // class OC_Shorty_HttpException
+
+?>
diff --git a/apps/shorty/lib/hooks.php b/apps/shorty/lib/hooks.php
new file mode 100644
index 00000000000..6ba59eccbda
--- /dev/null
+++ b/apps/shorty/lib/hooks.php
@@ -0,0 +1,64 @@
+<?php
+/**
+* @package shorty an ownCloud url shortener plugin
+* @category internet
+* @author Christian Reiner
+* @copyright 2011-2012 Christian Reiner <foss@christian-reiner.info>
+* @license GNU Affero General Public license (AGPL)
+* @link information
+* @link repository https://svn.christian-reiner.info/svn/app/oc/shorty
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the license, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.
+* If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * @file lib/hooks.php
+ * Static class providing routines to populate hooks called by other parts of ownCloud
+ * @author Christian Reiner
+ */
+
+/**
+ * @class OC_Shorty_Hooks
+ * @brief Static 'namespace' class for api hook population
+ * ownCloud propagates to use static classes as namespaces instead of OOP.
+ * This 'namespace' defines routines to populate hooks called by other parts of ownCloud
+ * @access public
+ * @author Christian Reiner
+ */
+class OC_Shorty_Hooks
+{
+ /**
+ * @brief Deletes all Shortys and preferences of a certain user
+ * @param paramters (array) parameters from postDeleteUser-Hook
+ * @return bool
+ */
+ public static function deleteUser ( $parameters )
+ {
+ OCP\Util::writeLog ( 'user post delete','wiping all users Shortys', OCP\Util::INFO );
+ $result = TRUE;
+ $param = array ( 'user' => OCP\User::getUser() );
+ // wipe shortys
+ $query = OCP\DB::prepare ( OC_Shorty_Query::WIPE_SHORTYS );
+ if ( FALSE===$query->execute($param) )
+ $result = FALSE;
+ // wipe preferences
+ $query = OCP\DB::prepare ( OC_Shorty_Query::WIPE_PREFERENCES );
+ if ( FALSE===$query->execute($param) )
+ $result = FALSE;
+ // report completion success
+ return $result;
+ }
+}
diff --git a/apps/shorty/lib/l10n.php b/apps/shorty/lib/l10n.php
new file mode 100644
index 00000000000..648130645a0
--- /dev/null
+++ b/apps/shorty/lib/l10n.php
@@ -0,0 +1,93 @@
+<?php
+/**
+* @package shorty an ownCloud url shortener plugin
+* @category internet
+* @author Christian Reiner
+* @copyright 2011-2012 Christian Reiner <foss@christian-reiner.info>
+* @license GNU Affero General Public license (AGPL)
+* @link information
+* @link repository https://svn.christian-reiner.info/svn/app/oc/shorty
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the license, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.
+* If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * @file lib/l10n.php
+ * Translation singleton
+ * @author Christian Reiner
+ */
+
+/**
+ * @class OC_Shorty_L10n
+ * @brief Convenient translation singleton
+ * @access public
+ * @author Christian Reiner
+ */
+class OC_Shorty_L10n
+{
+ /**
+ * @var OC_Shorty_L10n::dictionary
+ * @brief An internal dictionary file filled from the translation files provided.
+ * @access private
+ * @author Christian Reiner
+ */
+ private $dictionary;
+
+ /**
+ * @var OC_Shorty_L10n::instance
+ * @brief Internal singleton object
+ * @access private
+ * @author Christian Reiner
+ */
+ static private $instance=NULL;
+
+ /**
+ * @method OC_Shorty_L10n::__construct
+ * @brief
+ * @access private
+ * @author Christian Reiner
+ */
+ private function __construct ( ) { $this->dictionary = new OC_L10n('shorty'); }
+
+ /**
+ * @method OC_Shorty_L10n::t
+ * @brief Translates a given string into the users session language and fills any placeolders
+ * @param phrase to be translated
+ * @param … further arguments used as filling tokens in the tradition of printf strategies
+ * @returns translated phrase or the original phrase incase no translation could be found
+ * @access public
+ * @author Christian Reiner
+ */
+ static public function t ( $phrase )
+ {
+ // create singleton instance, if required
+ if ( ! self::$instance )
+ self::$instance = new OC_Shorty_L10n ( );
+ // handle different styles of how arguments can be handed over to this method
+ switch ( func_num_args() )
+ {
+ case 1: return self::$instance->dictionary->t ( $phrase, array() );
+ case 2: $arg = func_get_arg(1);
+ if ( is_array($arg) )
+ return self::$instance->dictionary->t ( $phrase, $arg );
+ else return self::$instance->dictionary->t ( $phrase, array($arg) );
+ default: $args = func_get_args();
+ array_shift ( $args );
+ return self::$instance->dictionary->t ( $phrase, $args );
+ }
+ }
+} // class OC_Shorty_L10n
+?>
diff --git a/apps/shorty/lib/meta.php b/apps/shorty/lib/meta.php
new file mode 100644
index 00000000000..91937bd3c8a
--- /dev/null
+++ b/apps/shorty/lib/meta.php
@@ -0,0 +1,213 @@
+<?php
+/**
+* @package shorty an ownCloud url shortener plugin
+* @category internet
+* @author Christian Reiner
+* @copyright 2011-2012 Christian Reiner <foss@christian-reiner.info>
+* @license GNU Affero General Public license (AGPL)
+* @link information
+* @link repository https://svn.christian-reiner.info/svn/app/oc/shorty
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the license, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.
+* If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * @file lib/meta.php
+ * Routines to retrieve meta information about a remote url
+ * @author Christian Reiner
+ */
+
+/**
+ * @class OC_Shorty_Meta
+ * @brief Static 'namespace' class for url meta information retrieval
+ * ownCloud propagates to use static classes as namespaces instead of OOP.
+ * This 'namespace' defines routines for the retrieval of meta information about remote urls.
+ * @access public
+ * @author Christian Reiner
+ */
+class OC_Shorty_Meta
+{
+
+ /**
+ * @method OC_Shorty_Meta::fetchMetaData
+ * @brief Retrieves the meta information to a given remote url
+ * @param url decoded target url for which meta information if requested
+ * @returns associative array holding the requested meta data
+ * @access public
+ * @author Christian Reiner
+ */
+ static function fetchMetaData ( $url )
+ {
+ $url_token = parse_url ( $url );
+ // some sane fallback values, in case we cannot get the meta data
+ $meta = array();
+ $meta['target'] = $url;
+ $meta['title'] = strtolower ( $url_token['host'] );
+ $meta['scheme'] = strtolower ( $url_token['scheme'] );
+ $meta['mimetype'] = 'application/octet-stream';
+ $meta['schemicon'] = self::selectIcon ( 'scheme', strtolower($url_token['scheme']) );
+ // we wont bother retrieving data about other protocols than http or ftp
+ if ( ! in_array(strtolower($url_token['scheme']),array('http','https','ftp','ftps')) )
+ return $meta;
+ // to fetch meta data we rely on curl being installed
+ if ( ! function_exists('curl_init') )
+ return $meta;
+ // try to retrieve the meta data
+ $handle = curl_init ( );
+ curl_setopt ( $handle, CURLOPT_URL, $url );
+ curl_setopt ( $handle, CURLOPT_RETURNTRANSFER, 1 );
+ curl_setopt ( $handle, CURLOPT_FOLLOWLOCATION, TRUE );
+ curl_setopt ( $handle, CURLOPT_MAXREDIRS, 10 );
+ if ( FALSE!==($page=curl_exec($handle)) )
+ {
+ // try to extract title from page
+ preg_match ( "/<head>.*<title>(.*)<\/title>.*<\/head>/si", $page, $match );
+ $meta['title'] = htmlspecialchars_decode ( $match[1] );
+ $meta['staticon'] = self::selectIcon ( 'state', TRUE );
+ // final url after a possible redirection
+ $meta['final'] = curl_getinfo ( $handle, CURLINFO_EFFECTIVE_URL );
+ // try to extract favicon from page
+ preg_match ( '/<[^>]*link[^>]*(rel=["\']icon["\']|rel=["\']shortcut icon["\']) .*href=["\']([^>]*)["\'].*>/iU', $page, $match );
+ if (1<sizeof($match))
+ {
+ // the specified uri might be an url, an absolute or a relative path
+ // we have to turn it into an url to be able to display it out of context
+ $favicon = htmlspecialchars_decode ( $match[2] );
+ // test for an url
+ if (parse_url($favicon,PHP_URL_SCHEME))
+ {
+ $meta['favicon'] = $favicon;
+ }
+ // test for an absolute path
+ elseif ( 0===strpos(parse_url($favicon,PHP_URL_PATH),'/') )
+ {
+ $url_token = parse_url($meta['final']);
+ $meta['favicon'] = sprintf( '%s://%s/%s', $url_token['scheme'], $url_token['host'], $favicon );
+ }
+ // so it appears to be a relative path
+ else
+ {
+ $url_token = parse_url($meta['final']);
+ $meta['favicon'] = sprintf( '%s://%s%s%s', $url_token['scheme'], $url_token['host'], dirname($url_token['path']), $favicon );
+ }
+ }
+ $meta['mimetype'] = preg_replace ( '/^([^;]+);.*/i', '$1', curl_getinfo($handle,CURLINFO_CONTENT_TYPE) );
+ $meta['mimicon'] = self::selectIcon ( 'mimetype', $meta['mimetype'] );
+ $meta['code'] = curl_getinfo ( $handle, CURLINFO_HTTP_CODE );
+ $meta['status'] = OC_Shorty_L10n::t ( self::selectCode('status',$meta['code']) );
+ $meta['explanation'] = OC_Shorty_L10n::t ( self::selectCode('explanation',$meta['code']) );
+ }
+ curl_close ( $handle );
+ // that's it !
+ return $meta;
+ } // function fetchMetaData
+
+ /**
+ * @method OC_Shorty_Meta::selectCode
+ * @brief Some helper utility used to resolve numeric http status codes into human readable strings
+ * @param aspect a string indicating a section/pool a code is to be resolved in
+ * @param identifier a string indicating a specific code to be resolved
+ * @returns a human readable string resolving the specified numeric status code
+ * @throws OC_Shorty_Exception in case of an undefined code to be resolved
+ * @access public
+ * @author Christian Reiner
+ */
+ static function selectCode ( $aspect, $identifier )
+ {
+ // map of official http status codes
+ $_code_map = array
+ (
+ 'status' => OC_Shorty_Type::$HTTPCODE,
+ 'explanation' => array
+ (
+ 200 => 'Target url is valid and resolved.',
+ 201 => 'The request has been fulfilled and created a new ressource.',
+ 202 => 'The request has been accepted.',
+ 203 => 'The request yielded in non-authorative information.',
+ 204 => 'The request has been fulfilled but not produced any content.',
+ 205 => 'The request has been fulfilled and the view should be reset.',
+ 206 => 'The request has been fulfilled partially.',
+ )
+ );
+ // resolve specified code against map or provide some fallback content
+ if ( key_exists($aspect,$_code_map) && key_exists($identifier,$_code_map[$aspect]) )
+ return $_code_map[$aspect][$identifier];
+ else
+ {
+ switch ( $aspect )
+ {
+ case 'status': return sprintf("Status %s [unknown]",$identifier);
+ case 'explanation': return sprintf("[Undefined status code '%s']",$identifier);
+ default: throw new OC_Shorty_Exception ( "unknown aspect '%s' requested to resolve code '%s'",
+ array($aspect,$identifier) );
+ } // switch
+ }
+ } // function selectCode
+
+ /**
+ * @method OC_Shorty_Meta::selectIcon
+ * @brief Some helper utility for the easy integrate of icon references into templates and alike
+ * @param aspect a string indicating a section/pool an icon is to be chosen from
+ * @param identifier a string indicating a specific icon to be referenced
+ * @returns a hyper reference to an icon in form of a string
+ * @access public
+ * @author Christian Reiner
+ */
+ static function selectIcon ( $aspect, $identifier )
+ {
+ switch ( $aspect )
+ {
+ case 'state':
+ switch ($identifier)
+ {
+ case TRUE: return OCP\Util::imagePath('shorty', 'status/good.png');
+ case FALSE: return OCP\Util::imagePath('shorty', 'status/bad.png');
+ default: return OCP\Util::imagePath('shorty', 'status/neutral.png');
+ } // switch identifier
+ case 'scheme':
+ switch ($identifier)
+ {
+ case 'http':
+ case 'https': return OCP\Util::imagePath('shorty', 'scheme/H.png');
+ case 'ftp':
+ case 'ftps': return OCP\Util::imagePath('shorty', 'scheme/F.png');
+ case 'sftp': return OCP\Util::imagePath('shorty', 'scheme/S.png');
+ case 'mailto': return OCP\Util::imagePath('shorty', 'scheme/M.png');
+ case 'gopher': return OCP\Util::imagePath('shorty', 'scheme/G.png');
+ case 'webdav':
+ case 'webdavs': return OCP\Util::imagePath('shorty', 'scheme/W.png');
+ default: return OCP\Util::imagePath('shorty', 'blank.png');
+ } // switch identifier
+ case 'mimetype':
+ $identifier = explode('/',$identifier);
+ switch ($identifier[0])
+ {
+ case 'audio': return OCP\Util::imagePath('core', 'filetypes/audio.png');
+ case 'text': return OCP\Util::imagePath('core', 'filetypes/text.png');
+ case 'video': return OCP\Util::imagePath('core', 'filetypes/video.png');
+ case 'application':
+ switch ($identifier[1])
+ {
+ case 'pdf': return OCP\Util::imagePath('core', 'filetypes/application-pdf.png');
+ default: return OCP\Util::imagePath('shorty', 'blank.png');
+ } // switch identifier[1]
+ default: return OCP\Util::imagePath('shorty', 'blank.png');
+ } // switch identifier[0]
+ } // switch aspect
+ } // function selectIcon
+
+} // class OC_Shorty_Meta
+?>
diff --git a/apps/shorty/lib/query.php b/apps/shorty/lib/query.php
new file mode 100644
index 00000000000..6501a54d927
--- /dev/null
+++ b/apps/shorty/lib/query.php
@@ -0,0 +1,57 @@
+<?php
+/**
+* @package shorty an ownCloud url shortener plugin
+* @category internet
+* @author Christian Reiner
+* @copyright 2011-2012 Christian Reiner <foss@christian-reiner.info>
+* @license GNU Affero General Public license (AGPL)
+* @link information
+* @link repository https://svn.christian-reiner.info/svn/app/oc/shorty
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the license, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.
+* If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * @file lib/query.php
+ * Static catalog of sql queries
+ * @author Christian Reiner
+ */
+
+/**
+ * @class OC_Shorty_Query
+ * @brief Static catalog of sql queries
+ * These query templates are referenced by a OC_Shorty_Query::URL_...
+ * They have to be prapared by adding an array of parameters
+ * @access public
+ * @author Christian Reiner
+ */
+class OC_Shorty_Query
+{
+ const URL_INSERT = "INSERT INTO *PREFIX*shorty (id,status,favicon,title,source,target,user,until,created,notes) VALUES (:id,:status,:favicon,:title,:source,:target,:user,:until,CURRENT_DATE,:notes)";
+ const URL_DELETE = "DELETE FROM *PREFIX*shorty WHERE user=:user AND id=:id";
+ const URL_REMOVE = "DELETE FROM *PREFIX*shorty WHERE user=:user AND 'deleted'=status";
+ const URL_UPDATE = "UPDATE *PREFIX*shorty SET status=:status,title=:title,until=:until,notes=:notes WHERE user=:user AND id=:id";
+ const URL_STATUS = "UPDATE *PREFIX*shorty SET status=:status WHERE user=:user AND id=:id";
+ const URL_CLICK = "UPDATE *PREFIX*shorty SET accessed=CURRENT_TIMESTAMP, clicks=(clicks+1) WHERE id=:id";
+ const URL_FORWARD = "SELECT user,source,target,status,(until IS NOT NULL AND until!='' AND until<CURRENT_TIMESTAMP) AS expired FROM *PREFIX*shorty WHERE id=:id";
+ const URL_SOURCE = "SELECT id,source,target,status,(until IS NOT NULL AND until!='' AND until<CURRENT_TIMESTAMP) AS expired FROM *PREFIX*shorty WHERE source=:source";
+ const URL_VERIFY = "SELECT id,status,favicon,title,source,target,clicks,created,accessed,until,notes FROM *PREFIX*shorty WHERE user=:user AND id=:id LIMIT 1";
+ const URL_LIST = "SELECT id,status,favicon,title,source,target,clicks,created,accessed,until,notes FROM *PREFIX*shorty WHERE user=:user ORDER BY :sort";
+ const URL_COUNT = "SELECT count(*) AS sum_shortys,IFNULL(sum(clicks),0) AS sum_clicks FROM *PREFIX*shorty WHERE user=:user";
+ const WIPE_SHORTYS = "DELETE FROM *PREFIX*shorty WHERE user=:user";
+ const WIPE_PREFERENCES = "DELETE FROM *PREFIX*preferences WHERE user=:user";
+} // class OC_Shorty_Query
+?>
diff --git a/apps/shorty/lib/tools.php b/apps/shorty/lib/tools.php
new file mode 100644
index 00000000000..2b3bac70672
--- /dev/null
+++ b/apps/shorty/lib/tools.php
@@ -0,0 +1,235 @@
+<?php
+/**
+* @package shorty an ownCloud url shortener plugin
+* @category internet
+* @author Christian Reiner
+* @copyright 2011-2012 Christian Reiner <foss@christian-reiner.info>
+* @license GNU Affero General Public license (AGPL)
+* @link information
+* @link repository https://svn.christian-reiner.info/svn/app/oc/shorty
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the license, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.
+* If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * @file lib/tools.php
+ * A collection of general utility routines
+ * @author Christian Reiner
+ */
+
+/**
+ * @class OC_Shorty_Tools
+ * @brief Collection of a few practical routines, a tool box
+ * @access public
+ * @author Christian Reiner
+ */
+class OC_Shorty_Tools
+{
+ // internal flag indicating if output buffering should be used to prevent accidentially output during ajax requests
+ static $ob_usage = TRUE;
+ // internal flag indicating if there is currently an output buffer active
+ static $ob_active = FALSE;
+
+ /**
+ * @method OC_Shorty_Tools::ob_control
+ * @param on (boolean) wether to activate or deactivate the buffer
+ * @access public
+ * @author Christian Reiner
+ */
+ static function ob_control ( $on=TRUE )
+ {
+ $output = NULL;
+ if ( self::$ob_usage )
+ {
+ // attempt to use outpout buffering
+ if ( $on )
+ {
+ // start buffering if possible and not yet started before
+ if ( function_exists('ob_start') // output buffers installed at all ?
+ && ! self::$ob_active ) // don't stack buffers (create buffer only, if not yet started)
+ {
+ ob_implicit_flush ( FALSE );
+ ob_start ( );
+ self::$ob_active = TRUE;
+ }
+ } // if $on==TRUE
+ else
+ {
+ // end buffering _if_ it has been started before
+ if ( self::$ob_active )
+ {
+ $output = ob_get_contents ( );
+ ob_end_clean ( );
+ self::$ob_active = FALSE;
+ }
+ } // if $on==FALSE
+ } // if ob_usage
+ return $output;
+ } // function ob_control
+
+ /**
+ * @method OC_Shorty_Tools::db_escape
+ * @brief escape a value for incusion in db statements
+ * @param value (string) value to be escaped
+ * @returns (string) escaped string value
+ * @throws OC_Shorty_Exception in case of an unknown database engine
+ * @access public
+ * @author Christian Reiner
+ * @todo use mdb2::quote() / mdb2:.escape() instead ?
+ */
+ static function db_escape ( $value )
+ {
+ $type = OCP\Config::getSystemValue ( 'dbtype', 'sqlite' );
+ switch ( $type )
+ {
+ case 'sqlite':
+ case 'sqlite3':
+ return sqlite_escape_string ( $value );
+ case 'pgsql':
+ return pg_escape_string ( $value );
+ case 'mysql':
+ if (get_magic_quotes_gpc())
+ return mysql_real_escape_string ( stripslashes($value) );
+ else return mysql_real_escape_string ( $value );
+ }
+ throw new OC_Shorty_Exception ( "unknown database backend type '%1'", array($type) );
+ } // function db_escape
+
+ /**
+ * @method OC_Shorty_Tools::db_timestamp
+ * @brief current timestamp as required by db engine
+ * @returns (string) current timestamp as required by db engine
+ * @throws OC_Shorty_Exception in case of an unknown database engine
+ * @access public
+ * @author Christian Reiner
+ * @todo not really required any more, we rely on CURRENT_TIMESTAMP instead
+ */
+ static function db_timestamp ( )
+ {
+ $type = OCP\Config::getSystemValue( "dbtype", "sqlite" );
+ switch ( $type )
+ {
+ case 'sqlite':
+ case 'sqlite3': return "strftime('%s','now')";
+ case 'mysql': return 'UNIX_TIMESTAMP()';
+ case 'pgsql': return "date_part('epoch',now())::integer";
+ }
+ throw new OC_Shorty_Exception ( "unknown database backend type '%1'", array($type) );
+ } // function db_timestamp
+
+ /**
+ * @method OC_Shorty_Tools::shorty_id
+ * @brief Creates a unique id to be used for a new shorty entry
+ * @returns (string) valid and unique id
+ * @access public
+ * @author Christian Reiner
+ */
+ static function shorty_id ( )
+ {
+ // each shorty installation uses a (once self generated) 62 char alphabet
+ $alphabet=OCP\Config::getAppValue('shorty','id-alphabet');
+ if ( empty($alphabet) )
+ {
+ $alphabet = self::randomAlphabet(62);
+ OCP\Config::setAppValue ( 'shorty', 'id-alphabet', $alphabet );
+ }
+ // use alphabet to generate a id being unique over time
+ return self::convertToAlphabet ( str_replace(array(' ','.'),'',microtime()), $alphabet );
+ } // function shorty_id
+
+ /**
+ *
+ */
+ static function randomAlphabet ($length)
+ {
+ if ( ! is_integer($length) )
+ return FALSE;
+ $c = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxwz0123456789";
+ for($l=0;$l<$length;$l++) $s .= $c{rand(0,strlen($c))};
+ return str_shuffle($s);
+ } // function randomAlphabet
+
+ /**
+ * @method OC_Shorty_Tools::convertToAlphabet
+ * @brief Converts a given decimal number into an arbitrary base (alphabet)
+ * @param number decimal value to be converted
+ * @returns (string) converted value in string notation
+ * @access public
+ * @author Christian Reiner
+ */
+ static function convertToAlphabet ( $number, $alphabet )
+ {
+ $alphabetLen = strlen($alphabet);
+ $decVal = (int) $number;
+ $number = FALSE;
+ $nslen = 0;
+ $pos = 1;
+ while ($decVal > 0)
+ {
+ $valPerChar = pow($alphabetLen, $pos);
+ $curChar = floor($decVal / $valPerChar);
+ if ($curChar >= $alphabetLen)
+ {
+ $pos++;
+ } else {
+ $decVal -= ($curChar * $valPerChar);
+ if ($number === FALSE)
+ {
+ $number = str_repeat($alphabet{1}, $pos);
+ $nslen = $pos;
+ }
+ $number = substr($number, 0, ($nslen - $pos)) . $alphabet{$curChar} . substr($number, (($nslen - $pos) + 1));
+ $pos--;
+ }
+ }
+ if ($number === FALSE) $number = $alphabet{1};
+ return $number;
+ }
+
+ /**
+ * @method OC_Shorty_Tools::relayUrl
+ * @brief Generates a relay url for a given id acting as a href target for all backends
+ * @param id (string) shorty id as shorty identification
+ * @returns (string) generated absolute relay url
+ * @access public
+ * @author Christian Reiner
+ */
+ static function relayUrl ($id)
+ {
+ return sprintf ( '%s?service=%s&id=%s', OCP\Util::linkToAbsolute("", "public.php"), 'shorty_relay', $id );
+ } // function relayUrl
+
+ /**
+ * @method OC_Shorty_Tools::countShortys
+ * @brief Returns the total number of entries and clicks from the database
+ * @returns (array) two elements sum_shortys & sum_clicks holding an integer each
+ * @access public
+ * @author Christian Reiner
+ */
+ static function countShorties ()
+ {
+ $param = array
+ (
+ ':user' => OCP\User::getUser ( ),
+ );
+ $query = OCP\DB::prepare ( OC_Shorty_Query::URL_COUNT );
+ $result = $query->execute($param);
+ $reply = $result->fetchAll();
+ return $reply[0];
+ } // function countShorties
+
+} // class OC_Shorty_Tools
+?>
diff --git a/apps/shorty/lib/type.php b/apps/shorty/lib/type.php
new file mode 100644
index 00000000000..97cbf04ddb4
--- /dev/null
+++ b/apps/shorty/lib/type.php
@@ -0,0 +1,291 @@
+<?php
+/**
+* @package shorty an ownCloud url shortener plugin
+* @category internet
+* @author Christian Reiner
+* @copyright 2011-2012 Christian Reiner <foss@christian-reiner.info>
+* @license GNU Affero General Public license (AGPL)
+* @link information
+* @link repository https://svn.christian-reiner.info/svn/app/oc/shorty
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the license, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.
+* If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * @file lib/type.php
+ * Type handling, recognition and verification routines
+ * @author Christian Reiner
+ */
+
+/**
+ * @class OC_Shorty_Type
+ * @brief Static 'namespace' class offering routines and constants used to handle type recognition and value verification
+ * @access public
+ * @author Christian Reiner
+ */
+class OC_Shorty_Type
+{
+ // the 'types' of values we deal with, actually more something like flavours
+ const ID = 'id';
+ const STATUS = 'status';
+ const SORTKEY = 'sortkey';
+ const SORTVAL = 'sortval';
+ const STRING = 'string';
+ const URL = 'url';
+ const INTEGER = 'integer';
+ const FLOAT = 'float';
+ const DATE = 'date';
+ const TIMESTAMP = 'timestamp';
+ // a list of all valid list sorting codes
+ static $SORTING = array (
+ '' =>'created DESC', // default
+ 'aa'=>'accessed', 'ad'=>'accessed DESC',
+ 'ca'=>'created', 'cd'=>'created DESC',
+ 'da'=>'until', 'dd'=>'until DESC',
+ 'ha'=>'clicks', 'hd'=>'clicks DESC',
+ 'ka'=>'id', 'kd'=>'id DESC',
+ 'sa'=>'status', 'sd'=>'status DESC',
+ 'ta'=>'title', 'td'=>'title DESC',
+ 'ua'=>'target', 'ud'=>'target DESC' );
+ // a list of all valid user preferences
+ static $PREFERENCE = array (
+ 'backend-type' => OC_Shorty_Type::STRING,
+ 'backend-static-base' => OC_Shorty_Type::URL,
+ 'backend-bitly-user' => OC_Shorty_Type::STRING,
+ 'backend-bitly-key' => OC_Shorty_Type::STRING,
+ 'backend-google-key' => OC_Shorty_Type::STRING,
+ 'backend-tinycc-user' => OC_Shorty_Type::STRING,
+ 'backend-tinycc-key' => OC_Shorty_Type::STRING,
+ 'sms-control' => OC_Shorty_Type::STRING,
+ 'list-sort-code' => OC_Shorty_Type::SORTKEY,
+ );
+ // valid status for entries
+ static $STATUS = array (
+ 'blocked',
+ 'private',
+ 'shared',
+ 'public',
+ 'deleted',
+ );
+ // a list of implemented backends
+ static $BACKENDS = array (
+ 'none' => ' [ none ] ',
+ 'static' => 'static backend',
+// 'bitly' => 'bitly.com service',
+// 'cligs' => 'cli.gs service',
+ 'isgd' => 'is.gd service',
+ 'google' => 'goo.gl service',
+// 'tinycc' => 'tiny.cc service',
+ 'tinyurl' => 'ti.ny service',
+ );
+ // a list of all valid system settings
+ static $SETTING = array (
+ 'backend-static-base' => OC_Shorty_Type::URL,
+ );
+ static $HTTPCODE = array (
+ 200 => 'Ok',
+ 201 => 'Created',
+ 202 => 'Accepted',
+ 203 => 'Non-Authoritative Information',
+ 204 => 'No Content',
+ 205 => 'Reset Content',
+ 206 => 'Partial Content',
+ 300 => 'Multiple Choices',
+ 301 => 'Moved Permanently',
+ 302 => 'Found',
+ 303 => 'See Other',
+ 304 => 'Not Modified',
+ 305 => 'Use Proxy',
+ 306 => '(unused)',
+ 307 => 'Temporary Redirect',
+ 400 => 'Bad Request',
+ 401 => 'Unauthorized',
+ 402 => 'Payment Required',
+ 403 => 'Forbidden',
+ 404 => 'Not Found',
+ 405 => 'Method Not Allowed',
+ 406 => 'Not Acceptable',
+ 407 => 'Proxy Authentication Required',
+ 408 => 'Request Timeout',
+ 409 => 'Conflict',
+ 410 => 'Gone',
+ 411 => 'Length Required',
+ 412 => 'Precondition Failed',
+ 413 => 'Request Entity Too Large',
+ 414 => 'Request-URI Too Long',
+ 415 => 'Unsupported Media Type',
+ 416 => 'Requested Range Not Satisfiable',
+ 417 => 'Expectation Failed',
+ 500 => 'Internal Server Error',
+ 501 => 'Not Implemented',
+ 502 => 'Bad Gateway',
+ 503 => 'Service Unavailable',
+ 504 => 'Gateway Timeout',
+ 505 => 'HTTP Version Not Supported',
+ );
+
+ /**
+ * @method OC_Shorty_Type::validate
+ * @brief Validates a given value against a type specific regular expression
+ * Validates a given value according to the claimed type of the value.
+ * Validation is done by matching the value against a type specific regular expression.
+ * @param value the value to be verified according to the specified type
+ * @param type the type the value is said to belong to, important for verification
+ * @param strict flag indicating if the verification should be done strict, that is if an exception should be thrown in case of a failure
+ * @returns the value itself in case of a positive validation, NULL or an exception in case of a failure, depending on the flag indication strict mode
+ * @throws error indicating a failed validation in case of strict mode
+ * @access public
+ * @author Christian Reiner
+ */
+ static function validate ( $value, $type, $strict=FALSE )
+ {
+ switch ( $type )
+ {
+ case self::ID:
+ if ( preg_match ( '/^[a-z0-9]{2,20}$/i', $value ) )
+ return $value;
+ elseif ( ! $strict)
+ return NULL;
+ throw new OC_Shorty_Exception ( "invalid value '%s' for type '%s'", array( ((24<sizeof($value))?$value:substr($value,0,21).'…'),$type) );
+ case self::STATUS:
+ if ( in_array($value,OC_Shorty_Type::$STATUS) )
+ return $value;
+ elseif ( ! $strict)
+ return NULL;
+ throw new OC_Shorty_Exception ( "invalid value '%s' for type '%s'", array( ((24<sizeof($value))?$value:substr($value,0,21).'…'),$type) );
+ case self::SORTKEY:
+ if ( array_key_exists ( trim($value), self::$SORTING ) )
+ return $value;
+ elseif ( ! $strict)
+ return NULL;
+ throw new OC_Shorty_Exception ( "invalid value '%s' for type '%s'", array( ((24<sizeof($value))?$value:substr($value,0,21).'…'),$type) );
+ case self::SORTVAL:
+ if ( in_array ( trim($value), self::$SORTING ) )
+ return $value;
+ elseif ( ! $strict)
+ return NULL;
+ throw new OC_Shorty_Exception ( "invalid value '%s' for type '%s'", array( ((24<sizeof($value))?$value:substr($value,0,21).'…'),$type) );
+ case self::STRING:
+ if ( preg_match ( '/^.*$/x', str_replace("\n","\\n",$value) ) )
+ return str_replace("\n","\\n",$value);
+ elseif ( ! $strict)
+ return NULL;
+ throw new OC_Shorty_Exception ( "invalid value '%s' for type '%s'", array( ((24<sizeof($value))?$value:substr($value,0,21).'…'),$type) );
+ case self::URL:
+// $pattern = '/^([a-zA-Z][a-zA-Z][a-zA-Z0-9]+)\:\/\/([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&amp;%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*(\/($|[a-zA-Z0-9\.\;\:\,\@\?\'\\\+&amp;%\$#\=~_\-]+)?)*$/';
+ $pattern = '/^([a-zA-Z][a-zA-Z][a-zA-Z0-9]+)\:\/\/([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&amp;%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*(\/($|.+)?)*$/';
+ if ( preg_match ( $pattern, $value ) )
+ return $value;
+ elseif ( ! $strict)
+ return NULL;
+ throw new OC_Shorty_Exception ( "invalid value '%s' for type '%s'", array( ((24<sizeof($value))?$value:substr($value,0,21).'…'),$type) );
+ case self::INTEGER:
+ if ( preg_match ( '/^[0-9]+$/', $value ) )
+ return $value;
+ elseif ( ! $strict)
+ return NULL;
+ throw new OC_Shorty_Exception ( "invalid value '%s' for type '%s'", array( ((24<sizeof($value))?$value:substr($value,0,21).'…'),$type) );
+ case self::FLOAT:
+ if ( preg_match ( '/^[0-9]+(\.[0-9]+)?$/', $value ) )
+ return $value;
+ throw new OC_Shorty_Exception ( "invalid value '%s' for type '%s'", array( ((24<sizeof($value))?$value:substr($value,0,21).'…'),$type) );
+ case self::TIMESTAMP:
+ if ( preg_match ( '/^[0-9]{10}$/', $value ) )
+ return $value;
+ elseif ( ! $strict)
+ return NULL;
+ throw new OC_Shorty_Exception ( "invalid value '%s' for type '%s'", array( ((24<sizeof($value))?$value:substr($value,0,21).'…'),$type) );
+ case self::DATE:
+ if (FALSE!==($time=strtotime($value)))
+ return $time;
+ elseif ( ! $strict)
+ return NULL;
+ throw new OC_Shorty_Exception ( "invalid value '%s' for type '%s'", array( ((24<sizeof($value))?$value:substr($value,0,21).'…'),$type) );
+ } // switch $type
+ throw new OC_Shorty_Exception ( "unknown request argument type '%s'", array($type) );
+ } // function is_valid
+
+ /**
+ * @method OC_Shorty_Type::normalize
+ * @brief cleanup and formal normalization of a given value according to its type
+ * Normalizes a given value according to its claimed type.
+ * This typically means trimming of string values, but sometimes also more specific actions.
+ * @param value the value to be normalized
+ * @param type the supposed type of the value
+ * @param strict boolean flag indicating if the normalization should be done in a strict way
+ * @returns the normalized value
+ * @throws error indicating a parameter violation
+ * @access public
+ * @author Christian Reiner
+ */
+ static function normalize ( $value, $type, $strict=FALSE )
+ {
+ if (NULL===(self::validate($value,$type,$strict)))
+ {
+ if ( ! $strict)
+ return NULL;
+ else
+ throw new OC_Shorty_Exception ( "invalid value '%1\$s' for type '%2\$s'", array($value,$type) );
+ } // if
+ switch ( $type )
+ {
+ case self::ID: return trim ( $value );
+ case self::STATUS: return trim ( $value );
+ case self::SORTKEY: return trim ( $value );
+ case self::SORTVAL: return trim ( $value );
+ case self::STRING: return trim ( $value );
+ case self::URL: return trim ( $value );
+ case self::INTEGER: return sprintf ( '%d', $value );
+ case self::FLOAT: return sprintf ( '%f', $value );
+ case self::TIMESTAMP: return trim ( $value );
+ case self::DATE: return date ( 'Y-m-d', self::validate($value,OC_Shorty_Type::DATE) );
+ } // switch $type
+ throw new OC_Shorty_Exception ( "unknown request argument type '%s'", array($type) );
+ } // function normalize
+
+ /**
+ * @method OC_Shorty_Type::req_argument
+ * @brief returns checked request argument or throws an error
+ * @param arg (string) name of the request argument to get_argument
+ * @param strict (bool) controls if an exception will be thrown upon a missing argument
+ * @returns (string) checked and prepared value of request argument
+ * @throws error indicating a parameter violation
+ * @access public
+ * @author Christian Reiner
+ */
+ static function req_argument ( $arg, $type, $strict=FALSE )
+ {
+ switch ( $_SERVER['REQUEST_METHOD'] )
+ {
+ case 'POST':
+ if ( isset($_POST[$arg]) && !empty($_POST[$arg]) )
+ return self::normalize ( urldecode($_POST[$arg]), $type ) ;
+ elseif ( ! $strict)
+ return NULL;
+ throw new OC_Shorty_Exception ( "missing mandatory argument '%1s'", array($arg) );
+ case 'GET':
+ if ( isset($_GET[$arg]) && !empty($_GET[$arg]) )
+ return self::normalize ( urldecode(trim($_GET[$arg])), $type, $strict );
+ elseif ( ! $strict)
+ return NULL;
+ throw new OC_Shorty_Exception ( "missing mandatory argument '%1s'", array($arg) );
+ default:
+ throw new OC_Shorty_Exception ( "unexpected http request method '%1s'", array($_SERVER['REQUEST_METHOD']) );
+ }
+ } // function req_argument
+
+} // class OC_Shorty_Query
+?>