From 0a921c4b5f6e028691c4aa7d63a008ba7e4aefd8 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Tue, 9 Dec 2014 15:53:56 -0500 Subject: [PATCH 01/72] Add session list Webservice - refs BT#9167 --- main/inc/lib/sessionmanager.lib.php | 44 ++++++++++ main/webservices/registration.soap.php | 108 ++++++++++++++++++++++++- 2 files changed, 151 insertions(+), 1 deletion(-) diff --git a/main/inc/lib/sessionmanager.lib.php b/main/inc/lib/sessionmanager.lib.php index 51cf69d49e..fb2bea0b9a 100755 --- a/main/inc/lib/sessionmanager.lib.php +++ b/main/inc/lib/sessionmanager.lib.php @@ -5438,4 +5438,48 @@ class SessionManager )); } + /** + * Returns the list of session (name, short description, start date, end date) from category. + * The short description is an extra field value + * @param $categoryId + * @return mixed + */ + public static function getSessionBriefListByCategory($categoryId) + { + $categoryId = (int) $categoryId; + $sessionList = array(); + if ($categoryId > 0) { + $sTable = Database::get_main_table(TABLE_MAIN_SESSION); + $sfTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD); + $sfvTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES); + $joinTable = $sfTable . ' sf INNER JOIN ' . $sfvTable . ' sfv ON sf.id = sfv.field_id'; + $sessionList = Database::select( + 'id, name, date_start, date_end', + $sTable, + array( + 'where' => array( + 'session_category_id = ?' => $categoryId + ) + ) + ); + $sessionFieldValueList = Database::select( + 'sfv.session_id AS id, sfv.field_value AS description', + $joinTable, + array( + 'where' => array( + 'sf.field_variable = ?' => 'as_description' + ) + ) + ); + + } + + foreach ($sessionList as $id => &$session) { + $session['description'] = isset($sessionFieldValueList[$id]) ? + $sessionFieldValueList[$id]['description'] : + ''; + } + + return $sessionList; + } } diff --git a/main/webservices/registration.soap.php b/main/webservices/registration.soap.php index 931c521aec..85ee140762 100755 --- a/main/webservices/registration.soap.php +++ b/main/webservices/registration.soap.php @@ -13,6 +13,9 @@ require_once $libpath.'add_course.lib.inc.php'; $debug = false; define('WS_ERROR_SECRET_KEY', 1); +define('WS_ERROR_NOT_FOUND_RESULT', 2); +define('WS_ERROR_INVALID_INPUT', 3); + function return_error($code) { $fault = null; @@ -20,6 +23,12 @@ function return_error($code) { case WS_ERROR_SECRET_KEY: $fault = new soap_fault('Server', '', 'Secret key is not correct or params are not correctly set'); break; + case WS_ERROR_NOT_FOUND_RESULT: + $fault = new soap_fault('Server', '', 'Not found any result from the query'); + break; + case WS_ERROR_INVALID_INPUT: + $fault = new soap_fault('Server', '', 'The input variables are invalid o are not correctly set'); + break; } return $fault; } @@ -5437,7 +5446,7 @@ $server->wsdl->addComplexType( 'SOAP-ENC:Array', array(), array( - array('ref'=>'SOAP:ENC:arrayType', + array('ref'=>'SOAP-ENC:arrayType', 'wsdl:arrayType'=>'tns:session[]') ), 'tns:session' @@ -5542,6 +5551,103 @@ function WSUserSubscribedInCourse ($params) return (CourseManager::is_user_subscribed_in_course($userId,$courseCode)); } +/** WSSessionListInCategory */ + +// Output params for WSSessionListInCategory +$server->wsdl->addComplexType( + 'sessionBrief', + 'complexType', + 'struct', + 'all', + '', + array( + 'name' => array('name' => 'name', 'type' => 'xsd:string'), //Course string code + 'description' => array('name' => 'description', 'type' => 'xsd:string'), //Chamilo user_id + 'date_start' => array('name' => 'start_date', 'type' => 'xsd:string'), + 'date_end' => array('name' => 'end_date', 'type' => 'xsd:string'), + ) +); + +$server->wsdl->addComplexType( + 'sessionBriefList', + 'complexType', + 'array', + '', + 'SOAP-ENC:Array', + array(), + array( + array('ref'=>'SOAP-ENC:arrayType', + 'wsdl:arrayType'=>'tns:sessionBrief[]') + ), + 'tns:sessionBrief' +); + +// Input params for editing users +$server->wsdl->addComplexType( + 'sessionCategoryInput', + 'complexType', + 'struct', + 'all', + '', + array( + 'id' => array('name' => 'id', 'type' => 'xsd:string'), //Course string code + 'name' => array('name' => 'name', 'type' => 'xsd:string'), //Chamilo user_id + 'secret_key' => array('name' => 'secret_key', 'type' => 'xsd:string') + ) +); + +// Register the method to expose +$server->register('WSSessionListInCategory', // method name + array('sessionCategoryInput' => 'tns:sessionCategoryInput'), // input parameters + array('return' => 'tns:sessionBriefList'), // output parameters + 'urn:WSRegistration', // namespace + 'urn:WSRegistration#WSSessionListInCategory', // soapaction + 'rpc', // style + 'encoded', // use + 'This service checks if user assigned to course' // documentation +); + + +/** + * @param $params + * @return null|soap_fault + */ +function WSSessionListInCategory($params) { + global $debug; + + if ($debug) error_log('WSUserSubscribedInCourse'); + if ($debug) error_log('Params '. print_r($params, 1)); + if (!WSHelperVerifyKey($params)) { + + return return_error(WS_ERROR_SECRET_KEY); + } + // Check if category ID is set + if (!empty($params['id']) && empty($params['category_name'])) { + $sessionCategoryId = $params['id']; + } elseif (!empty($params['category_name'])) { + // Check if category name is set + $sessionCategoryId = SessionManager::getSessionCategoryIdByName($params['category_name']); + if (is_array($sessionCategoryId)) { + $sessionCategoryId = current($sessionCategoryId); + } + } else { + // Return soap fault Not valid input params + + return return_error(WS_ERROR_INVALID_INPUT); + } + + // Get the session brief List by category + + $sessionList = SessionManager::getSessionBriefListByCategory($sessionCategoryId); + + if (empty($sessionList)) { + + return return_error(WS_ERROR_NOT_FOUND_RESULT); + } + + return $sessionList; +} + // Add more webservices by Hooks if (!empty($hook)) { $hook->setEventData(array('server' => $server)); From 0c77db9dd5db3cf62e336fc2fc6996461cf7a8f3 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Thu, 11 Dec 2014 11:41:06 -0500 Subject: [PATCH 02/72] Init advanced subscription plugin - refs BT#9092 --- plugin/advancedsubscription/README.md | 4 + plugin/advancedsubscription/config.php | 15 + plugin/advancedsubscription/index.php | 7 + plugin/advancedsubscription/install.php | 15 + plugin/advancedsubscription/lang/english.php | 21 ++ plugin/advancedsubscription/lang/french.php | 21 ++ plugin/advancedsubscription/lang/spanish.php | 21 ++ plugin/advancedsubscription/plugin.php | 12 + plugin/advancedsubscription/readme.txt | 2 + .../advanced_subscription_plugin.class.php | 286 ++++++++++++++++++ plugin/advancedsubscription/src/index.php | 1 + plugin/advancedsubscription/uninstall.php | 16 + 12 files changed, 421 insertions(+) create mode 100644 plugin/advancedsubscription/README.md create mode 100644 plugin/advancedsubscription/config.php create mode 100644 plugin/advancedsubscription/index.php create mode 100644 plugin/advancedsubscription/install.php create mode 100644 plugin/advancedsubscription/lang/english.php create mode 100644 plugin/advancedsubscription/lang/french.php create mode 100644 plugin/advancedsubscription/lang/spanish.php create mode 100644 plugin/advancedsubscription/plugin.php create mode 100644 plugin/advancedsubscription/readme.txt create mode 100644 plugin/advancedsubscription/src/advanced_subscription_plugin.class.php create mode 100644 plugin/advancedsubscription/src/index.php create mode 100644 plugin/advancedsubscription/uninstall.php diff --git a/plugin/advancedsubscription/README.md b/plugin/advancedsubscription/README.md new file mode 100644 index 0000000000..5e08c22523 --- /dev/null +++ b/plugin/advancedsubscription/README.md @@ -0,0 +1,4 @@ +Advanced subscription plugin for Chamilo LMS +======================================= +@TODO:Edit README.md + diff --git a/plugin/advancedsubscription/config.php b/plugin/advancedsubscription/config.php new file mode 100644 index 0000000000..fbaf47a779 --- /dev/null +++ b/plugin/advancedsubscription/config.php @@ -0,0 +1,15 @@ + + * @package chamilo.plugin.advanced_subscription + */ + +define('TABLE_ADV_SUB_QUEUE', 'plugin_advsub_queue'); +define('TABLE_ADV_SUB_MAIL', 'plugin_advsub_mail'); +define('TABLE_ADV_SUB_MAIL_TYPE', 'plugin_advsub_mail_type'); +define('TABLE_ADV_SUB_MAIL_STATUS', 'plugin_advsub_mail_status'); +require_once __DIR__ . '/../../main/inc/global.inc.php'; +require_once api_get_path(LIBRARY_PATH) . 'plugin.class.php'; +require_once api_get_path(PLUGIN_PATH) . 'advancedsubscription/src/advanced_subscription_plugin.class.php'; diff --git a/plugin/advancedsubscription/index.php b/plugin/advancedsubscription/index.php new file mode 100644 index 0000000000..6ae74e5060 --- /dev/null +++ b/plugin/advancedsubscription/index.php @@ -0,0 +1,7 @@ +install(); diff --git a/plugin/advancedsubscription/lang/english.php b/plugin/advancedsubscription/lang/english.php new file mode 100644 index 0000000000..99dba6639c --- /dev/null +++ b/plugin/advancedsubscription/lang/english.php @@ -0,0 +1,21 @@ +Plugins) + * @package chamilo.plugin.advanced_subscription + */ +/** + * Plugin details (must be present) + */ +require_once __DIR__ . '/config.php'; +$plugin_info = AdvancedSubscriptionPlugin::create()->get_info(); diff --git a/plugin/advancedsubscription/readme.txt b/plugin/advancedsubscription/readme.txt new file mode 100644 index 0000000000..d99dd4cf2a --- /dev/null +++ b/plugin/advancedsubscription/readme.txt @@ -0,0 +1,2 @@ +Advanced subscription plugin

+@TODO: Complete readme.txt diff --git a/plugin/advancedsubscription/src/advanced_subscription_plugin.class.php b/plugin/advancedsubscription/src/advanced_subscription_plugin.class.php new file mode 100644 index 0000000000..a92e106de1 --- /dev/null +++ b/plugin/advancedsubscription/src/advanced_subscription_plugin.class.php @@ -0,0 +1,286 @@ + 'boolean', + 'ws_url' => 'text', + 'min_profile_percentage' => 'text', + 'max_expended_uit' => 'text', + 'max_expended_num' => 'text', + 'max_course_times' => 'text', + 'check_induction' => 'boolean', + 'confirmation_message' => 'wysiwyg' + ); + + parent::__construct('1.0', 'Daniel Alejandro Barreto Alva', $parameters); + } + + /** + * Instance the plugin + * @staticvar null $result + * @return AdvancedSubscriptionPlugin + */ + static function create() + { + static $result = null; + + return $result ? $result : $result = new self(); + } + + /** + * Install the plugin + * @return void + */ + public function install() + { + $this->installDatabase(); + } + + /** + * Uninstall the plugin + * @return void + */ + public function uninstall() + { + $this->unistallDatabase(); + } + + /** + * Create the database tables for the plugin + * @return void + */ + private function installDatabase() + { + $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); + $pAdvSubMailTable = Database::get_main_table(TABLE_ADV_SUB_MAIL); + $pAdvSubMailTypeTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_TYPE); + $pAdvSubMailStatusTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_STATUS); + + $sql = "CREATE TABLE IF NOT EXISTS $pAdvSubQueueTable (" . + "id int UNSIGNED NOT NULL AUTO_INCREMENT, " . + "session_id varchar(255) NOT NULL, " . + "user_id int UNSIGNED NOT NULL, " . + "status int UNSIGNED NOT NULL, " . + "created_at datetime NOT NULL, " . + "updated_at datetime NULL, " . + "PRIMARY KEY PK_tour_log (id)); "; + + $sql .= "CREATE TABLE $pAdvSubMailTypeTable ( " . + "id int UNSIGNED NOT NULL AUTO_INCREMENT, " . + "description char(20), " . + "PRIMARY KEY PK_advsub_mail_type (id) " . + "); "; + $sql .= "CREATE TABLE $pAdvSubMailTable ( " . + "id int UNSIGNED NOT NULL AUTO_INCREMENT, " . + "message_id, mail_type_id, mail_status_id, " . + "PRIMARY KEY PK_advsub_mail (id) " . + "); "; + + $sql .= "CREATE TABLE $pAdvSubMailStatusTable ( " . + "id int UNSIGNED NOT NULL AUTO_INCREMENT, " . + "description char(20), " . + "PRIMARY KEY PK_advsub_mail_status (id) " . + "); "; + + echo $sql; + //Database::query($sql); + } + + /** + * Drop the database tables for the plugin + * @return void + */ + private function unistallDatabase() + { + $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); + $pAdvSubMailTable = Database::get_main_table(TABLE_ADV_SUB_MAIL); + $pAdvSubMailTypeTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_TYPE); + $pAdvSubMailStatusTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_STATUS); + + $sql = "DROP TABLE IF EXISTS $pAdvSubQueueTable; "; + $sql .= "DROP TABLE IF EXISTS $pAdvSubMailTable; "; + $sql .= "DROP TABLE IF EXISTS $pAdvSubMailTypeTable; "; + $sql .= "DROP TABLE IF EXISTS $pAdvSubMailStatusTable; "; + + Database::query($sql); + } + + /** + * Return true if user is able to be added to queue for session subscription + * @param $userId + * @throws Exception + * @return bool + */ + public function isAbleToRequest($userId) + { + $isAble = false; + $advSubPlugin = self::create(); + $wsUrl = $advSubPlugin->get('ws_url'); + // @TODO: Get connection status from user by WS + $isConnected = true; + if ($isConnected) { + $profileCompletedMin = $advSubPlugin->get('min_profile_percentage'); + // @TODO: Get completed profile percentage by WS + $profileCompleted = 100.0; + if ($profileCompleted > $profileCompletedMin) { + $checkInduction = $advSubPlugin->get('check_induction'); + // @TODO: check if user have completed at least one induction session + $completedInduction = true; + if (!$checkInduction || $completedInduction) { + $uitMax = $advSubPlugin->get('uit_value'); + $uitMax *= $advSubPlugin->get('max_expended_uit'); + // @TODO: Get UIT completed by user this year by WS + $uitUser = 0; + if ($uitMax > $uitUser) { + $expendedTimeMax = $advSubPlugin->get('max_expended_time'); + // @TODO: Get Expended time from user data + $expendedTime = 0; + if ($expendedTimeMax > $expendedTime) { + $expendedNumMax = $advSubPlugin->get('max_expended_num'); + // @TODO: Get Expended num from user + $expendedNum = 0; + if ($expendedNumMax > $expendedNum) { + $isAble = true; + } else { + throw new \Exception(get_lang('AdvancedSubscriptionCourseXLimitReached')); + } + } else { + throw new \Exception(get_lang('AdvancedSubscriptionTimeXLimitReached')); + } + } else { + throw new \Exception(get_lang('AdvancedSubscriptionCostXLimitReached')); + } + } else { + throw new \Exception(get_lang('AdvancedSubscriptionIncompleteInduction')); + } + } else { + throw new \Exception(get_lang('AdvancedSubscriptionProfileIncomplete')); + } + } else { + throw new \Exception(get_lang('AdvancedSubscriptionNotConnected')); + } + + return $isAble; + } + + /** + * @param $userId + * @param $sessionId + */ + public function addToQueue($userId, $sessionId) + { + $now = api_get_utc_datetime(); + $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); + $sql = "INSERT INTO $pAdvSubQueueTable ( " . + "session_id, user_id, status, created_at, updated_at " . + ") VALUES ( " . + "$sessionId, $userId, 0, $now, NULL "; + "); "; + + } + + /** + * @param $userId + * @param $sessionId + * @return bool|string + */ + public function startSubscription($userId, $sessionId) + { + $result = false; + $advSub = self::create(); + try { + if ($advSub->isAbleToRequest($userId)) { + $advSub->addToQueue($userId, $sessionId); + $result = true; + } else { + throw new \Exception(get_lang('AdvancedSubscriptionNotMoreAble')); + } + } catch (Exception $e) { + $result = $e->getMessage(); + } + + return $result; + } + + /** + * Check whether the tour should be displayed to the user + * @param string $currentPageClass The class of the current page + * @param int $userId The user id + * @return boolean If the user has seen the tour return false, otherwise return true + */ + public function checkTourForUser($currentPageClass, $userId) + { + $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); + $pAdvSubMailTable = Database::get_main_table(TABLE_ADV_SUB_MAIL); + $pAdvSubMailTypeTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_TYPE); + $pAdvSubMailStatusTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_STATUS); + $pluginTourLogTable = Database::get_main_table(TABLE_TOUR_LOG); + + $checkResult = Database::select('count(1) as qty', $pluginTourLogTable, array( + 'where' => array( + "page_class = '?' AND " => $currentPageClass, + "user_id = ?" => intval($userId) + )), 'first'); + + if ($checkResult !== false) { + if ($checkResult['qty'] > 0) { + return false; + } + } + + return true; + } + + /** + * Set the tour as seen + * @param string $currentPageClass The class of the current page + * @param int $userId The user id + * @return void + */ + public function saveCompletedTour($currentPageClass, $userId) + { + $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); + $pAdvSubMailTable = Database::get_main_table(TABLE_ADV_SUB_MAIL); + $pAdvSubMailTypeTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_TYPE); + $pAdvSubMailStatusTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_STATUS); + $pluginTourLogTable = Database::get_main_table(TABLE_TOUR_LOG); + + Database::insert($pluginTourLogTable, array( + 'page_class' => $currentPageClass, + 'user_id' => intval($userId), + 'visualization_datetime' => api_get_utc_datetime() + )); + } + + /** + * Get the configuration to show the tour in pages + * @return array The config data + */ + public function getTourConfig() + { + $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); + $pAdvSubMailTable = Database::get_main_table(TABLE_ADV_SUB_MAIL); + $pAdvSubMailTypeTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_TYPE); + $pAdvSubMailStatusTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_STATUS); + $pluginPath = api_get_path(PLUGIN_PATH) . 'tour/'; + + $jsonContent = file_get_contents($pluginPath . 'config/tour.json'); + + $jsonData = json_decode($jsonContent, true); + + return $jsonData; + } +} diff --git a/plugin/advancedsubscription/src/index.php b/plugin/advancedsubscription/src/index.php new file mode 100644 index 0000000000..b3d9bbc7f3 --- /dev/null +++ b/plugin/advancedsubscription/src/index.php @@ -0,0 +1 @@ +uninstall(); From fdd0ad4d70773d3731cf83249489d0298e672305 Mon Sep 17 00:00:00 2001 From: Imanol Losada Date: Wed, 3 Dec 2014 10:05:13 -0500 Subject: [PATCH 03/72] Create advancedsubscription plugin - refs BT#9092 Conflicts: plugin/advancedsubscription/config.php plugin/advancedsubscription/index.php plugin/advancedsubscription/install.php plugin/advancedsubscription/lang/english.php plugin/advancedsubscription/lang/spanish.php plugin/advancedsubscription/plugin.php plugin/advancedsubscription/readme.txt plugin/advancedsubscription/uninstall.php --- plugin/advancedsubscription/install.php | 4 +- plugin/advancedsubscription/lang/english.php | 2 +- plugin/advancedsubscription/lang/spanish.php | 16 ++++- .../advanced_subscription_plugin.class.php | 63 +++++++++++++++++++ plugin/advancedsubscription/license.txt | 1 + plugin/advancedsubscription/readme.txt | 1 + plugin/advancedsubscription/uninstall.php | 7 ++- 7 files changed, 88 insertions(+), 6 deletions(-) create mode 100755 plugin/advancedsubscription/lib/advanced_subscription_plugin.class.php create mode 100644 plugin/advancedsubscription/license.txt diff --git a/plugin/advancedsubscription/install.php b/plugin/advancedsubscription/install.php index 9a4fd87b3a..a194fc807e 100644 --- a/plugin/advancedsubscription/install.php +++ b/plugin/advancedsubscription/install.php @@ -3,11 +3,13 @@ /** * This script is included by main/admin/settings.lib.php and generally * includes things to execute in the main database (settings_current table) - * @package chamilo.plugin.buycourses + * @package chamilo.plugin.advancedsubscription */ + /** * Initialization */ + require_once dirname(__FILE__) . '/config.php'; if (!api_is_platform_admin()) { die ('You must have admin permissions to install plugins'); diff --git a/plugin/advancedsubscription/lang/english.php b/plugin/advancedsubscription/lang/english.php index 99dba6639c..5c61d55318 100644 --- a/plugin/advancedsubscription/lang/english.php +++ b/plugin/advancedsubscription/lang/english.php @@ -18,4 +18,4 @@ $strings['AdvancedSubscriptionIncompleteInduction'] = "Usted aún no ha completa $strings['AdvancedSubscriptionCostXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s UIT para los cursos que ha seguido este año"; $strings['AdvancedSubscriptionTimeXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s horas para los cursos que ha seguido este año"; $strings['AdvancedSubscriptionCourseXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s cursos que ha seguido este año"; -$strings['AdvancedSubscriptionNotMoreAble'] = "Lo sentimos, usted ya no cumple con las condiciones iniciales para poder inscribirse al curso"; \ No newline at end of file +$strings['AdvancedSubscriptionNotMoreAble'] = "Lo sentimos, usted ya no cumple con las condiciones iniciales para poder inscribirse al curso"; diff --git a/plugin/advancedsubscription/lang/spanish.php b/plugin/advancedsubscription/lang/spanish.php index 99dba6639c..6f10f48491 100644 --- a/plugin/advancedsubscription/lang/spanish.php +++ b/plugin/advancedsubscription/lang/spanish.php @@ -18,4 +18,18 @@ $strings['AdvancedSubscriptionIncompleteInduction'] = "Usted aún no ha completa $strings['AdvancedSubscriptionCostXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s UIT para los cursos que ha seguido este año"; $strings['AdvancedSubscriptionTimeXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s horas para los cursos que ha seguido este año"; $strings['AdvancedSubscriptionCourseXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s cursos que ha seguido este año"; -$strings['AdvancedSubscriptionNotMoreAble'] = "Lo sentimos, usted ya no cumple con las condiciones iniciales para poder inscribirse al curso"; \ No newline at end of file +$strings['AdvancedSubscriptionNotMoreAble'] = "Lo sentimos, usted ya no cumple con las condiciones iniciales para poder inscribirse al curso"; + +//Needed in order to show the plugin title +$strings['tool_enable'] = 'Suscripción avanzada activada'; +$strings['tool_enable_help'] = "Escoja si desea activar la suscripción avanzada."; +$strings['yearly_cost_limit'] = 'Límite de UITs'; +$strings['yearly_cost_limit_help'] = "El límite de UITs de cursos que se pueden llevar en un año calendario del año actual."; +$strings['yearly_hours_limit'] = 'Límite de horas lectivas'; +$strings['yearly_hours_limit_help'] = "El límite de horas lectivas de cursos que se pueden llevar en un año calendario del año actual."; +$strings['yearly_cost_unit_converter'] = 'Valor de un UIT'; +$strings['yearly_cost_unit_converter_help'] = "El valor en Soles de un UIT del año actual."; +$strings['courses_count_limit'] = 'Límite de sesiones'; +$strings['courses_count_limit_help'] = "El límite de cantidad de cursos (sesiones) que se pueden llevar en un año calendario del año actual y que no sean el curso de inducción"; +$strings['course_session_credit_year_start_date'] = 'Fecha de inicio'; +$strings['course_session_credit_year_start_date_help'] = "Fecha de inicio del año (día/mes)"; diff --git a/plugin/advancedsubscription/lib/advanced_subscription_plugin.class.php b/plugin/advancedsubscription/lib/advanced_subscription_plugin.class.php new file mode 100755 index 0000000000..1ba517379f --- /dev/null +++ b/plugin/advancedsubscription/lib/advanced_subscription_plugin.class.php @@ -0,0 +1,63 @@ + + */ +class AdvancedSubscriptionPlugin extends Plugin +{ + //public $isCoursePlugin = true; + + /** + * create (a singleton function that ensures AdvancedSubscriptionPlugin instance is + * created only once. If it is already created, it returns the instance) + * @return object AdvancedSubscriptionPlugin instance + */ + public static function create() + { + static $result = null; + return $result ? $result : $result = new self(); + } + + /** + * Constructor + * @return void + */ + protected function __construct() + { + parent::__construct( + '0.1', + 'Imanol Losada', + array( + 'tool_enable' => 'boolean', + 'yearly_cost_limit' => 'text', + 'yearly_hours_limit' => 'text', + 'yearly_cost_unit_converter' => 'text', + 'courses_count_limit' => 'text', + 'course_session_credit_year_start_date' => 'text' + ) + ); + } + + /** + * install (installs the plugin) + * @return void + */ + public function install() + { + + } + /** + * install (uninstalls the plugin and removes all plugin's tables and/or rows) + * @return void + */ + public function uninstall() + { + $tSettings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT); + Database::query("DELETE FROM $tSettings WHERE subkey = 'advancedsubscription'"); + } +} diff --git a/plugin/advancedsubscription/license.txt b/plugin/advancedsubscription/license.txt new file mode 100644 index 0000000000..a7619191f8 --- /dev/null +++ b/plugin/advancedsubscription/license.txt @@ -0,0 +1 @@ +This plugin, as the rest of Chamilo, is released under the GNU/GPLv3 license. diff --git a/plugin/advancedsubscription/readme.txt b/plugin/advancedsubscription/readme.txt index d99dd4cf2a..dd46052900 100644 --- a/plugin/advancedsubscription/readme.txt +++ b/plugin/advancedsubscription/readme.txt @@ -1,2 +1,3 @@ Advanced subscription plugin

@TODO: Complete readme.txt +This plugin enables Chamilo to extend its subscribe parameters. diff --git a/plugin/advancedsubscription/uninstall.php b/plugin/advancedsubscription/uninstall.php index 85cb3df537..4ee930e3c5 100644 --- a/plugin/advancedsubscription/uninstall.php +++ b/plugin/advancedsubscription/uninstall.php @@ -4,13 +4,14 @@ * This script is included by main/admin/settings.lib.php when unselecting a plugin * and is meant to remove things installed by the install.php script in both * the global database and the courses tables - * @package chamilo.plugin.buycourses - */ + * @package chamilo.plugin.advancedsubscription +*/ + /** * Queries */ require_once dirname(__FILE__) . '/config.php'; if (!api_is_platform_admin()) { - die ('You must have admin permissions to install plugins'); + die ('You must have admin permissions to uninstall plugins'); } AdvancedSubscriptionPlugin::create()->uninstall(); From 78c28b802aa0739a047df0133cda43a6f4286d3a Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Thu, 11 Dec 2014 12:20:56 -0500 Subject: [PATCH 04/72] Complete merge with BT#9091 - refs BT#9092 --- plugin/advancedsubscription/config.php | 2 +- plugin/advancedsubscription/lang/spanish.php | 30 +++++---- .../advanced_subscription_plugin.class.php | 63 ------------------- plugin/advancedsubscription/plugin.php | 2 +- .../advanced_subscription_plugin.class.php | 29 +++++---- 5 files changed, 34 insertions(+), 92 deletions(-) delete mode 100755 plugin/advancedsubscription/lib/advanced_subscription_plugin.class.php diff --git a/plugin/advancedsubscription/config.php b/plugin/advancedsubscription/config.php index fbaf47a779..d47802dd43 100644 --- a/plugin/advancedsubscription/config.php +++ b/plugin/advancedsubscription/config.php @@ -3,7 +3,7 @@ /** * Config the plugin * @author Daniel Alejandro Barreto Alva - * @package chamilo.plugin.advanced_subscription + * @package chamilo.plugin.advancedsubscription */ define('TABLE_ADV_SUB_QUEUE', 'plugin_advsub_queue'); diff --git a/plugin/advancedsubscription/lang/spanish.php b/plugin/advancedsubscription/lang/spanish.php index 6f10f48491..f833606f65 100644 --- a/plugin/advancedsubscription/lang/spanish.php +++ b/plugin/advancedsubscription/lang/spanish.php @@ -3,24 +3,10 @@ /* Strings for settings */ $strings['plugin_title'] = 'Inscripción Avanzada'; $strings['plugin_comment'] = 'Plugin que permite gestionar la inscripción en cola a sesiones con comunicación a a un portal externo'; -$strings['uit_value'] = 'Valor de la Unidad Impositiva Tributaria (UIT)'; $strings['ws_url'] = 'URL del Webservice'; -$strings['min_profile_percentage'] = 'Porcentaje mínimo de perfil completado'; -$strings['max_expended_uit'] = 'Limite anual de cursos en UIT por año(Medido en UIT)'; -$strings['max_expended_num'] = 'Limite anual de cursos en horas por año(Medido en UIT)'; -$strings['max_course_times'] = 'Limite anual de cantidad de cursos por año'; +$strings['ws_url_help'] = 'La URL de la cual se solicitará información para el proceso de la inscripción avanzada'; $strings['check_induction'] = 'Activar requerimiento de curso inducción'; - -/* String for error message about requirements */ -$strings['AdvancedSubscriptionNotConnected'] = "Usted no está conectado en la plataforma. Por favor ingrese su usuario / constraseña para poder inscribirse"; -$strings['AdvancedSubscriptionProfileIncomplete'] = "Su perfil no es lo suficientemente completo para poder inscribirse al curso. Por favor complete su perfil"; -$strings['AdvancedSubscriptionIncompleteInduction'] = "Usted aún no ha completado el curso de inducción. Por favor complete el curso inducción"; -$strings['AdvancedSubscriptionCostXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s UIT para los cursos que ha seguido este año"; -$strings['AdvancedSubscriptionTimeXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s horas para los cursos que ha seguido este año"; -$strings['AdvancedSubscriptionCourseXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s cursos que ha seguido este año"; -$strings['AdvancedSubscriptionNotMoreAble'] = "Lo sentimos, usted ya no cumple con las condiciones iniciales para poder inscribirse al curso"; - -//Needed in order to show the plugin title +$strings['check_induction_help'] = 'Escoja si se requiere que se complete los cursos de inducción'; $strings['tool_enable'] = 'Suscripción avanzada activada'; $strings['tool_enable_help'] = "Escoja si desea activar la suscripción avanzada."; $strings['yearly_cost_limit'] = 'Límite de UITs'; @@ -33,3 +19,15 @@ $strings['courses_count_limit'] = 'Límite de sesiones'; $strings['courses_count_limit_help'] = "El límite de cantidad de cursos (sesiones) que se pueden llevar en un año calendario del año actual y que no sean el curso de inducción"; $strings['course_session_credit_year_start_date'] = 'Fecha de inicio'; $strings['course_session_credit_year_start_date_help'] = "Fecha de inicio del año (día/mes)"; + + +/* String for error message about requirements */ +$strings['AdvancedSubscriptionNotConnected'] = "Usted no está conectado en la plataforma. Por favor ingrese su usuario / constraseña para poder inscribirse"; +$strings['AdvancedSubscriptionProfileIncomplete'] = "Su perfil no es lo suficientemente completo para poder inscribirse al curso. Por favor complete su perfil"; +$strings['AdvancedSubscriptionIncompleteInduction'] = "Usted aún no ha completado el curso de inducción. Por favor complete el curso inducción"; +$strings['AdvancedSubscriptionCostXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s UIT para los cursos que ha seguido este año"; +$strings['AdvancedSubscriptionTimeXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s horas para los cursos que ha seguido este año"; +$strings['AdvancedSubscriptionCourseXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s cursos que ha seguido este año"; +$strings['AdvancedSubscriptionNotMoreAble'] = "Lo sentimos, usted ya no cumple con las condiciones iniciales para poder inscribirse al curso"; + +//Needed in order to show the plugin title diff --git a/plugin/advancedsubscription/lib/advanced_subscription_plugin.class.php b/plugin/advancedsubscription/lib/advanced_subscription_plugin.class.php deleted file mode 100755 index 1ba517379f..0000000000 --- a/plugin/advancedsubscription/lib/advanced_subscription_plugin.class.php +++ /dev/null @@ -1,63 +0,0 @@ - - */ -class AdvancedSubscriptionPlugin extends Plugin -{ - //public $isCoursePlugin = true; - - /** - * create (a singleton function that ensures AdvancedSubscriptionPlugin instance is - * created only once. If it is already created, it returns the instance) - * @return object AdvancedSubscriptionPlugin instance - */ - public static function create() - { - static $result = null; - return $result ? $result : $result = new self(); - } - - /** - * Constructor - * @return void - */ - protected function __construct() - { - parent::__construct( - '0.1', - 'Imanol Losada', - array( - 'tool_enable' => 'boolean', - 'yearly_cost_limit' => 'text', - 'yearly_hours_limit' => 'text', - 'yearly_cost_unit_converter' => 'text', - 'courses_count_limit' => 'text', - 'course_session_credit_year_start_date' => 'text' - ) - ); - } - - /** - * install (installs the plugin) - * @return void - */ - public function install() - { - - } - /** - * install (uninstalls the plugin and removes all plugin's tables and/or rows) - * @return void - */ - public function uninstall() - { - $tSettings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT); - Database::query("DELETE FROM $tSettings WHERE subkey = 'advancedsubscription'"); - } -} diff --git a/plugin/advancedsubscription/plugin.php b/plugin/advancedsubscription/plugin.php index c3e488788d..a6640a7ba4 100644 --- a/plugin/advancedsubscription/plugin.php +++ b/plugin/advancedsubscription/plugin.php @@ -3,7 +3,7 @@ /** * This script is a configuration file for the date plugin. You can use it as a master for other platform plugins (course plugins are slightly different). * These settings will be used in the administration interface for plugins (Chamilo configuration settings->Plugins) - * @package chamilo.plugin.advanced_subscription + * @package chamilo.plugin.advancedsubscription */ /** * Plugin details (must be present) diff --git a/plugin/advancedsubscription/src/advanced_subscription_plugin.class.php b/plugin/advancedsubscription/src/advanced_subscription_plugin.class.php index a92e106de1..499e2846e9 100644 --- a/plugin/advancedsubscription/src/advanced_subscription_plugin.class.php +++ b/plugin/advancedsubscription/src/advanced_subscription_plugin.class.php @@ -4,7 +4,7 @@ * @TODO: Improve description * This class is used to add an advanced subscription allowing the admin to * create user queues requesting a subscribe to a session - * @package chamilo.plugin.advanced_subscription + * @package chamilo.plugin.advancedsubscription */ class AdvancedSubscriptionPlugin extends Plugin @@ -15,17 +15,19 @@ class AdvancedSubscriptionPlugin extends Plugin function __construct() { $parameters = array( - 'uit_value' => 'boolean', + 'tool_enable' => 'boolean', + 'yearly_cost_limit' => 'text', + 'yearly_hours_limit' => 'text', + 'yearly_cost_unit_converter' => 'text', + 'courses_count_limit' => 'text', + 'course_session_credit_year_start_date' => 'text', 'ws_url' => 'text', 'min_profile_percentage' => 'text', - 'max_expended_uit' => 'text', - 'max_expended_num' => 'text', - 'max_course_times' => 'text', 'check_induction' => 'boolean', 'confirmation_message' => 'wysiwyg' ); - parent::__construct('1.0', 'Daniel Alejandro Barreto Alva', $parameters); + parent::__construct('1.0', 'Imanol Losada, Daniel Barreto', $parameters); } /** @@ -103,8 +105,9 @@ class AdvancedSubscriptionPlugin extends Plugin * Drop the database tables for the plugin * @return void */ - private function unistallDatabase() + private function uninstallDatabase() { + /* Drop plugin tables */ $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); $pAdvSubMailTable = Database::get_main_table(TABLE_ADV_SUB_MAIL); $pAdvSubMailTypeTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_TYPE); @@ -116,6 +119,10 @@ class AdvancedSubscriptionPlugin extends Plugin $sql .= "DROP TABLE IF EXISTS $pAdvSubMailStatusTable; "; Database::query($sql); + + /* Delete settings */ + $tSettings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT); + Database::query("DELETE FROM $tSettings WHERE subkey = 'advancedsubscription'"); } /** @@ -140,16 +147,16 @@ class AdvancedSubscriptionPlugin extends Plugin // @TODO: check if user have completed at least one induction session $completedInduction = true; if (!$checkInduction || $completedInduction) { - $uitMax = $advSubPlugin->get('uit_value'); - $uitMax *= $advSubPlugin->get('max_expended_uit'); + $uitMax = $advSubPlugin->get('yearly_cost_unit_converter'); + $uitMax *= $advSubPlugin->get('yearly_cost_limit'); // @TODO: Get UIT completed by user this year by WS $uitUser = 0; if ($uitMax > $uitUser) { - $expendedTimeMax = $advSubPlugin->get('max_expended_time'); + $expendedTimeMax = $advSubPlugin->get('yearly_hours_limit'); // @TODO: Get Expended time from user data $expendedTime = 0; if ($expendedTimeMax > $expendedTime) { - $expendedNumMax = $advSubPlugin->get('max_expended_num'); + $expendedNumMax = $advSubPlugin->get('courses_count_limit'); // @TODO: Get Expended num from user $expendedNum = 0; if ($expendedNumMax > $expendedNum) { From 60257aab2b79f83d3c39399688bd3952393b37c8 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Thu, 11 Dec 2014 12:49:51 -0500 Subject: [PATCH 05/72] Add empty tpl - refs BT#9092 --- .../views/advsub_approval_admin_accepted_notice_admin.tpl | 1 + .../views/advsub_approval_admin_accepted_notice_student.tpl | 1 + .../views/advsub_approval_admin_accepted_notice_superior.tpl | 1 + .../views/advsub_approval_admin_rejected_notice_admin.tpl | 1 + .../views/advsub_approval_admin_rejected_notice_student.tpl | 1 + .../views/advsub_approval_admin_rejected_notice_superior.tpl | 1 + .../views/advsub_request_approve_confirmed.tpl | 1 + .../views/advsub_request_approved_info_admin.tpl | 1 + .../views/advsub_request_approved_reminder.tpl | 1 + .../views/advsub_request_disapprove_confirmed.tpl | 1 + plugin/advancedsubscription/views/advsub_request_received.tpl | 1 + .../views/advsub_request_received_reminder.tpl | 1 + plugin/advancedsubscription/views/advsub_request_superior.tpl | 1 + .../views/advsub_request_superior_approved.tpl | 1 + .../views/advsub_request_superior_disapproved.tpl | 1 + .../views/advsub_request_superior_reminder.tpl | 1 + 16 files changed, 16 insertions(+) create mode 100644 plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl create mode 100644 plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_student.tpl create mode 100644 plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_superior.tpl create mode 100644 plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_admin.tpl create mode 100644 plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_student.tpl create mode 100644 plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_superior.tpl create mode 100644 plugin/advancedsubscription/views/advsub_request_approve_confirmed.tpl create mode 100644 plugin/advancedsubscription/views/advsub_request_approved_info_admin.tpl create mode 100644 plugin/advancedsubscription/views/advsub_request_approved_reminder.tpl create mode 100644 plugin/advancedsubscription/views/advsub_request_disapprove_confirmed.tpl create mode 100644 plugin/advancedsubscription/views/advsub_request_received.tpl create mode 100644 plugin/advancedsubscription/views/advsub_request_received_reminder.tpl create mode 100644 plugin/advancedsubscription/views/advsub_request_superior.tpl create mode 100644 plugin/advancedsubscription/views/advsub_request_superior_approved.tpl create mode 100644 plugin/advancedsubscription/views/advsub_request_superior_disapproved.tpl create mode 100644 plugin/advancedsubscription/views/advsub_request_superior_reminder.tpl diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl @@ -0,0 +1 @@ + diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_student.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_student.tpl new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_student.tpl @@ -0,0 +1 @@ + diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_superior.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_superior.tpl new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_superior.tpl @@ -0,0 +1 @@ + diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_admin.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_admin.tpl new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_admin.tpl @@ -0,0 +1 @@ + diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_student.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_student.tpl new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_student.tpl @@ -0,0 +1 @@ + diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_superior.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_superior.tpl new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_superior.tpl @@ -0,0 +1 @@ + diff --git a/plugin/advancedsubscription/views/advsub_request_approve_confirmed.tpl b/plugin/advancedsubscription/views/advsub_request_approve_confirmed.tpl new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/plugin/advancedsubscription/views/advsub_request_approve_confirmed.tpl @@ -0,0 +1 @@ + diff --git a/plugin/advancedsubscription/views/advsub_request_approved_info_admin.tpl b/plugin/advancedsubscription/views/advsub_request_approved_info_admin.tpl new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/plugin/advancedsubscription/views/advsub_request_approved_info_admin.tpl @@ -0,0 +1 @@ + diff --git a/plugin/advancedsubscription/views/advsub_request_approved_reminder.tpl b/plugin/advancedsubscription/views/advsub_request_approved_reminder.tpl new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/plugin/advancedsubscription/views/advsub_request_approved_reminder.tpl @@ -0,0 +1 @@ + diff --git a/plugin/advancedsubscription/views/advsub_request_disapprove_confirmed.tpl b/plugin/advancedsubscription/views/advsub_request_disapprove_confirmed.tpl new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/plugin/advancedsubscription/views/advsub_request_disapprove_confirmed.tpl @@ -0,0 +1 @@ + diff --git a/plugin/advancedsubscription/views/advsub_request_received.tpl b/plugin/advancedsubscription/views/advsub_request_received.tpl new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/plugin/advancedsubscription/views/advsub_request_received.tpl @@ -0,0 +1 @@ + diff --git a/plugin/advancedsubscription/views/advsub_request_received_reminder.tpl b/plugin/advancedsubscription/views/advsub_request_received_reminder.tpl new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/plugin/advancedsubscription/views/advsub_request_received_reminder.tpl @@ -0,0 +1 @@ + diff --git a/plugin/advancedsubscription/views/advsub_request_superior.tpl b/plugin/advancedsubscription/views/advsub_request_superior.tpl new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/plugin/advancedsubscription/views/advsub_request_superior.tpl @@ -0,0 +1 @@ + diff --git a/plugin/advancedsubscription/views/advsub_request_superior_approved.tpl b/plugin/advancedsubscription/views/advsub_request_superior_approved.tpl new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/plugin/advancedsubscription/views/advsub_request_superior_approved.tpl @@ -0,0 +1 @@ + diff --git a/plugin/advancedsubscription/views/advsub_request_superior_disapproved.tpl b/plugin/advancedsubscription/views/advsub_request_superior_disapproved.tpl new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/plugin/advancedsubscription/views/advsub_request_superior_disapproved.tpl @@ -0,0 +1 @@ + diff --git a/plugin/advancedsubscription/views/advsub_request_superior_reminder.tpl b/plugin/advancedsubscription/views/advsub_request_superior_reminder.tpl new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/plugin/advancedsubscription/views/advsub_request_superior_reminder.tpl @@ -0,0 +1 @@ + From 791e457b6d96d83153078127a88b892fc490af22 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Fri, 12 Dec 2014 14:16:54 -0500 Subject: [PATCH 06/72] Add AdvancedSubscriptions class methods - refs BT#9092 --- plugin/advancedsubscription/lang/spanish.php | 7 +- .../advanced_subscription_plugin.class.php | 218 +++++++++++------- plugin/advancedsubscription/src/index.php | 30 +++ 3 files changed, 164 insertions(+), 91 deletions(-) diff --git a/plugin/advancedsubscription/lang/spanish.php b/plugin/advancedsubscription/lang/spanish.php index f833606f65..76eabeb901 100644 --- a/plugin/advancedsubscription/lang/spanish.php +++ b/plugin/advancedsubscription/lang/spanish.php @@ -7,8 +7,8 @@ $strings['ws_url'] = 'URL del Webservice'; $strings['ws_url_help'] = 'La URL de la cual se solicitará información para el proceso de la inscripción avanzada'; $strings['check_induction'] = 'Activar requerimiento de curso inducción'; $strings['check_induction_help'] = 'Escoja si se requiere que se complete los cursos de inducción'; -$strings['tool_enable'] = 'Suscripción avanzada activada'; -$strings['tool_enable_help'] = "Escoja si desea activar la suscripción avanzada."; +$strings['tool_enable'] = 'Inscripción avanzada activada'; +$strings['tool_enable_help'] = "Escoja si desea activar la inscripción avanzada."; $strings['yearly_cost_limit'] = 'Límite de UITs'; $strings['yearly_cost_limit_help'] = "El límite de UITs de cursos que se pueden llevar en un año calendario del año actual."; $strings['yearly_hours_limit'] = 'Límite de horas lectivas'; @@ -29,5 +29,8 @@ $strings['AdvancedSubscriptionCostXLimitReached'] = "Lo sentimos, usted ya ha al $strings['AdvancedSubscriptionTimeXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s horas para los cursos que ha seguido este año"; $strings['AdvancedSubscriptionCourseXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s cursos que ha seguido este año"; $strings['AdvancedSubscriptionNotMoreAble'] = "Lo sentimos, usted ya no cumple con las condiciones iniciales para poder inscribirse al curso"; +$strings['AdvancedSubscriptionIncompleteParams'] = "Los parámetros enviados no están completos o no son los correctos."; + +$strings['AdvancedSubscriptionIsNotEnabled'] = "La inscripción avanzada no está activada"; //Needed in order to show the plugin title diff --git a/plugin/advancedsubscription/src/advanced_subscription_plugin.class.php b/plugin/advancedsubscription/src/advanced_subscription_plugin.class.php index 499e2846e9..334d8ecff5 100644 --- a/plugin/advancedsubscription/src/advanced_subscription_plugin.class.php +++ b/plugin/advancedsubscription/src/advanced_subscription_plugin.class.php @@ -9,6 +9,11 @@ class AdvancedSubscriptionPlugin extends Plugin { + const ADVSUB_QUEUE_STATUS_START = 0; + const ADVSUB_QUEUE_STATUS_BOSS_DISAPPROVED = 1; + const ADVSUB_QUEUE_STATUS_BOSS_APPROVED = 2; + const ADVSUB_QUEUE_STATUS_ADMIN_DISAPPROVED = 3; + const ADVSUB_QUEUE_STATUS_ADMIN_APPROVED = 10; /** * Constructor */ @@ -57,7 +62,7 @@ class AdvancedSubscriptionPlugin extends Plugin */ public function uninstall() { - $this->unistallDatabase(); + $this->uninstallDatabase(); } /** @@ -127,60 +132,68 @@ class AdvancedSubscriptionPlugin extends Plugin /** * Return true if user is able to be added to queue for session subscription - * @param $userId + * @param int $userId + * @param array $params MUST have keys: + * "is_connected" Indicate if the user is online on external web + * "profile_completed" Percentage of completed profile, given by WS * @throws Exception * @return bool */ - public function isAbleToRequest($userId) + public function isAbleToRequest($userId, $params = array()) { - $isAble = false; - $advSubPlugin = self::create(); - $wsUrl = $advSubPlugin->get('ws_url'); - // @TODO: Get connection status from user by WS - $isConnected = true; - if ($isConnected) { - $profileCompletedMin = $advSubPlugin->get('min_profile_percentage'); - // @TODO: Get completed profile percentage by WS - $profileCompleted = 100.0; - if ($profileCompleted > $profileCompletedMin) { - $checkInduction = $advSubPlugin->get('check_induction'); - // @TODO: check if user have completed at least one induction session - $completedInduction = true; - if (!$checkInduction || $completedInduction) { - $uitMax = $advSubPlugin->get('yearly_cost_unit_converter'); - $uitMax *= $advSubPlugin->get('yearly_cost_limit'); - // @TODO: Get UIT completed by user this year by WS - $uitUser = 0; - if ($uitMax > $uitUser) { - $expendedTimeMax = $advSubPlugin->get('yearly_hours_limit'); - // @TODO: Get Expended time from user data - $expendedTime = 0; - if ($expendedTimeMax > $expendedTime) { - $expendedNumMax = $advSubPlugin->get('courses_count_limit'); - // @TODO: Get Expended num from user - $expendedNum = 0; - if ($expendedNumMax > $expendedNum) { - $isAble = true; + if (isset($params['is_connected']) && isset($params['profile_completed'])) { + $isAble = false; + $advSubPlugin = self::create(); + $wsUrl = $advSubPlugin->get('ws_url'); + // @TODO: Get connection status from user by WS + $isConnected = $params['is_connected']; + if ($isConnected) { + $profileCompletedMin = $advSubPlugin->get('min_profile_percentage'); + // @TODO: Get completed profile percentage by WS + $profileCompleted = (float) $params['profile_completed']; + if ($profileCompleted > $profileCompletedMin) { + $checkInduction = $advSubPlugin->get('check_induction'); + // @TODO: check if user have completed at least one induction session + $completedInduction = true; + if (!$checkInduction || $completedInduction) { + $uitMax = $advSubPlugin->get('yearly_cost_unit_converter'); + $uitMax *= $advSubPlugin->get('yearly_cost_limit'); + // @TODO: Get UIT completed by user this year by WS + $uitUser = 0; + if ($uitMax > $uitUser) { + $expendedTimeMax = $advSubPlugin->get('yearly_hours_limit'); + // @TODO: Get Expended time from user data + $expendedTime = 0; + if ($expendedTimeMax > $expendedTime) { + $expendedNumMax = $advSubPlugin->get('courses_count_limit'); + // @TODO: Get Expended num from user + $expendedNum = 0; + if ($expendedNumMax > $expendedNum) { + $isAble = true; + } else { + throw new \Exception(get_lang('AdvancedSubscriptionCourseXLimitReached')); + } } else { - throw new \Exception(get_lang('AdvancedSubscriptionCourseXLimitReached')); + throw new \Exception(get_lang('AdvancedSubscriptionTimeXLimitReached')); } } else { - throw new \Exception(get_lang('AdvancedSubscriptionTimeXLimitReached')); + throw new \Exception(get_lang('AdvancedSubscriptionCostXLimitReached')); } } else { - throw new \Exception(get_lang('AdvancedSubscriptionCostXLimitReached')); + throw new \Exception(get_lang('AdvancedSubscriptionIncompleteInduction')); } } else { - throw new \Exception(get_lang('AdvancedSubscriptionIncompleteInduction')); + throw new \Exception(get_lang('AdvancedSubscriptionProfileIncomplete')); } } else { - throw new \Exception(get_lang('AdvancedSubscriptionProfileIncomplete')); + throw new \Exception(get_lang('AdvancedSubscriptionNotConnected')); } + + return $isAble; } else { - throw new \Exception(get_lang('AdvancedSubscriptionNotConnected')); + throw new \Exception($this->get_lang('AdvancedSubscriptionIncompleteParams')); } - return $isAble; } /** @@ -223,71 +236,98 @@ class AdvancedSubscriptionPlugin extends Plugin } /** - * Check whether the tour should be displayed to the user - * @param string $currentPageClass The class of the current page - * @param int $userId The user id - * @return boolean If the user has seen the tour return false, otherwise return true + * Check if session is open for subscription + * @param $sessionId + * @param string $fieldVariable + * @return bool */ - public function checkTourForUser($currentPageClass, $userId) + public function isSessionOpen($sessionId, $fieldVariable = 'es_abierta') { - $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); - $pAdvSubMailTable = Database::get_main_table(TABLE_ADV_SUB_MAIL); - $pAdvSubMailTypeTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_TYPE); - $pAdvSubMailStatusTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_STATUS); - $pluginTourLogTable = Database::get_main_table(TABLE_TOUR_LOG); - - $checkResult = Database::select('count(1) as qty', $pluginTourLogTable, array( - 'where' => array( - "page_class = '?' AND " => $currentPageClass, - "user_id = ?" => intval($userId) - )), 'first'); - - if ($checkResult !== false) { - if ($checkResult['qty'] > 0) { - return false; + $sessionId = (int) $sessionId; + $fieldVariable = Database::escape_string($fieldVariable); + $isOpen = false; + if ($sessionId > 0 && !empty($fieldVariable)) { + $sfTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD); + $sfvTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES); + $joinTable = $sfvTable . ' sfv INNER JOIN ' . $sfTable . ' sf ON sfv.field_id = sf.id '; + $row = Database::select( + 'sfv.field_value as field_value', + $joinTable, + array( + 'where' => array( + 'sfv.session_id = ? AND ' => $sessionId, + 'sf.field_variable = ?' => $fieldVariable, + ) + ) + ); + if (isset($row[0]) && is_array($row[0])) { + $isOpen = (bool) $row[0]['field_value']; } } - return true; + return $isOpen; } - /** - * Set the tour as seen - * @param string $currentPageClass The class of the current page - * @param int $userId The user id - * @return void - */ - public function saveCompletedTour($currentPageClass, $userId) + public function approvedByBoss() { - $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); - $pAdvSubMailTable = Database::get_main_table(TABLE_ADV_SUB_MAIL); - $pAdvSubMailTypeTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_TYPE); - $pAdvSubMailStatusTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_STATUS); - $pluginTourLogTable = Database::get_main_table(TABLE_TOUR_LOG); - Database::insert($pluginTourLogTable, array( - 'page_class' => $currentPageClass, - 'user_id' => intval($userId), - 'visualization_datetime' => api_get_utc_datetime() - )); } - /** - * Get the configuration to show the tour in pages - * @return array The config data - */ - public function getTourConfig() + public function disapprovedByBoss() { - $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); - $pAdvSubMailTable = Database::get_main_table(TABLE_ADV_SUB_MAIL); - $pAdvSubMailTypeTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_TYPE); - $pAdvSubMailStatusTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_STATUS); - $pluginPath = api_get_path(PLUGIN_PATH) . 'tour/'; - $jsonContent = file_get_contents($pluginPath . 'config/tour.json'); + } - $jsonData = json_decode($jsonContent, true); + public function approvedByAdmin() + { - return $jsonData; + } + + public function disapprovedByAdmin() + { + + } + + public function confirmTermsAndConditions() + { + + } + + public function checkToken() + { + + } + + public function sendMail() + { + + } + + /** + * Count the users in queue filtered by params (sessions, status) + * @param array $params Input array containing the set of + * session and status to count from queue + * e.g: + * array('sessions' => array(215, 218, 345, 502), + * 'status' => array(0, 1, 2)) + * @return int + */ + public function countQueueByParams($params) + { + $count = 0; + if (!empty($params) && is_array($params)) { + $advsubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); + $where['1 = ? '] = 1; + if (isset($params['sessions']) && is_array($params['sessions'])) { + $where['AND session_id IN ( ? ) '] = implode($params['sessions']); + } + if (isset($params['status']) && is_array($params['status'])) { + $where['AND status IN ( ? ) '] = implode($params['status']); + } + $where['where'] = $where; + $count = Database::select('COUNT(*)', $advsubQueueTable, $where); + $count = $count[0]; + } + return $count; } } diff --git a/plugin/advancedsubscription/src/index.php b/plugin/advancedsubscription/src/index.php index b3d9bbc7f3..1c6ecb8580 100644 --- a/plugin/advancedsubscription/src/index.php +++ b/plugin/advancedsubscription/src/index.php @@ -1 +1,31 @@ get_lang('CourseListOnSale'); + $templateName = $plugin->get_lang('BuyCourses'); + + $tpl = new Template($templateName); + $tpl->assign('isAdmin', $isAdmin); + $tpl->assign('title', $title); + $tpl->assign('BuySessions', $plugin->get_lang('BuySessions')); + $tpl->assign('BuyCourses', $templateName); + $tpl->assign('ConfigurationOfSessionsAndPrices', $plugin->get_lang('ConfigurationOfSessionsAndPrices')); + $tpl->assign('ConfigurationOfCoursesAndPrices', $plugin->get_lang('ConfigurationOfCoursesAndPrices')); + $tpl->assign('ConfigurationOfPayments', $plugin->get_lang('ConfigurationOfPayments')); + $tpl->assign('OrdersPendingOfPayment', $plugin->get_lang('OrdersPendingOfPayment')); + $listing_tpl = 'buycourses/view/index.tpl'; + $content = $tpl->fetch($listing_tpl); + $tpl->assign('content', $content); + // If the user is NOT an administrator, redirect it to course/session buy list + $isAdmin ? $tpl->display_one_col_template() : header('Location: src/list.php'); +} From 7825df05a1b872441a650bfd4f0f0fb55aa6e808 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Thu, 18 Dec 2014 18:11:35 -0500 Subject: [PATCH 07/72] Update, do not use eval for get_plugin_lang() method - refs BT#9092 --- main/inc/lib/internationalization.lib.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main/inc/lib/internationalization.lib.php b/main/inc/lib/internationalization.lib.php index 8025b630b5..f483e04c50 100755 --- a/main/inc/lib/internationalization.lib.php +++ b/main/inc/lib/internationalization.lib.php @@ -3348,12 +3348,12 @@ function get_datepicker_langage_code() { /** * Returns the variable translated - * @param $variable the string to translate - * @param $pluginName the Plugin name + * @param string $variable the string to translate + * @param string $pluginName the Plugin name * @return string the variable translated */ function get_plugin_lang($variable, $pluginName) { - eval("\$plugin = {$pluginName}::create();"); + $plugin = $pluginName::create(); return $plugin->get_lang($variable); } /** From 01bea2856bb77379d666be37cc7059ece45b295e Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Mon, 12 Jan 2015 14:54:35 -0500 Subject: [PATCH 08/72] Update mail method, add phpcrypt library into plugin - refs BT#9092 --- main/webservices/registration.soap.php | 97 -- .../advancedsubscription/ajax/advsub.ajax.php | 97 ++ plugin/advancedsubscription/config.php | 19 +- .../cron/notify_by_mail.php | 65 + .../resources/phpcrypt/.gitignore | 3 + .../resources/phpcrypt/CHANGELOG | 157 +++ .../resources/phpcrypt/Cipher.php | 257 ++++ .../resources/phpcrypt/Core.php | 622 +++++++++ .../resources/phpcrypt/Includes.inc.php | 40 + .../resources/phpcrypt/Mode.php | 334 +++++ .../resources/phpcrypt/Padding.php | 328 +++++ .../resources/phpcrypt/README.md | 209 +++ .../resources/phpcrypt/ciphers/3DES.php | 251 ++++ .../resources/phpcrypt/ciphers/3Way.php | 340 +++++ .../resources/phpcrypt/ciphers/AES128.php | 71 + .../resources/phpcrypt/ciphers/AES192.php | 72 + .../resources/phpcrypt/ciphers/AES256.php | 72 + .../resources/phpcrypt/ciphers/ARC4.php | 201 +++ .../resources/phpcrypt/ciphers/Blowfish.php | 602 ++++++++ .../resources/phpcrypt/ciphers/CAST128.php | 1210 +++++++++++++++++ .../resources/phpcrypt/ciphers/CAST256.php | 656 +++++++++ .../resources/phpcrypt/ciphers/DES.php | 595 ++++++++ .../resources/phpcrypt/ciphers/Enigma.php | 264 ++++ .../resources/phpcrypt/ciphers/RC2.php | 341 +++++ .../resources/phpcrypt/ciphers/Rijndael.php | 1041 ++++++++++++++ .../phpcrypt/ciphers/Rijndael128.php | 98 ++ .../phpcrypt/ciphers/Rijndael192.php | 76 ++ .../phpcrypt/ciphers/Rijndael256.php | 76 ++ .../resources/phpcrypt/ciphers/SimpleXOR.php | 145 ++ .../resources/phpcrypt/ciphers/Skipjack.php | 391 ++++++ .../resources/phpcrypt/ciphers/Vigenere.php | 249 ++++ .../phpcrypt/examples/aes_256_example.php | 36 + .../phpcrypt/examples/arc4_stream_example.php | 28 + .../phpcrypt/examples/basic_example.php | 33 + .../examples/basic_example_secure.php | 32 + .../phpcrypt/examples/create_key_example.php | 61 + .../resources/phpcrypt/examples/file.txt | 20 + .../examples/file_encryption_example.php | 66 + .../phpcrypt/examples/mode_iv_examples.php | 61 + .../phpcrypt/examples/padding_examples.php | 88 ++ .../phpcrypt/examples/phpcrypt_vs_mcrypt.php | 97 ++ .../phpcrypt/licenses/ECCN_5D002.txt | 7 + .../resources/phpcrypt/licenses/GPL.txt | 674 +++++++++ .../resources/phpcrypt/modes/CBC.php | 167 +++ .../resources/phpcrypt/modes/CFB.php | 130 ++ .../resources/phpcrypt/modes/CTR.php | 202 +++ .../resources/phpcrypt/modes/ECB.php | 142 ++ .../resources/phpcrypt/modes/NCFB.php | 171 +++ .../resources/phpcrypt/modes/NOFB.php | 164 +++ .../resources/phpcrypt/modes/OFB.php | 126 ++ .../resources/phpcrypt/modes/PCBC.php | 159 +++ .../resources/phpcrypt/modes/Raw.php | 116 ++ .../resources/phpcrypt/modes/Stream.php | 69 + .../resources/phpcrypt/phpCrypt.php | 457 +++++++ .../src/AdvancedSubscriptionPlugin.class.php | 629 +++++++++ .../src/HookAdvancedSubscription.class.php | 204 +++ .../advanced_subscription_plugin.class.php | 333 ----- plugin/advancedsubscription/src/index.php | 74 +- plugin/advancedsubscription/test.php | 23 + plugin/advancedsubscription/views/index.tpl | 0 60 files changed, 12897 insertions(+), 451 deletions(-) create mode 100644 plugin/advancedsubscription/ajax/advsub.ajax.php create mode 100644 plugin/advancedsubscription/cron/notify_by_mail.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/.gitignore create mode 100644 plugin/advancedsubscription/resources/phpcrypt/CHANGELOG create mode 100644 plugin/advancedsubscription/resources/phpcrypt/Cipher.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/Core.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/Includes.inc.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/Mode.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/Padding.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/README.md create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/3DES.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/3Way.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/AES128.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/AES192.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/AES256.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/ARC4.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/Blowfish.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/CAST128.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/CAST256.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/DES.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/Enigma.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/RC2.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/Rijndael.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/Rijndael128.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/Rijndael192.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/Rijndael256.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/SimpleXOR.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/Skipjack.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/ciphers/Vigenere.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/examples/aes_256_example.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/examples/arc4_stream_example.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/examples/basic_example.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/examples/basic_example_secure.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/examples/create_key_example.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/examples/file.txt create mode 100644 plugin/advancedsubscription/resources/phpcrypt/examples/file_encryption_example.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/examples/mode_iv_examples.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/examples/padding_examples.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/examples/phpcrypt_vs_mcrypt.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/licenses/ECCN_5D002.txt create mode 100644 plugin/advancedsubscription/resources/phpcrypt/licenses/GPL.txt create mode 100644 plugin/advancedsubscription/resources/phpcrypt/modes/CBC.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/modes/CFB.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/modes/CTR.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/modes/ECB.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/modes/NCFB.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/modes/NOFB.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/modes/OFB.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/modes/PCBC.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/modes/Raw.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/modes/Stream.php create mode 100644 plugin/advancedsubscription/resources/phpcrypt/phpCrypt.php create mode 100644 plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php create mode 100644 plugin/advancedsubscription/src/HookAdvancedSubscription.class.php delete mode 100644 plugin/advancedsubscription/src/advanced_subscription_plugin.class.php create mode 100644 plugin/advancedsubscription/test.php create mode 100644 plugin/advancedsubscription/views/index.tpl diff --git a/main/webservices/registration.soap.php b/main/webservices/registration.soap.php index 85ee140762..26f0497439 100755 --- a/main/webservices/registration.soap.php +++ b/main/webservices/registration.soap.php @@ -5551,103 +5551,6 @@ function WSUserSubscribedInCourse ($params) return (CourseManager::is_user_subscribed_in_course($userId,$courseCode)); } -/** WSSessionListInCategory */ - -// Output params for WSSessionListInCategory -$server->wsdl->addComplexType( - 'sessionBrief', - 'complexType', - 'struct', - 'all', - '', - array( - 'name' => array('name' => 'name', 'type' => 'xsd:string'), //Course string code - 'description' => array('name' => 'description', 'type' => 'xsd:string'), //Chamilo user_id - 'date_start' => array('name' => 'start_date', 'type' => 'xsd:string'), - 'date_end' => array('name' => 'end_date', 'type' => 'xsd:string'), - ) -); - -$server->wsdl->addComplexType( - 'sessionBriefList', - 'complexType', - 'array', - '', - 'SOAP-ENC:Array', - array(), - array( - array('ref'=>'SOAP-ENC:arrayType', - 'wsdl:arrayType'=>'tns:sessionBrief[]') - ), - 'tns:sessionBrief' -); - -// Input params for editing users -$server->wsdl->addComplexType( - 'sessionCategoryInput', - 'complexType', - 'struct', - 'all', - '', - array( - 'id' => array('name' => 'id', 'type' => 'xsd:string'), //Course string code - 'name' => array('name' => 'name', 'type' => 'xsd:string'), //Chamilo user_id - 'secret_key' => array('name' => 'secret_key', 'type' => 'xsd:string') - ) -); - -// Register the method to expose -$server->register('WSSessionListInCategory', // method name - array('sessionCategoryInput' => 'tns:sessionCategoryInput'), // input parameters - array('return' => 'tns:sessionBriefList'), // output parameters - 'urn:WSRegistration', // namespace - 'urn:WSRegistration#WSSessionListInCategory', // soapaction - 'rpc', // style - 'encoded', // use - 'This service checks if user assigned to course' // documentation -); - - -/** - * @param $params - * @return null|soap_fault - */ -function WSSessionListInCategory($params) { - global $debug; - - if ($debug) error_log('WSUserSubscribedInCourse'); - if ($debug) error_log('Params '. print_r($params, 1)); - if (!WSHelperVerifyKey($params)) { - - return return_error(WS_ERROR_SECRET_KEY); - } - // Check if category ID is set - if (!empty($params['id']) && empty($params['category_name'])) { - $sessionCategoryId = $params['id']; - } elseif (!empty($params['category_name'])) { - // Check if category name is set - $sessionCategoryId = SessionManager::getSessionCategoryIdByName($params['category_name']); - if (is_array($sessionCategoryId)) { - $sessionCategoryId = current($sessionCategoryId); - } - } else { - // Return soap fault Not valid input params - - return return_error(WS_ERROR_INVALID_INPUT); - } - - // Get the session brief List by category - - $sessionList = SessionManager::getSessionBriefListByCategory($sessionCategoryId); - - if (empty($sessionList)) { - - return return_error(WS_ERROR_NOT_FOUND_RESULT); - } - - return $sessionList; -} - // Add more webservices by Hooks if (!empty($hook)) { $hook->setEventData(array('server' => $server)); diff --git a/plugin/advancedsubscription/ajax/advsub.ajax.php b/plugin/advancedsubscription/ajax/advsub.ajax.php new file mode 100644 index 0000000000..c0e251e771 --- /dev/null +++ b/plugin/advancedsubscription/ajax/advsub.ajax.php @@ -0,0 +1,97 @@ + 16 ? + $plugin->decrypt(Security::remove_XSS($_REQUEST['data'])) : + null : + null; +// Get data +if (isset($data) && is_array($data)) { + // Action code + $a = isset($data['a']) ? $data['a'] : null; + // User ID + $u = isset($data['u']) ? $data['u'] : null; + // Session ID + $s = isset($data['s']) ? $data['s'] : null; + // More data + $params['is_connected'] = isset($data['is_connected']) ? $data['is_connected'] : false; + $params['profile_completed'] = isset($data['profile_completed']) ? $data['profile_completed'] : 0; + $params['accept'] = isset($data['accept']) ? $data['accept'] : false; +} else { + // Action code + $a = isset($_REQUEST['a']) ? Security::remove_XSS($_REQUEST['a']) : null; + // User ID + $u = isset($_REQUEST['u']) ? Security::remove_XSS($_REQUEST['u']) : null; + // Session ID + $s = isset($_REQUEST['s']) ? Security::remove_XSS($_REQUEST['s']) : null; + // More data + $params['is_connected'] = isset($_REQUEST['is_connected']) ? $_REQUEST['is_connected'] : false; + $params['profile_completed'] = isset($_REQUEST['profile_completed']) ? $_REQUEST['profile_completed'] : 0; + $params['accept'] = isset($_REQUEST['accept']) ? $_REQUEST['accept'] : false; +} +// Init result array +$result = array('error' => true, 'errorMessage' => 'There was an error'); +if (!empty($a) && !empty($u)) { + switch($a) { + case 'first': // Check minimum requirements + try { + $res = AdvancedSubscriptionPlugin::create()->isAbleToRequest($u, $params); + if ($res) { + $result['error'] = false; + $result['errorMessage'] = 'No error'; + $result['pass'] = true; + } else { + $result['errorMessage'] = 'User can not be subscribed'; + $result['pass'] = false; + } + } catch (\Exception $e) { + $result['errorMessage'] = $e->getMessage(); + } + break; + case 'second': // Subscription + $res = AdvancedSubscriptionPlugin::create()->startSubscription($u, $s, $params); + if ($res === true) { + $result['error'] = false; + $result['errorMessage'] = 'No error'; + $result['pass'] = true; + } else { + if (is_string($res)) { + $result['errorMessage'] = $res; + } else { + $result['errorMessage'] = 'User can not be subscribed'; + } + $result['pass'] = false; + } + break; + case 'third': // Encrypt + $plugin = AdvancedSubscriptionPlugin::create(); + $res = $plugin->encrypt($data); + if (!empty($res) && strlen($res) > 16) { + $result['error'] = false; + $result['errorMessage'] = 'No error'; + $result['pass'] = true; + } else { + if (is_string($res)) { + $result['errorMessage'] = $res; + } else { + $result['errorMessage'] = 'User can not be subscribed'; + } + $result['pass'] = false; + } + break; + default: + $result['errorMessage'] = 'Action do not exist!'; + break; + } +} + +echo json_encode($result); diff --git a/plugin/advancedsubscription/config.php b/plugin/advancedsubscription/config.php index d47802dd43..924b1b1208 100644 --- a/plugin/advancedsubscription/config.php +++ b/plugin/advancedsubscription/config.php @@ -10,6 +10,23 @@ define('TABLE_ADV_SUB_QUEUE', 'plugin_advsub_queue'); define('TABLE_ADV_SUB_MAIL', 'plugin_advsub_mail'); define('TABLE_ADV_SUB_MAIL_TYPE', 'plugin_advsub_mail_type'); define('TABLE_ADV_SUB_MAIL_STATUS', 'plugin_advsub_mail_status'); + +define('ADV_SUB_ACTION_STUDENT_REQUEST', 0); +define('ADV_SUB_ACTION_SUPERIOR_APPROVE', 1); +define('ADV_SUB_ACTION_SUPERIOR_DISAPPROVE', 2); +define('ADV_SUB_ACTION_SUPERIOR_SELECT', 3); +define('ADV_SUB_ACTION_ADMIN_APPROVE', 4); +define('ADV_SUB_ACTION_ADMIN_DISAPPROVE', 5); + + +define('ADV_SUB_QUEUE_STATUS_START', 0); +define('ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED', 1); +define('ADV_SUB_QUEUE_STATUS_BOSS_APPROVED', 2); +define('ADV_SUB_QUEUE_STATUS_ADMIN_DISAPPROVED', 3); +define('ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED', 10); + require_once __DIR__ . '/../../main/inc/global.inc.php'; +require_once __DIR__ . '/resources/phpcrypt/phpCrypt.php'; require_once api_get_path(LIBRARY_PATH) . 'plugin.class.php'; -require_once api_get_path(PLUGIN_PATH) . 'advancedsubscription/src/advanced_subscription_plugin.class.php'; +require_once api_get_path(PLUGIN_PATH) . 'advancedsubscription/src/AdvancedSubscriptionPlugin.class.php'; +require_once api_get_path(PLUGIN_PATH) . 'advancedsubscription/src/HookAdvancedSubscription.class.php'; diff --git a/plugin/advancedsubscription/cron/notify_by_mail.php b/plugin/advancedsubscription/cron/notify_by_mail.php new file mode 100644 index 0000000000..10e6aeff00 --- /dev/null +++ b/plugin/advancedsubscription/cron/notify_by_mail.php @@ -0,0 +1,65 @@ + + */ + +/** + * Init + */ +require_once '../../../main/inc/global.inc.php'; + +/** + * Get database handle + */ + +$nowUtc = api_get_utc_datetime(); +$weekAgoUtc = api_get_utc_datetime(strtotime('-1 week')); +$sTable = Database::get_main_table(TABLE_MAIN_SESSION); +$uUserTable = Database::get_main_table(TABLE_MAIN_SESSION_USER); +$limitArea = 'limit_area'; +//define('USER_RELATION_TYPE_BOSS', 8); +//define('TABLE_ADV_SUB_QUEUE', 'plugin_advsub_queue'); +//define('TABLE_ADV_SUB_MAIL', 'plugin_advsub_mail'); + +$sessionAdvSub = array(); +$sessionQueue = array(); +$userAdmins = array(); + +$advSubQueueTable = TABLE_ADVSUB_QUEUE; +$advSubMailTable = TABLE_ADVSUB_MAIL; +$advSubMails = Database::select('id, created_at, user_id, status', $advSubMailTable); +$advSubQueue = Database::select('id, status_id, user_id, updated_at', $advSubQueueTable, array('where' => array('start_date > ?' => $nowUtc))); +$sessionIds = Database::select('id', $sTable, array('where' => array('start_date > ?' => $nowUtc))); +$users = Database::select('user_id ASS boss_id, friend_user_id AS id', $uUserTable, array('where' => array('relation_type = ?' => USER_RELATION_TYPE_BOSS))); +$sField = new ExtraField('session'); +$sFieldValue = new ExtraFieldValue('session'); +$areaCounts = array(); +foreach ($users as $userId => $bossId) { + $areaCounts[$bossId] ++; +} +foreach ($advSubMails as $id => $advSubMail) { + $userSubMail[$advSubMail['user_id']][] = $id; +} +foreach ($sessionIds as $sessionId) { + $bossId = $advSubQueue[$sessionQueue[$sessionId]]['user_id']; + $sLimitArea = $sFieldValue->get_values_by_handler_and_field_variable($sessionId, $limitArea); + if ($sLimitArea > $sQueueCount[$bossId]) { + // Register data + $chooseUser = true; + } + if ($advSubMail[end($userSubMail[$bossId])]['created_at'] < $weekAgoUtc) { + // Send mail again + // Session x Boss -> user, status, buttons + if ($chooseUser) { + // Use choose user tpl + } + } + foreach ($userAdmins as $adminId => $userAdmin) { + if ($advSubMail[end($userSubMail[$adminId])]['created_at'] < $weekAgoUtc) { + // send queue status 2 + } + } +} diff --git a/plugin/advancedsubscription/resources/phpcrypt/.gitignore b/plugin/advancedsubscription/resources/phpcrypt/.gitignore new file mode 100644 index 0000000000..ee20530739 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/.gitignore @@ -0,0 +1,3 @@ +/.project +/.directory +test/ \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/CHANGELOG b/plugin/advancedsubscription/resources/phpcrypt/CHANGELOG new file mode 100644 index 0000000000..a07d4eba50 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/CHANGELOG @@ -0,0 +1,157 @@ +2014-05-09 phpCrypt-0.5.1 Ryan Gilfether + + * Fixed error message in Rijndael.php which inaccurately + reported an incorrect key size in bits instead of bytes + + * Fixed a typo in the blockSize() call in the Rijdael.php + contructor + +2013-09-18 phpCrypt-0.5 Ryan Gilfether + + * Added CAST-128 cipher + + * Added CAST-256 cipher + + * Added support for 8 and 16 byte keys in addition + to 24 byte keys for Triple DES (3DES) + + * Removed the OneTimePad cipher. This was redundant since + the SimpleXOR cipher is the same as a one time pad when + the key length is the same as the length of data length, + and the key is unique for each block of data. + + * Added PHP_Crypt::createKey(), a helper function to generate + a random string of bytes that can be used as a key for a + cipher. See the examples directory to see how it is used. + + * Added PHP_Crypt::setKey() so that it is possible to set + the key to a new value without having to create an new + instance of phpCrypt + + * Renamed PHP_Crypt::cipherSetKey() to PHP_Crypt::cipherKey() + + * Updated the constants used for PHP_Crypt::createKey() and + PHP_Crypt::createIV(). Both now use the PHP_Crypt::RAND + constants. The PHP_Crypt::IV constants have been removed. + + * Changed SimpleXOR from a block cipher to a stream cipher + since this is what it really is. + + * In Cipher.php made the $key member private, renamed + setKey() to key(), and key() is now used to retrieve the + current key in use by all extending classes + + * Minor changes to how RC2::splitBytes() works using + array_map() + + * Fixed an error message that occurs in php 5.3 in RC2.php + + * Renamed Base.php to Core.php + + * Replaced for() loops with array_map() in Core.php where + possible for minor speed improvements + + * Shortened the name of functions in Core.php, and updated + all files that use those functions. + + * Create a workaround in Core::rotateBitsLeft32() and + Core::rotateBitsRight32() which caused them to not always + work correctly on 32 bit platforms + + * Fixed Core::uInt() and Core::uInt32() which caused them to + not always work correctly on 32 bit platforms + + * Major bug fix in how CTR mode works. Previously it was not + fully compatible with mCrypt's CTR mode. + +2013-07-21 phpCrypt-0.4 Ryan Gilfether + + * Added the 3-Way cipher. phpCrypt's implementation is + compatible with mCrypts implementation, though there may + be a bug in mCrypt's 3-Way gamma() function. phpCrypt + mimics the bug to make it compatible, if it is a bug. + Unfortunately I do no know enough about 3-Way nor could + I find much information on it to know if the gamma() function + is suppose to behave the way it does. Please read phpCrypt's + 3Way::gamma() function comment for further information. + + * Windows users now have the option to create an IV using + the secure random number generator found in the Microsoft + CAPICOM SDK. The new constant is PHP_Crypt::IV_WIN_COM. + View the README file for more information. + + * Fixed a bug in CTR mode where the last few bytes may + not get passed to the cipher in some cases + + * Mode::CreateIV() now hashes the random string of bytes + before returning it as the IV. This helps in the adding + additional 'randomness' to the IV + + * Bug fixes and minor speed improvements in some of the + modes. + + * Updated all functions and calculations to handle block + size in bytes instead of bits. This makes the API less + confusing and fewer conversions from bits to bytes. + +2013-07-19 phpCrypt-0.3.2 Ryan Gilfether + + * Version 0.3.1 contained some incomplete files and bugs + which were not fixed before the release. This version + addresses those issues. + + * Fixes in the examples code + + * Removed the PHP_Crypt::setIV() function and renamed to + PHP_Crypt::IV() + +2013-07-18 phpCrypt-0.3.1 Ryan Gilfether + + * Found a major bug in the way IV's are used in Encryption + and Decryption. The $iv parameter has been removed from + PHP_Crypt::Encrypt() and PHP_Crypt::Decrypt() function, and + instead the IV should be set with PHP_Crypt::setIV() + + * Updated the code in the 'examples' directory to reflect + the changes made to correct the IV bug + + * Updated README and README.md to reflect the changes made + for the IV bug + +2013-07-12 phpCrypt-0.3 Ryan Gilfether + + * Added the Blowfish Cipher + + * Updated CryptBase::decimal2Hex() with a parameter to force + the returned hex to specified byte size + + * Updated RC2.php to use the uInt() function + + * Added PHP_Crypt::SetIV() function + + * Removed the $iv parameter from PHP_Crypt::CreateIV(), + now to set the IV use the PHP_Crypt::SetIV() function, + or pass the IV in the encrypt() or decrypt() function + + * Renamed CryptBase.php to Base.php. Removed it as a parent + class to all other classes except the Cipher class, as it + was the only class that really needed it. + + * General performance improvements + +2013-06-28 phpCrypt-0.2 Ryan Gilfether + + * Fixed Enigma so that it works on both 64 and 32 bit platforms + + * Renamed & fixed the following functions in CryptBase.php + to use native PHP function calls: + uInt(), sInt(), uInt32(), sInt32(), uChar(), sChar() + +2013-06-24 phpCrypt-0.1 Ryan Gilfether + + * The initial release of phpCrypt 0.1 + +Copyright 2013 Ryan Gilfether http://www.gilfether.com/phpcrypt +Copying and distribution of this file, with or without modification, +are permitted provided the copyright notice and this notice are +preserved. \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/Cipher.php b/plugin/advancedsubscription/resources/phpcrypt/Cipher.php new file mode 100644 index 0000000000..1631aca3de --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/Cipher.php @@ -0,0 +1,257 @@ +. + */ + + +namespace PHP_Crypt; +require_once(dirname(__FILE__)."/Core.php"); +require_once(dirname(__FILE__)."/phpCrypt.php"); + +/** + * Generic parent class for ciphers. Should not be used directly, + * instead a class should extend from this class + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2005 Ryan Gilfether + */ +abstract class Cipher extends Core +{ + /** @type integer ENCRYPT Indicates when we are in encryption mode */ + const ENCRYPT = 1; + + /** @type integer DECRYPT Indicates when we are in decryption mode */ + const DECRYPT = 2; + + /** @type integer BLOCK Indicates that a cipher is a block cipher */ + const BLOCK = 1; + + /** @type integer STREAM Indicates that a cipher is a stream cipher */ + const STREAM = 2; + + /** @type string $cipher_name Stores the name of the cipher */ + protected $cipher_name = ""; + + /** @type integer $block_size The block size of the cipher in bytes */ + protected $block_size = 0; + + /** + * @type integer $operation Indicates if a cipher is Encrypting or Decrypting + * this can be set to either Cipher::ENCRYPT or Cipher::DECRYPT + */ + protected $operation = self::ENCRYPT; // can be either Cipher::ENCRYPT | Cipher::DECRYPT; + + /** @type string $key Stores the key for the Cipher */ + private $key = ""; + + /** @type integer $key_len Keep track of the key length, so we don't + have to make repeated calls to strlen() to find the length */ + private $key_len = 0; + + + /** + * Constructor + * + * @param string $name one of the predefined ciphers + * @param string $key The key used for encryption + * @param int Optional, the required size of a key for the cipher + * @return void + */ + protected function __construct($name, $key = "", $required_key_sz = 0) + { + $this->name($name); + $this->key($key, $required_key_sz); + } + + + /** + * Destructor + * + * @return void + */ + protected function __destruct() + { + + } + + + + /********************************************************************** + * ABSTRACT METHODS + * + * The abstract methods required by inheriting classes to implement + **********************************************************************/ + + /** + * The cipher's encryption function. Must be defined + * by the class inheriting this Cipher object. This function + * will most often be called from within the Mode object + * + * @param string $text The text to be encrypted + * @return boolean Always returns false + */ + abstract public function encrypt(&$text); + + + /** + * The cipher's decryption function. Must be defined + * by the class inheriting this Cipher object. This function + * will most often be called from within the Mode object + * + * @param string $text The text to decrypt + * @return boolean Always returns false + */ + abstract public function decrypt(&$text); + + + /** + * Indiciates whether the cipher is a block or stream cipher + * + * @return integer Returns either Cipher::BLOCK or Cipher::STREAM + */ + abstract public function type(); + + + + + /********************************************************************** + * PUBLIC METHODS + * + **********************************************************************/ + + /** + * Determine if we are Encrypting or Decrypting + * Since some ciphers use the same algorithm to Encrypt or Decrypt but with only + * slight differences, we need a way to check if we are Encrypting or Decrypting + * An example is DES, which uses the same algorithm except that when Decrypting + * the sub_keys are reversed + * + * @param integer $op Sets the operation to Cipher::ENCRYPT or Cipher::DECRYPT + * @return integer The current operation, either Cipher::ENCRYPT or Cipher::DECRYPT + */ + public function operation($op = 0) + { + if($op == self::ENCRYPT || $op == self::DECRYPT) + $this->operation = $op; + + return $this->operation; + } + + + /** + * Return the name of cipher that is currently being used + * + * @return string The cipher name + */ + public function name($name = "") + { + if($name != "") + $this->cipher_name = $name; + + return $this->cipher_name; + } + + + /** + * Size of the data in Bits that get used during encryption + * + * @param integer $bytes Number of bytes each block of data is required by the cipher + * @return integer The number of bytes each block of data required by the cipher + */ + public function blockSize($bytes = 0) + { + if($bytes > 0) + $this->block_size = $bytes; + + // in some cases a blockSize is not set, such as stream ciphers. + // so just return 0 for the block size + if(!isset($this->block_size)) + return 0; + + return $this->block_size; + } + + + /** + * Returns the size (in bytes) required by the cipher. + * + * @return integer The number of bytes the cipher requires the key to be + */ + public function keySize() + { + return $this->key_len; + } + + + /** + * Set the cipher key used for encryption/decryption. This function + * may lengthen or shorten the key to meet the size requirements of + * the cipher. + * + * If the $key parameter is not given, this function simply returns the + * current key being used. + * + * @param string $key Optional, A key for the cipher + * @param integer $req_sz The byte size required for the key + * @return string They key, which may have been modified to fit size + * requirements + */ + public function key($key = "", $req_sz = 0) + { + if($key != "" && $key != null) + { + // in the case where the key is changed changed after + // creating a new Cipher object and the $req_sz was not + // given, we need to make sure the new key meets the size + // requirements. This can be determined from the $this->key_len + // member set from the previous key + if($this->key_len > 0 && $req_sz == 0) + $req_sz = $this->key_len; + else + $this->key_len = strlen($key); + + if($req_sz > 0) + { + if($this->key_len > $req_sz) + { + // shorten the key length + $key = substr($key, 0, $req_sz); + $this->key_len = $req_sz; + } + else if($this->key_len < $req_sz) + { + // send a notice that the key was too small + // NEVER PAD THE KEY, THIS WOULD BE INSECURE!!!!! + $msg = strtoupper($this->name())." requires a $req_sz byte key, {$this->key_len} bytes received"; + trigger_error($msg, E_USER_WARNING); + + return false; + } + } + + $this->key = $key; + } + + return $this->key; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/Core.php b/plugin/advancedsubscription/resources/phpcrypt/Core.php new file mode 100644 index 0000000000..d139dbaf3e --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/Core.php @@ -0,0 +1,622 @@ +. + */ + +namespace PHP_Crypt; + +/** + * A base class that should not be used directly. It is intended as a base + * object that should be extended and provides tools that child objects may use. + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Core +{ + /** @type integer HASH_LEN The length of md5() hash string */ + const HASH_LEN = 16; + + + /** + * Constructor + * + */ + protected function __construct() + { + + } + + + /** + * Destructor + * + */ + protected function __destruct() + { + + } + + + /** + * Convert hexidecimal to a binary string (ex: "00110110") + * + * @param string $hex A string containing a hexidecimal number + * @return string A string representation of a binary + */ + public static function hex2Bin($hex) + { + // if we do not have an even number of hex characters + // append a 0 to the beginning to make it even + if(strlen($hex) % 2) + $hex = "0$hex"; + + $parts = str_split($hex, 2); + $parts = array_map(function($v) { + $v = base_convert($v, 16, 2); + return str_pad($v, 8, "0", STR_PAD_LEFT); + }, $parts); + + return implode("", $parts); + } + + + /** + * Convert hex to a string + * + * @param string $hex A string representation of Hex (IE: "1a2b3c" not 0x1a2b3c) + * @return string a string + */ + public static function hex2Str($hex) + { + // php version >= 5.4 have a hex2bin function, use it + // if it exists + if(function_exists("hex2bin")) + return hex2bin($hex); + + $parts = str_split($hex, 2); + $parts = array_map(function($v) { + return chr(Core::hex2Dec($v)); + }, $parts); + + return implode("", $parts); + } + + + /** + * Converts Hex to Decimal + * This function just calls php's hexdec() function, but I + * encapsulated it in this function to keep things uniform + * and have all possible conversion function available in + * the Cipher class + * + * @param string $hex A hex number to convert to decimal + * @return integer A decimal number + */ + public static function hex2Dec($hex) + { + return hexdec($hex); + } + + + /** + * Convert binary string (ie 00110110) to hex + * + * @param string $bin A binary string + * @return string A string representation of hexidecimal number + */ + public static function bin2Hex($bin) + { + $parts = str_split($bin, 8); + + $parts = array_map(function($v) { + $v = str_pad($v, 8, "0", STR_PAD_LEFT); + $v = dechex(bindec($v)); + return str_pad($v, 2, "0", STR_PAD_LEFT); + }, $parts); + + return implode("", $parts); + } + + + /** + * Converts a binary representation (ie 01101011) back to a string + * + * @param string $bin a binary representation string + * @return string A string of characters representing the binary + */ + public static function bin2Str($bin) + { + $hex = self::bin2Hex($bin); + return self::hex2Str($hex); + } + + + /** + * Convert a binary string (ie: 01101011) to a decimal number + * + * @param string A string representation of a binary number + * @return integer The number converted from the binary string + */ + public static function bin2Dec($bin) + { + return bindec($bin); + } + + + /** + * Convert a string to hex + * This function calls the PHP bin2hex(), and is here + * for consistency with the other string functions + * + * @param string $str A string + * @return string A string representation of hexidecimal number + */ + public static function str2Hex($str) + { + return bin2hex($str); + } + + + /** + * Convert a string of characters to a decimal number + * + * @param string $str The string to convert to decimal + * @return integer The integer converted from the string + */ + public static function str2Dec($str) + { + $hex = self::str2Hex($str); + return self::hex2Dec($hex); + } + + + /** + * Converts a string to binary representation (ie 01101011) + * + * @param string $str A string + * @return string A binary representation of the the string + */ + public static function str2Bin($str) + { + $hex = self::str2Hex($str); + $parts = str_split($hex, 2); + + $parts = array_map(function($v) { + return Core::hex2Bin($v); + }, $parts); + + return implode("", $parts); + } + + + /** + * Converts Decimal to Hex + * This function just calls php's dechex() function, but I + * encapsulated it in this function to keep things uniform + * and have all possible conversion function available in + * the Cipher class + * + * The parameter $req_bytes will pad the return hex with NULL (00) + * until the hex represents the number of bytes given to $req_bytes + * This is because dechex() drops null bytes from the Hex, which may + * be needed in some cases + * + * @param integer $dec A decimal number to convert + * @param integer $req_bytes Optional, forces the string to be at least + * $req_bytes in size, this is needed because on occasion left most null bytes + * are dropped in dechex(), causing the string to have a shorter byte + * size than the initial integer. + * @return string A hexidecimal representation of the decimal number + */ + public static function dec2Hex($dec, $req_bytes = 0) + { + $hex = dechex($dec); + + // if we do not have an even number of hex characters + // append a 0 to the beginning. dechex() drops leading 0's + if(strlen($hex) % 2) + $hex = "0$hex"; + + // if the number of bytes in the hex is less than + // what we need it to be, add null bytes to the + // front of the hex to padd it to the required size + if(($req_bytes * 2) > strlen($hex)) + $hex = str_pad($hex, ($req_bytes * 2), "0", STR_PAD_LEFT); + + return $hex; + } + + + /** + * Converts Decimal to Binary + * This function just calls php's decbin() function, but I + * encapsulated it in this function to keep things uniform + * and have all possible conversion function available in + * the Cipher class + * + * @param integer $dec A decimal number to convert + * @param integer $req_bytes Optional, forces the string to be at least + * $req_bytes in size, this is needed because on occasion left most null bytes + * are dropped in dechex(), causing the string to have a shorter byte + * size than the initial integer. + * @return string A binary representation of the decimal number + */ + public static function dec2Bin($dec, $req_bytes = 0) + { + $hex = self::dec2Hex($dec, $req_bytes); + return self::hex2Bin($hex); + } + + + /** + * Convert a decimal to a string of bytes + * + * @param integer $dec A decimal number + * @param integer $req_bytes Optional, forces the string to be at least + * $req_bytes in size, this is needed because on occasion left most null bytes + * are dropped in dechex(), causing the string to have a shorter byte + * size than the initial integer. + * @return string A string with the number of bytes equal to $dec + */ + public static function dec2Str($dec, $req_bytes = 0) + { + $hex = self::dec2Hex($dec, $req_bytes); + return self::hex2Str($hex); + } + + + /** + * XORs two binary strings (representation of binary, ie 01101011), + * assumed to be equal length + * + * @param string $a A string that represents binary + * @param string $b A string that represents binary + * @return string A representation of binary + */ + public static function xorBin($a, $b) + { + $len_a = strlen($a); + $len_b = strlen($b); + $width = $len_a; + + // first determine if the two binary strings are the same length, + // and if not get them to the same length + if($len_a > $len_b) + { + $width = $len_a; + $b = str_pad($b, $width, "0", STR_PAD_LEFT); + } + else if($len_a < $len_b) + { + $width = $len_b; + $a = str_pad($a, $width, "0", STR_PAD_LEFT); + } + + // fortunately PHP knows how to XOR each byte in a string + // so we don't have to loop to do it + $bin = self::bin2Str($a) ^ self::bin2Str($b); + return self::str2Bin($bin); + } + + + /** + * ExclusiveOR hex values. Supports an unlimited number of parameters. + * The values are string representations of hex values + * IE: "0a1b2c3d" not 0x0a1b2c3d + * + * @param string Unlimited number parameters, each a string representation of hex + * @return string A string representation of the result in Hex + */ + public static function xorHex() + { + $hex = func_get_args(); + $count = func_num_args(); + + // we need a minimum of 2 values + if($count < 2) + return false; + + // first get all hex values to an even number + array_walk($hex, function(&$val, $i){ + if(strlen($val) % 2) + $val = "0".$val; + }); + + $res = 0; + for($i = 0; $i < $count; ++$i) + { + // if this is the first loop, set the 'result' to the first + // hex value + if($i == 0) + $res = $hex[0]; + else + { + // to make the code easier to follow + $h1 = $res; + $h2 = $hex[$i]; + + // get lengths + $len1 = strlen($h1); + $len2 = strlen($h2); + + // now check that both hex values are the same length, + // if not pad them with 0's until they are + if($len1 > $len2) + $h2 = str_pad($h2, $len1, "0", STR_PAD_LEFT); + else if($len1 < $len2) + $h1 = str_pad($h1, $len2, "0", STR_PAD_LEFT); + + // PHP knows how to XOR each byte in a string, so convert the + // hex to a string, XOR, and convert back + $res = self::hex2Str($h1) ^ self::hex2Str($h2); + $res = self::str2Hex($res); + } + } + + return $res; + } + + + /** + * Forces an integer to be signed + * + * @param integer $int An integer + * @return integer An signed integer + */ + public static function sInt($int) + { + $arr = unpack("i", pack("i", $int)); + return $arr[1]; + } + + + /** + * Forces an integer to be unsigned + * + * @param integer $int A signed integer + * @return integer An unsigned integer + */ + public static function uInt($int) + { + $arr = unpack("I", pack("I", $int)); + $ret = $arr[1]; + + // On 32 bit platforms unpack() and pack() do not convert + // from signed to unsigned properly all the time, it will return + // the same negative number given to it, the work around is + // to use sprintf(). + // Tested with php 5.3.x on Windows XP & Linux 32bit + if($ret < 0) + $ret = sprintf("%u", $ret) + 0; // convert from string to int + + return $ret; + } + + + /** + * Forces an integer to be a 32 bit signed integer + * + * @param integer $int An integer + * @return integer An signed 32 bit integer + */ + public static function sInt32($int) + { + if(PHP_INT_SIZE === 4) // 32 bit + return self::sInt($int); + else // PHP_INT_SIZE === 8 // 64 bit + { + $arr = unpack("l", pack("l", $int)); + return $arr[1]; + } + } + + + /** + * Force an integer to be a 32 bit unsigned integer + * + * @param integer $int An integer + * @return integer An unsigned 32 bit integer + */ + public static function uInt32($int) + { + if(PHP_INT_SIZE === 4) // 32 bit + return self::uInt($int); + else // PHP_INT_SIZE === 8 // 64 bit + { + $arr = unpack("L", pack("L", $int)); + return $arr[1]; + } + } + + + /** + * Converts an integer to the value for an signed char + * + * @param integer $int The integer to convert to a signed char + * @return integer A signed integer, representing a signed char + */ + public static function sChar($int) + { + $arr = unpack("c", pack("c", $int)); + return $arr[1]; + } + + + /** + * Converts an integer to the value for an unsigned char + * + * @param integer $int The integer to convert to a unsigned char + * @return integer An unsigned integer, representing a unsigned char + */ + public static function uChar($int) + { + $arr = unpack("C", pack("C", $int)); + return $arr[1]; + } + + + /** + * Rotates bits Left, appending the bits pushed off the left onto the right + * + * @param integer $n The integer to rotate bits to the left + * @param integer $shifts The number of shifts left to make + * @return integer The resulting value from the rotation + */ + public static function rotBitsLeft32($i, $shifts) + { + if($shifts <= 0) + return $i; + + $shifts &= 0x1f; /* higher rotates would not bring anything */ + + // this is causing problems on 32 bit platform + //return self::uInt32(($i << $shifts) | ($i >> (32 - $shifts))); + + // so lets cheat: convert to binary string, rotate left, and + // convert back to decimal + $i = self::dec2Bin(self::uInt32($i), 4); + $i = substr($i, $shifts).substr($i, 0, $shifts); + return self::bin2Dec($i); + + } + + + /** + * Rotates bits right, appending the bits pushed off the right onto the left + * + * @param integer $n The integer to rotate bits to the right + * @param integer $shifts The number of shifts right to make + * @return integer The resulting value from the rotation + */ + public static function rotBitsRight32($i, $shifts) + { + if($shifts <= 0) + return $i; + + $shifts &= 0x1f; /* higher rotates would not bring anything */ + + // this might cause problems on 32 bit platforms since rotBitsLeft32 was + // having a problem with some bit shifts on 32 bits + // return self::uInt32(($i >> $shifts) | ($i << (32 - $shifts))); + + // so lets cheat: convert to binary string, rotate right, + // and convert back to decimal + $i = self::dec2Bin($i, 4); + $i = substr($i, (-1 * $shifts)).substr($i, 0, (-1 * $shifts)); + return self::bin2Dec($i); + } + + + /** + * Create a string of random bytes, used for creating an IV + * and a random key. See PHP_Crypt::createKey() and PHP_Crypt::createIV() + * There are 4 ways to auto generate random bytes by setting $src parameter + * PHP_Crypt::RAND - Default, uses mt_rand() + * PHP_Crypt::RAND_DEV_RAND - Unix only, uses /dev/random + * PHP_Crypt::RAND_DEV_URAND - Unix only, uses /dev/urandom + * PHP_Crypt::RAND_WIN_COM - Windows only, uses Microsoft's CAPICOM SDK + * + * @param string $src Optional, Use the $src to create the random bytes + * by default PHP_Crypt::RAND is used when $src is not specified + * @param integer $byte_len The length of the byte string to create + * @return string A random string of bytes + */ + public static function randBytes($src = PHP_Crypt::RAND, $byte_len = PHP_Crypt::RAND_DEFAULT_SZ) + { + $bytes = ""; + $err_msg = ""; + + if($src == PHP_Crypt::RAND_DEV_RAND) + { + if(file_exists(PHP_Crypt::RAND_DEV_RAND)) + $bytes = file_get_contents(PHP_CRYPT::RAND_DEV_RAND, false, null, 0, $byte_len); + else + $err_msg = PHP_Crypt::RAND_DEV_RAND." not found"; + } + else if($src == PHP_Crypt::RAND_DEV_URAND) + { + if(file_exists(PHP_Crypt::RAND_DEV_URAND)) + $bytes = file_get_contents(PHP_CRYPT::RAND_DEV_URAND, false, null, 0, $byte_len); + else + $err_msg = PHP_Crypt::RAND_DEV_URAND." not found"; + } + else if($src == PHP_Crypt::RAND_WIN_COM) + { + if(extension_loaded('com_dotnet')) + { + // http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx + try + { + // request a random number in $byte_len bytes, returned + // as base_64 encoded string. This is because PHP munges the + // binary data on Windows + $com = @new \COM("CAPICOM.Utilities.1"); + $bytes = $com->GetRandom($byte_len, 0); + } + catch(Exception $e) + { + $err_msg = "Windows COM exception: ".$e->getMessage(); + } + + if(!$bytes) + $err_msg = "Windows COM failed to create random string of bytes"; + } + else + $err_msg = "The COM_DOTNET extension is not loaded"; + } + + // trigger a warning if something went wrong + if($err_msg != "") + trigger_error("$err_msg. Defaulting to PHP_Crypt::RAND", E_USER_WARNING); + + // if the random bytes where not created properly or PHP_Crypt::RAND was + // passed as the $src param, create the bytes using mt_rand(). It's not + // the most secure option but we have no other choice + if(strlen($bytes) < $byte_len) + { + $bytes = ""; + + // md5() hash a random number to get a 16 byte string, keep looping + // until we have a string as long or longer than the ciphers block size + for($i = 0; ($i * self::HASH_LEN) < $byte_len; ++$i) + $bytes .= md5(mt_rand(), true); + } + + // because $bytes may have come from mt_rand() or /dev/urandom which are not + // cryptographically secure, lets add another layer of 'randomness' before + // the final md5() below + $bytes = str_shuffle($bytes); + + // md5() the $bytes to add extra randomness. Since md5() only returns + // 16 bytes, we may need to loop to generate a string of $bytes big enough for + // some ciphers which have a block size larger than 16 bytes + $tmp = ""; + $loop = ceil(strlen($bytes) / self::HASH_LEN); + for($i = 0; $i < $loop; ++$i) + $tmp .= md5(substr($bytes, ($i * self::HASH_LEN), self::HASH_LEN), true); + + // grab the number of bytes equal to the requested $byte_len + return substr($tmp, 0, $byte_len); + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/Includes.inc.php b/plugin/advancedsubscription/resources/phpcrypt/Includes.inc.php new file mode 100644 index 0000000000..c37b10a996 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/Includes.inc.php @@ -0,0 +1,40 @@ + \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/Mode.php b/plugin/advancedsubscription/resources/phpcrypt/Mode.php new file mode 100644 index 0000000000..8297415761 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/Mode.php @@ -0,0 +1,334 @@ +. + */ + +namespace PHP_Crypt; + +require_once(dirname(__FILE__)."/Padding.php"); +require_once(dirname(__FILE__)."/phpCrypt.php"); + +/** + * A base class that should not be used directly. Instead, all mode classes should + * extend this one. It provides tools that may be used for any type of Mode. + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2005 Ryan Gilfether + */ +abstract class Mode +{ + /** + * @type object $cipher The cipher object used within the mode + */ + protected $cipher = null; + + /** + * @type string $iv The IV used for the mode, not all Modes + * use an IV so this may be empty + */ + protected $iv = ""; + + /** + * @type string $register For modes that use a register to do + * encryption/decryption. This stores the unencrypted register. + */ + protected $register = ""; + + /** + * @type string $enc_register For modes that use a register to do + * encryption/decryption. This stores the encrypted register + */ + protected $enc_register = ""; + + /** + * @type integer $block_size The byte size of the block to + * encrypt/decrypt for the Mode + */ + private $block_size = 0; + + /** @type string $mode_name The name of mode currently used */ + private $mode_name = ""; + + /** + * @type string $padding The type of padding to use when required. + * Padding types are defined in phpCrypt class. Defaults to + * PHP_Crypt::PAD_ZERO + */ + private $padding = PHP_Crypt::PAD_ZERO; + + + /** + * Constructor + * Sets the cipher object that will be used for encryption + * + * @param object $cipher One of the phpCrypt encryption cipher objects + * @param string $mode_name The name of phpCrypt's modes, as defined in the mode + * @return void + */ + protected function __construct($mode_name, $cipher) + { + $this->name($mode_name); + $this->cipher($cipher); + $this->block_size = $this->cipher->blockSize(); + } + + + /** + * Destructor + * + * @return void + */ + protected function __destruct() + { + + } + + + + /********************************************************************** + * ABSTRACT METHODS + * + * The abstract methods required by inheriting classes to implement + **********************************************************************/ + + /** + * All modes must have encrypt(), which implements + * the mode using the cipher's encrypiton algorithm + * + * @param string $text A String to encrypt + * @return boolean Always returns true + */ + abstract public function encrypt(&$text); + + + /** + * All modes must have decrypt(), which implements + * the mode using the cipher's encryption algorithm + * + * @param string $text A String to decrypt + * @return boolean Always returns true + */ + abstract public function decrypt(&$text); + + + /** + * Indicates whether or not a mode requires an IV + * + * @return boolean Always returns true or false + */ + abstract public function requiresIV(); + + + + + /********************************************************************** + * PUBLIC METHODS + * + **********************************************************************/ + + /** + * Create an IV if the Mode used requires an IV. + * The IV should be saved and used for Encryption/Decryption + * of the same blocks of data. + * There are 3 ways to auto generate an IV by setting $src parameter + * PHP_Crypt::RAND - Default, uses mt_rand() + * PHP_Crypt::RAND_DEV_RAND - Unix only, uses /dev/random + * PHP_Crypt::RAND_DEV_URAND - Unix only, uses /dev/urandom + * PHP_Crypt::RAND_WIN_COM - Windows only, uses Microsoft's CAPICOM SDK + * + * @param string $src Optional, Sets how the IV is generated, must be + * one of the predefined PHP_Crypt RAND constants. Defaults to + * PHP_Crypt::RAND if none is given. + * @return string The IV that is being used by the mode + */ + public function createIV($src = PHP_Crypt::RAND) + { + // if the mode does not use an IV, lets not waste time + if(!$this->requiresIV()) + return false; + + $iv = Core::randBytes($src, $this->block_size); + return $this->IV($iv); + } + + + /** + * Sets or Returns an IV for the mode to use. If the $iv parameter + * is not given, this function only returns the current IV in use. + * + * @param string $iv Optional, An IV to use for the mode and cipher selected + * @return string The current IV being used + */ + public function IV($iv = null) + { + if($iv != null) + { + // check that the iv is the correct length, + $len = strlen($iv); + if($len != $this->block_size) + { + $msg = "Incorrect IV size. Supplied length: $len bytes, Required: {$this->block_size} bytes"; + trigger_error($msg, E_USER_WARNING); + } + + $this->clearRegisters(); + $this->register = $iv; + $this->iv = $iv; + } + + return $this->iv; + } + + + /** + * Checks to see if the current mode requires an IV and that it is set + * if it is required. Triggers E_USER_WARNING an IV is required and not set + * + * @return void + */ + public function checkIV() + { + if($this->requiresIV() && strlen($this->register) == 0) + { + $msg = strtoupper($this->mode_name)." mode requires an IV or the IV is empty"; + trigger_error($msg, E_USER_WARNING); + } + } + + + /** + * Sets and returns the name of the mode being used + * If $name parameter is set, sets the mode. If + * $name is not set, returns the current mode in use + * + * @param string $name Optional, One of the predefined + * phpCrypt mode constant names + * @return string One of the predefined phpCrypt mode + * constant mode names + */ + public function name($name = "") + { + if($name != "") + $this->mode_name = $name; + + return $this->mode_name; + } + + + /** + * Sets or Returns the padding type used with the mode + * If the $type parameter is not given, this function + * returns the the padding type only. + * + * @param string $type One of the predefined padding types + * @return void + */ + public function padding($type = "") + { + if($type != "") + $this->padding = $type; + + return $this->padding; + } + + + /** + * Returns or Sets the cipher object being used + * If the $cipher parameter is set with a cipher object, + * the cipher current cipher will be set to this cipher. + * If the $cipher parameter is not set, returns the + * current cipher object being used. + * + * @param object $cipher Optional, An object of type Cipher + * @return object An object of type Cipher + */ + public function cipher($cipher = null) + { + if(is_object($cipher)) + $this->cipher = $cipher; + + return $this->cipher; + } + + + + + /********************************************************************** + * PROTECTED METHODS + * + **********************************************************************/ + + /** + * Pads str so that final block is $block_bits in size, if the final block + * is $block_bits, then an additional block is added that is $block_bits in size + * The padding should be set by phpCrypt::setPadding() + * + * @param string $str the string to be padded + * @return boolean Returns true + */ + protected function pad(&$str) + { + $len = strlen($str); + $bytes = $this->cipher->blockSize(); // returns bytes + + // now determine the next multiple of blockSize(), then find + // the difference between that and the length of $str, + // this is how many padding bytes we will need + $num = ceil($len / $bytes) * $bytes; + $num = $num - $len; + + Padding::pad($str, $num, $this->padding); + return true; + } + + + /** + * Strip out the padded blocks created from Pad(). + * Padding type should be set by phpCrypt::setPadding() + * + * @param string $str the string to strip padding from + * @return boolean Returns True + */ + protected function strip(&$str) + { + Padding::strip($str, $this->padding); + return true; + } + + + /********************************************************************** + * PRIVATE METHODS + * + **********************************************************************/ + + /** + * Clears the registers used for some modes + * + * @return void + */ + private function clearRegisters() + { + $this->register = ""; + $this->enc_register = ""; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/Padding.php b/plugin/advancedsubscription/resources/phpcrypt/Padding.php new file mode 100644 index 0000000000..313a8b737b --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/Padding.php @@ -0,0 +1,328 @@ +. + */ + +namespace PHP_Crypt; + +include_once(dirname(__FILE__)."/phpCrypt.php"); + +/** + * Implement the following byte padding standards: + * ANSI X.923 + * ISO 10126 + * PKCS7 + * ISO/IEC 7816-4 + * Zero (NULL Byte) Padding + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Padding +{ + /** + * Constructor + * + * @return void + */ + public function __construct() { } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() { } + + + /** + * Returns a string padded using the specified padding scheme + * + * @param string $text The string to pad + * @param integer $bytes The number of bytes to pad + * @param integer $type One of the predefined padding types + * @return boolean True on success, false on error + */ + public static function pad(&$text, $bytes, $type = PHP_Crypt::ZERO) + { + // if the size of padding is not greater than 1 + // just return true, no padding will be done + if(!($bytes > 0)) + return true; + + switch($type) + { + case PHP_Crypt::PAD_ZERO: + return self::zeroPad($text, $bytes); + break; + case PHP_Crypt::PAD_ANSI_X923: + return self::ansiX923Pad($text, $bytes); + break; + case PHP_Crypt::PAD_ISO_10126: + return self::iso10126Pad($text, $bytes); + break; + case PHP_Crypt::PAD_PKCS7: + return self::pkcs7Pad($text, $bytes); + break; + case PHP_Crypt::PAD_ISO_7816_4: + return self::iso7816Pad($text, $bytes); + break; + default: + trigger_error("$type is not a valid padding type.", E_USER_NOTICE); + return self::zeroPad($text, $bytes); + } + + return true; + } + + + /** + * Strips padding from a string + * + * @param string $text The string strip padding from + * @param integer $type One of the predefined padding types + * @return boolean True on success, false on error + */ + public static function strip(&$text, $type = PHP_Crypt::ZERO) + { + switch($type) + { + case PHP_Crypt::PAD_ZERO: + return self::zeroStrip($text); + break; + case PHP_Crypt::PAD_ANSI_X923: + return self::ansiX923Strip($text); + break; + case PHP_Crypt::PAD_ISO_10126: + return self::iso10126Strip($text); + break; + case PHP_Crypt::PAD_PKCS7: + return self::pkcs7Strip($text); + break; + case PHP_Crypt::PAD_ISO_7816_4: + return self::iso7816Strip($text); + break; + default: + trigger_error("$type is not a valid padding type.", E_USER_NOTICE); + return self::zeroStrip($text); + } + + return true; + } + + + /** + * Pads a string with null bytes + * + * @param string $text The string to be padded + * @param integer $bytes The number of bytes to pad + * @return boolean Returns true + */ + private static function zeroPad(&$text, $bytes) + { + $len = $bytes + strlen($text); + $text = str_pad($text, $len, chr(0), STR_PAD_RIGHT); + return true; + } + + + /** + * Strips null padding off a string + * NOTE: This is generally a bad idea as there is no way + * to distinguish a null byte that is not padding from + * a null byte that is padding. Stripping null padding should + * be handled by the developer at the application level. + * + * @param string $text The string with null padding to strip + * @return boolean Returns true + */ + private static function zeroStrip(&$text) + { + // with NULL byte padding, we should not strip off the + // null bytes, instead leave this to the developer at the + // application level + //$text = preg_replace('/\0+$/', '', $text); + return true; + } + + + /** + * Pads a string using ANSI X.923 + * Adds null padding to the string, except for the last byte + * which indicates the number of bytes padded + * + * @param string $text The string to pad + * @param integer The number of bytes to pad + * @return boolean Returns true + */ + private static function ansiX923Pad(&$text, $bytes) + { + $len = $bytes + strlen($text); + $text = str_pad($text, ($len-1), "\0", STR_PAD_RIGHT); + $text .= chr($bytes); + return true; + } + + + /** + * Strips ANSI X.923 padding from a string + * + * @param string $text The string to strip padding from + * @return boolean Returns true + */ + private static function ansiX923Strip(&$text) + { + $pos = strlen($text) - 1; + $c = ord($text[$pos]); + + if($c == 0) + return true; + else if($c == 1) + $text = substr($text, 0, -1); + else + { + // the total null bytes are 1 less than the value of the final byte + $nc = $c - 1; + $text = preg_replace('/\0{'.$nc.'}'.preg_quote(chr($c)).'$/', "", $text); + } + + return true; + } + + + /** + * Pads a string using ISO 10126 + * Adds random bytes to the end of the string, except for the last + * byte which indicates the number of padded bytes + * + * @param string $text The string to pad + * @param integer The number of bytes to pad + * @return boolean Returns true + */ + private static function iso10126Pad(&$text, $bytes) + { + // create the random pad bytes, we do one less than + // needed because the last byte is reserved for the + // number of padded bytes + for($i = 0; $i < ($bytes - 1); ++$i) + $text .= chr(mt_rand(0, 255)); + + // add the byte to indicate the padding length + $text .= chr($bytes); + return true; + } + + + /** + * Strips ISO 10126 padding from a string + * + * @param string $text The string to strip padding from + * @return boolean Returns true + */ + private static function iso10126Strip(&$text) + { + $pos = strlen($text) - 1; + $c = ord($text[$pos]) * -1; + + // if we got a null byte at the end of the string, + // just return + if($c == 0) + return true; + + $text = substr($text, 0, $c); + return true; + } + + + /** + * Pads a string using PKCS7 + * Adds padding using the bytes with the value of the + * number of bytes need for padding + * + * @param string $text The string to pad + * @param integer The number of bytes to pad + * @return boolean Returns true + */ + private static function pkcs7Pad(&$text, $bytes) + { + $len = $bytes + strlen($text); + $text = str_pad($text, $len, chr($bytes), STR_PAD_RIGHT); + return true; + } + + + /** + * Strips PKCS7 padding from a string + * + * @param string $text The string to strip padding from + * @return boolean Returns true + */ + private static function pkcs7Strip(&$text) + { + $pos = strlen($text) - 1; + $c = ord($text[$pos]); + + if($c == 0) + return true; + + $text = preg_replace('/'.preg_quote(chr($c)).'{'.$c.'}$/', "", $text); + return true; + } + + + /** + * Pads a string using ISO/IEC 7816-4 + * Adds byte 0x80 followed by null bytes to pad a string + * + * @param string $text The string to pad + * @param integer The number of bytes to pad + * @return boolean Returns true + */ + private static function iso7816Pad(&$text, $bytes) + { + $text .= chr(0x80); + $len = $bytes + strlen($text); + + // if we are only padding one byte, then 0x80 is all we need + // else we follow up with null bytes + if($bytes > 1) + $text = str_pad($text, ($len - 1), chr(0), STR_PAD_RIGHT); + + return true; + } + + + /** + * Strips ISO/IEC 7816-4 padding from a string + * + * @param string $text The string to strip padding from + * @return boolean Returns true + */ + private static function iso7816Strip(&$text) + { + $c = chr(0x80); + $text = preg_replace('/'.preg_quote($c).'\0*$/', '', $text); + return true; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/README.md b/plugin/advancedsubscription/resources/phpcrypt/README.md new file mode 100644 index 0000000000..475a323a75 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/README.md @@ -0,0 +1,209 @@ +phpCrypt - A PHP Encryption Library API +===================================================== + +WHAT IS PHPCRYPT? +----------------- + +phpCrypt is an encryption library written in PHP. It aims to implement +all major encryption ciphers, modes, padding methods, and other tools +used for encryption and decryption. phpCrypt does not rely on mCrypt, +PHP extentions, or PEAR libraries. + +It currently support many widely used ciphers. In addition it +supports many popular encryption modes. There are also tools to implement +the different padding schemes, as well as multiple methods of creating an +Initialization Vector (IV) for modes that require one. + +phpCrypt is developed by Ryan Gilfether + +phpCrypt is always in development. If you have any questions, found a bug, +or have a feature request, you can contact Ryan at + + +WHAT DOES IT WORK ON? +--------------------- + +phpCrypt version 0.x works with PHP 5.3 or later. It will run on any +32 or 64 bit operating system that has PHP available for it. + +SUPPORTED ENCRYPTION CIPHERS, MODES, PADDING +-------------------------------------------- + +The list of supported encryption ciphers and modes is continually growing, +each new version of phpCrypt will add new ciphers or modes. The current list +of supported ciphers and modes are listed below: + +Ciphers: + + 3Way, AES, ARC4 (RC4), Blowfish, CAST-128, CAST-256, DES, Triple DES, + Enigma, RC2, Rijndael, SimpleXOR, Skipjack, Vigenere + +Modes: + + CBC, CFB, CTR, ECB, NCFB, NOFB, OFB, PCBC + +Padding: + + ANSI X.923, ISO 10126, PKCS7, ISO/IEC 7816-4, Zero (NULL Byte) + +DOCUMENTATION +------------- + +This README file serves as the documentation. The phpCrypt website also +lists all the constants you need to select ciphers, modes, padding, and +IV methods, which is availabe at http://www.gilfether.com/phpcrypt. In addition, +phpCrypt comes with an `examples` directory which has sample code to help get +you started. + +phpCrypt is easy to use. An example of encrypting a string using AES-128 +with CBC mode is demonstrated below. Also note that if you are new to encryption +using the AES-128 cipher with CBC mode is a simple yet secure way of getting +started. + + createIV(); + $encrypt = $crypt->encrypt($data); + + $crypt->IV($iv); + $decrypt = $crypt->decrypt($encrypt); + ?> + +BYTE PADDING +------------ + +Some modes require a block of data to be padded if it's shorter than than +required block size of the cipher. For example DES encryption works on +8 byte blocks of data. If you a have a block of 6 bytes, then it +may need to be padded 2 bytes before it can be encrypted. Some modes don't +require the data to be padded. + +By default phpCrypt uses NULL byte padding when necessary, keeping it +compatible with mCrypt. + +phpCrypt has other padding methods available as well. You can specify +the padding you wish to use in two ways. The easiest method is to declare it +in the constructor like so: + + $crypt = new PHP_Crypt($key, PHP_Crypt::CIPHER_AES_128, PHP_Crypt::MODE_CBC, PHP_Crypt::PAD_PKCS7); + +Optionally, you can also call the phpCrypt::padding() method to set the padding: + + $crypt = new PHP_Crypt($key, PHP_Crypt::CIPHER_AES_128, PHP_Crypt::MODE_CBC); + $crypt->padding(PHP_Crypt::PAD_PKCS7); + +In the event the padding is set for a mode that does not require padding, the +padding method is ignored. You can get a full list of padding methods available +at http://www.gilfether.com/phpcrypt. + +You always have the option of padding the data yourself before sending it +through phpCrypt. In this case you do not need to worry about the phpCrypt +padding methods. + +NOTE: NULL byte padding is not stripped off during decryption. This is left for +you to do. phpCrypt can not determine whether a null byte is part of the +original data or was added as padding. + +CREATING INITIALIZATION VECTORS +------------------------------- + +By default phpCrypt will use the PHP mt_rand() to generate random data used +to create the IV. This method is supported on all operating systems, however +there are more secure ways to generate random data depending on your +operating system + +**LINUX & UNIX** + +On Unix based systems, phpCrypt supports reading from `/dev/random` and +`/dev/urandom`. This can be done by passing one of the following constants +to phpCrypt::createIV(): + + $iv = $crypt->createIV(PHP_Crypt::RAND_DEV_RAND); + or + $iv = $crypt->createIV(PHP_Crypt::RAND_DEV_URAND); + +**MICROSOFT WINDOWS** + +On Windows systems, you have the option to use the random number generator +found in the Microsoft CAPICOM SDK which is more secure. Before this will +work you must install the Microsoft CAPICOM SDK and enable the PHP `com_dotnet` +extension: + +- Download CAPICOM from Microsoft at http://www.microsoft.com/en-us/download/details.aspx?id=25281 +- Double click the MSI file you downloaded and follow the install directions +- Open a command prompt and register the DLL: `regsvr32 C:\Program Files\PATH TO\CAPICOM SDK\Lib\X86\capicom.dll` +- Now edit php.ini to enable the com_dotnet extension: `extension=php_com_dotnet.dll` +- If you are running PHP as an Apache module, restart Apache. + +To use the Windows random number generator in CAPICOM you would call createIV() like so: + + $iv = $crypt->createIV(PHP_Crypt::RAND_WIN_COM); + +**SUPPLYING YOUR OWN IV** + +You have the option of creating an IV yourself without using phpCrypt::createIV(). +If you wish to create your own IV or use one that was given to you for decryption, +set the IV using phpCrypt::IV() method: + + $crypt->IV($your_custom_iv); + +The IV length must be equal to the block size used by the cipher. If the IV is not +the correct length phpCrypt will issue a PHP Warning and fail. + +Not all modes require an IV. In the event the IV is set for a mode that does not +require an IV, the IV is ignored. You can get a full list of IV constants and a +list of modes that require an IV at http://www.gilfether.com/phpcrypt + +CREATING A KEY +-------------- + +phpCrypt includes a helper function to create a string of random bytes to use as +a key. This can be used in place of setting your own key as shown in the examples +above. The PHP_Crypt::RAND constants are the same as the ones used for the createIV() +function. The second parameter indicates the number of random bytes to create. + + + +See the examples directory for example code demonstrating the createKey() function. + +The key length must be the size (in bytes) required by the cipher. phpCrypt does not +pad the key, it will issue a PHP warning and fail if the key size is too small. +Cipher key lengths are listed at http://www.gilfether.com/phpcrypt + + +FULL LIST OF CONSTANTS +---------------------- + +For the full list of constants available for Ciphers, Modes, Padding, and IV creation, +visit the phpCrypt website: http://www.gilfether.com/phpcrypt + + +GPL STUFF +--------- + +This file is part of phpCrypt + +phpCrypt is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Please read the GPL file included in this distribution for the full license. diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/3DES.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/3DES.php new file mode 100644 index 0000000000..b494ca8f8a --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/3DES.php @@ -0,0 +1,251 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/DES.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements Triple DES Encryption (3DES) + * Extends the Cipher_DES class. Triple DES does 3 DES rounds for + * both encryption and decryption. It requires an 8, 16, or 24 byte + * key. If the key is 8 or 16 bytes, it is expanded to 24 bytes + * before it is used + * + * Resources used to implement this algorithm(in addition to those + * listed in DES.php): + * http://en.wikipedia.org/wiki/Triple_DES + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Cipher_3DES extends Cipher_DES +{ + /** @type integer BYTES_BLOCK The size of the block, in bytes */ + const BYTES_BLOCK = 8; // 64 bits + + /** @type integer BYTES_KEY The size of the key. The key can be + 8, 16, or 24 bytes but gets expanded to 24 bytes before used */ + const BYTES_KEY = 24; + + + /** + * Constructor + * + * @param string $key The key used for Encryption/Decryption + * @return void + */ + public function __construct($key) + { + $key_len = strlen($key); + + if($key_len == 8 || $key_len == 16) + $key = self::expandKey($key, $key_len); + else if($key_len < self::BYTES_KEY) + { + $msg = PHP_Crypt::CIPHER_3DES." requires an 8, 16, or 24 byte key. "; + $msg .= "$key_len bytes received."; + trigger_error($msg, E_USER_WARNING); + } + // else if the key is longer than 24 bytes, phpCrypt will shorten it + + // set the 3DES key, note that we call __construct1() not __construct() + // this is a second contructor we created for classes that extend the + // DES class + parent::__construct1(PHP_Crypt::CIPHER_3DES, $key, self::BYTES_KEY); + + // 3DES requires that data is 64 bits + $this->blockSize(self::BYTES_BLOCK); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypt plain text data using TripleDES + * For encryption 3DES takes a 192 bit key, splits + * it into 3 64 bit parts, and then does the following + * DES ENCRYPT(key1) -> DES DECRYPT(key2) -> DES ENCRYPT(key3) + * + * @param string $data A plain text string + * @return boolean Returns true + */ + public function encrypt(&$text) + { + $blocksz = $this->blockSize(); + + for($i = 0; $i < 3; ++$i) + { + $key = substr($this->key(), ($i * 8), $blocksz); + $this->keyPermutation($key); + + if($i % 2) // round 1 + $this->operation(parent::DECRYPT); + else // rounds 0 and 2 + $this->operation(parent::ENCRYPT); + + $this->des($text); + } + + return true; + } + + + /** + * Decrypt a TripleDES encrypted string + * For decryption 3DES takes a 192 bit key, splits + * it into 3 64 bit parts, and then does the following + * DES DECRYPT(key1) -> DES ENCRYPT(key2) -> DES DECRYPT(key3) + * + * @param string $encrypted A DES encrypted string + * @return boolean Returns true + */ + public function decrypt(&$text) + { + $blocksz = $this->blockSize(); + + for($i = 2; $i >= 0; --$i) + { + $key = substr($this->key(), ($i * 8), $blocksz); + $this->keyPermutation($key); + + if($i % 2) // round 1 + $this->operation(parent::ENCRYPT); + else // round 0 and 2 + $this->operation(parent::DECRYPT); + + $this->des($text); + } + + return true; + } + + + /** + * We overload the DES::keyPermutation() function so it takes + * a 64 bit key as a parameter. This is because 3DES uses a 192 bit + * key which is split into 3 64 bit parts, each of which must be + * passed through the keyPermutation() function + * Key permutation, based on tables $_pc1 and $_pc2 + * Create 16 subkeys, each of which is 48-bits long. + * NOTE: The $key parameter is required, however because PHP expects + * an overloaded method to contain the same number of parameters + * (when E_STRICT is set) as the parent class, we make it optional + * to shut the 'error' up + * + * @param string $key A 64 bit key + * @return void + */ + private function keyPermutation($key = "") + { + $this->sub_keys = array(); + $pc1m = array(); + $pcr = array(); + $c = array(); + $d = array(); + + // convert the key to binary + $binkey = parent::str2Bin($key); + + // reduce the key down to 56bits based on table $_pc1 + for($i = 0; $i < 56; ++$i) + { + $pos = parent::$_pc1[$i] - 1; + $pc1m[$i] = $binkey[$pos]; + } + + // split $pc1m in half (C0 and D0) + $c[0] = array_slice($pc1m, 0, 28); + $d[0] = array_slice($pc1m, 28, 28); + + // now that $c[0] and $d[0] are defined, create 16 blocks for Cn and Dn + // where 1 <= n <= 16 + for($i = 1; $i <= 16; ++$i) + { + // now set the next Cn and Dn as the previous Cn and Dn + $c[$i] = $c[$i-1]; + $d[$i] = $d[$i-1]; + + for($j = 0; $j < parent::$_key_sched[$i-1]; ++$j) + { + // do a left shift, move each bit one place to the left, + // except for the first bit, which is cycled to the end + // of the block. + $c[$i][] = array_shift($c[$i]); + $d[$i][] = array_shift($d[$i]); + } + + // We now form the sub_keys (Kn), for 1<=n<=16, by applying the + // following permutation table to each of the concatenated + // pairs CnDn. Each pair has 56 bits, but PC-2 only uses 48 + // of these. + $CnDn = array_merge($c[$i], $d[$i]); + $this->sub_keys[$i-1] = ""; + for($j = 0; $j < 48; ++$j) + $this->sub_keys[$i-1] .= $CnDn[parent::$_pc2[$j] - 1]; + } + + // the sub_keys are created, we are done with the key permutation + } + + + /** + * Triple DES accepts an 8, 16, or 24 bytes key. If the key is + * 8 or 16 bytes, it is expanded to 24 bytes + * An 8 byte key is expanded by repeating it 3 times to make a 24 + * byte key + * A 16 byte key add the first 8 bytes to the end of the string + * to make a 24 byte key + * + * @param string $key The 8 or 16 byte key to expand + * @return string If the key given is 8 or 16 bytes it returns the + * expanded 24 byte key, else it returns the original key unexpanded + */ + private static function expandKey($key, $len) + { + // if we were given an 8 byte key, repeat it + // 3 times to produce a 24 byte key + if($len == 8) + $key = str_repeat($key, 3); + + // if we were given a 16 byte key, add the first + // 8 bytes to the end of the key to produce 24 bytes + if($len == 16) + $key .= substr($key, 0, 8); + + // return the key + return $key; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/3Way.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/3Way.php new file mode 100644 index 0000000000..e5da24d5fa --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/3Way.php @@ -0,0 +1,340 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements The 3Way Cipher + * There may be a bug with this implementation of 3-Way. Due + * to lack of information on this cipher, the mCrypt + * implementation of 3-Way was used to help develop phpCrypt's + * version. The gamma() function in mCrypt's 3-way.c does + * not modifiy the values passed into it. I am not sure + * if this is a bug, or if it is by design though I suspect + * it may not be intended to work that way. For compatibility + * with mCrypt's 3-Way implementation, phpCrypts 3-Way gamma() + * function does nothing, and leaves the value passed into it + * unmodified as well. If this is found to be incorrect I + * will make the necessary changes to correct it. Please view + * the gamma() function in this class for more information. + * + * Resources used to implement this algorithm: + * mCrypt's 3-way.c + * http://www.quadibloc.com/crypto/co040307.htm + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Cipher_3Way extends Cipher +{ + /** @type integer BYTES_BLOCK The size of the block, in bytes */ + const BYTES_BLOCK = 12; // 96 bits; + + /** @type integer BYTES_KEY The size of the key, in bytes */ + const BYTES_KEY = 12; // 96 bits; + + /** @type integer ROUNDS The number of rounds to implement */ + const ROUNDS = 11; + + /** @type array $_rconst_enc The round constants for encryption */ + private static $_rcon_enc = array(); + + /** @type array $_rconst_enc The round constants for decryption */ + private static $_rcon_dec = array(); + + + /** + * Constructor + * + * @param string $key The key used for Encryption/Decryption + * @return void + */ + public function __construct($key) + { + // set the key, make sure the required length is set in bytes + parent::__construct(PHP_Crypt::CIPHER_3WAY, $key, self::BYTES_KEY); + + // set the block size + $this->blockSize(self::BYTES_BLOCK); + + // initialize the round constants + $this->initTables(); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypt plain text data + * + * @param string $data A 96 bit plain data + * @return boolean Returns true + */ + public function encrypt(&$data) + { + $this->operation(parent::ENCRYPT); + return $this->threeway($data); + } + + + /** + * Decrypt an encrypted string + * + * @param string $data A 96 bit block encrypted data + * @return boolean Returns true + */ + public function decrypt(&$data) + { + $this->operation(parent::DECRYPT); + return $this->threeway($data); + } + + + /** + * The same alorigthm is used for both Encryption, and Decryption + * + * @param string $data A 96 bit block of data + * @return boolean Returns true + */ + private function threeway(&$data) + { + // first split $data into three 32 bit parts + $data = str_split($data, 4); + $data = array_map("parent::str2Dec", $data); + + // split the key into three 32 bit parts + $key = str_split($this->key(), 4); + $key = array_map("parent::str2Dec", $key); + + // determine which round constant to use + if($this->operation() == parent::ENCRYPT) + $rcon = self::$_rcon_enc; + else + $rcon = self::$_rcon_dec; + + if($this->operation() == parent::DECRYPT) + { + $this->theta($key); + $this->invertBits($key); + $this->invertBits($data); + } + + // 3Way uses 11 rounds + for($i = 0; $i < self::ROUNDS; ++$i) + { + $data[0] = parent::uInt32($data[0] ^ $key[0] ^ ($rcon[$i] << 16)); + $data[1] = parent::uInt32($data[1] ^ $key[1]); + $data[2] = parent::uInt32($data[2] ^ $key[2] ^ $rcon[$i]); + + $this->rho($data); + } + + $data[0] = parent::uInt32($data[0] ^ $key[0] ^ ($rcon[self::ROUNDS] << 16)); + $data[1] = parent::uInt32($data[1] ^ $key[1]); + $data[2] = parent::uInt32($data[2] ^ $key[2] ^ $rcon[self::ROUNDS]); + + $this->theta($data); + + if($this->operation() == parent::DECRYPT) + $this->invertBits($data); + + // assemble the three 32 bit parts back to a 96 bit string + $data = parent::dec2Str($data[0], 4).parent::dec2Str($data[1], 4). + parent::dec2Str($data[2], 4); + + return true; + } + + + /** + * 3-Way's Theta function + * This was translated from mcrypt's 3-Way theta() function + * + * @param array $d A 3 element array of 32 bit integers + * @return void + */ + private function theta(&$d) + { + $tmp = array(); + + $tmp[0] = parent::uInt32( + $d[0] ^ ($d[0] >> 16) ^ ($d[1] << 16) ^ ($d[1] >> 16) ^ ($d[2] << 16) ^ + ($d[1] >> 24) ^ ($d[2] << 8) ^ ($d[2] >> 8) ^ ($d[0] << 24) ^ ($d[2] >> 16) ^ + ($d[0] << 16) ^ ($d[2] >> 24) ^ ($d[0] << 8) + ); + + $tmp[1] = parent::uInt32( + $d[1] ^ ($d[1] >> 16) ^ ($d[2] << 16) ^ ($d[2] >> 16) ^ ($d[0] << 16) ^ + ($d[2] >> 24) ^ ($d[0] << 8) ^ ($d[0] >> 8) ^ ($d[1] << 24) ^ ($d[0] >> 16) ^ + ($d[1] << 16) ^ ($d[0] >> 24) ^ ($d[1] << 8) + ); + + $tmp[2] = parent::uInt32( + $d[2] ^ ($d[2] >> 16) ^ ($d[0] << 16) ^ ($d[0] >> 16) ^ ($d[1] << 16) ^ + ($d[0] >> 24) ^ ($d[1] << 8) ^ ($d[1] >> 8) ^ ($d[2] << 24) ^ ($d[1] >> 16) ^ + ($d[2] << 16) ^ ($d[1] >> 24) ^ ($d[2] << 8) + ); + + $d = $tmp; + } + + + /** + * 3-Ways gamma() function + * NOTE: After extensive testing against mcrypt's 3way, it appears + * mcrypt's 3way gamma() function does not modify the array passed into + * it. During testing mcrypt's 3way gamma() function returned the exact + * same values sent into it. I'm confused as to why this is, and + * can't find enough information about 3-Way to know if this is correct + * though I suspect it's not. For compatibility, I am going to make + * phpCrypt's 3way gamma() function leave the values unmodified. I will change + * this at a later date if I find this is incorrect and mcrypt has a bug + * + * This was translated from mcrypt's 3-Way gamma() function + * + * @param array $d A 3 element array of 32 bit integers + * @return void + */ + private function gamma(&$d) + { + /* + $tmp = array(); + + $tmp[0] = parent::uInt32($d[0] ^ ($d[1] | (~$d[2]))); + $tmp[1] = parent::uInt32($d[1] ^ ($d[2] | (~$d[0]))); + $tmp[2] = parent::uInt32($d[2] ^ ($d[0] | (~$d[1]))); + + $d = $tmp; + */ + } + + + /** + * Applies several of 3Way's functions used for encryption and decryption + * NOTE: Please read the comments in the $this->gamma() function. This + * function calls the $this->gamma() function which does not do anything. + * + * @param array $d A 3 element 32 bit integer array + * @return void + */ + private function rho(&$d) + { + $this->theta($d); + $this->pi1($d); + $this->gamma($d); + $this->pi2($d); + } + + + /** + * 3Way's PI_1 function + * This was taken from mcrypt's 3-way pi_1() function + * + * @param array $d A 3 element 32 bit integer array + * @return void + */ + private function pi1(&$d) + { + $d[0] = parent::uInt32(($d[0] >> 10) ^ ($d[0] << 22)); + $d[2] = parent::uInt32(($d[2] << 1) ^ ($d[2] >> 31)); + } + + + /** + * 3Way's PI_2 function + * This was taken from mcrypt's 3-way pi_2() function + * + * @param array $d A 3 element 32 bit integer array + * @return void + */ + private function pi2(&$d) + { + $d[0] = parent::uInt32(($d[0] << 1) ^ ($d[0] >> 31)); + $d[2] = parent::uInt32(($d[2] >> 10) ^ ($d[2] << 22)); + } + + + /** + * Reverse the bits of each element of array $d, and + * reverses the order of array $d, used only during + * decryption + * + * @param array $d A 3 element array of a 32 bit integers + * @return void + */ + private function invertBits(&$d) + { + $d = array_map("parent::dec2Bin", $d); + $d = array_map("strrev", $d); + $d = array_map("parent::bin2Dec", $d); + $d = array_reverse($d); + } + + + /** + * Initialize the tables used in 3Way Encryption. + * + * @return void + */ + private function initTables() + { + // round constants for encryption + self::$_rcon_enc = array( + 0x0B0B, 0x1616, 0x2C2C, 0x5858, + 0xB0B0, 0x7171, 0xE2E2, 0xD5D5, + 0xBBBB, 0x6767, 0xCECE, 0x8D8D + ); + + // round constants for decryption + self::$_rcon_dec = array( + 0xB1B1, 0x7373, 0xE6E6, 0xDDDD, + 0xABAB, 0x4747, 0x8E8E, 0x0D0D, + 0x1A1A, 0x3434, 0x6868, 0xD0D0 + ); + } + + + /** + * Indicates this is a block cipher + * + * @return integer Returns Cipher::BLOCK + */ + public function type() + { + return parent::BLOCK; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/AES128.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/AES128.php new file mode 100644 index 0000000000..e9f8b918aa --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/AES128.php @@ -0,0 +1,71 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../phpCrypt.php"); +require_once(dirname(__FILE__)."/Rijndael128.php"); + + +/** + * Implement Advanced Encryption Standard (AES) + * Since AES-128 is the same as Rijndael-128, this + * class extends Cipher_Rijndael_128, and all the work + * is done there. + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Cipher_AES_128 extends Cipher_Rijndael_128 +{ + /** @type integer BYTES_BLOCK The size of the block, in bytes */ + const BYTES_BLOCK = 16; //128 bits; + + /** @type integer BYTES_KEY The size of the key, in bytes */ + const BYTES_KEY = 16; // 128 bits; + + /** + * Constructor, Sets the key used for encryption. + * + * @param string $key string containing the user supplied encryption key + * @return void + */ + public function __construct($key) + { + // Setup AES by calling the second constructor in Rijndael_128 + // The block size is set here too, since all AES implementations use 128 bit blocks + parent::__construct1(PHP_Crypt::CIPHER_AES_128, $key, self::BYTES_KEY); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/AES192.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/AES192.php new file mode 100644 index 0000000000..ab640e6c3e --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/AES192.php @@ -0,0 +1,72 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../phpCrypt.php"); +require_once(dirname(__FILE__)."/Rijndael128.php"); + + +/** + * Implement Advanced Encryption Standard (AES) + * Both AES-192 and Rijndael-128 operate on 128 bit blocks. + * The only difference is AES-192 uses a 192 bit key, where + * as Rijndael-128 can uses a variable length key. + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Cipher_AES_192 extends Cipher_Rijndael_128 +{ + /** @type integer BYTES_BLOCK The size of the block, in bytes */ + const BYTES_BLOCK = 16; // 128 bits; + + /** @type integer BYTES_KEY The size of the key, in bytes */ + const BYTES_KEY = 24; // 192 bits; + + /** + * Constructor + * Sets the key used for encryption. + * + * @param string $key string containing the user supplied encryption key + * @return void + */ + public function __construct($key) + { + // Setup AES by calling the second constructor in Rijndael_128 + // The block size is set here too, since all AES implementations use 128 bit blocks + parent::__construct1(PHP_Crypt::CIPHER_AES_192, $key, self::BYTES_KEY); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/AES256.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/AES256.php new file mode 100644 index 0000000000..2263eef246 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/AES256.php @@ -0,0 +1,72 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../phpCrypt.php"); +require_once(dirname(__FILE__)."/Rijndael128.php"); + + +/** + * Implement Advanced Encryption Standard (AES) + * Both AES-256 and Rijndael-128 operate on 128 bit blocks. + * The only difference is AES-256 uses a 256 bit key, where + * as Rijndael-128 can uses a variable length key. + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Cipher_AES_256 extends Cipher_Rijndael_128 +{ + /** @type integer BYTES_BLOCK The size of the block, in bytes */ + const BYTES_BLOCK = 16; // 128 bits; + + /** @type integer BITS_KEY The size of the key, in bytes */ + const BYTES_KEY = 32; // 256 bits; + + /** + * Constructor + * Sets the key used for encryption. + * + * @param string $key string containing the user supplied encryption key + * @return void + */ + public function __construct($key) + { + // Setup AES by calling the second constructor in Rijndael_128 + // The block size is set here too, since all AES implementations use 128 bit blocks + parent::__construct1(PHP_Crypt::CIPHER_AES_256, $key, self::BYTES_KEY); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/ARC4.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/ARC4.php new file mode 100644 index 0000000000..8e9adc686c --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/ARC4.php @@ -0,0 +1,201 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements ARC4 Encryption + * ARC4 is an alternative name for RC4, RC4 is trademarked + * Resources used to implement this algorithm: + * http://calccrypto.wikidot.com/algorithms:rc4 + * http://en.wikipedia.org/wiki/RC4 + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Cipher_ARC4 extends Cipher +{ + /** @type string $_s The S List */ + private $_s = ""; + + /** @type string $_key_stream The Key Stream */ + private $_key_stream = ""; + + + /** + * Constructor + * + * @param string $key The key used for Encryption/Decryption + * @return void + */ + public function __construct($key) + { + // set the ARC4 key + parent::__construct(PHP_Crypt::CIPHER_ARC4, $key); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypt plain text data using ARC4 + * + * @param string $data A plain text string, 8 bytes long + * @return boolean Returns true + */ + public function encrypt(&$text) + { + $this->operation(parent::ENCRYPT); + return $this->arc4($text); + } + + + /** + * Decrypt a ARC4 encrypted string + * + * @param string $encrypted A ARC4 encrypted string, 8 bytes long + * @return boolean Returns true + */ + public function decrypt(&$text) + { + $this->operation(parent::DECRYPT); + return $this->arc4($text); + } + + + /** + * Performs the ARC4 algorithm, since encryption and decryption + * are the same, all the work is done here + * + * @param string $text The string to encrypt/decrypt + * @return boolean Returns true + */ + private function arc4(&$text) + { + $len = strlen($text); + $this->prga($len); + + for($i = 0; $i < $len; ++$i) + $text[$i] = $text[$i] ^ $this->_key_stream[$i]; + + return true; + } + + + /** + * The key scheduling algorithm (KSA) + * + * @return void + */ + private function ksa() + { + $j = 0; + $this->_s = array(); + $keylen = $this->keySize(); + $key = $this->key(); + + // fill $this->_s with all the values from 0-255 + for($i = 0; $i < 256; ++$i) + $this->_s[$i] = $i; + + // the changing S List + for($i = 0; $i < 256; ++$i) + { + $k = $key[$i % $keylen]; + $j = ($j + $this->_s[$i] + ord($k)) % 256; + + // swap bytes + self::swapBytes($this->_s[$i], $this->_s[$j]); + } + } + + + /** + * The Pseudo-Random Generation Algorithm (PGRA) + * Creates the key stream used for encryption / decryption + * + * @param integer $data_len The length of the data we are encrypting/decrypting + * @return void + */ + private function prga($data_len) + { + $i = 0; + $j = 0; + $this->_key_stream = ""; + + // set up the key schedule + $this->ksa(); + + for($c = 0; $c < $data_len; ++$c) + { + $i = ($i + 1) % 256; + $j = ($j + $this->_s[$i]) % 256; + + // swap bytes + self::swapBytes($this->_s[$i], $this->_s[$j]); + + $pos = ($this->_s[$i] + $this->_s[$j]) % 256; + $this->_key_stream .= chr($this->_s[$pos]); + } + } + + + /** + * Swap two individual bytes + * + * @param string $a A single byte + * @param string $b A single byte + * @return void + */ + private static function swapBytes(&$a, &$b) + { + $tmp = $a; + $a = $b; + $b = $tmp; + } + + + /** + * Indicates that this is a stream cipher + * + * @return integer Returns Cipher::STREAM + */ + public function type() + { + return parent::STREAM; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/Blowfish.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/Blowfish.php new file mode 100644 index 0000000000..da6b07de4f --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/Blowfish.php @@ -0,0 +1,602 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements The Blowfish Cipher + * + * Resources used to implement this algorithm: + * Applied Cryptography, Bruce Schneier, pp 336-339 + * http://www.quadibloc.com/crypto/co040304.htm + * http://www.freemedialibrary.com/index.php/Blowfish_test_vectors + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Cipher_Blowfish extends Cipher +{ + /** @type integer BYTES_BLOCK The size of the block, in bytes */ + const BYTES_BLOCK = 8; // 64 bits; + + // a variable length key, between 8 - 448 bits + //const BYTES_KEY = 0; + + /** @type array $_sbox1 S-Box 1 */ + private static $_sbox1 = array(); + + /** @type string $_sbox2 S-Box 2 */ + private static $_sbox2 = array(); + + /** @type string $_sbox3 S-Box 3 */ + private static $_sbox3 = array(); + + /** @type string $_sbox4 S-Box 4 */ + private static $_sbox4 = array(); + + /** @type array $_p The P-Array, 18 elements long */ + private static $_p = array(); + + /** @type integer $key_pos Used for keyChunk(), to determine the current + position in the key */ + private $key_pos = 0; + + /** + * Constructor + * + * @param string $key The key used for Encryption/Decryption + * @return void + */ + public function __construct($key) + { + // the max length of the key is 448 bits (56 bytes) + $keylen = strlen($key); + if($keylen > 56) + { + $key = substr($key, 0, 56); + $keylen = 56; + } + else if($keylen < 1) + { + $msg = "No key given. The key must be between 1 - 56 bytes."; + trigger_error($msg, E_USER_WARNING); + } + + // set the key, make sure the required length is set in bits + parent::__construct(PHP_Crypt::CIPHER_BLOWFISH, $key, $keylen); + + // set the block size + $this->blockSize(self::BYTES_BLOCK); + + $this->initTables(); + $this->subKeys(); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypt plain text data + * + * @param string $data A 64 bit (8 byte) plain text string + * @return boolean Returns true + */ + public function encrypt(&$data) + { + $this->operation(parent::ENCRYPT); + return $this->blowfish($data); + } + + + /** + * Decrypt an encrypted string + * + * @param string $data A 64 bit block of Blowfish encrypted data + * @return boolean Returns true + */ + public function decrypt(&$data) + { + $this->operation(parent::DECRYPT); + return $this->blowfish($data); + } + + + /** + * The same alorigthm is used for both Encryption, and Decryption + * + * @param string $data A 64 bit block of data + * @return boolean Returns true + */ + private function blowfish(&$data) + { + // divide the data into into two 32 bit halves + $xl = parent::str2Dec(substr($data, 0, 4)); + $xr = parent::str2Dec(substr($data, 4, 4)); + + for($i = 0; $i < 16; ++$i) + { + if($this->operation() == parent::ENCRYPT) + $xl ^= self::$_p[$i]; + else + $xl ^= self::$_p[17-$i]; + + // perform F() on the left half, and XOR with the right half + $xr = $this->F($xl) ^ $xr; + + // swap $xl and $xr + $tmp = $xr; + $xr = $xl; + $xl = $tmp; + } + + // swap $xl and $xr after the 16th round to undo the last swap + $tmp = $xl; + $xl = $xr; + $xr = $tmp; + + // XOR the final two elements of $_p + if($this->operation() == parent::ENCRYPT) + { + $xr ^= self::$_p[16]; + $xl = $xl ^ self::$_p[17]; + } + else // parent::DECRYPT + { + $xr ^= self::$_p[1]; + $xl ^= self::$_p[0]; + } + + // recombine the two halves, force them to be 4 bytes each + $data = parent::dec2Str($xl, 4).parent::dec2Str($xr, 4); + + return true; + } + + + /** + * Blowfish's F() function + * + * @param string $i A 32 bit integer + */ + private function F($i) + { + // split the 32 bits into four 8 bit parts + $x[0] = $i & 0xff; // first byte + $x[1] = ($i >> 8) & 0xff; // second byte + $x[2] = ($i >> 16) & 0xff; // third byte + $x[3] = ($i >> 24) & 0xff; // fourth byte + + // perform F(), make sure all values returned are + // unsigned 32 bit + $f = parent::uInt32(self::$_sbox1[$x[3]] + self::$_sbox2[$x[2]]); + $f = parent::uInt32($f ^ self::$_sbox3[$x[1]]); + $f = parent::uInt32($f + self::$_sbox4[$x[0]]); + + return $f; + } + + + /** + * Generates the subkeys used in Blowfish + * + * @return void + */ + private function subKeys() + { + // now xor each element of $_p with 32 bits from the key + for($i = 0; $i < 18; ++$i) + { + $c = $this->keyChunk(4); + self::$_p[$i] ^= parent::str2Dec($c); + } + + // start with an 8 byte null string + $zero = "\0\0\0\0\0\0\0\0"; + + // now we loop, each loop replacing elements of $_p, or an $_sbox with the + // repeatedly encrypted zero string + for($i = 0; $i < 1042; $i += 2) + { + // encrypt the 64 bit null string + $this->encrypt($zero); + + // split the encrypted null string into two 32 bit parts + $z0 = parent::str2Dec(substr($zero, 0, 4)); + $z1 = parent::str2Dec(substr($zero, 4, 4)); + + // now fill the $_p, $_sbox1, $_sbox2, $_sbox3, $_sbox4 + // with 4 bytes from the repeatedly encrypted 8 byte null string + if($i < 18) + { + self::$_p[$i] = $z0; + self::$_p[$i + 1] = $z1; + } + else if($i >= 18 && $i < 274) + { + self::$_sbox1[$i - 18] = $z0; + self::$_sbox1[$i - 18 + 1] = $z1; + } + else if($i >= 274 && $i < 530) + { + self::$_sbox2[$i - 274] = $z0; + self::$_sbox2[$i - 274 + 1] = $z1; + } + else if($i >= 530 && $i < 786) + { + self::$_sbox3[$i - 530] = $z0; + self::$_sbox3[$i - 530 + 1] = $z1; + } + else if($i >= 786 && $i < 1042) + { + self::$_sbox4[$i -786] = $z0; + self::$_sbox4[$i - 786 + 1] = $z1; + } + } + } + + + /** + * Returns a substring of $this->key. The size of the substring is set in the + * parameter $size. Each call to this function returns a substring starting + * in the position where the last substring ended. Effectively it rotates + * through the key, when it reaches the end, it starts over at the + * beginning of the key and continues on. You can reset the current position + * by setting the parameter $reset=true, which will start the key back at the + * first byte of the $this->key string. + * + * @param integer $size The size of the substring to return, in bytes + * @param bool $reset If set to true, sets the position back to 0, the first + * byte of the key string + * @return string The next substring of the key + */ + private function keyChunk($size = 1, $reset = false) + { + if($reset || $this->key_pos >= $this->keySize()) + $this->key_pos = 0; + + $bytes = substr($this->key(), $this->key_pos, $size); + $len = strlen($bytes); + if($len < $size) + { + $bytes .= substr($this->key(), 0, $size - $len); + $this->key_pos = $size - $len; + } + else + $this->key_pos += $size; + + return $bytes; + } + + + /** + * Initialize the tables used in Blowfish Encryption. These + * are calculated from the value of PI. We grabbed + * these from the mcrypt blowfish source, which already had + * these values calculated + * + * @return void + */ + private function initTables() + { + self::$_sbox1 = array( + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a + ); + + self::$_sbox2 = array( + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 + ); + + self::$_sbox3 = array( + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 + ); + + self::$_sbox4 = array( + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 + ); + + self::$_p = array( + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b + ); + } + + + /** + * Indicates this is a block cipher + * + * @return integer Returns Cipher::BLOCK + */ + public function type() + { + return parent::BLOCK; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/CAST128.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/CAST128.php new file mode 100644 index 0000000000..f137082443 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/CAST128.php @@ -0,0 +1,1210 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements The CAST-128 Cipher + * + * Resources used to implement this algorithm: + * http://tools.ietf.org/html/rfc2144 + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Cipher_CAST_128 extends Cipher +{ + /** @type integer BYTES_BLOCK The size of the block, in bytes */ + const BYTES_BLOCK = 8; // 64 bits; + + //const BYTES_KEY = 0; // between 40 - 128 bits + + const BYTES_KEY_SMALL = 10; + const BYTES_KEY_MAX = 16; + const BYTES_KEY_MIN = 5; + + /** @type array $_s1 An array of 256 unsigned integers */ + private static $_s1 = array(); + + /** @type array $_s2 An array of 256 unsigned integers */ + private static $_s2 = array(); + + /** @type array $_s3 An array of 256 unsigned integers */ + private static $_s3 = array(); + + /** @type array $_s4 An array of 256 unsigned integers */ + private static $_s4 = array(); + + /** @type array $_s5 An array of 256 unsigned integers */ + private static $_s5 = array(); + + /** @type array $_s6 An array of 256 unsigned integers */ + private static $_s6 = array(); + + /** @type array $_s7 An array of 256 unsigned integers */ + private static $_s7 = array(); + + /** @type array $_s8 An array of 256 unsigned integers */ + private static $_s8 = array(); + + /** @type string $_mkey The 16 byte masking subkey */ + private $_mkey = ""; + + /** @type string $_rkey The 16 byte rotate subkey */ + private $_rkey = ""; + + + /** + * Constructor + * + * @param string $key The key used for Encryption/Decryption + * @return void + */ + public function __construct($key) + { + // the length of the key is is between 5 - 16 bytes (40 - 128 bits) + $keylen = strlen($key); + if($keylen > self::BYTES_KEY_MAX) + { + $key = substr($key, 0, self::BYTES_KEY_MAX); + $keylen = self::BYTES_KEY_MAX; + } + else if($keylen < self::BYTES_KEY_MIN) + { + $msg = PHP_Crypt::CIPHER_CAST_128." requires a key size between "; + $msg .= "5 - 16 bytes."; + trigger_error($msg, E_USER_WARNING); + } + + // set the key, make sure the required length is set in bytes + parent::__construct(PHP_Crypt::CIPHER_CAST_128, $key, $keylen); + + // set the block size + $this->blockSize(self::BYTES_BLOCK); + + // initialize the sboxes constants + $this->initTables(); + + // create the sub keys using the sboxes + $this->createSubKeys(); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypt plain text data + * + * @param string $data A block of plain data + * @return boolean Returns true + */ + public function encrypt(&$data) + { + $this->operation(parent::ENCRYPT); + + // split the block in half, left and right + $l = parent::str2Dec(substr($data, 0, 4)); + $r = parent::str2Dec(substr($data, 4, 4)); + + // We do only 12 rounds if we have a key 10 bytes or less. + // If we have a key greater than 10 bytes, we do the 12 rounds + // then proceed to the additional 4 rounds for a total of 16 + for($i = 0; $i < 12; $i += 3) + { + // f1 + $tmp = $r; + $r = $l ^ $this->f1($r, $i); + $l = $tmp; + + // f2 + $tmp = $r; + $r = $l ^ $this->f2($r, $i + 1); + $l = $tmp; + + // f3 + $tmp = $r; + $r = $l ^ $this->f3($r, $i + 2); + $l = $tmp; + } + + // only do the full 16 rounds if the key is longer than + // 10 bytes (80 bits) + if($this->keySize() > self::BYTES_KEY_SMALL) + { + // f1 + $tmp = $r; + $r = $l ^ $this->f1($r, 12); + $l = $tmp; + + // f2 + $tmp = $r; + $r = $l ^ $this->f2($r, 13); + $l = $tmp; + + // f3 + $tmp = $r; + $r = $l ^ $this->f3($r, 14); + $l = $tmp; + + // f1 + $tmp = $r; + $r = $l ^ $this->f1($r, 15); + $l = $tmp; + } + + // swap the two halfs + $data = parent::dec2Str($r, 4).parent::dec2Str($l, 4); + + return true; + } + + + /** + * Decrypt an encrypted string, it does all the steps of encryption, + * but in reverse. + * + * @param string $data A block of encrypted data + * @return boolean Returns true + */ + public function decrypt(&$data) + { + $this->operation(parent::DECRYPT); + + // split the block in half, left and right + $l = parent::str2Dec(substr($data, 0, 4)); + $r = parent::str2Dec(substr($data, 4, 4)); + + // only do the full 16 rounds if the key is longer than + // 10 bytes (80 bits) + if($this->keySize() > self::BYTES_KEY_SMALL) + { + // f1 + $tmp = $r; + $r = $l ^ $this->f1($r, 15); + $l = $tmp; + + // f3 + $tmp = $r; + $r = $l ^ $this->f3($r, 14); + $l = $tmp; + + // f2 + $tmp = $r; + $r = $l ^ $this->f2($r, 13); + $l = $tmp; + + // f1 + $tmp = $r; + $r = $l ^ $this->f1($r, 12); + $l = $tmp; + } + + // We do only 12 rounds if we have a key 10 bytes or less. + for($i = 11; $i >= 2; $i -= 3) + { + // f3 + $tmp = $r; + $r = $l ^ $this->f3($r, $i); + $l = $tmp; + + // f2 + $tmp = $r; + $r = $l ^ $this->f2($r, $i - 1); + $l = $tmp; + + // f1 + $tmp = $r; + $r = $l ^ $this->f1($r, $i - 2); + $l = $tmp; + } + + // swap the two halfs + $data = parent::dec2Str($r, 4).parent::dec2Str($l, 4); + + return true; + } + + + /** + * Cast 128 F1 function + * + * @param $r integer The right half of the data being encrypted in cast_128() + * @param $i integer The round number (1-16) in cast_128() + * @return integer The value after the F1 transformation + */ + private function f1($r, $i) + { + $n = $this->_mkey[$i] + $r; + $n = parent::uInt32(parent::rotBitsLeft32($n, $this->_rkey[$i])); + $n = parent::dec2Str($n, 4); + + $f = parent::uInt32( + ((self::$_s1[ord($n[0])] ^ self::$_s2[ord($n[1])]) - + self::$_s3[ord($n[2])]) + self::$_s4[ord($n[3])] + ); + + return $f; + } + + + /** + * Cast 128 F2 function + * + * @param $r integer The right half of the data being encrypted in cast_128() + * @param $i integer The round number (1-16) in cast_128() + * @return integer The value after the F2 transformation + */ + private function f2($r, $i) + { + $n = $this->_mkey[$i] ^ $r; + $n = parent::uInt32(parent::rotBitsLeft32($n, $this->_rkey[$i])); + $n = parent::dec2Str($n, 4); + + $f = parent::uInt32( + ((self::$_s1[ord($n[0])] - self::$_s2[ord($n[1])]) + + self::$_s3[ord($n[2])]) ^ self::$_s4[ord($n[3])] + ); + + return $f; + } + + + /** + * Cast 128 F3 function + * + * @param $r integer The right half of the data being encrypted in cast_128() + * @param $i integer The round number (1-16) in cast_128() + * @return integer The value after the F3 transformation + */ + private function f3($r, $i) + { + $n = $this->_mkey[$i] - $r; + $n = parent::uInt32(parent::rotBitsLeft32($n, $this->_rkey[$i])); + $n = parent::dec2Str($n, 4); + + $f = parent::uInt32( + ((self::$_s1[ord($n[0])] + self::$_s2[ord($n[1])]) ^ + self::$_s3[ord($n[2])]) - self::$_s4[ord($n[3])] + ); + + return $f; + } + + + /** + * Creates the subkeys $_mkey (the masking key) and + * $_rkey (the rotate key) which are 16 bytes each. These are + * created from the original key. The original key is null + * padded up to 16 bytes and expanded to 32 bytes. It is then + * split in half to create $_mkey and $_rkey + * + * @return void + */ + private function createSubKeys() + { + $x = $this->key(); + $z = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; // init to 16 bytes + $skey = array(); + + // the max length of the key is 16 bytes, however if it is + // less, pad it with null to get ito to 16 bytes + if($this->keySize() < self::BYTES_KEY_MAX) + $x = str_pad($x, self::BYTES_KEY_MAX, "\0", STR_PAD_RIGHT); + + /* + * NOW FOR THE UGLY PART, THIS IS TAKEN FROM PAGE 3-4 OF + * http://tools.ietf.org/html/rfc2144 + */ + + // two loops, each loop does 16 bytes for a total of 32 bytes + for($i = 0; $i < 2; ++$i) + { + // z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8] + $tmp = substr($x, 0x00, 4); + $tmp = parent::dec2Str( + parent::uInt32( + parent::str2Dec($tmp) ^ self::$_s5[ord($x[0x0d])] ^ + self::$_s6[ord($x[0x0f])] ^ self::$_s7[ord($x[0x0c])] ^ + self::$_s8[ord($x[0x0e])] ^ self::$_s7[ord($x[0x08])] + ), 4); + $z = substr_replace($z, $tmp, 0x00, 4); + + //print "Z0: ".parent::str2Hex($z)." (".strlen($z).")\n"; + + // z4z5z6z7 = x8x9xAxB ^ S5[z0] ^ S6[z2] ^ S7[z1] ^ S8[z3] ^ S8[xA] + $tmp = substr($x, 0x08, 4); + $tmp = parent::dec2Str( + parent::uInt32( + parent::str2Dec($tmp) ^ self::$_s5[ord($z[0x00])] ^ + self::$_s6[ord($z[0x02])] ^ self::$_s7[ord($z[0x01])] ^ + self::$_s8[ord($z[0x03])] ^ self::$_s8[ord($x[0x0a])] + ), 4); + $z = substr_replace($z, $tmp, 0x04, 4); + + // z8z9zAzB = xCxDxExF ^ S5[z7] ^ S6[z6] ^ S7[z5] ^ S8[z4] ^ S5[x9] + $tmp = substr($x, 0x0c, 4); + $tmp = parent::dec2Str( + parent::uInt32( + parent::str2Dec($tmp) ^ self::$_s5[ord($z[0x07])] ^ + self::$_s6[ord($z[0x06])] ^ self::$_s7[ord($z[0x05])] ^ + self::$_s8[ord($z[0x04])] ^ self::$_s5[ord($x[0x09])] + ), 4); + $z = substr_replace($z, $tmp, 0x08, 4); + + // zCzDzEzF = x4x5x6x7 ^ S5[zA] ^ S6[z9] ^ S7[zB] ^ S8[z8] ^ S6[xB] + $tmp = substr($x, 0x04, 4); + $tmp = parent::dec2Str( + parent::uInt32( + parent::str2Dec($tmp) ^ self::$_s5[ord($z[0x0a])] ^ + self::$_s6[ord($z[0x09])] ^ self::$_s7[ord($z[0x0b])] ^ + self::$_s8[ord($z[0x08])] ^ self::$_s6[ord($x[0x0b])] + ), 4); + $z = substr_replace($z, $tmp, 0x0c, 4); + + //print "Z: ".parent::str2Hex($z)." (".strlen($z).")\n"; + + // K1 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2] + $skey[] = parent::uInt32(self::$_s5[ord($z[0x08])] ^ self::$_s6[ord($z[0x09])] ^ + self::$_s7[ord($z[0x07])] ^ self::$_s8[ord($z[0x06])] ^ + self::$_s5[ord($z[0x02])] + ); + + // K2 = S5[zA] ^ S6[zB] ^ S7[z5] ^ S8[z4] ^ S6[z6] + $skey[] = parent::uInt32( + self::$_s5[ord($z[0x0a])] ^ self::$_s6[ord($z[0x0b])] ^ + self::$_s7[ord($z[0x05])] ^ self::$_s8[ord($z[0x04])] ^ + self::$_s6[ord($z[0x06])] + ); + + // K3 = S5[zC] ^ S6[zD] ^ S7[z3] ^ S8[z2] ^ S7[z9] + $skey[] = parent::uInt32( + self::$_s5[ord($z[0x0c])] ^ self::$_s6[ord($z[0x0d])] ^ + self::$_s7[ord($z[0x03])] ^ self::$_s8[ord($z[0x02])] ^ + self::$_s7[ord($z[0x09])] + ); + + // K4 = S5[zE] ^ S6[zF] ^ S7[z1] ^ S8[z0] ^ S8[zC] + $skey[] = parent::uInt32( + self::$_s5[ord($z[0x0e])] ^ self::$_s6[ord($z[0x0f])] ^ + self::$_s7[ord($z[0x01])] ^ self::$_s8[ord($z[0x00])] ^ + self::$_s8[ord($z[0x0c])] + ); + + // x0x1x2x3 = z8z9zAzB ^ S5[z5] ^ S6[z7] ^ S7[z4] ^ S8[z6] ^ S7[z0] + $tmp = substr($z, 0x08, 4); + $tmp = parent::dec2Str( + parent::uInt32( + parent::str2Dec($tmp) ^ self::$_s5[ord($z[0x05])] ^ + self::$_s6[ord($z[0x07])] ^ self::$_s7[ord($z[0x04])] ^ + self::$_s8[ord($z[0x06])] ^ self::$_s7[ord($z[0x00])] + ), 4); + $x = substr_replace($x, $tmp, 0x00, 4); + + // x4x5x6x7 = z0z1z2z3 ^ S5[x0] ^ S6[x2] ^ S7[x1] ^ S8[x3] ^ S8[z2] + $tmp = substr($z, 0x00, 4); + $tmp = parent::dec2Str( + parent::uInt32( + parent::str2Dec($tmp) ^ self::$_s5[ord($x[0x00])] ^ + self::$_s6[ord($x[0x02])] ^ self::$_s7[ord($x[0x01])] ^ + self::$_s8[ord($x[0x03])] ^ self::$_s8[ord($z[0x02])] + ), 4); + $x = substr_replace($x, $tmp, 0x04, 4); + + // x8x9xAxB = z4z5z6z7 ^ S5[x7] ^ S6[x6] ^ S7[x5] ^ S8[x4] ^ S5[z1] + $tmp = substr($z, 0x04, 4); + $tmp = parent::dec2Str( + parent::uInt32( + parent::str2Dec($tmp) ^ self::$_s5[ord($x[0x07])] ^ + self::$_s6[ord($x[0x06])] ^ self::$_s7[ord($x[0x05])] ^ + self::$_s8[ord($x[0x04])] ^ self::$_s5[ord($z[0x01])] + ), 4); + $x = substr_replace($x, $tmp, 0x08, 4); + + // xCxDxExF = zCzDzEzF ^ S5[xA] ^ S6[x9] ^ S7[xB] ^ S8[x8] ^ S6[z3] + $tmp = substr($z, 0x0c, 4); + $tmp = parent::dec2Str( + parent::uInt32( + parent::str2Dec($tmp) ^ self::$_s5[ord($x[0x0a])] ^ + self::$_s6[ord($x[0x09])] ^ self::$_s7[ord($x[0x0b])] ^ + self::$_s8[ord($x[0x08])] ^ self::$_s6[ord($z[0x03])] + ), 4); + $x = substr_replace($x, $tmp, 0x0c, 4); + + // K5 = S5[x3] ^ S6[x2] ^ S7[xC] ^ S8[xD] ^ S5[x8] + $skey[] = parent::uInt32( + self::$_s5[ord($x[0x03])] ^ self::$_s6[ord($x[0x02])] ^ + self::$_s7[ord($x[0x0c])] ^ self::$_s8[ord($x[0x0d])] ^ + self::$_s5[ord($x[0x08])] + ); + + // K6 = S5[x1] ^ S6[x0] ^ S7[xE] ^ S8[xF] ^ S6[xD] + $skey[] = parent::uInt32( + self::$_s5[ord($x[0x01])] ^ self::$_s6[ord($x[0x00])] ^ + self::$_s7[ord($x[0x0e])] ^ self::$_s8[ord($x[0x0f])] ^ + self::$_s6[ord($x[0x0d])] + ); + + // K7 = S5[x7] ^ S6[x6] ^ S7[x8] ^ S8[x9] ^ S7[x3] + $skey[] = parent::uInt32( + self::$_s5[ord($x[0x07])] ^ self::$_s6[ord($x[0x06])] ^ + self::$_s7[ord($x[0x08])] ^ self::$_s8[ord($x[0x09])] ^ + self::$_s7[ord($x[0x03])] + ); + + // K8 = S5[x5] ^ S6[x4] ^ S7[xA] ^ S8[xB] ^ S8[x7] + $skey[] = parent::uInt32( + self::$_s5[ord($x[0x05])] ^ self::$_s6[ord($x[0x04])] ^ + self::$_s7[ord($x[0x0a])] ^ self::$_s8[ord($x[0x0b])] ^ + self::$_s8[ord($x[0x07])] + ); + + // z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8] + $tmp = substr($x, 0x00, 4); + $tmp = parent::dec2Str( + parent::uInt32( + parent::str2Dec($tmp) ^ self::$_s5[ord($x[0x0d])] ^ + self::$_s6[ord($x[0x0f])] ^ self::$_s7[ord($x[0x0c])] ^ + self::$_s8[ord($x[0x0e])] ^ self::$_s7[ord($x[0x08])] + ), 4); + $z = substr_replace($z, $tmp, 0x00, 4); + + // z4z5z6z7 = x8x9xAxB ^ S5[z0] ^ S6[z2] ^ S7[z1] ^ S8[z3] ^ S8[xA] + $tmp = substr($x, 0x08, 4); + $tmp = parent::dec2Str( + parent::uInt32( + parent::str2Dec($tmp) ^ self::$_s5[ord($z[0x00])] ^ + self::$_s6[ord($z[0x02])] ^ self::$_s7[ord($z[0x01])] ^ + self::$_s8[ord($z[0x03])] ^ self::$_s8[ord($x[0x0a])] + ), 4); + $z = substr_replace($z, $tmp, 0x04, 4); + + // z8z9zAzB = xCxDxExF ^ S5[z7] ^ S6[z6] ^ S7[z5] ^ S8[z4] ^ S5[x9] + $tmp = substr($x, 0x0c, 4); + $tmp = parent::dec2Str( + parent::uInt32( + parent::str2Dec($tmp) ^ self::$_s5[ord($z[0x07])] ^ + self::$_s6[ord($z[0x06])] ^ self::$_s7[ord($z[0x05])] ^ + self::$_s8[ord($z[0x04])] ^ self::$_s5[ord($x[0x09])] + ), 4); + $z = substr_replace($z, $tmp, 0x08, 4); + + // zCzDzEzF = x4x5x6x7 ^ S5[zA] ^ S6[z9] ^ S7[zB] ^ S8[z8] ^ S6[xB] + $tmp = substr($x, 0x04, 4); + $tmp = parent::dec2Str( + parent::uInt32( + parent::str2Dec($tmp) ^ self::$_s5[ord($z[0x0a])] ^ + self::$_s6[ord($z[0x09])] ^ self::$_s7[ord($z[0x0b])] ^ + self::$_s8[ord($z[0x08])] ^ self::$_s6[ord($x[0x0b])] + ), 4); + $z = substr_replace($z, $tmp, 0x0c, 4); + + // K9 = S5[z3] ^ S6[z2] ^ S7[zC] ^ S8[zD] ^ S5[z9] + $skey[] = parent::uInt32( + self::$_s5[ord($z[0x03])] ^ self::$_s6[ord($z[0x02])] ^ + self::$_s7[ord($z[0x0c])] ^ self::$_s8[ord($z[0x0d])] ^ + self::$_s5[ord($z[0x09])] + ); + + // K10 = S5[z1] ^ S6[z0] ^ S7[zE] ^ S8[zF] ^ S6[zC] + $skey[] = parent::uInt32( + self::$_s5[ord($z[0x01])] ^ self::$_s6[ord($z[0x00])] ^ + self::$_s7[ord($z[0x0e])] ^ self::$_s8[ord($z[0x0f])] ^ + self::$_s6[ord($z[0x0c])] + ); + + // K11 = S5[z7] ^ S6[z6] ^ S7[z8] ^ S8[z9] ^ S7[z2] + $skey[] = parent::uInt32( + self::$_s5[ord($z[0x07])] ^ self::$_s6[ord($z[0x06])] ^ + self::$_s7[ord($z[0x08])] ^ self::$_s8[ord($z[0x09])] ^ + self::$_s7[ord($z[0x02])] + ); + + // K12 = S5[z5] ^ S6[z4] ^ S7[zA] ^ S8[zB] ^ S8[z6] + $skey[] = parent::uInt32( + self::$_s5[ord($z[0x05])] ^ self::$_s6[ord($z[0x04])] ^ + self::$_s7[ord($z[0x0a])] ^ self::$_s8[ord($z[0x0b])] ^ + self::$_s8[ord($z[0x06])] + ); + + // x0x1x2x3 = z8z9zAzB ^ S5[z5] ^ S6[z7] ^ S7[z4] ^ S8[z6] ^ S7[z0] + $tmp = substr($z, 0x08, 4); + $tmp = parent::dec2Str( + parent::uInt32( + parent::str2Dec($tmp) ^ self::$_s5[ord($z[0x05])] ^ + self::$_s6[ord($z[0x07])] ^ self::$_s7[ord($z[0x04])] ^ + self::$_s8[ord($z[0x06])] ^ self::$_s7[ord($z[0x00])] + ), 4); + $x = substr_replace($x, $tmp, 0x00, 4); + + // x4x5x6x7 = z0z1z2z3 ^ S5[x0] ^ S6[x2] ^ S7[x1] ^ S8[x3] ^ S8[z2] + $tmp = substr($z, 0x00, 4); + $tmp = parent::dec2Str( + parent::uInt32( + parent::str2Dec($tmp) ^ self::$_s5[ord($x[0x00])] ^ + self::$_s6[ord($x[0x02])] ^ self::$_s7[ord($x[0x01])] ^ + self::$_s8[ord($x[0x03])] ^ self::$_s8[ord($z[0x02])] + ), 4); + $x = substr_replace($x, $tmp, 0x04, 4); + + // x8x9xAxB = z4z5z6z7 ^ S5[x7] ^ S6[x6] ^ S7[x5] ^ S8[x4] ^ S5[z1] + $tmp = substr($z, 0x04, 4); + $tmp = parent::dec2Str( + parent::uInt32( + parent::str2Dec($tmp) ^ self::$_s5[ord($x[0x07])] ^ + self::$_s6[ord($x[0x06])] ^ self::$_s7[ord($x[0x05])] ^ + self::$_s8[ord($x[0x04])] ^ self::$_s5[ord($z[0x01])] + ), 4); + $x = substr_replace($x, $tmp, 0x08, 4); + + // xCxDxExF = zCzDzEzF ^ S5[xA] ^ S6[x9] ^ S7[xB] ^ S8[x8] ^ S6[z3] + $tmp = substr($z, 0x0c, 4); + $tmp = parent::dec2Str( + parent::uInt32( + parent::str2Dec($tmp) ^ self::$_s5[ord($x[0x0a])] ^ + self::$_s6[ord($x[0x09])] ^ self::$_s7[ord($x[0x0b])] ^ + self::$_s8[ord($x[0x08])] ^ self::$_s6[ord($z[0x03])] + ), 4); + $x = substr_replace($x, $tmp, 0x0c, 4); + + // K13 = S5[x8] ^ S6[x9] ^ S7[x7] ^ S8[x6] ^ S5[x3] + $skey[] = parent::uInt32( + self::$_s5[ord($x[0x08])] ^ self::$_s6[ord($x[0x09])] ^ + self::$_s7[ord($x[0x07])] ^ self::$_s8[ord($x[0x06])] ^ + self::$_s5[ord($x[0x03])] + ); + + // K14 = S5[xA] ^ S6[xB] ^ S7[x5] ^ S8[x4] ^ S6[x7] + $skey[] = parent::uInt32( + self::$_s5[ord($x[0x0a])] ^ self::$_s6[ord($x[0x0b])] ^ + self::$_s7[ord($x[0x05])] ^ self::$_s8[ord($x[0x04])] ^ + self::$_s6[ord($x[0x07])] + ); + + // K15 = S5[xC] ^ S6[xD] ^ S7[x3] ^ S8[x2] ^ S7[x8] + $skey[] = parent::uInt32( + self::$_s5[ord($x[0x0c])] ^ self::$_s6[ord($x[0x0d])] ^ + self::$_s7[ord($x[0x03])] ^ self::$_s8[ord($x[0x02])] ^ + self::$_s7[ord($x[0x08])] + ); + + // K16 = S5[xE] ^ S6[xF] ^ S7[x1] ^ S8[x0] ^ S8[xD] + $skey[] = parent::uInt32( + self::$_s5[ord($x[0x0e])] ^ self::$_s6[ord($x[0x0f])] ^ + self::$_s7[ord($x[0x01])] ^ self::$_s8[ord($x[0x00])] ^ + self::$_s8[ord($x[0x0d])] + ); + } + + // create the 16 byte masking and rotate subkeys + $this->_mkey = array_slice($skey, 0, 16); + $this->_rkey = array_slice($skey, 16, 16); + + // $_rkey only uses the least significant 5 bits + $this->_rkey = array_map(function($v) { + return $v &= 31; + }, $this->_rkey); + + // there is 4kb in the s5 - s8 sboxes, which are not needed after we + // create the subkeys, so free up the memory. unset() doesn't work here + for($i = 5; $i <= 8; ++$i) + self::${"_s$i"} = null; + } + + + /** + * Initialize the tables. + * + * @return void + */ + private function initTables() + { + // 256 unsigned 32 bit integers + self::$_s1 = array( + 0x30FB40D4, 0x9FA0FF0B, 0x6BECCD2F, 0x3F258C7A, + 0x1E213F2F, 0x9C004DD3, 0x6003E540, 0xCF9FC949, + 0xBFD4AF27, 0x88BBBDB5, 0xE2034090, 0x98D09675, + 0x6E63A0E0, 0x15C361D2, 0xC2E7661D, 0x22D4FF8E, + 0x28683B6F, 0xC07FD059, 0xFF2379C8, 0x775F50E2, + 0x43C340D3, 0xDF2F8656, 0x887CA41A, 0xA2D2BD2D, + 0xA1C9E0D6, 0x346C4819, 0x61B76D87, 0x22540F2F, + 0x2ABE32E1, 0xAA54166B, 0x22568E3A, 0xA2D341D0, + 0x66DB40C8, 0xA784392F, 0x004DFF2F, 0x2DB9D2DE, + 0x97943FAC, 0x4A97C1D8, 0x527644B7, 0xB5F437A7, + 0xB82CBAEF, 0xD751D159, 0x6FF7F0ED, 0x5A097A1F, + 0x827B68D0, 0x90ECF52E, 0x22B0C054, 0xBC8E5935, + 0x4B6D2F7F, 0x50BB64A2, 0xD2664910, 0xBEE5812D, + 0xB7332290, 0xE93B159F, 0xB48EE411, 0x4BFF345D, + 0xFD45C240, 0xAD31973F, 0xC4F6D02E, 0x55FC8165, + 0xD5B1CAAD, 0xA1AC2DAE, 0xA2D4B76D, 0xC19B0C50, + 0x882240F2, 0x0C6E4F38, 0xA4E4BFD7, 0x4F5BA272, + 0x564C1D2F, 0xC59C5319, 0xB949E354, 0xB04669FE, + 0xB1B6AB8A, 0xC71358DD, 0x6385C545, 0x110F935D, + 0x57538AD5, 0x6A390493, 0xE63D37E0, 0x2A54F6B3, + 0x3A787D5F, 0x6276A0B5, 0x19A6FCDF, 0x7A42206A, + 0x29F9D4D5, 0xF61B1891, 0xBB72275E, 0xAA508167, + 0x38901091, 0xC6B505EB, 0x84C7CB8C, 0x2AD75A0F, + 0x874A1427, 0xA2D1936B, 0x2AD286AF, 0xAA56D291, + 0xD7894360, 0x425C750D, 0x93B39E26, 0x187184C9, + 0x6C00B32D, 0x73E2BB14, 0xA0BEBC3C, 0x54623779, + 0x64459EAB, 0x3F328B82, 0x7718CF82, 0x59A2CEA6, + 0x04EE002E, 0x89FE78E6, 0x3FAB0950, 0x325FF6C2, + 0x81383F05, 0x6963C5C8, 0x76CB5AD6, 0xD49974C9, + 0xCA180DCF, 0x380782D5, 0xC7FA5CF6, 0x8AC31511, + 0x35E79E13, 0x47DA91D0, 0xF40F9086, 0xA7E2419E, + 0x31366241, 0x051EF495, 0xAA573B04, 0x4A805D8D, + 0x548300D0, 0x00322A3C, 0xBF64CDDF, 0xBA57A68E, + 0x75C6372B, 0x50AFD341, 0xA7C13275, 0x915A0BF5, + 0x6B54BFAB, 0x2B0B1426, 0xAB4CC9D7, 0x449CCD82, + 0xF7FBF265, 0xAB85C5F3, 0x1B55DB94, 0xAAD4E324, + 0xCFA4BD3F, 0x2DEAA3E2, 0x9E204D02, 0xC8BD25AC, + 0xEADF55B3, 0xD5BD9E98, 0xE31231B2, 0x2AD5AD6C, + 0x954329DE, 0xADBE4528, 0xD8710F69, 0xAA51C90F, + 0xAA786BF6, 0x22513F1E, 0xAA51A79B, 0x2AD344CC, + 0x7B5A41F0, 0xD37CFBAD, 0x1B069505, 0x41ECE491, + 0xB4C332E6, 0x032268D4, 0xC9600ACC, 0xCE387E6D, + 0xBF6BB16C, 0x6A70FB78, 0x0D03D9C9, 0xD4DF39DE, + 0xE01063DA, 0x4736F464, 0x5AD328D8, 0xB347CC96, + 0x75BB0FC3, 0x98511BFB, 0x4FFBCC35, 0xB58BCF6A, + 0xE11F0ABC, 0xBFC5FE4A, 0xA70AEC10, 0xAC39570A, + 0x3F04442F, 0x6188B153, 0xE0397A2E, 0x5727CB79, + 0x9CEB418F, 0x1CACD68D, 0x2AD37C96, 0x0175CB9D, + 0xC69DFF09, 0xC75B65F0, 0xD9DB40D8, 0xEC0E7779, + 0x4744EAD4, 0xB11C3274, 0xDD24CB9E, 0x7E1C54BD, + 0xF01144F9, 0xD2240EB1, 0x9675B3FD, 0xA3AC3755, + 0xD47C27AF, 0x51C85F4D, 0x56907596, 0xA5BB15E6, + 0x580304F0, 0xCA042CF1, 0x011A37EA, 0x8DBFAADB, + 0x35BA3E4A, 0x3526FFA0, 0xC37B4D09, 0xBC306ED9, + 0x98A52666, 0x5648F725, 0xFF5E569D, 0x0CED63D0, + 0x7C63B2CF, 0x700B45E1, 0xD5EA50F1, 0x85A92872, + 0xAF1FBDA7, 0xD4234870, 0xA7870BF3, 0x2D3B4D79, + 0x42E04198, 0x0CD0EDE7, 0x26470DB8, 0xF881814C, + 0x474D6AD7, 0x7C0C5E5C, 0xD1231959, 0x381B7298, + 0xF5D2F4DB, 0xAB838653, 0x6E2F1E23, 0x83719C9E, + 0xBD91E046, 0x9A56456E, 0xDC39200C, 0x20C8C571, + 0x962BDA1C, 0xE1E696FF, 0xB141AB08, 0x7CCA89B9, + 0x1A69E783, 0x02CC4843, 0xA2F7C579, 0x429EF47D, + 0x427B169C, 0x5AC9F049, 0xDD8F0F00, 0x5C8165BF + ); + + // 256 unsigned 32 bit integers + self::$_s2 = array( + 0x1F201094, 0xEF0BA75B, 0x69E3CF7E, 0x393F4380, + 0xFE61CF7A, 0xEEC5207A, 0x55889C94, 0x72FC0651, + 0xADA7EF79, 0x4E1D7235, 0xD55A63CE, 0xDE0436BA, + 0x99C430EF, 0x5F0C0794, 0x18DCDB7D, 0xA1D6EFF3, + 0xA0B52F7B, 0x59E83605, 0xEE15B094, 0xE9FFD909, + 0xDC440086, 0xEF944459, 0xBA83CCB3, 0xE0C3CDFB, + 0xD1DA4181, 0x3B092AB1, 0xF997F1C1, 0xA5E6CF7B, + 0x01420DDB, 0xE4E7EF5B, 0x25A1FF41, 0xE180F806, + 0x1FC41080, 0x179BEE7A, 0xD37AC6A9, 0xFE5830A4, + 0x98DE8B7F, 0x77E83F4E, 0x79929269, 0x24FA9F7B, + 0xE113C85B, 0xACC40083, 0xD7503525, 0xF7EA615F, + 0x62143154, 0x0D554B63, 0x5D681121, 0xC866C359, + 0x3D63CF73, 0xCEE234C0, 0xD4D87E87, 0x5C672B21, + 0x071F6181, 0x39F7627F, 0x361E3084, 0xE4EB573B, + 0x602F64A4, 0xD63ACD9C, 0x1BBC4635, 0x9E81032D, + 0x2701F50C, 0x99847AB4, 0xA0E3DF79, 0xBA6CF38C, + 0x10843094, 0x2537A95E, 0xF46F6FFE, 0xA1FF3B1F, + 0x208CFB6A, 0x8F458C74, 0xD9E0A227, 0x4EC73A34, + 0xFC884F69, 0x3E4DE8DF, 0xEF0E0088, 0x3559648D, + 0x8A45388C, 0x1D804366, 0x721D9BFD, 0xA58684BB, + 0xE8256333, 0x844E8212, 0x128D8098, 0xFED33FB4, + 0xCE280AE1, 0x27E19BA5, 0xD5A6C252, 0xE49754BD, + 0xC5D655DD, 0xEB667064, 0x77840B4D, 0xA1B6A801, + 0x84DB26A9, 0xE0B56714, 0x21F043B7, 0xE5D05860, + 0x54F03084, 0x066FF472, 0xA31AA153, 0xDADC4755, + 0xB5625DBF, 0x68561BE6, 0x83CA6B94, 0x2D6ED23B, + 0xECCF01DB, 0xA6D3D0BA, 0xB6803D5C, 0xAF77A709, + 0x33B4A34C, 0x397BC8D6, 0x5EE22B95, 0x5F0E5304, + 0x81ED6F61, 0x20E74364, 0xB45E1378, 0xDE18639B, + 0x881CA122, 0xB96726D1, 0x8049A7E8, 0x22B7DA7B, + 0x5E552D25, 0x5272D237, 0x79D2951C, 0xC60D894C, + 0x488CB402, 0x1BA4FE5B, 0xA4B09F6B, 0x1CA815CF, + 0xA20C3005, 0x8871DF63, 0xB9DE2FCB, 0x0CC6C9E9, + 0x0BEEFF53, 0xE3214517, 0xB4542835, 0x9F63293C, + 0xEE41E729, 0x6E1D2D7C, 0x50045286, 0x1E6685F3, + 0xF33401C6, 0x30A22C95, 0x31A70850, 0x60930F13, + 0x73F98417, 0xA1269859, 0xEC645C44, 0x52C877A9, + 0xCDFF33A6, 0xA02B1741, 0x7CBAD9A2, 0x2180036F, + 0x50D99C08, 0xCB3F4861, 0xC26BD765, 0x64A3F6AB, + 0x80342676, 0x25A75E7B, 0xE4E6D1FC, 0x20C710E6, + 0xCDF0B680, 0x17844D3B, 0x31EEF84D, 0x7E0824E4, + 0x2CCB49EB, 0x846A3BAE, 0x8FF77888, 0xEE5D60F6, + 0x7AF75673, 0x2FDD5CDB, 0xA11631C1, 0x30F66F43, + 0xB3FAEC54, 0x157FD7FA, 0xEF8579CC, 0xD152DE58, + 0xDB2FFD5E, 0x8F32CE19, 0x306AF97A, 0x02F03EF8, + 0x99319AD5, 0xC242FA0F, 0xA7E3EBB0, 0xC68E4906, + 0xB8DA230C, 0x80823028, 0xDCDEF3C8, 0xD35FB171, + 0x088A1BC8, 0xBEC0C560, 0x61A3C9E8, 0xBCA8F54D, + 0xC72FEFFA, 0x22822E99, 0x82C570B4, 0xD8D94E89, + 0x8B1C34BC, 0x301E16E6, 0x273BE979, 0xB0FFEAA6, + 0x61D9B8C6, 0x00B24869, 0xB7FFCE3F, 0x08DC283B, + 0x43DAF65A, 0xF7E19798, 0x7619B72F, 0x8F1C9BA4, + 0xDC8637A0, 0x16A7D3B1, 0x9FC393B7, 0xA7136EEB, + 0xC6BCC63E, 0x1A513742, 0xEF6828BC, 0x520365D6, + 0x2D6A77AB, 0x3527ED4B, 0x821FD216, 0x095C6E2E, + 0xDB92F2FB, 0x5EEA29CB, 0x145892F5, 0x91584F7F, + 0x5483697B, 0x2667A8CC, 0x85196048, 0x8C4BACEA, + 0x833860D4, 0x0D23E0F9, 0x6C387E8A, 0x0AE6D249, + 0xB284600C, 0xD835731D, 0xDCB1C647, 0xAC4C56EA, + 0x3EBD81B3, 0x230EABB0, 0x6438BC87, 0xF0B5B1FA, + 0x8F5EA2B3, 0xFC184642, 0x0A036B7A, 0x4FB089BD, + 0x649DA589, 0xA345415E, 0x5C038323, 0x3E5D3BB9, + 0x43D79572, 0x7E6DD07C, 0x06DFDF1E, 0x6C6CC4EF, + 0x7160A539, 0x73BFBE70, 0x83877605, 0x4523ECF1 + ); + + // 256 unsigned 32 bit integers + self::$_s3 = array( + 0x8DEFC240, 0x25FA5D9F, 0xEB903DBF, 0xE810C907, + 0x47607FFF, 0x369FE44B, 0x8C1FC644, 0xAECECA90, + 0xBEB1F9BF, 0xEEFBCAEA, 0xE8CF1950, 0x51DF07AE, + 0x920E8806, 0xF0AD0548, 0xE13C8D83, 0x927010D5, + 0x11107D9F, 0x07647DB9, 0xB2E3E4D4, 0x3D4F285E, + 0xB9AFA820, 0xFADE82E0, 0xA067268B, 0x8272792E, + 0x553FB2C0, 0x489AE22B, 0xD4EF9794, 0x125E3FBC, + 0x21FFFCEE, 0x825B1BFD, 0x9255C5ED, 0x1257A240, + 0x4E1A8302, 0xBAE07FFF, 0x528246E7, 0x8E57140E, + 0x3373F7BF, 0x8C9F8188, 0xA6FC4EE8, 0xC982B5A5, + 0xA8C01DB7, 0x579FC264, 0x67094F31, 0xF2BD3F5F, + 0x40FFF7C1, 0x1FB78DFC, 0x8E6BD2C1, 0x437BE59B, + 0x99B03DBF, 0xB5DBC64B, 0x638DC0E6, 0x55819D99, + 0xA197C81C, 0x4A012D6E, 0xC5884A28, 0xCCC36F71, + 0xB843C213, 0x6C0743F1, 0x8309893C, 0x0FEDDD5F, + 0x2F7FE850, 0xD7C07F7E, 0x02507FBF, 0x5AFB9A04, + 0xA747D2D0, 0x1651192E, 0xAF70BF3E, 0x58C31380, + 0x5F98302E, 0x727CC3C4, 0x0A0FB402, 0x0F7FEF82, + 0x8C96FDAD, 0x5D2C2AAE, 0x8EE99A49, 0x50DA88B8, + 0x8427F4A0, 0x1EAC5790, 0x796FB449, 0x8252DC15, + 0xEFBD7D9B, 0xA672597D, 0xADA840D8, 0x45F54504, + 0xFA5D7403, 0xE83EC305, 0x4F91751A, 0x925669C2, + 0x23EFE941, 0xA903F12E, 0x60270DF2, 0x0276E4B6, + 0x94FD6574, 0x927985B2, 0x8276DBCB, 0x02778176, + 0xF8AF918D, 0x4E48F79E, 0x8F616DDF, 0xE29D840E, + 0x842F7D83, 0x340CE5C8, 0x96BBB682, 0x93B4B148, + 0xEF303CAB, 0x984FAF28, 0x779FAF9B, 0x92DC560D, + 0x224D1E20, 0x8437AA88, 0x7D29DC96, 0x2756D3DC, + 0x8B907CEE, 0xB51FD240, 0xE7C07CE3, 0xE566B4A1, + 0xC3E9615E, 0x3CF8209D, 0x6094D1E3, 0xCD9CA341, + 0x5C76460E, 0x00EA983B, 0xD4D67881, 0xFD47572C, + 0xF76CEDD9, 0xBDA8229C, 0x127DADAA, 0x438A074E, + 0x1F97C090, 0x081BDB8A, 0x93A07EBE, 0xB938CA15, + 0x97B03CFF, 0x3DC2C0F8, 0x8D1AB2EC, 0x64380E51, + 0x68CC7BFB, 0xD90F2788, 0x12490181, 0x5DE5FFD4, + 0xDD7EF86A, 0x76A2E214, 0xB9A40368, 0x925D958F, + 0x4B39FFFA, 0xBA39AEE9, 0xA4FFD30B, 0xFAF7933B, + 0x6D498623, 0x193CBCFA, 0x27627545, 0x825CF47A, + 0x61BD8BA0, 0xD11E42D1, 0xCEAD04F4, 0x127EA392, + 0x10428DB7, 0x8272A972, 0x9270C4A8, 0x127DE50B, + 0x285BA1C8, 0x3C62F44F, 0x35C0EAA5, 0xE805D231, + 0x428929FB, 0xB4FCDF82, 0x4FB66A53, 0x0E7DC15B, + 0x1F081FAB, 0x108618AE, 0xFCFD086D, 0xF9FF2889, + 0x694BCC11, 0x236A5CAE, 0x12DECA4D, 0x2C3F8CC5, + 0xD2D02DFE, 0xF8EF5896, 0xE4CF52DA, 0x95155B67, + 0x494A488C, 0xB9B6A80C, 0x5C8F82BC, 0x89D36B45, + 0x3A609437, 0xEC00C9A9, 0x44715253, 0x0A874B49, + 0xD773BC40, 0x7C34671C, 0x02717EF6, 0x4FEB5536, + 0xA2D02FFF, 0xD2BF60C4, 0xD43F03C0, 0x50B4EF6D, + 0x07478CD1, 0x006E1888, 0xA2E53F55, 0xB9E6D4BC, + 0xA2048016, 0x97573833, 0xD7207D67, 0xDE0F8F3D, + 0x72F87B33, 0xABCC4F33, 0x7688C55D, 0x7B00A6B0, + 0x947B0001, 0x570075D2, 0xF9BB88F8, 0x8942019E, + 0x4264A5FF, 0x856302E0, 0x72DBD92B, 0xEE971B69, + 0x6EA22FDE, 0x5F08AE2B, 0xAF7A616D, 0xE5C98767, + 0xCF1FEBD2, 0x61EFC8C2, 0xF1AC2571, 0xCC8239C2, + 0x67214CB8, 0xB1E583D1, 0xB7DC3E62, 0x7F10BDCE, + 0xF90A5C38, 0x0FF0443D, 0x606E6DC6, 0x60543A49, + 0x5727C148, 0x2BE98A1D, 0x8AB41738, 0x20E1BE24, + 0xAF96DA0F, 0x68458425, 0x99833BE5, 0x600D457D, + 0x282F9350, 0x8334B362, 0xD91D1120, 0x2B6D8DA0, + 0x642B1E31, 0x9C305A00, 0x52BCE688, 0x1B03588A, + 0xF7BAEFD5, 0x4142ED9C, 0xA4315C11, 0x83323EC5, + 0xDFEF4636, 0xA133C501, 0xE9D3531C, 0xEE353783 + ); + + // 256 unsigned 32 bit integers + self::$_s4 = array( + 0x9DB30420, 0x1FB6E9DE, 0xA7BE7BEF, 0xD273A298, + 0x4A4F7BDB, 0x64AD8C57, 0x85510443, 0xFA020ED1, + 0x7E287AFF, 0xE60FB663, 0x095F35A1, 0x79EBF120, + 0xFD059D43, 0x6497B7B1, 0xF3641F63, 0x241E4ADF, + 0x28147F5F, 0x4FA2B8CD, 0xC9430040, 0x0CC32220, + 0xFDD30B30, 0xC0A5374F, 0x1D2D00D9, 0x24147B15, + 0xEE4D111A, 0x0FCA5167, 0x71FF904C, 0x2D195FFE, + 0x1A05645F, 0x0C13FEFE, 0x081B08CA, 0x05170121, + 0x80530100, 0xE83E5EFE, 0xAC9AF4F8, 0x7FE72701, + 0xD2B8EE5F, 0x06DF4261, 0xBB9E9B8A, 0x7293EA25, + 0xCE84FFDF, 0xF5718801, 0x3DD64B04, 0xA26F263B, + 0x7ED48400, 0x547EEBE6, 0x446D4CA0, 0x6CF3D6F5, + 0x2649ABDF, 0xAEA0C7F5, 0x36338CC1, 0x503F7E93, + 0xD3772061, 0x11B638E1, 0x72500E03, 0xF80EB2BB, + 0xABE0502E, 0xEC8D77DE, 0x57971E81, 0xE14F6746, + 0xC9335400, 0x6920318F, 0x081DBB99, 0xFFC304A5, + 0x4D351805, 0x7F3D5CE3, 0xA6C866C6, 0x5D5BCCA9, + 0xDAEC6FEA, 0x9F926F91, 0x9F46222F, 0x3991467D, + 0xA5BF6D8E, 0x1143C44F, 0x43958302, 0xD0214EEB, + 0x022083B8, 0x3FB6180C, 0x18F8931E, 0x281658E6, + 0x26486E3E, 0x8BD78A70, 0x7477E4C1, 0xB506E07C, + 0xF32D0A25, 0x79098B02, 0xE4EABB81, 0x28123B23, + 0x69DEAD38, 0x1574CA16, 0xDF871B62, 0x211C40B7, + 0xA51A9EF9, 0x0014377B, 0x041E8AC8, 0x09114003, + 0xBD59E4D2, 0xE3D156D5, 0x4FE876D5, 0x2F91A340, + 0x557BE8DE, 0x00EAE4A7, 0x0CE5C2EC, 0x4DB4BBA6, + 0xE756BDFF, 0xDD3369AC, 0xEC17B035, 0x06572327, + 0x99AFC8B0, 0x56C8C391, 0x6B65811C, 0x5E146119, + 0x6E85CB75, 0xBE07C002, 0xC2325577, 0x893FF4EC, + 0x5BBFC92D, 0xD0EC3B25, 0xB7801AB7, 0x8D6D3B24, + 0x20C763EF, 0xC366A5FC, 0x9C382880, 0x0ACE3205, + 0xAAC9548A, 0xECA1D7C7, 0x041AFA32, 0x1D16625A, + 0x6701902C, 0x9B757A54, 0x31D477F7, 0x9126B031, + 0x36CC6FDB, 0xC70B8B46, 0xD9E66A48, 0x56E55A79, + 0x026A4CEB, 0x52437EFF, 0x2F8F76B4, 0x0DF980A5, + 0x8674CDE3, 0xEDDA04EB, 0x17A9BE04, 0x2C18F4DF, + 0xB7747F9D, 0xAB2AF7B4, 0xEFC34D20, 0x2E096B7C, + 0x1741A254, 0xE5B6A035, 0x213D42F6, 0x2C1C7C26, + 0x61C2F50F, 0x6552DAF9, 0xD2C231F8, 0x25130F69, + 0xD8167FA2, 0x0418F2C8, 0x001A96A6, 0x0D1526AB, + 0x63315C21, 0x5E0A72EC, 0x49BAFEFD, 0x187908D9, + 0x8D0DBD86, 0x311170A7, 0x3E9B640C, 0xCC3E10D7, + 0xD5CAD3B6, 0x0CAEC388, 0xF73001E1, 0x6C728AFF, + 0x71EAE2A1, 0x1F9AF36E, 0xCFCBD12F, 0xC1DE8417, + 0xAC07BE6B, 0xCB44A1D8, 0x8B9B0F56, 0x013988C3, + 0xB1C52FCA, 0xB4BE31CD, 0xD8782806, 0x12A3A4E2, + 0x6F7DE532, 0x58FD7EB6, 0xD01EE900, 0x24ADFFC2, + 0xF4990FC5, 0x9711AAC5, 0x001D7B95, 0x82E5E7D2, + 0x109873F6, 0x00613096, 0xC32D9521, 0xADA121FF, + 0x29908415, 0x7FBB977F, 0xAF9EB3DB, 0x29C9ED2A, + 0x5CE2A465, 0xA730F32C, 0xD0AA3FE8, 0x8A5CC091, + 0xD49E2CE7, 0x0CE454A9, 0xD60ACD86, 0x015F1919, + 0x77079103, 0xDEA03AF6, 0x78A8565E, 0xDEE356DF, + 0x21F05CBE, 0x8B75E387, 0xB3C50651, 0xB8A5C3EF, + 0xD8EEB6D2, 0xE523BE77, 0xC2154529, 0x2F69EFDF, + 0xAFE67AFB, 0xF470C4B2, 0xF3E0EB5B, 0xD6CC9876, + 0x39E4460C, 0x1FDA8538, 0x1987832F, 0xCA007367, + 0xA99144F8, 0x296B299E, 0x492FC295, 0x9266BEAB, + 0xB5676E69, 0x9BD3DDDA, 0xDF7E052F, 0xDB25701C, + 0x1B5E51EE, 0xF65324E6, 0x6AFCE36C, 0x0316CC04, + 0x8644213E, 0xB7DC59D0, 0x7965291F, 0xCCD6FD43, + 0x41823979, 0x932BCDF6, 0xB657C34D, 0x4EDFD282, + 0x7AE5290C, 0x3CB9536B, 0x851E20FE, 0x9833557E, + 0x13ECF0B0, 0xD3FFB372, 0x3F85C5C1, 0x0AEF7ED2 + ); + + // 256 unsigned 32 bit integers + self::$_s5 = array( + 0x7EC90C04, 0x2C6E74B9, 0x9B0E66DF, 0xA6337911, + 0xB86A7FFF, 0x1DD358F5, 0x44DD9D44, 0x1731167F, + 0x08FBF1FA, 0xE7F511CC, 0xD2051B00, 0x735ABA00, + 0x2AB722D8, 0x386381CB, 0xACF6243A, 0x69BEFD7A, + 0xE6A2E77F, 0xF0C720CD, 0xC4494816, 0xCCF5C180, + 0x38851640, 0x15B0A848, 0xE68B18CB, 0x4CAADEFF, + 0x5F480A01, 0x0412B2AA, 0x259814FC, 0x41D0EFE2, + 0x4E40B48D, 0x248EB6FB, 0x8DBA1CFE, 0x41A99B02, + 0x1A550A04, 0xBA8F65CB, 0x7251F4E7, 0x95A51725, + 0xC106ECD7, 0x97A5980A, 0xC539B9AA, 0x4D79FE6A, + 0xF2F3F763, 0x68AF8040, 0xED0C9E56, 0x11B4958B, + 0xE1EB5A88, 0x8709E6B0, 0xD7E07156, 0x4E29FEA7, + 0x6366E52D, 0x02D1C000, 0xC4AC8E05, 0x9377F571, + 0x0C05372A, 0x578535F2, 0x2261BE02, 0xD642A0C9, + 0xDF13A280, 0x74B55BD2, 0x682199C0, 0xD421E5EC, + 0x53FB3CE8, 0xC8ADEDB3, 0x28A87FC9, 0x3D959981, + 0x5C1FF900, 0xFE38D399, 0x0C4EFF0B, 0x062407EA, + 0xAA2F4FB1, 0x4FB96976, 0x90C79505, 0xB0A8A774, + 0xEF55A1FF, 0xE59CA2C2, 0xA6B62D27, 0xE66A4263, + 0xDF65001F, 0x0EC50966, 0xDFDD55BC, 0x29DE0655, + 0x911E739A, 0x17AF8975, 0x32C7911C, 0x89F89468, + 0x0D01E980, 0x524755F4, 0x03B63CC9, 0x0CC844B2, + 0xBCF3F0AA, 0x87AC36E9, 0xE53A7426, 0x01B3D82B, + 0x1A9E7449, 0x64EE2D7E, 0xCDDBB1DA, 0x01C94910, + 0xB868BF80, 0x0D26F3FD, 0x9342EDE7, 0x04A5C284, + 0x636737B6, 0x50F5B616, 0xF24766E3, 0x8ECA36C1, + 0x136E05DB, 0xFEF18391, 0xFB887A37, 0xD6E7F7D4, + 0xC7FB7DC9, 0x3063FCDF, 0xB6F589DE, 0xEC2941DA, + 0x26E46695, 0xB7566419, 0xF654EFC5, 0xD08D58B7, + 0x48925401, 0xC1BACB7F, 0xE5FF550F, 0xB6083049, + 0x5BB5D0E8, 0x87D72E5A, 0xAB6A6EE1, 0x223A66CE, + 0xC62BF3CD, 0x9E0885F9, 0x68CB3E47, 0x086C010F, + 0xA21DE820, 0xD18B69DE, 0xF3F65777, 0xFA02C3F6, + 0x407EDAC3, 0xCBB3D550, 0x1793084D, 0xB0D70EBA, + 0x0AB378D5, 0xD951FB0C, 0xDED7DA56, 0x4124BBE4, + 0x94CA0B56, 0x0F5755D1, 0xE0E1E56E, 0x6184B5BE, + 0x580A249F, 0x94F74BC0, 0xE327888E, 0x9F7B5561, + 0xC3DC0280, 0x05687715, 0x646C6BD7, 0x44904DB3, + 0x66B4F0A3, 0xC0F1648A, 0x697ED5AF, 0x49E92FF6, + 0x309E374F, 0x2CB6356A, 0x85808573, 0x4991F840, + 0x76F0AE02, 0x083BE84D, 0x28421C9A, 0x44489406, + 0x736E4CB8, 0xC1092910, 0x8BC95FC6, 0x7D869CF4, + 0x134F616F, 0x2E77118D, 0xB31B2BE1, 0xAA90B472, + 0x3CA5D717, 0x7D161BBA, 0x9CAD9010, 0xAF462BA2, + 0x9FE459D2, 0x45D34559, 0xD9F2DA13, 0xDBC65487, + 0xF3E4F94E, 0x176D486F, 0x097C13EA, 0x631DA5C7, + 0x445F7382, 0x175683F4, 0xCDC66A97, 0x70BE0288, + 0xB3CDCF72, 0x6E5DD2F3, 0x20936079, 0x459B80A5, + 0xBE60E2DB, 0xA9C23101, 0xEBA5315C, 0x224E42F2, + 0x1C5C1572, 0xF6721B2C, 0x1AD2FFF3, 0x8C25404E, + 0x324ED72F, 0x4067B7FD, 0x0523138E, 0x5CA3BC78, + 0xDC0FD66E, 0x75922283, 0x784D6B17, 0x58EBB16E, + 0x44094F85, 0x3F481D87, 0xFCFEAE7B, 0x77B5FF76, + 0x8C2302BF, 0xAAF47556, 0x5F46B02A, 0x2B092801, + 0x3D38F5F7, 0x0CA81F36, 0x52AF4A8A, 0x66D5E7C0, + 0xDF3B0874, 0x95055110, 0x1B5AD7A8, 0xF61ED5AD, + 0x6CF6E479, 0x20758184, 0xD0CEFA65, 0x88F7BE58, + 0x4A046826, 0x0FF6F8F3, 0xA09C7F70, 0x5346ABA0, + 0x5CE96C28, 0xE176EDA3, 0x6BAC307F, 0x376829D2, + 0x85360FA9, 0x17E3FE2A, 0x24B79767, 0xF5A96B20, + 0xD6CD2595, 0x68FF1EBF, 0x7555442C, 0xF19F06BE, + 0xF9E0659A, 0xEEB9491D, 0x34010718, 0xBB30CAB8, + 0xE822FE15, 0x88570983, 0x750E6249, 0xDA627E55, + 0x5E76FFA8, 0xB1534546, 0x6D47DE08, 0xEFE9E7D4 + ); + + // 256 unsigned 32 bit integers + self::$_s6 = array( + 0xF6FA8F9D, 0x2CAC6CE1, 0x4CA34867, 0xE2337F7C, + 0x95DB08E7, 0x016843B4, 0xECED5CBC, 0x325553AC, + 0xBF9F0960, 0xDFA1E2ED, 0x83F0579D, 0x63ED86B9, + 0x1AB6A6B8, 0xDE5EBE39, 0xF38FF732, 0x8989B138, + 0x33F14961, 0xC01937BD, 0xF506C6DA, 0xE4625E7E, + 0xA308EA99, 0x4E23E33C, 0x79CBD7CC, 0x48A14367, + 0xA3149619, 0xFEC94BD5, 0xA114174A, 0xEAA01866, + 0xA084DB2D, 0x09A8486F, 0xA888614A, 0x2900AF98, + 0x01665991, 0xE1992863, 0xC8F30C60, 0x2E78EF3C, + 0xD0D51932, 0xCF0FEC14, 0xF7CA07D2, 0xD0A82072, + 0xFD41197E, 0x9305A6B0, 0xE86BE3DA, 0x74BED3CD, + 0x372DA53C, 0x4C7F4448, 0xDAB5D440, 0x6DBA0EC3, + 0x083919A7, 0x9FBAEED9, 0x49DBCFB0, 0x4E670C53, + 0x5C3D9C01, 0x64BDB941, 0x2C0E636A, 0xBA7DD9CD, + 0xEA6F7388, 0xE70BC762, 0x35F29ADB, 0x5C4CDD8D, + 0xF0D48D8C, 0xB88153E2, 0x08A19866, 0x1AE2EAC8, + 0x284CAF89, 0xAA928223, 0x9334BE53, 0x3B3A21BF, + 0x16434BE3, 0x9AEA3906, 0xEFE8C36E, 0xF890CDD9, + 0x80226DAE, 0xC340A4A3, 0xDF7E9C09, 0xA694A807, + 0x5B7C5ECC, 0x221DB3A6, 0x9A69A02F, 0x68818A54, + 0xCEB2296F, 0x53C0843A, 0xFE893655, 0x25BFE68A, + 0xB4628ABC, 0xCF222EBF, 0x25AC6F48, 0xA9A99387, + 0x53BDDB65, 0xE76FFBE7, 0xE967FD78, 0x0BA93563, + 0x8E342BC1, 0xE8A11BE9, 0x4980740D, 0xC8087DFC, + 0x8DE4BF99, 0xA11101A0, 0x7FD37975, 0xDA5A26C0, + 0xE81F994F, 0x9528CD89, 0xFD339FED, 0xB87834BF, + 0x5F04456D, 0x22258698, 0xC9C4C83B, 0x2DC156BE, + 0x4F628DAA, 0x57F55EC5, 0xE2220ABE, 0xD2916EBF, + 0x4EC75B95, 0x24F2C3C0, 0x42D15D99, 0xCD0D7FA0, + 0x7B6E27FF, 0xA8DC8AF0, 0x7345C106, 0xF41E232F, + 0x35162386, 0xE6EA8926, 0x3333B094, 0x157EC6F2, + 0x372B74AF, 0x692573E4, 0xE9A9D848, 0xF3160289, + 0x3A62EF1D, 0xA787E238, 0xF3A5F676, 0x74364853, + 0x20951063, 0x4576698D, 0xB6FAD407, 0x592AF950, + 0x36F73523, 0x4CFB6E87, 0x7DA4CEC0, 0x6C152DAA, + 0xCB0396A8, 0xC50DFE5D, 0xFCD707AB, 0x0921C42F, + 0x89DFF0BB, 0x5FE2BE78, 0x448F4F33, 0x754613C9, + 0x2B05D08D, 0x48B9D585, 0xDC049441, 0xC8098F9B, + 0x7DEDE786, 0xC39A3373, 0x42410005, 0x6A091751, + 0x0EF3C8A6, 0x890072D6, 0x28207682, 0xA9A9F7BE, + 0xBF32679D, 0xD45B5B75, 0xB353FD00, 0xCBB0E358, + 0x830F220A, 0x1F8FB214, 0xD372CF08, 0xCC3C4A13, + 0x8CF63166, 0x061C87BE, 0x88C98F88, 0x6062E397, + 0x47CF8E7A, 0xB6C85283, 0x3CC2ACFB, 0x3FC06976, + 0x4E8F0252, 0x64D8314D, 0xDA3870E3, 0x1E665459, + 0xC10908F0, 0x513021A5, 0x6C5B68B7, 0x822F8AA0, + 0x3007CD3E, 0x74719EEF, 0xDC872681, 0x073340D4, + 0x7E432FD9, 0x0C5EC241, 0x8809286C, 0xF592D891, + 0x08A930F6, 0x957EF305, 0xB7FBFFBD, 0xC266E96F, + 0x6FE4AC98, 0xB173ECC0, 0xBC60B42A, 0x953498DA, + 0xFBA1AE12, 0x2D4BD736, 0x0F25FAAB, 0xA4F3FCEB, + 0xE2969123, 0x257F0C3D, 0x9348AF49, 0x361400BC, + 0xE8816F4A, 0x3814F200, 0xA3F94043, 0x9C7A54C2, + 0xBC704F57, 0xDA41E7F9, 0xC25AD33A, 0x54F4A084, + 0xB17F5505, 0x59357CBE, 0xEDBD15C8, 0x7F97C5AB, + 0xBA5AC7B5, 0xB6F6DEAF, 0x3A479C3A, 0x5302DA25, + 0x653D7E6A, 0x54268D49, 0x51A477EA, 0x5017D55B, + 0xD7D25D88, 0x44136C76, 0x0404A8C8, 0xB8E5A121, + 0xB81A928A, 0x60ED5869, 0x97C55B96, 0xEAEC991B, + 0x29935913, 0x01FDB7F1, 0x088E8DFA, 0x9AB6F6F5, + 0x3B4CBF9F, 0x4A5DE3AB, 0xE6051D35, 0xA0E1D855, + 0xD36B4CF1, 0xF544EDEB, 0xB0E93524, 0xBEBB8FBD, + 0xA2D762CF, 0x49C92F54, 0x38B5F331, 0x7128A454, + 0x48392905, 0xA65B1DB8, 0x851C97BD, 0xD675CF2F + ); + + // 256 unsigned 32 bit integers + self::$_s7 = array( + 0x85E04019, 0x332BF567, 0x662DBFFF, 0xCFC65693, + 0x2A8D7F6F, 0xAB9BC912, 0xDE6008A1, 0x2028DA1F, + 0x0227BCE7, 0x4D642916, 0x18FAC300, 0x50F18B82, + 0x2CB2CB11, 0xB232E75C, 0x4B3695F2, 0xB28707DE, + 0xA05FBCF6, 0xCD4181E9, 0xE150210C, 0xE24EF1BD, + 0xB168C381, 0xFDE4E789, 0x5C79B0D8, 0x1E8BFD43, + 0x4D495001, 0x38BE4341, 0x913CEE1D, 0x92A79C3F, + 0x089766BE, 0xBAEEADF4, 0x1286BECF, 0xB6EACB19, + 0x2660C200, 0x7565BDE4, 0x64241F7A, 0x8248DCA9, + 0xC3B3AD66, 0x28136086, 0x0BD8DFA8, 0x356D1CF2, + 0x107789BE, 0xB3B2E9CE, 0x0502AA8F, 0x0BC0351E, + 0x166BF52A, 0xEB12FF82, 0xE3486911, 0xD34D7516, + 0x4E7B3AFF, 0x5F43671B, 0x9CF6E037, 0x4981AC83, + 0x334266CE, 0x8C9341B7, 0xD0D854C0, 0xCB3A6C88, + 0x47BC2829, 0x4725BA37, 0xA66AD22B, 0x7AD61F1E, + 0x0C5CBAFA, 0x4437F107, 0xB6E79962, 0x42D2D816, + 0x0A961288, 0xE1A5C06E, 0x13749E67, 0x72FC081A, + 0xB1D139F7, 0xF9583745, 0xCF19DF58, 0xBEC3F756, + 0xC06EBA30, 0x07211B24, 0x45C28829, 0xC95E317F, + 0xBC8EC511, 0x38BC46E9, 0xC6E6FA14, 0xBAE8584A, + 0xAD4EBC46, 0x468F508B, 0x7829435F, 0xF124183B, + 0x821DBA9F, 0xAFF60FF4, 0xEA2C4E6D, 0x16E39264, + 0x92544A8B, 0x009B4FC3, 0xABA68CED, 0x9AC96F78, + 0x06A5B79A, 0xB2856E6E, 0x1AEC3CA9, 0xBE838688, + 0x0E0804E9, 0x55F1BE56, 0xE7E5363B, 0xB3A1F25D, + 0xF7DEBB85, 0x61FE033C, 0x16746233, 0x3C034C28, + 0xDA6D0C74, 0x79AAC56C, 0x3CE4E1AD, 0x51F0C802, + 0x98F8F35A, 0x1626A49F, 0xEED82B29, 0x1D382FE3, + 0x0C4FB99A, 0xBB325778, 0x3EC6D97B, 0x6E77A6A9, + 0xCB658B5C, 0xD45230C7, 0x2BD1408B, 0x60C03EB7, + 0xB9068D78, 0xA33754F4, 0xF430C87D, 0xC8A71302, + 0xB96D8C32, 0xEBD4E7BE, 0xBE8B9D2D, 0x7979FB06, + 0xE7225308, 0x8B75CF77, 0x11EF8DA4, 0xE083C858, + 0x8D6B786F, 0x5A6317A6, 0xFA5CF7A0, 0x5DDA0033, + 0xF28EBFB0, 0xF5B9C310, 0xA0EAC280, 0x08B9767A, + 0xA3D9D2B0, 0x79D34217, 0x021A718D, 0x9AC6336A, + 0x2711FD60, 0x438050E3, 0x069908A8, 0x3D7FEDC4, + 0x826D2BEF, 0x4EEB8476, 0x488DCF25, 0x36C9D566, + 0x28E74E41, 0xC2610ACA, 0x3D49A9CF, 0xBAE3B9DF, + 0xB65F8DE6, 0x92AEAF64, 0x3AC7D5E6, 0x9EA80509, + 0xF22B017D, 0xA4173F70, 0xDD1E16C3, 0x15E0D7F9, + 0x50B1B887, 0x2B9F4FD5, 0x625ABA82, 0x6A017962, + 0x2EC01B9C, 0x15488AA9, 0xD716E740, 0x40055A2C, + 0x93D29A22, 0xE32DBF9A, 0x058745B9, 0x3453DC1E, + 0xD699296E, 0x496CFF6F, 0x1C9F4986, 0xDFE2ED07, + 0xB87242D1, 0x19DE7EAE, 0x053E561A, 0x15AD6F8C, + 0x66626C1C, 0x7154C24C, 0xEA082B2A, 0x93EB2939, + 0x17DCB0F0, 0x58D4F2AE, 0x9EA294FB, 0x52CF564C, + 0x9883FE66, 0x2EC40581, 0x763953C3, 0x01D6692E, + 0xD3A0C108, 0xA1E7160E, 0xE4F2DFA6, 0x693ED285, + 0x74904698, 0x4C2B0EDD, 0x4F757656, 0x5D393378, + 0xA132234F, 0x3D321C5D, 0xC3F5E194, 0x4B269301, + 0xC79F022F, 0x3C997E7E, 0x5E4F9504, 0x3FFAFBBD, + 0x76F7AD0E, 0x296693F4, 0x3D1FCE6F, 0xC61E45BE, + 0xD3B5AB34, 0xF72BF9B7, 0x1B0434C0, 0x4E72B567, + 0x5592A33D, 0xB5229301, 0xCFD2A87F, 0x60AEB767, + 0x1814386B, 0x30BCC33D, 0x38A0C07D, 0xFD1606F2, + 0xC363519B, 0x589DD390, 0x5479F8E6, 0x1CB8D647, + 0x97FD61A9, 0xEA7759F4, 0x2D57539D, 0x569A58CF, + 0xE84E63AD, 0x462E1B78, 0x6580F87E, 0xF3817914, + 0x91DA55F4, 0x40A230F3, 0xD1988F35, 0xB6E318D2, + 0x3FFA50BC, 0x3D40F021, 0xC3C0BDAE, 0x4958C24C, + 0x518F36B2, 0x84B1D370, 0x0FEDCE83, 0x878DDADA, + 0xF2A279C7, 0x94E01BE8, 0x90716F4B, 0x954B8AA3 + ); + + // 256 unsigned 32 bit integers + self::$_s8 = array( + 0xE216300D, 0xBBDDFFFC, 0xA7EBDABD, 0x35648095, + 0x7789F8B7, 0xE6C1121B, 0x0E241600, 0x052CE8B5, + 0x11A9CFB0, 0xE5952F11, 0xECE7990A, 0x9386D174, + 0x2A42931C, 0x76E38111, 0xB12DEF3A, 0x37DDDDFC, + 0xDE9ADEB1, 0x0A0CC32C, 0xBE197029, 0x84A00940, + 0xBB243A0F, 0xB4D137CF, 0xB44E79F0, 0x049EEDFD, + 0x0B15A15D, 0x480D3168, 0x8BBBDE5A, 0x669DED42, + 0xC7ECE831, 0x3F8F95E7, 0x72DF191B, 0x7580330D, + 0x94074251, 0x5C7DCDFA, 0xABBE6D63, 0xAA402164, + 0xB301D40A, 0x02E7D1CA, 0x53571DAE, 0x7A3182A2, + 0x12A8DDEC, 0xFDAA335D, 0x176F43E8, 0x71FB46D4, + 0x38129022, 0xCE949AD4, 0xB84769AD, 0x965BD862, + 0x82F3D055, 0x66FB9767, 0x15B80B4E, 0x1D5B47A0, + 0x4CFDE06F, 0xC28EC4B8, 0x57E8726E, 0x647A78FC, + 0x99865D44, 0x608BD593, 0x6C200E03, 0x39DC5FF6, + 0x5D0B00A3, 0xAE63AFF2, 0x7E8BD632, 0x70108C0C, + 0xBBD35049, 0x2998DF04, 0x980CF42A, 0x9B6DF491, + 0x9E7EDD53, 0x06918548, 0x58CB7E07, 0x3B74EF2E, + 0x522FFFB1, 0xD24708CC, 0x1C7E27CD, 0xA4EB215B, + 0x3CF1D2E2, 0x19B47A38, 0x424F7618, 0x35856039, + 0x9D17DEE7, 0x27EB35E6, 0xC9AFF67B, 0x36BAF5B8, + 0x09C467CD, 0xC18910B1, 0xE11DBF7B, 0x06CD1AF8, + 0x7170C608, 0x2D5E3354, 0xD4DE495A, 0x64C6D006, + 0xBCC0C62C, 0x3DD00DB3, 0x708F8F34, 0x77D51B42, + 0x264F620F, 0x24B8D2BF, 0x15C1B79E, 0x46A52564, + 0xF8D7E54E, 0x3E378160, 0x7895CDA5, 0x859C15A5, + 0xE6459788, 0xC37BC75F, 0xDB07BA0C, 0x0676A3AB, + 0x7F229B1E, 0x31842E7B, 0x24259FD7, 0xF8BEF472, + 0x835FFCB8, 0x6DF4C1F2, 0x96F5B195, 0xFD0AF0FC, + 0xB0FE134C, 0xE2506D3D, 0x4F9B12EA, 0xF215F225, + 0xA223736F, 0x9FB4C428, 0x25D04979, 0x34C713F8, + 0xC4618187, 0xEA7A6E98, 0x7CD16EFC, 0x1436876C, + 0xF1544107, 0xBEDEEE14, 0x56E9AF27, 0xA04AA441, + 0x3CF7C899, 0x92ECBAE6, 0xDD67016D, 0x151682EB, + 0xA842EEDF, 0xFDBA60B4, 0xF1907B75, 0x20E3030F, + 0x24D8C29E, 0xE139673B, 0xEFA63FB8, 0x71873054, + 0xB6F2CF3B, 0x9F326442, 0xCB15A4CC, 0xB01A4504, + 0xF1E47D8D, 0x844A1BE5, 0xBAE7DFDC, 0x42CBDA70, + 0xCD7DAE0A, 0x57E85B7A, 0xD53F5AF6, 0x20CF4D8C, + 0xCEA4D428, 0x79D130A4, 0x3486EBFB, 0x33D3CDDC, + 0x77853B53, 0x37EFFCB5, 0xC5068778, 0xE580B3E6, + 0x4E68B8F4, 0xC5C8B37E, 0x0D809EA2, 0x398FEB7C, + 0x132A4F94, 0x43B7950E, 0x2FEE7D1C, 0x223613BD, + 0xDD06CAA2, 0x37DF932B, 0xC4248289, 0xACF3EBC3, + 0x5715F6B7, 0xEF3478DD, 0xF267616F, 0xC148CBE4, + 0x9052815E, 0x5E410FAB, 0xB48A2465, 0x2EDA7FA4, + 0xE87B40E4, 0xE98EA084, 0x5889E9E1, 0xEFD390FC, + 0xDD07D35B, 0xDB485694, 0x38D7E5B2, 0x57720101, + 0x730EDEBC, 0x5B643113, 0x94917E4F, 0x503C2FBA, + 0x646F1282, 0x7523D24A, 0xE0779695, 0xF9C17A8F, + 0x7A5B2121, 0xD187B896, 0x29263A4D, 0xBA510CDF, + 0x81F47C9F, 0xAD1163ED, 0xEA7B5965, 0x1A00726E, + 0x11403092, 0x00DA6D77, 0x4A0CDD61, 0xAD1F4603, + 0x605BDFB0, 0x9EEDC364, 0x22EBE6A8, 0xCEE7D28A, + 0xA0E736A0, 0x5564A6B9, 0x10853209, 0xC7EB8F37, + 0x2DE705CA, 0x8951570F, 0xDF09822B, 0xBD691A6C, + 0xAA12E4F2, 0x87451C0F, 0xE0F6A27A, 0x3ADA4819, + 0x4CF1764F, 0x0D771C2B, 0x67CDB156, 0x350D8384, + 0x5938FA0F, 0x42399EF3, 0x36997B07, 0x0E84093D, + 0x4AA93E61, 0x8360D87B, 0x1FA98B0C, 0x1149382C, + 0xE97625A5, 0x0614D1B7, 0x0E25244B, 0x0C768347, + 0x589E8D82, 0x0D2059D1, 0xA466BB1E, 0xF8DA0A82, + 0x04F19130, 0xBA6E4EC0, 0x99265164, 0x1EE7230D, + 0x50B2AD80, 0xEAEE6801, 0x8DB2A283, 0xEA8BF59E + ); + } + + + /** + * Indicates this is a block cipher + * + * @return integer Returns Cipher::BLOCK + */ + public function type() + { + return parent::BLOCK; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/CAST256.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/CAST256.php new file mode 100644 index 0000000000..2615a4447e --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/CAST256.php @@ -0,0 +1,656 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements The CAST-256 Cipher + * + * Resources used to implement this algorithm: + * http://www.ietf.org/rfc/rfc2612.txt + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Cipher_CAST_256 extends Cipher +{ + /** @type integer BYTES_BLOCK The size of the block, in bytes */ + const BYTES_BLOCK = 16; // 128 bits; + + //const BYTES_KEY = 0; // between 128, 160, 192, 224, 256 bits + + /** @type integer BYTES_KEY_MAX The max key size, in bytes */ + const BYTES_KEY_MAX = 32; + + /** @type array $_s1 An array of 256 unsigned integers */ + private static $_s1 = array(); + + /** @type array $_s2 An array of 256 unsigned integers */ + private static $_s2 = array(); + + /** @type array $_s3 An array of 256 unsigned integers */ + private static $_s3 = array(); + + /** @type array $_s4 An array of 256 unsigned integers */ + private static $_s4 = array(); + + private static $_req_key_sizes = array(16, 20, 24, 28, 32); + + /** @type string $_mkey The 16 byte masking subkey */ + private $_mkey = array(); + + /** @type string $_rkey The 16 byte rotate subkey */ + private $_rkey = array(); + + + /** + * Constructor + * + * @param string $key The key used for Encryption/Decryption + * @return void + */ + public function __construct($key) + { + $keylen = strlen($key); + + if($keylen > self::BYTES_KEY_MAX) + { + $key = substr($key, 0, self::BYTES_KEY_MAX); + $keylen = self::BYTES_KEY_MAX; + } + else if(!in_array($keylen, self::$_req_key_sizes)) + { + $msg = PHP_Crypt::CIPHER_CAST_256." requires a key size of 16, "; + $msg .= "20, 24, 28, or 32 bytes."; + trigger_error($msg, E_USER_WARNING); + } + + // set the key, make sure the required length is set in bytes + parent::__construct(PHP_Crypt::CIPHER_CAST_256, $key, $keylen); + + // set the block size + $this->blockSize(self::BYTES_BLOCK); + + // initialize the sboxes constants + $this->initTables(); + + // create the sub keys using the sboxes + $this->createSubKeys(); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypt plain text data + * + * @param string $data A 128 bit block of plain data + * @return boolean Returns true + */ + public function encrypt(&$data) + { + $this->operation(parent::ENCRYPT); + + // first split the data into four 32 bit blocks, reverse + // the string order of each block, convert the blocks of data to integers + $data = str_split($data, 4); + $data = array_map("strrev", $data); + $data = array_map("parent::str2Dec", $data); + + // do the first 6 loops + for($i = 0; $i < 6; ++$i) + { + + $data[2] ^= $this->f1($data[3], $this->_mkey[$i][0], $this->_rkey[$i][0]); + $data[1] ^= $this->f2($data[2], $this->_mkey[$i][1], $this->_rkey[$i][1]); + $data[0] ^= $this->f3($data[1], $this->_mkey[$i][2], $this->_rkey[$i][2]); + $data[3] ^= $this->f1($data[0], $this->_mkey[$i][3], $this->_rkey[$i][3]); + } + + // the second 6 loops are done in a different order + for($i = 6; $i < 12; ++$i) + { + + $data[3] ^= $this->f1($data[0], $this->_mkey[$i][3], $this->_rkey[$i][3]); + $data[0] ^= $this->f3($data[1], $this->_mkey[$i][2], $this->_rkey[$i][2]); + $data[1] ^= $this->f2($data[2], $this->_mkey[$i][1], $this->_rkey[$i][1]); + $data[2] ^= $this->f1($data[3], $this->_mkey[$i][0], $this->_rkey[$i][0]); + } + + // convert the decimals back to a string, reverse the string so it's + // in the correct order + $data = array_map(function($v) { + $v = Core::dec2Str($v, 4); + return strrev($v); + }, $data); + + // glue the string back together + $data = implode("", $data); + + return true; + } + + + /** + * Decrypt an encrypted string, it does all the steps of encryption, + * but in reverse. + * + * @param string $data A 128 bit block of encrypted data + * @return boolean Returns true + */ + public function decrypt(&$data) + { + $this->operation(parent::DECRYPT); + + // first split the data into four 32 bit blocks, reverse + // the string order of each block, convert the blocks of data to integers + $data = str_split($data, 4); + $data = array_map("strrev", $data); + $data = array_map("parent::str2Dec", $data); + + // do the first 6 loops + for($i = 11; $i >= 6; --$i) + { + $data[2] ^= $this->f1($data[3], $this->_mkey[$i][0], $this->_rkey[$i][0]); + $data[1] ^= $this->f2($data[2], $this->_mkey[$i][1], $this->_rkey[$i][1]); + $data[0] ^= $this->f3($data[1], $this->_mkey[$i][2], $this->_rkey[$i][2]); + $data[3] ^= $this->f1($data[0], $this->_mkey[$i][3], $this->_rkey[$i][3]); + } + + // the second 6 loops are done in a different order + for($i = 5; $i >= 0; --$i) + { + $data[3] ^= $this->f1($data[0], $this->_mkey[$i][3], $this->_rkey[$i][3]); + $data[0] ^= $this->f3($data[1], $this->_mkey[$i][2], $this->_rkey[$i][2]); + $data[1] ^= $this->f2($data[2], $this->_mkey[$i][1], $this->_rkey[$i][1]); + $data[2] ^= $this->f1($data[3], $this->_mkey[$i][0], $this->_rkey[$i][0]); + } + + // convert the decimals back to a string, reverse the string so it's + // in the correct order + $data = array_map(function($v) { + $v = Core::dec2Str($v, 4); + return strrev($v); + }, $data); + + // glue the string back together + $data = implode("", $data); + + return true; + } + + + /** + * CAST-256 F1 function + * + * @param $d integer The the data input + * @param $m integer The 32 bit masking key + * @param $r integer The round number + * @return integer The value after the F1 calculation + */ + private function f1($d, $m, $r) + { + $n = parent::uInt32($m + $d); + $n = parent::uInt32(parent::rotBitsLeft32($n, $r)); + $n = parent::dec2Str($n, 4); + + return parent::uInt32( + ((self::$_s1[ord($n[0])] ^ self::$_s2[ord($n[1])]) - + self::$_s3[ord($n[2])]) + self::$_s4[ord($n[3])] + ); + } + + + /** + * CAST-256 F2 function + * + * @param $d integer The the data input + * @param $m integer The 32 bit masking key + * @param $r integer The round number + * @return integer The value after the F2 calculation + */ + private function f2($d, $m, $r) + { + $n = parent::uInt32($m ^ $d); + $n = parent::uInt32(parent::rotBitsLeft32($n, $r)); + $n = parent::dec2Str($n, 4); + + return parent::uInt32( + ((self::$_s1[ord($n[0])] - self::$_s2[ord($n[1])]) + + self::$_s3[ord($n[2])]) ^ self::$_s4[ord($n[3])] + ); + } + + + /** + * CAST-256 F3 function + * + * @param $d integer The the data input + * @param $m integer The 32 bit masking key + * @param $r integer The round number + * @return integer The value after the F3 calculation + */ + private function f3($d, $m, $r) + { + $n = parent::uInt32($m - $d); + $n = parent::uInt32(parent::rotBitsLeft32($n, $r)); + $n = parent::dec2Str($n, 4); + + return parent::uInt32( + ((self::$_s1[ord($n[0])] + self::$_s2[ord($n[1])]) ^ + self::$_s3[ord($n[2])]) - self::$_s4[ord($n[3])] + ); + } + + + /** + * Creates the subkeys $_mkey (the masking key) and + * $_rkey (the rotate key) which are 16 bytes each. These are + * created from the original key. The original key is null + * padded up to 16 bytes and expanded to 32 bytes. It is then + * split in half to create $_mkey and $_rkey + * + * @return void + */ + private function createSubKeys() + { + $cm = 0x5A827999; + $mm = 0x6ED9EBA1; + $cr = 19; + $mr = 17; + $tm = array(); + $tr = array(); + $xkey = $this->key(); + $tmpkey = array(); + + // if the key is less than 32 bytes, pad it to 32 bytes + // for the key expansion + if($this->keySize() < 32) + $xkey = str_pad($xkey, 32, "\0", STR_PAD_RIGHT); + + // split the key up into 4 byte parts, reverse the string, + // then convert each part into a 32 bit integer + $xkey = str_split($xkey, 4); + $xkey = array_map("strrev", $xkey); + $xkey = array_map("parent::str2Dec", $xkey); + + // set up the values need for creating round and masking keys + for($i = 0; $i < 24; ++$i) + { + $tm[$i] = array(); + $tr[$i] = array(); + + for($j = 0; $j < 8; ++$j) + { + $tm[$i][$j] = $cm; + $cm = parent::uInt32($cm + $mm); + $tr[$i][$j] = $cr; + $cr = parent::uInt32($cr + $mr); + } + } + + // now create the round and masking keys + for($i = 0; $i < 12; ++$i) + { + $j = 2 * $i; + + $xkey[6] = parent::uInt32($xkey[6] ^ $this->f1($xkey[7], $tm[$j][0], $tr[$j][0])); + $xkey[5] = parent::uInt32($xkey[5] ^ $this->f2($xkey[6], $tm[$j][1], $tr[$j][1])); + $xkey[4] = parent::uInt32($xkey[4] ^ $this->f3($xkey[5], $tm[$j][2], $tr[$j][2])); + $xkey[3] = parent::uInt32($xkey[3] ^ $this->f1($xkey[4], $tm[$j][3], $tr[$j][3])); + $xkey[2] = parent::uInt32($xkey[2] ^ $this->f2($xkey[3], $tm[$j][4], $tr[$j][4])); + $xkey[1] = parent::uInt32($xkey[1] ^ $this->f3($xkey[2], $tm[$j][5], $tr[$j][5])); + $xkey[0] = parent::uInt32($xkey[0] ^ $this->f1($xkey[1], $tm[$j][6], $tr[$j][6])); + $xkey[7] = parent::uInt32($xkey[7] ^ $this->f2($xkey[0], $tm[$j][7], $tr[$j][7])); + + $j = (2 * $i) + 1; + $xkey[6] = parent::uInt32($xkey[6] ^ $this->f1($xkey[7], $tm[$j][0], $tr[$j][0])); + $xkey[5] = parent::uInt32($xkey[5] ^ $this->f2($xkey[6], $tm[$j][1], $tr[$j][1])); + $xkey[4] = parent::uInt32($xkey[4] ^ $this->f3($xkey[5], $tm[$j][2], $tr[$j][2])); + $xkey[3] = parent::uInt32($xkey[3] ^ $this->f1($xkey[4], $tm[$j][3], $tr[$j][3])); + $xkey[2] = parent::uInt32($xkey[2] ^ $this->f2($xkey[3], $tm[$j][4], $tr[$j][4])); + $xkey[1] = parent::uInt32($xkey[1] ^ $this->f3($xkey[2], $tm[$j][5], $tr[$j][5])); + $xkey[0] = parent::uInt32($xkey[0] ^ $this->f1($xkey[1], $tm[$j][6], $tr[$j][6])); + $xkey[7] = parent::uInt32($xkey[7] ^ $this->f2($xkey[0], $tm[$j][7], $tr[$j][7])); + + // take the least 5 significant bits of each $xkey byte below and assign it + // to the round key + $this->_rkey[$i][0] = $xkey[0] & 31; + $this->_rkey[$i][1] = $xkey[2] & 31; + $this->_rkey[$i][2] = $xkey[4] & 31; + $this->_rkey[$i][3] = $xkey[6] & 31; + + // now create 32 byte masking keys + $this->_mkey[$i][0] = $xkey[7]; + $this->_mkey[$i][1] = $xkey[5]; + $this->_mkey[$i][2] = $xkey[3]; + $this->_mkey[$i][3] = $xkey[1]; + } + } + + + /** + * Initialize the tables + * + * @return void + */ + private function initTables() + { + // 256 unsigned 32 bit integers + self::$_s1 = array( + 0x30FB40D4, 0x9FA0FF0B, 0x6BECCD2F, 0x3F258C7A, + 0x1E213F2F, 0x9C004DD3, 0x6003E540, 0xCF9FC949, + 0xBFD4AF27, 0x88BBBDB5, 0xE2034090, 0x98D09675, + 0x6E63A0E0, 0x15C361D2, 0xC2E7661D, 0x22D4FF8E, + 0x28683B6F, 0xC07FD059, 0xFF2379C8, 0x775F50E2, + 0x43C340D3, 0xDF2F8656, 0x887CA41A, 0xA2D2BD2D, + 0xA1C9E0D6, 0x346C4819, 0x61B76D87, 0x22540F2F, + 0x2ABE32E1, 0xAA54166B, 0x22568E3A, 0xA2D341D0, + 0x66DB40C8, 0xA784392F, 0x004DFF2F, 0x2DB9D2DE, + 0x97943FAC, 0x4A97C1D8, 0x527644B7, 0xB5F437A7, + 0xB82CBAEF, 0xD751D159, 0x6FF7F0ED, 0x5A097A1F, + 0x827B68D0, 0x90ECF52E, 0x22B0C054, 0xBC8E5935, + 0x4B6D2F7F, 0x50BB64A2, 0xD2664910, 0xBEE5812D, + 0xB7332290, 0xE93B159F, 0xB48EE411, 0x4BFF345D, + 0xFD45C240, 0xAD31973F, 0xC4F6D02E, 0x55FC8165, + 0xD5B1CAAD, 0xA1AC2DAE, 0xA2D4B76D, 0xC19B0C50, + 0x882240F2, 0x0C6E4F38, 0xA4E4BFD7, 0x4F5BA272, + 0x564C1D2F, 0xC59C5319, 0xB949E354, 0xB04669FE, + 0xB1B6AB8A, 0xC71358DD, 0x6385C545, 0x110F935D, + 0x57538AD5, 0x6A390493, 0xE63D37E0, 0x2A54F6B3, + 0x3A787D5F, 0x6276A0B5, 0x19A6FCDF, 0x7A42206A, + 0x29F9D4D5, 0xF61B1891, 0xBB72275E, 0xAA508167, + 0x38901091, 0xC6B505EB, 0x84C7CB8C, 0x2AD75A0F, + 0x874A1427, 0xA2D1936B, 0x2AD286AF, 0xAA56D291, + 0xD7894360, 0x425C750D, 0x93B39E26, 0x187184C9, + 0x6C00B32D, 0x73E2BB14, 0xA0BEBC3C, 0x54623779, + 0x64459EAB, 0x3F328B82, 0x7718CF82, 0x59A2CEA6, + 0x04EE002E, 0x89FE78E6, 0x3FAB0950, 0x325FF6C2, + 0x81383F05, 0x6963C5C8, 0x76CB5AD6, 0xD49974C9, + 0xCA180DCF, 0x380782D5, 0xC7FA5CF6, 0x8AC31511, + 0x35E79E13, 0x47DA91D0, 0xF40F9086, 0xA7E2419E, + 0x31366241, 0x051EF495, 0xAA573B04, 0x4A805D8D, + 0x548300D0, 0x00322A3C, 0xBF64CDDF, 0xBA57A68E, + 0x75C6372B, 0x50AFD341, 0xA7C13275, 0x915A0BF5, + 0x6B54BFAB, 0x2B0B1426, 0xAB4CC9D7, 0x449CCD82, + 0xF7FBF265, 0xAB85C5F3, 0x1B55DB94, 0xAAD4E324, + 0xCFA4BD3F, 0x2DEAA3E2, 0x9E204D02, 0xC8BD25AC, + 0xEADF55B3, 0xD5BD9E98, 0xE31231B2, 0x2AD5AD6C, + 0x954329DE, 0xADBE4528, 0xD8710F69, 0xAA51C90F, + 0xAA786BF6, 0x22513F1E, 0xAA51A79B, 0x2AD344CC, + 0x7B5A41F0, 0xD37CFBAD, 0x1B069505, 0x41ECE491, + 0xB4C332E6, 0x032268D4, 0xC9600ACC, 0xCE387E6D, + 0xBF6BB16C, 0x6A70FB78, 0x0D03D9C9, 0xD4DF39DE, + 0xE01063DA, 0x4736F464, 0x5AD328D8, 0xB347CC96, + 0x75BB0FC3, 0x98511BFB, 0x4FFBCC35, 0xB58BCF6A, + 0xE11F0ABC, 0xBFC5FE4A, 0xA70AEC10, 0xAC39570A, + 0x3F04442F, 0x6188B153, 0xE0397A2E, 0x5727CB79, + 0x9CEB418F, 0x1CACD68D, 0x2AD37C96, 0x0175CB9D, + 0xC69DFF09, 0xC75B65F0, 0xD9DB40D8, 0xEC0E7779, + 0x4744EAD4, 0xB11C3274, 0xDD24CB9E, 0x7E1C54BD, + 0xF01144F9, 0xD2240EB1, 0x9675B3FD, 0xA3AC3755, + 0xD47C27AF, 0x51C85F4D, 0x56907596, 0xA5BB15E6, + 0x580304F0, 0xCA042CF1, 0x011A37EA, 0x8DBFAADB, + 0x35BA3E4A, 0x3526FFA0, 0xC37B4D09, 0xBC306ED9, + 0x98A52666, 0x5648F725, 0xFF5E569D, 0x0CED63D0, + 0x7C63B2CF, 0x700B45E1, 0xD5EA50F1, 0x85A92872, + 0xAF1FBDA7, 0xD4234870, 0xA7870BF3, 0x2D3B4D79, + 0x42E04198, 0x0CD0EDE7, 0x26470DB8, 0xF881814C, + 0x474D6AD7, 0x7C0C5E5C, 0xD1231959, 0x381B7298, + 0xF5D2F4DB, 0xAB838653, 0x6E2F1E23, 0x83719C9E, + 0xBD91E046, 0x9A56456E, 0xDC39200C, 0x20C8C571, + 0x962BDA1C, 0xE1E696FF, 0xB141AB08, 0x7CCA89B9, + 0x1A69E783, 0x02CC4843, 0xA2F7C579, 0x429EF47D, + 0x427B169C, 0x5AC9F049, 0xDD8F0F00, 0x5C8165BF + ); + + // 256 unsigned 32 bit integers + self::$_s2 = array( + 0x1F201094, 0xEF0BA75B, 0x69E3CF7E, 0x393F4380, + 0xFE61CF7A, 0xEEC5207A, 0x55889C94, 0x72FC0651, + 0xADA7EF79, 0x4E1D7235, 0xD55A63CE, 0xDE0436BA, + 0x99C430EF, 0x5F0C0794, 0x18DCDB7D, 0xA1D6EFF3, + 0xA0B52F7B, 0x59E83605, 0xEE15B094, 0xE9FFD909, + 0xDC440086, 0xEF944459, 0xBA83CCB3, 0xE0C3CDFB, + 0xD1DA4181, 0x3B092AB1, 0xF997F1C1, 0xA5E6CF7B, + 0x01420DDB, 0xE4E7EF5B, 0x25A1FF41, 0xE180F806, + 0x1FC41080, 0x179BEE7A, 0xD37AC6A9, 0xFE5830A4, + 0x98DE8B7F, 0x77E83F4E, 0x79929269, 0x24FA9F7B, + 0xE113C85B, 0xACC40083, 0xD7503525, 0xF7EA615F, + 0x62143154, 0x0D554B63, 0x5D681121, 0xC866C359, + 0x3D63CF73, 0xCEE234C0, 0xD4D87E87, 0x5C672B21, + 0x071F6181, 0x39F7627F, 0x361E3084, 0xE4EB573B, + 0x602F64A4, 0xD63ACD9C, 0x1BBC4635, 0x9E81032D, + 0x2701F50C, 0x99847AB4, 0xA0E3DF79, 0xBA6CF38C, + 0x10843094, 0x2537A95E, 0xF46F6FFE, 0xA1FF3B1F, + 0x208CFB6A, 0x8F458C74, 0xD9E0A227, 0x4EC73A34, + 0xFC884F69, 0x3E4DE8DF, 0xEF0E0088, 0x3559648D, + 0x8A45388C, 0x1D804366, 0x721D9BFD, 0xA58684BB, + 0xE8256333, 0x844E8212, 0x128D8098, 0xFED33FB4, + 0xCE280AE1, 0x27E19BA5, 0xD5A6C252, 0xE49754BD, + 0xC5D655DD, 0xEB667064, 0x77840B4D, 0xA1B6A801, + 0x84DB26A9, 0xE0B56714, 0x21F043B7, 0xE5D05860, + 0x54F03084, 0x066FF472, 0xA31AA153, 0xDADC4755, + 0xB5625DBF, 0x68561BE6, 0x83CA6B94, 0x2D6ED23B, + 0xECCF01DB, 0xA6D3D0BA, 0xB6803D5C, 0xAF77A709, + 0x33B4A34C, 0x397BC8D6, 0x5EE22B95, 0x5F0E5304, + 0x81ED6F61, 0x20E74364, 0xB45E1378, 0xDE18639B, + 0x881CA122, 0xB96726D1, 0x8049A7E8, 0x22B7DA7B, + 0x5E552D25, 0x5272D237, 0x79D2951C, 0xC60D894C, + 0x488CB402, 0x1BA4FE5B, 0xA4B09F6B, 0x1CA815CF, + 0xA20C3005, 0x8871DF63, 0xB9DE2FCB, 0x0CC6C9E9, + 0x0BEEFF53, 0xE3214517, 0xB4542835, 0x9F63293C, + 0xEE41E729, 0x6E1D2D7C, 0x50045286, 0x1E6685F3, + 0xF33401C6, 0x30A22C95, 0x31A70850, 0x60930F13, + 0x73F98417, 0xA1269859, 0xEC645C44, 0x52C877A9, + 0xCDFF33A6, 0xA02B1741, 0x7CBAD9A2, 0x2180036F, + 0x50D99C08, 0xCB3F4861, 0xC26BD765, 0x64A3F6AB, + 0x80342676, 0x25A75E7B, 0xE4E6D1FC, 0x20C710E6, + 0xCDF0B680, 0x17844D3B, 0x31EEF84D, 0x7E0824E4, + 0x2CCB49EB, 0x846A3BAE, 0x8FF77888, 0xEE5D60F6, + 0x7AF75673, 0x2FDD5CDB, 0xA11631C1, 0x30F66F43, + 0xB3FAEC54, 0x157FD7FA, 0xEF8579CC, 0xD152DE58, + 0xDB2FFD5E, 0x8F32CE19, 0x306AF97A, 0x02F03EF8, + 0x99319AD5, 0xC242FA0F, 0xA7E3EBB0, 0xC68E4906, + 0xB8DA230C, 0x80823028, 0xDCDEF3C8, 0xD35FB171, + 0x088A1BC8, 0xBEC0C560, 0x61A3C9E8, 0xBCA8F54D, + 0xC72FEFFA, 0x22822E99, 0x82C570B4, 0xD8D94E89, + 0x8B1C34BC, 0x301E16E6, 0x273BE979, 0xB0FFEAA6, + 0x61D9B8C6, 0x00B24869, 0xB7FFCE3F, 0x08DC283B, + 0x43DAF65A, 0xF7E19798, 0x7619B72F, 0x8F1C9BA4, + 0xDC8637A0, 0x16A7D3B1, 0x9FC393B7, 0xA7136EEB, + 0xC6BCC63E, 0x1A513742, 0xEF6828BC, 0x520365D6, + 0x2D6A77AB, 0x3527ED4B, 0x821FD216, 0x095C6E2E, + 0xDB92F2FB, 0x5EEA29CB, 0x145892F5, 0x91584F7F, + 0x5483697B, 0x2667A8CC, 0x85196048, 0x8C4BACEA, + 0x833860D4, 0x0D23E0F9, 0x6C387E8A, 0x0AE6D249, + 0xB284600C, 0xD835731D, 0xDCB1C647, 0xAC4C56EA, + 0x3EBD81B3, 0x230EABB0, 0x6438BC87, 0xF0B5B1FA, + 0x8F5EA2B3, 0xFC184642, 0x0A036B7A, 0x4FB089BD, + 0x649DA589, 0xA345415E, 0x5C038323, 0x3E5D3BB9, + 0x43D79572, 0x7E6DD07C, 0x06DFDF1E, 0x6C6CC4EF, + 0x7160A539, 0x73BFBE70, 0x83877605, 0x4523ECF1 + ); + + // 256 unsigned 32 bit integers + self::$_s3 = array( + 0x8DEFC240, 0x25FA5D9F, 0xEB903DBF, 0xE810C907, + 0x47607FFF, 0x369FE44B, 0x8C1FC644, 0xAECECA90, + 0xBEB1F9BF, 0xEEFBCAEA, 0xE8CF1950, 0x51DF07AE, + 0x920E8806, 0xF0AD0548, 0xE13C8D83, 0x927010D5, + 0x11107D9F, 0x07647DB9, 0xB2E3E4D4, 0x3D4F285E, + 0xB9AFA820, 0xFADE82E0, 0xA067268B, 0x8272792E, + 0x553FB2C0, 0x489AE22B, 0xD4EF9794, 0x125E3FBC, + 0x21FFFCEE, 0x825B1BFD, 0x9255C5ED, 0x1257A240, + 0x4E1A8302, 0xBAE07FFF, 0x528246E7, 0x8E57140E, + 0x3373F7BF, 0x8C9F8188, 0xA6FC4EE8, 0xC982B5A5, + 0xA8C01DB7, 0x579FC264, 0x67094F31, 0xF2BD3F5F, + 0x40FFF7C1, 0x1FB78DFC, 0x8E6BD2C1, 0x437BE59B, + 0x99B03DBF, 0xB5DBC64B, 0x638DC0E6, 0x55819D99, + 0xA197C81C, 0x4A012D6E, 0xC5884A28, 0xCCC36F71, + 0xB843C213, 0x6C0743F1, 0x8309893C, 0x0FEDDD5F, + 0x2F7FE850, 0xD7C07F7E, 0x02507FBF, 0x5AFB9A04, + 0xA747D2D0, 0x1651192E, 0xAF70BF3E, 0x58C31380, + 0x5F98302E, 0x727CC3C4, 0x0A0FB402, 0x0F7FEF82, + 0x8C96FDAD, 0x5D2C2AAE, 0x8EE99A49, 0x50DA88B8, + 0x8427F4A0, 0x1EAC5790, 0x796FB449, 0x8252DC15, + 0xEFBD7D9B, 0xA672597D, 0xADA840D8, 0x45F54504, + 0xFA5D7403, 0xE83EC305, 0x4F91751A, 0x925669C2, + 0x23EFE941, 0xA903F12E, 0x60270DF2, 0x0276E4B6, + 0x94FD6574, 0x927985B2, 0x8276DBCB, 0x02778176, + 0xF8AF918D, 0x4E48F79E, 0x8F616DDF, 0xE29D840E, + 0x842F7D83, 0x340CE5C8, 0x96BBB682, 0x93B4B148, + 0xEF303CAB, 0x984FAF28, 0x779FAF9B, 0x92DC560D, + 0x224D1E20, 0x8437AA88, 0x7D29DC96, 0x2756D3DC, + 0x8B907CEE, 0xB51FD240, 0xE7C07CE3, 0xE566B4A1, + 0xC3E9615E, 0x3CF8209D, 0x6094D1E3, 0xCD9CA341, + 0x5C76460E, 0x00EA983B, 0xD4D67881, 0xFD47572C, + 0xF76CEDD9, 0xBDA8229C, 0x127DADAA, 0x438A074E, + 0x1F97C090, 0x081BDB8A, 0x93A07EBE, 0xB938CA15, + 0x97B03CFF, 0x3DC2C0F8, 0x8D1AB2EC, 0x64380E51, + 0x68CC7BFB, 0xD90F2788, 0x12490181, 0x5DE5FFD4, + 0xDD7EF86A, 0x76A2E214, 0xB9A40368, 0x925D958F, + 0x4B39FFFA, 0xBA39AEE9, 0xA4FFD30B, 0xFAF7933B, + 0x6D498623, 0x193CBCFA, 0x27627545, 0x825CF47A, + 0x61BD8BA0, 0xD11E42D1, 0xCEAD04F4, 0x127EA392, + 0x10428DB7, 0x8272A972, 0x9270C4A8, 0x127DE50B, + 0x285BA1C8, 0x3C62F44F, 0x35C0EAA5, 0xE805D231, + 0x428929FB, 0xB4FCDF82, 0x4FB66A53, 0x0E7DC15B, + 0x1F081FAB, 0x108618AE, 0xFCFD086D, 0xF9FF2889, + 0x694BCC11, 0x236A5CAE, 0x12DECA4D, 0x2C3F8CC5, + 0xD2D02DFE, 0xF8EF5896, 0xE4CF52DA, 0x95155B67, + 0x494A488C, 0xB9B6A80C, 0x5C8F82BC, 0x89D36B45, + 0x3A609437, 0xEC00C9A9, 0x44715253, 0x0A874B49, + 0xD773BC40, 0x7C34671C, 0x02717EF6, 0x4FEB5536, + 0xA2D02FFF, 0xD2BF60C4, 0xD43F03C0, 0x50B4EF6D, + 0x07478CD1, 0x006E1888, 0xA2E53F55, 0xB9E6D4BC, + 0xA2048016, 0x97573833, 0xD7207D67, 0xDE0F8F3D, + 0x72F87B33, 0xABCC4F33, 0x7688C55D, 0x7B00A6B0, + 0x947B0001, 0x570075D2, 0xF9BB88F8, 0x8942019E, + 0x4264A5FF, 0x856302E0, 0x72DBD92B, 0xEE971B69, + 0x6EA22FDE, 0x5F08AE2B, 0xAF7A616D, 0xE5C98767, + 0xCF1FEBD2, 0x61EFC8C2, 0xF1AC2571, 0xCC8239C2, + 0x67214CB8, 0xB1E583D1, 0xB7DC3E62, 0x7F10BDCE, + 0xF90A5C38, 0x0FF0443D, 0x606E6DC6, 0x60543A49, + 0x5727C148, 0x2BE98A1D, 0x8AB41738, 0x20E1BE24, + 0xAF96DA0F, 0x68458425, 0x99833BE5, 0x600D457D, + 0x282F9350, 0x8334B362, 0xD91D1120, 0x2B6D8DA0, + 0x642B1E31, 0x9C305A00, 0x52BCE688, 0x1B03588A, + 0xF7BAEFD5, 0x4142ED9C, 0xA4315C11, 0x83323EC5, + 0xDFEF4636, 0xA133C501, 0xE9D3531C, 0xEE353783 + ); + + // 256 unsigned 32 bit integers + self::$_s4 = array( + 0x9DB30420, 0x1FB6E9DE, 0xA7BE7BEF, 0xD273A298, + 0x4A4F7BDB, 0x64AD8C57, 0x85510443, 0xFA020ED1, + 0x7E287AFF, 0xE60FB663, 0x095F35A1, 0x79EBF120, + 0xFD059D43, 0x6497B7B1, 0xF3641F63, 0x241E4ADF, + 0x28147F5F, 0x4FA2B8CD, 0xC9430040, 0x0CC32220, + 0xFDD30B30, 0xC0A5374F, 0x1D2D00D9, 0x24147B15, + 0xEE4D111A, 0x0FCA5167, 0x71FF904C, 0x2D195FFE, + 0x1A05645F, 0x0C13FEFE, 0x081B08CA, 0x05170121, + 0x80530100, 0xE83E5EFE, 0xAC9AF4F8, 0x7FE72701, + 0xD2B8EE5F, 0x06DF4261, 0xBB9E9B8A, 0x7293EA25, + 0xCE84FFDF, 0xF5718801, 0x3DD64B04, 0xA26F263B, + 0x7ED48400, 0x547EEBE6, 0x446D4CA0, 0x6CF3D6F5, + 0x2649ABDF, 0xAEA0C7F5, 0x36338CC1, 0x503F7E93, + 0xD3772061, 0x11B638E1, 0x72500E03, 0xF80EB2BB, + 0xABE0502E, 0xEC8D77DE, 0x57971E81, 0xE14F6746, + 0xC9335400, 0x6920318F, 0x081DBB99, 0xFFC304A5, + 0x4D351805, 0x7F3D5CE3, 0xA6C866C6, 0x5D5BCCA9, + 0xDAEC6FEA, 0x9F926F91, 0x9F46222F, 0x3991467D, + 0xA5BF6D8E, 0x1143C44F, 0x43958302, 0xD0214EEB, + 0x022083B8, 0x3FB6180C, 0x18F8931E, 0x281658E6, + 0x26486E3E, 0x8BD78A70, 0x7477E4C1, 0xB506E07C, + 0xF32D0A25, 0x79098B02, 0xE4EABB81, 0x28123B23, + 0x69DEAD38, 0x1574CA16, 0xDF871B62, 0x211C40B7, + 0xA51A9EF9, 0x0014377B, 0x041E8AC8, 0x09114003, + 0xBD59E4D2, 0xE3D156D5, 0x4FE876D5, 0x2F91A340, + 0x557BE8DE, 0x00EAE4A7, 0x0CE5C2EC, 0x4DB4BBA6, + 0xE756BDFF, 0xDD3369AC, 0xEC17B035, 0x06572327, + 0x99AFC8B0, 0x56C8C391, 0x6B65811C, 0x5E146119, + 0x6E85CB75, 0xBE07C002, 0xC2325577, 0x893FF4EC, + 0x5BBFC92D, 0xD0EC3B25, 0xB7801AB7, 0x8D6D3B24, + 0x20C763EF, 0xC366A5FC, 0x9C382880, 0x0ACE3205, + 0xAAC9548A, 0xECA1D7C7, 0x041AFA32, 0x1D16625A, + 0x6701902C, 0x9B757A54, 0x31D477F7, 0x9126B031, + 0x36CC6FDB, 0xC70B8B46, 0xD9E66A48, 0x56E55A79, + 0x026A4CEB, 0x52437EFF, 0x2F8F76B4, 0x0DF980A5, + 0x8674CDE3, 0xEDDA04EB, 0x17A9BE04, 0x2C18F4DF, + 0xB7747F9D, 0xAB2AF7B4, 0xEFC34D20, 0x2E096B7C, + 0x1741A254, 0xE5B6A035, 0x213D42F6, 0x2C1C7C26, + 0x61C2F50F, 0x6552DAF9, 0xD2C231F8, 0x25130F69, + 0xD8167FA2, 0x0418F2C8, 0x001A96A6, 0x0D1526AB, + 0x63315C21, 0x5E0A72EC, 0x49BAFEFD, 0x187908D9, + 0x8D0DBD86, 0x311170A7, 0x3E9B640C, 0xCC3E10D7, + 0xD5CAD3B6, 0x0CAEC388, 0xF73001E1, 0x6C728AFF, + 0x71EAE2A1, 0x1F9AF36E, 0xCFCBD12F, 0xC1DE8417, + 0xAC07BE6B, 0xCB44A1D8, 0x8B9B0F56, 0x013988C3, + 0xB1C52FCA, 0xB4BE31CD, 0xD8782806, 0x12A3A4E2, + 0x6F7DE532, 0x58FD7EB6, 0xD01EE900, 0x24ADFFC2, + 0xF4990FC5, 0x9711AAC5, 0x001D7B95, 0x82E5E7D2, + 0x109873F6, 0x00613096, 0xC32D9521, 0xADA121FF, + 0x29908415, 0x7FBB977F, 0xAF9EB3DB, 0x29C9ED2A, + 0x5CE2A465, 0xA730F32C, 0xD0AA3FE8, 0x8A5CC091, + 0xD49E2CE7, 0x0CE454A9, 0xD60ACD86, 0x015F1919, + 0x77079103, 0xDEA03AF6, 0x78A8565E, 0xDEE356DF, + 0x21F05CBE, 0x8B75E387, 0xB3C50651, 0xB8A5C3EF, + 0xD8EEB6D2, 0xE523BE77, 0xC2154529, 0x2F69EFDF, + 0xAFE67AFB, 0xF470C4B2, 0xF3E0EB5B, 0xD6CC9876, + 0x39E4460C, 0x1FDA8538, 0x1987832F, 0xCA007367, + 0xA99144F8, 0x296B299E, 0x492FC295, 0x9266BEAB, + 0xB5676E69, 0x9BD3DDDA, 0xDF7E052F, 0xDB25701C, + 0x1B5E51EE, 0xF65324E6, 0x6AFCE36C, 0x0316CC04, + 0x8644213E, 0xB7DC59D0, 0x7965291F, 0xCCD6FD43, + 0x41823979, 0x932BCDF6, 0xB657C34D, 0x4EDFD282, + 0x7AE5290C, 0x3CB9536B, 0x851E20FE, 0x9833557E, + 0x13ECF0B0, 0xD3FFB372, 0x3F85C5C1, 0x0AEF7ED2 + ); + } + + + /** + * Indicates this is a block cipher + * + * @return integer Returns Cipher::BLOCK + */ + public function type() + { + return parent::BLOCK; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/DES.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/DES.php new file mode 100644 index 0000000000..b1cb900cbf --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/DES.php @@ -0,0 +1,595 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements DES Encryption + * Resources used to implement this algorithm: + * J. Orlin Grabbe, The Des Algorithm Illustrated, http://orlingrabbe.com/des.htm + * Bruce Schneier, Applied Cryptography (2nd edition), 1996, pp. 265-300 + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2005 Ryan Gilfether + */ +class Cipher_DES extends Cipher +{ + /** @type integer BYTES_BLOCK The block size, in bytes */ + const BYTES_BLOCK = 8; // 64 bits + + /** @type integer BYTES_KEY The key size, in bytes */ + const BYTES_KEY = 8; // 64 bits + + /** @type array $sub_keys The permutated subkeys */ + protected $sub_keys = array(); + + /* + * Tables initialized in the initTables() + */ + + /** + * @type array $_pc1 Permutated choice 1 (PC1), + * This should be considered a constant + */ + protected static $_pc1 = array(); + + /** + * @type array $_pc2 Permutated choice 2 (PC2), + * This should be considered a constant + */ + protected static $_pc2 = array(); + + /** + * @type array $_key_sched The key schedule, + * This should be considered a constant + */ + protected static $_key_sched = array(); + + /** + * @type array $_ip The Initial Permutation (IP), + * This should be considered a constant + */ + private static $_ip = array(); + + /** + * @type array $_e The Expansion table (E), + * This should be considered a constant + */ + private static $_e = array(); + + /** + * @type array $_s The Substitution Box (S), + * This should be considered a constant + */ + private static $_s = array(); + + /** + * @type array $_p The Permutation table (P), + * This should be considered a constant + */ + private static $_p = array(); + + /** + * @type array $_ip The The Final Permutation table (FP), + * This should be considered a constant + */ + private static $_fp = array(); + + + /** + * Constructor, used only when calling this class directly + * for classes that extend this class, call __construct1() + * + * @param string $key The key used for Encryption/Decryption + * @return void + */ + public function __construct($key) + { + // set the DES key + parent::__construct(PHP_Crypt::CIPHER_DES, $key, self::BYTES_KEY); + + // initialize variables + $this->initTables(); + + // DES requires that data is 64 bits + $this->blockSize(self::BYTES_BLOCK); + + // create the 16 rounds of 56 bit keys + $this->keyPermutation(); + } + + + /** + * Second Constructor, used only by child classes that extend this class + * + * @param string $cipher The name of the cipher extending this class + * @param string $key The key used for Encryption/Decryption + * @param integer $key_byte_sz The required byte size of the extending cipher + * @return void + */ + protected function __construct1($cipher, $key, $key_byte_sz) + { + // set the key and key size + parent::__construct($cipher, $key, $key_byte_sz); + + // initialize variables + $this->initTables(); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypt plain text data using DES + * + * @param string $data A plain text string + * @return boolean Returns true + */ + public function encrypt(&$text) + { + $this->operation(parent::ENCRYPT); + return $this->des($text); + } + + + /** + * Decrypt a DES encrypted string + * + * @param string $encrypted A DES encrypted string + * @return boolean Returns true + */ + public function decrypt(&$text) + { + $this->operation(parent::DECRYPT); + return $this->des($text); + } + + + /** + * This is where the actual encrypt/decryption takes place. Since + * encryption and decryption are the same algorithm in DES, we only + * need one function to do both. + * + * @param string $data The string to be encrypted or decrypted + * @return boolean Returns true + */ + protected function des(&$data) + { + $l = array(); + $r = array(); + + // step two: Initial Permutation (IP) of plaintext + $data = $this->ip($data); + + // divide the permuted block IP into a left half L0 of 32 bits, + // and a right half R0 of 32 bits + $l[0] = substr($data, 0, 32); + $r[0] = substr($data, 32, 32); + + for($n = 1; $n <= 16; ++$n) + { + $l[$n] = $r[$n-1]; + + if($this->operation() == parent::DECRYPT) + $f = $this->F($r[$n-1], $this->sub_keys[16-$n]); + else + $f = $this->F($r[$n-1], $this->sub_keys[$n-1]); + + // XOR F with Ln + $r[$n] = $this->xorBin($l[$n-1], $f); + } + + // now we combine L[16] and R[16] back into a 64-bit string, but we reverse + // L[16] and R[16] so that it becomes R[16]L[16] + $data = $r[16].$l[16]; + + // now do the final permutation + $data = $this->fp($data); + $data = parent::bin2Str($data); + + return true; + } + + + /** + * The Key permutation, based on tables $_pc1 and $_pc2 + * Create 16 subkeys, each of which is 48-bits long. + * + * @return void + */ + private function keyPermutation() + { + $this->sub_keys = array(); + $pc1m = array(); + $pcr = array(); + $c = array(); + $d = array(); + + // convert the key to binary + $binkey = parent::str2Bin($this->key()); + + // reduce the key down to 56bits based on table $_pc1 + for($i = 0; $i < 56; ++$i) + $pc1m[$i] = $binkey[self::$_pc1[$i] - 1]; + + // split $pc1m in half (C0 and D0) + $c[0] = array_slice($pc1m, 0, 28); + $d[0] = array_slice($pc1m, 28, 28); + + // now that $c[0] and $d[0] are defined, create 16 blocks for Cn and Dn + // where 1 <= n <= 16 + for($i = 1; $i <= 16; ++$i) + { + // now set the next Cn and Dn as the previous Cn and Dn + $c[$i] = $c[$i-1]; + $d[$i] = $d[$i-1]; + + for($j = 0; $j < self::$_key_sched[$i-1]; ++$j) + { + // do a left shift, move each bit one place to the left, + // except for the first bit, which is cycled to the end + // of the block. + $c[$i][] = array_shift($c[$i]); + $d[$i][] = array_shift($d[$i]); + } + + // We now form the sub_keys (Kn), for 1<=n<=16, by applying the + // following permutation table to each of the concatenated + // pairs CnDn. Each pair has 56 bits, but PC-2 only uses 48 + // of these. + $CnDn = array_merge($c[$i], $d[$i]); + $this->sub_keys[$i-1] = ""; + for($j = 0; $j < 48; ++$j) + $this->sub_keys[$i-1] .= $CnDn[self::$_pc2[$j] - 1]; + } + + // the sub_keys are created, we are done with the key permutation + } + + + /** + * Initial Permutation (IP) + * Now we encode each 64-bit block of data. There is an initial permutation IP of + * the 64 bits of the message data M. This rearranges the bits according to the + * following table, where the entries in the table show the new arrangement of the + * bits from their initial order. The 58th bit of M becomes the first bit of IP. + * The 50th bit of M becomes the second bit of IP. The 7th bit of M is the last + * bit of IP. + * + * According to the book Applied Cryptography (Bruce Schneier, 2nd edition, pg. 271): + * The initial permution was used to make it easier to load plain text and cipher text + * data into a DES chip in byte-sized pieces when doing DES in hardware. The IP and FP + * are not necessary in software implementations and do not affect the security. However, + * the IP and FP are part of the DES standard and not implementing it would deviate from + * the standard, so we will do it here in phpCrypt. + * + * @param string $m The plain text message + * @return array the Initial Permutation (IP) + */ + private function ip($text) + { + $text = parent::str2Bin($text); + $ip = ""; + + // loop through the 64 bit block, ordering it occording to $_ip + for($i = 0; $i < 64; ++$i) + $ip .= $text[self::$_ip[$i] - 1]; + + return $ip; + } + + + /** + * Function F - To calculate f, we first expand each block Rn-1 from 32 bits to 48 bits. + * This is done by using a selection table that repeats some of the bits in Rn-1. We'll + * call the use of this selection table the function E. Thus E(Rn-1) has a 32 bit input + * block, and a 48 bit output block. + * + * @param array $r 32 bit binary, each bit in an array element + * @param string $k 48 bit binary string + * @return string 48 bit binary string + */ + private function f($r, $k) + { + $bin = parent::xorBin($k, $this->E($r)); + + // create a 32-bit string from $bits by passing it through the S-Boxes + $bin = $this->s($bin); + + // now send permute $bin as defined by table self::$_p + $bin = $this->p($bin); + + return $bin; + } + + + /** + * Function E - Let E be such that the 48 bits of its output, written as 8 blocks of + * 6 bits each, are obtained by selecting the bits in its inputs in order according + * to the self::$_e[] table. + * This is only used in the F() function + * + * @param array $r 32 bit binary, each bit in an array element + * @return string 48 bit binary string + */ + private function e($r) + { + $e = ""; + for($i = 0; $i < 48; ++$i) + $e .= $r[self::$_e[$i] - 1]; + + return $e; + } + + + /** + * S-Box + * Take a 48-bit string from F() and run it through the S-Boxes, this requires + * us to break up the 48-bit string into 8 groups of 6 bits before sending it + * through the S-Boxes + * + * @param string $bits The 48-bit string from F() to be processed + * @return string A 32-bit string from created from the 48-bit string after passing through S-Boxes + */ + private function s($bits) + { + $s = ""; + + for($i = 0; $i <= 42; $i += 6) + { + $sbits = substr($bits, $i, 6); + + // we need to determine the S-Box column number and row number + // from the 6 bit string passed in, this is done using the following method: + // The First & Last bits represent a number between 0-3, used to determine which row + // The middle 4 bits represent a number between 0-15, used to determine the column + $row = bindec("{$sbits[0]}{$sbits[5]}"); + $col = bindec("{$sbits[1]}{$sbits[2]}{$sbits[3]}{$sbits[4]}"); + + // determine the position in the S-BOX, S-Box table is in self::$_s[] + $pos = ($row * 16) + $col; + + // get the integer from the S-Box and convert it to binary + $bin = decbin(self::$_s[($i/6)][$pos]); + $s .= str_pad($bin, 4, "0", STR_PAD_LEFT); + } + + return $s; + } + + + /** + * Permutation P + * The permutation P is defined in self::$_p. P() returns a 32-bit output + * from a 32-bit input from a binary string from the S-BOX by permuting + * the bits of the input block. + * This is only used inside of F() function + * + * @param string $s A 32-bit string originating from being passed through S-Box + * @return string A 32-bit string, which is $s permuted through table self::$_p + */ + private function p($s) + { + $p = ""; + for($i = 0; $i < 32; ++$i) + $p .= $s[self::$_p[$i] - 1]; + + return $p; + } + + + /** + * Final Permutation (FP) + * Read the comment about IP and FP being unecessary in software implmented DES (though + * we will do it to follow the DES standard). + * + * @param string $bin A 64-bit binary string + * @return string A 64-bit binary string that has been run through self::$_fp[] table + */ + private function fp($bin) + { + $fp = ""; + for($i = 0; $i < 64; ++$i) + $fp .= $bin[self::$_fp[$i] - 1]; + + return $fp; + } + + + /** + * Initialize all the tables, this function is called inside the constructor + * + * @return void + */ + private function initTables() + { + // permuted choice 1 (PC1) + // these values are chars and should be run through chr() when used + self::$_pc1 = array( + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 + ); + + // permuted choice 2 (PC2) + // these values are chars and should be run through chr() when used + self::$_pc2 = array( + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 + ); + + // initial permutation (IP) + self::$_ip = array( + 58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, + 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7 + ); + + // expansion (E) + self::$_e = array( + 32, 1, 2, 3, 4, 5, + 4, 5, 6, 7, 8, 9, + 8, 9, 10, 11, 12, 13, + 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, + 20, 21, 22, 23, 24, 25, + 24, 25, 26, 27, 28, 29, + 28, 29, 30, 31, 32, 1 + ); + + // substition box (S) + self::$_s = array( + /* S1 */ + array( + 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, + 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, + 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, + 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 + ), + + /* S2 */ + array( + 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, + 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, + 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, + 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 + ), + + /* S3 */ + array( + 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, + 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, + 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 + ), + + /* S4 */ + array( + 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, + 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, + 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, + 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 + ), + + /* S5 */ + array( + 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, + 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, + 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, + 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 + ), + + /* S6 */ + array( + 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, + 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, + 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, + 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 + ), + + /* S7 */ + array( + 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, + 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, + 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, + 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 + ), + + /* S8 */ + array( + 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, + 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, + 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, + 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 + ) + ); + + // permutation (P) + self::$_p = array( + 16, 7, 20, 21, + 29, 12, 28, 17, + 1, 15, 23, 26, + 5, 18, 31, 10, + 2, 8, 24, 14, + 32, 27, 3, 9, + 19, 13, 30, 6, + 22, 11, 4, 25 + ); + + // final permutation (FP) + self::$_fp = array( + 40, 8, 48, 16, 56, 24, 64, 32, + 39, 7, 47, 15, 55, 23, 63, 31, + 38, 6, 46, 14, 54, 22, 62, 30, + 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, + 35, 3, 43, 11, 51, 19, 59, 27, + 34, 2, 42, 10, 50, 18, 58, 26, + 33, 1, 41, 9, 49, 17, 57, 25 + ); + + // key schedule used in KeyPermutation() + self::$_key_sched = array(1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1); + } + + + /** + * Indicates this is a block cipher + * + * @return integer Returns Cipher::BLOCK + */ + public function type() + { + return parent::BLOCK; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/Enigma.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/Enigma.php new file mode 100644 index 0000000000..32aed9acfb --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/Enigma.php @@ -0,0 +1,264 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements a 1 rotor version of the Enigma machine encryption. + * This is a historical cipher - different variations of Enigma were used + * by the Germans during WW2. However, old UNIX "crypt" command also used + * this cipher. This Cipher is outdated and should not be used for, + * encryption unless it's needed for use with compatibility with the old + * UNIX 'crypt' command. + * + * It seems that mcrypt's Enigma implementation which this is modeled after + * does everything in 32 bits, even on 64 bit platform. To make this compatible + * I am forcing ints to be 32 bits as well + * + * Resources used to implement this algorithm + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Cipher_Enigma extends Cipher +{ + const MASK = 0377; + + /** @type integer ROTORSZ The size of $t1,$t2,$t3,$deck */ + const ROTORSZ = 256; + + /** @type array $t1 An array of chars, ROTORSZ size */ + private $t1 = array(); + + /** @type array $t2 An array of chars, ROTORSZ size */ + private $t2 = array(); + + /** @type array $t3 An array of chars, ROTORSZ size */ + private $t3 = array(); + + /** @type array $deck An array of chars, ROTORSZ size */ + private $deck = array(); + + private $n1 = 0; + private $n2 = 0; + private $nr1 = 0; + private $nr2 = 0; + + /** @type string $xkey Stores the modified key */ + private $xkey = ""; + + + /** + * Constructor + * + * @param string $key The key used for Encryption/Decryption + * @return void + */ + public function __construct($key) + { + parent::__construct(PHP_Crypt::CIPHER_ENIGMA, $key, strlen($key)); + + $this->createKey(); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypt plain text data using Enigma + * + * @param string $str A plain text string of any length + * @return boolean Returns true + */ + public function encrypt(&$str) + { + $this->operation(parent::ENCRYPT); + return $this->enigma($str); + } + + + /** + * Decrypt an Enigma encrypted string + * + * @param string $str A Enigma encrypted string + * @return boolean Returns true + */ + public function decrypt(&$str) + { + $this->operation(parent::DECRYPT); + return $this->enigma($str); + } + + + /** + * Peforms the actual Enigma encryption/decryption. Since + * the algorithm is the same for both, we do it all in + * this one function + * + * @param string $str A string to encrypt or decrypt + * @return boolean Returns true + */ + private function enigma(&$str) + { + // zero out the counters + $this->n1 = 0; + $this->n2 = 0; + $this->nr1 = 0; + $this->nr2 = 0; + + $max = strlen($str); + for($j = 0; $j < $max; ++$j) + { + $i = ord($str[$j]); + $this->nr1 = $this->n1; + + $pos1 = ($i + $this->nr1) & self::MASK; + $pos3 = ($this->t1[$pos1] + $this->nr2) & self::MASK; + $pos2 = ($this->t3[$pos3] - $this->nr2) & self::MASK; + $i = $this->t2[$pos2] - $this->nr1; + + $str[$j] = chr($i); + $this->n1++; + + if($this->n1 == self::ROTORSZ) + { + $this->n1 = 0; + $this->n2++; + + if($this->n2 == self::ROTORSZ) + $this->n2 = 0; + + $this->nr2 = $this->n2; + } + } + + return true; + } + + + /** + * The code for this function was translated to PHP from mcrypt's enigma.c, + * I was not able to find sufficient documentation to create my own + * version of this function. + * Enigma requires a 13 byte key, this function will + * lengthen the key to get it to 13 bytes long if it's short. It also + * Sets $deck, and $t1, $t2, $t3 which I think are the Enigma rotors. + * + * @return void + */ + private function createKey() + { + $this->deck = array(); + $this->t1 = array(); + $this->t2 = array_fill(0, self::ROTORSZ, 0); + $this->t3 = $this->t2; + $this->xkey = $this->key(); + $klen = $this->keySize(); + + // get the key to exactly 13 bytes if it's less than 13 + if($klen < 13) + $this->xkey = str_pad($this->xkey, 13, chr(0), STR_PAD_RIGHT); + + $seed = 123; + for($i = 0; $i < 13; ++$i) + $seed = parent::sInt32($seed) * ord($this->xkey[$i]) + $i; + + // sets $t1 and $deck + for($i = 0; $i < self::ROTORSZ; ++$i) + { + $this->t1[] = $i; + $this->deck[] = $i; + } + + // sets $t3 + for($i = 0; $i < self::ROTORSZ; ++$i) + { + // make sure the return values are 32 bit + $seed = 5 * parent::sInt32($seed) + ord($this->xkey[$i % 13]); + $seed = parent::sInt32($seed); + + // force the returned value to be an unsigned int + //$random = parent::uint32($seed % 65521); + $random = parent::uInt($seed % 65521); + + $k = self::ROTORSZ - 1 - $i; + $ic = ($random & self::MASK) % ($k + 1); + + // make sure the returned value is an unsigned int + $random = parent::uInt($random >> 8); + + $temp = $this->t1[$k]; + $this->t1[$k] = $this->t1[$ic]; + $this->t1[$ic] = $temp; + if($this->t3[$k] != 0) + continue; + + $ic = ($random & self::MASK) % $k; + while($this->t3[$ic] != 0) + $ic = ($ic + 1) % $k; + + $this->t3[$k] = $ic; + $this->t3[$ic] = $k; + } + + // sets $t2 + for($i = 0; $i < self::ROTORSZ; ++$i) + { + $pos = $this->t1[$i] & self::MASK; + $this->t2[$pos] = $i; + } + + // now convert $t1, $t2, $t3, $deck values to signed chars, + // PHP's chr() function returns an unsigned char, so we have + // to use use our own + $this->t1 = array_map("parent::sChar", $this->t1); + $this->t2 = array_map("parent::sChar", $this->t2); + $this->t3 = array_map("parent::sChar", $this->t3); + $this->deck = array_map("parent::sChar", $this->deck); + } + + + /** + * Indicates this is a stream cipher + * + * @return integer Returns Cipher::STREAM + */ + public function type() + { + return parent::STREAM; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/RC2.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/RC2.php new file mode 100644 index 0000000000..85f8584555 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/RC2.php @@ -0,0 +1,341 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements RC2 Encryption + * The key size must be a multiple of 8 bits, between 8-128 bits + * Most of this was implemented by reading the original RC2 + * C source code, and recreating it in PHP + * + * Resources used to implement this algorithm + * https://groups.google.com/forum/?fromgroups=#!msg/sci.crypt/m1UFiFMC89Y/cLyO5tr1g_MJ + * http://tools.ietf.org/html/rfc2268 + * http://www.ipa.go.jp/security/rfc/RFC2268EN.html + * http://www.umich.edu/~x509/ssleay/rrc2.html + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Cipher_RC2 extends Cipher +{ + /** @type integer BYTES_BLOCK The size of the block, in bytes */ + const BYTES_BLOCK = 8; // 64 bits + + // rc2 has a variable length key, between 1 - 128 bytes (8-1024 bits) + //const BYTES_KEY = 0; + + /** @type array $_sbox RC2's sBox, initialized in initTables() */ + private static $_sbox = array(); + + /** @type string $xkey The expanded key */ + private $xkey = ""; + + + /** + * Constructor + * + * @param string $key The key used for Encryption/Decryption + * @return void + */ + public function __construct($key) + { + // the key must be between 1 and 128 bytes, keys larger than + // 128 bytes are truncated in expandedKey() + $keylen = strlen($key); + if($keylen < 1) + { + $err = "Key size is $keylen bits, Key size must be between 1 and 128 bytes"; + trigger_error($err, E_USER_WARNING); + } + + // set the key + parent::__construct(PHP_Crypt::CIPHER_RC2, $key, $keylen); + + // set the block size + $this->blockSize(self::BYTES_BLOCK); + + // initialize the tables + $this->initTables(); + + // expand the key to 128 bytes + $this->expandKey(); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypt plain text data using RC2 + * + * @param string $text A 64 bit (8 byte) plain text string + * @return boolean Returns true + */ + public function encrypt(&$text) + { + $this->operation(parent::ENCRYPT); + + // split up the message and key into 4 16 bit parts (2 byte words), + // then convert each array element to an integer + $w = self::splitBytes($text); + $k = self::splitBytes($this->xkey); + $j = 0; // the key index + + for($i = 0; $i < 16; ++$i) + { + $j = $i * 4; + + /* This is where it gets ugly, RC2 relies on unsigned ints. PHP does + * not have a nice way to handle unsigned ints, so we have to rely on sprintf. + * To make RC2 compatible with mCrypt, I also forced everything to 32 bit + * When I test against mcrypt and the original rc2 C source, I get 32 bit + * results, even on a 64 bit platform + */ + + // 16 rounds of RC2's Mixing algorithm for each 2 byte 'word' as + // required by RC2 + $w[0] += parent::uInt($w[1] & ~$w[3]) + parent::uInt($w[2] & $w[3]) + $k[$j + 0]; + $w[0] = sprintf("%u", $w[0] << 1) + sprintf("%u", $w[0] >> 15 & 1); + $w[0] = parent::uInt32($w[0]); + + $w[1] += parent::uInt($w[2] & ~$w[0]) + parent::uInt($w[3] & $w[0]) + $k[$j + 1]; + $w[1] = parent::uInt($w[1] << 2) + parent::uInt($w[1] >> 14 & 3); + $w[1] = parent::uInt32($w[1]); + + $w[2] += parent::uInt($w[3] & ~$w[1]) + parent::uInt($w[0] & $w[1]) + $k[$j + 2]; + $w[2] = parent::uInt($w[2] << 3) + parent::uInt($w[2] >> 13 & 7); + $w[2] = parent::uInt32($w[2]); + + $w[3] += parent::uInt($w[0] & ~$w[2]) + parent::uInt($w[1] & $w[2]) + $k[$j + 3]; + $w[3] = parent::uInt($w[3] << 5) + parent::uInt($w[3] >> 11 & 31); + $w[3] = parent::uInt32($w[3]); + + // rounds 5 and 11 get rc2's Mash + if($i == 4 || $i == 10) + { + $w[0] += $k[$w[3] & 63]; + $w[1] += $k[$w[0] & 63]; + $w[2] += $k[$w[1] & 63]; + $w[3] += $k[$w[2] & 63]; + } + } + + /* truthfully, I am not clear why this is required. It was not mentioned + * in any of the documentation I read, however reading the original RC2 C + * source code, this was done and in order for me to get the + * correct results in PHP I needed to do this as well + */ + $max = count($w); + for($i = 0; $i < $max; ++$i) + { + $pos = $i * 2; + $text[$pos] = chr($w[$i]); + $text[$pos+1] = chr($w[$i] >> 8); + } + + return true; + } + + + /** + * Decrypt a RC2 encrypted string + * + * @param string $text A RC2 encrypted string + * @return boolean Returns true + */ + public function decrypt(&$text) + { + $this->operation(parent::DECRYPT); + + // first split up the message into four 16 bit parts (2 bytes), + // then convert each array element to an integer + $w = self::splitBytes($text); + $k = self::splitBytes($this->xkey); + $j = 0; // the key index + + for($i = 15; $i >= 0; --$i) + { + $j = $i * 4; + + /* This is where it gets ugly, RC2 relies on unsigned ints. PHP does + * not have a nice way to handle unsigned ints, so we have to rely on sprintf. + * To make RC2 compatible with mCrypt, I also forced everything to 32 bit + * When I test against mcrypt and the original rc2 C source, I get 32 bit + * results, even on a 64 bit platform + */ + + $w[3] &= 65535; + $w[3] = parent::uInt($w[3] << 11) + parent::uInt($w[3] >> 5); + $w[3] -= parent::uInt($w[0] & ~$w[2]) + parent::uInt($w[1] & $w[2]) + $k[$j + 3]; + $w[3] = parent::uInt32($w[3]); + + $w[2] &= 65535; + $w[2] = parent::uInt($w[2] << 13) + parent::uInt($w[2] >> 3); + $w[2] -= parent::uInt($w[3] & ~$w[1]) + parent::uInt($w[0] & $w[1]) + $k[$j + 2]; + $w[2] = parent::uInt32($w[2]); + + $w[1] &= 65535; + $w[1] = parent::uInt($w[1] << 14) + parent::uInt($w[1] >> 2); + $w[1] -= parent::uInt($w[2] & ~$w[0]) + parent::uInt($w[3] & $w[0]) + $k[$j + 1]; + $w[1] = parent::uInt32($w[1]); + + $w[0] &= 65535; + $w[0] = parent::uInt($w[0] << 15) + parent::uInt($w[0] >> 1); + $w[0] -= parent::uInt($w[1] & ~$w[3]) + parent::uInt($w[2] & $w[3]) + $k[$j + 0]; + $w[0] = parent::uInt32($w[0]); + + if($i == 5 || $i == 11) + { + $w[3] -= $k[$w[2] & 63]; + $w[2] -= $k[$w[1] & 63]; + $w[1] -= $k[$w[0] & 63]; + $w[0] -= $k[$w[3] & 63]; + } + } + + + /* I am not clear why this is required. It was not mentioned + * in any of the documentation I read, however reading the original RC2 C + * source code, this was done and in order for me to get the + * correct results in PHP I needed to do this as well + */ + $max = count($w); + for($i = 0; $i < $max; ++$i) + { + $pos = $i * 2; + $text[$pos] = chr($w[$i]); + $text[$pos+1] = chr($w[$i] >> 8); + } + + return true; + } + + + /** + * Splits an 8 byte string into four array elements of 2 bytes each, swaps the bytes + * of each array element, and converts the result into an integer + * + * @param string $str The 8 byte string to split and convert + * @return array An array of 4 elements, each with 2 bytes + */ + private static function splitBytes($str) + { + $arr = str_split($str, 2); + + return array_map(function($b){ + return Core::str2Dec($b[1].$b[0]); + }, $arr); + } + + + /** + * Expands the key to 128 bits. RC2 uses an initial key size between + * 8 - 128 bits, then takes the initial key and expands it out to 128 + * bits, which is used for encryption + * + * @return void + */ + private function expandKey() + { + // start by copying the key to the xkey variable + $this->xkey = $this->key(); + $len = $this->keySize(); + + // the max length of the key is 128 bytes + if($len > 128) + $this->xkey = substr($this->xkey, 0, 128); + + // now expanded the rest of the key to 128 bytes, using the sbox + for($i = $len; $i < 128; ++$i) + { + $byte1 = ord($this->xkey[$i - $len]); + $byte2 = ord($this->xkey[$i - 1]); + $pos = ($byte1 + $byte2); + + // the sbox is only 255 bytes, so if we extend past that + // we need to modulo 256 so we have a valid position + if($pos > 255) + $pos -= 256; + + $this->xkey .= chr(self::$_sbox[$pos]); + } + + // now replace the first byte of the key with it's position in the sbox + $pos = ord($this->xkey[0]); + $this->xkey[0] = chr(self::$_sbox[$pos]); + } + + + /** + * Initialize tables + * + * @return void + */ + private function initTables() + { + self::$_sbox = array( + 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, + 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, + 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32, + 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, + 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, + 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, + 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03, + 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, + 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, + 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec, + 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, + 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, + 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9, + 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, + 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, + 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad + ); + } + + + /** + * Indicates this is a block cipher + * + * @return integer Returns Cipher::BLOCK + */ + public function type() + { + return parent::BLOCK; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/Rijndael.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/Rijndael.php new file mode 100644 index 0000000000..08e0273133 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/Rijndael.php @@ -0,0 +1,1041 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../Cipher.php"); + + +/** + * Base class to implement Rijndael (and AES) + * This class can not be used directly, instead one + * one of the child classes that inherit this class + * should be used. + * References used to implement this cipher: + * http://www.net-security.org/dl/articles/AESbyExample.pdf + * http://www.quadibloc.com/crypto/co040401.htm + * http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors + * FIPS 197 (fips-197.pdf) + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +abstract class Cipher_Rijndael extends Cipher +{ + /** @type string $xkey The expanded key */ + private $xkey = ""; + + /** + * @type array $_key_sizes The accepted key sizes in bytes, + * this should be considered a constant + */ + private static $_key_sizes = array(16, 24, 32); + + + // THE FOLLOWING TABLES ARE INITIALIZED IN initTables() + + /** + * @type array $_s The sbox, + * this should be considered a constant + */ + private static $_s = array(); + + /** + * @type array $_s_inv The inverse sbox + * this should be considered a constant + */ + private static $_s_inv = array(); + + /** + * @type array $_rcon The round constant, + * this should be considered a constant + */ + private static $_rcon = array(); + + /** + * @type array $s_matrix_mult The matrix multiplication table, + * this should be considered a constant + */ + private static $_matrix_mult = array(); + + /** + * @type array $_matrix_mult_inv The matrix multiplication + * inverse table, this should be considered a constant + */ + private static $_matrix_mult_inv = array(); + + /* + * Galois Multiplication lookup tables, + * initialized in initTables() + */ + /** + * @type array $_gm2 The Galois Multiplication table + * for muliplying by 2, this should be considered a constant + */ + private static $_gm2 = array(); + + /** + * @type array $_gm3 The Galois Multiplication table + * for muliplying by 3, this should be considered a constant + */ + private static $_gm3 = array(); + + /** + * @type array $_gm9 The Galois Multiplication table + * for muliplying by 9, this should be considered a constant + */ + private static $_gm9 = array(); + + /** + * @type array $_gm11 The Galois Multiplication table + * for muliplying by 11, this should be considered a constant + */ + private static $_gm11 = array(); + + /** + * @type array $_gm13 The Galois Multiplication table + * for muliplying by 13, this should be considered a constant + */ + private static $_gm13 = array(); + + /** + * @type array $_gm14 The Galois Multiplication table + * for muliplying by 14, this should be considered a constant + */ + private static $_gm14 = array(); + + + /** + * Constructor + * Sets the key used for encryption. Also sets the requied block size + * + * @param string The cipher name as set in a constant in the child class + * @param string $key string containing the user supplied encryption key + * @param integer $len Optional, the key size in bytes - used only by the AES child classes + * @return void + */ + public function __construct($cipher_name, $key, $len = 0) + { + // AES will pass in a $len, since it has a fixed key size, other + // rijndael implementations can use variable key sizes, supported + // sizes are stored in self::$_key_sizes + if($len == 0) + { + // the key must be one of the following lengths: 16, 24, 32 bytes + $len = strlen($key); + if(!in_array($len, self::$_key_sizes)) + { + $msg = "Incorrect key length for ".strtoupper($cipher_name).". "; + $msg .= "Received $len bytes."; + trigger_error($msg, E_USER_WARNING); + } + } + + // Setup the key + parent::__construct($cipher_name, $key, $len); + + // initialize the tables used for rijndael/aes + $this->initTables(); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Performs Rijndael encryption + * + * @param string @text The string to encrypt + * @return boolean Returns true + */ + public function encrypt(&$text) + { + // set the operation to decryption + $this->operation(parent::ENCRYPT); + + $loops = 0; + $key_sz = $this->keySize(); + $blk_sz = $this->blockSize(); + + // if the key and block size is 16, do 10 rounds + // if the key or block size is 24, and neither is longer than 24, do 12 rounds + // if either key or block size is 32, do 14 rounds + if($key_sz == 16 && $blk_sz == 16) + $loops = 10; + else if(($key_sz == 24 || $blk_sz == 24) && $key_sz <= 24 && $blk_sz <= 24) + $loops = 12; + else if($key_sz == 32 || $blk_sz == 32) + $loops = 14; + + // now begin the encryption + $this->addRoundKey($text, 0); + + for($i = 1; $i <= $loops; ++$i) + { + $this->byteSub($text); + $this->shiftRow($text); + + // the last iteration does not use mixColumn + if($i < $loops) + $this->mixColumn($text); + + $this->addRoundKey($text, $i); + } + + return true; + } + + + /** + * Performs Rijndael decryption + * + * @param string @text The string to decrypt + * @return boolean Returns true + */ + public function decrypt(&$text) + { + // set the operation to decryption + $this->operation(parent::DECRYPT); + + $loops = 0; + $key_sz = $this->keySize(); + $blk_sz = $this->blockSize(); + + // if the key and block size is 16, do 10 rounds + // if the key or block size is 24, and neither is longer than 24, do 12 rounds + // if either key or block size is 32, do 14 rounds + if($key_sz == 16 && $blk_sz == 16) + $loops = 10; + else if(($key_sz == 24 || $blk_sz == 24) && $key_sz <= 24 && $blk_sz <= 24) + $loops = 12; + else if($key_sz == 32 || $blk_sz == 32) + $loops = 14; + + // now begin the decryption + $this->addRoundKey($text, 0); + + for($i = 1; $i <= $loops; ++$i) + { + $this->shiftRow($text); + $this->byteSub($text); + $this->addRoundKey($text, $i); + + // the last iteration does not use mixColumn + if($i < $loops) + $this->mixColumn($text); + } + + return true; + } + + + /** + * Indicates that this is a block cipher + * + * @return integer Returns Cipher::BLOCK + */ + public function type() + { + return parent::BLOCK; + } + + + /** + * Do the multiplication required in mixColumn() + * We follow the description the multiplication from Wikipedia: + * http://en.wikipedia.org/wiki/Advanced_Encryption_Standard#The_MixColumns_step + * + * @param integer $m A value from self::$_matrix_mult or self::$_matrix_mult_inv + * @param integer $byte The value to multipy by $m + * @return integer The result of the multiplication + */ + protected function mixColumnMultiply($m, $byte) + { + // if multiplying by 1, then we just return the same number + if($m == 0x01) + return $byte; + + $hex = parent::dec2Hex($byte); + $row = parent::hex2Dec($hex[0]); + $col = parent::hex2Dec($hex[1]); + $pos = ($row * 16) + $col; + + // multiply by 2 (comes from self::$_matrix_mult during encryption) + if($m == 0x02) + return self::$_gm2[$pos]; + + // multiply by 3 (comes from self::$_matrix_mult during encryption) + if($m == 0x03) + return self::$_gm3[$pos]; + + // multiply by 9 (comes from self::$_matrix_mult_inv during decryption) + if($m == 0x09) + return self::$_gm9[$pos]; + + // multiply by 11 (comes from self::$_matrix_mult_inv during decryption) + if($m == 0x0b) + return self::$_gm11[$pos]; + + // multiply by 13 (comes from self::$_matrix_mult_inv during decryption) + if($m == 0x0d) + return self::$_gm13[$pos]; + + // multiply by 14 (comes from self::$_matrix_mult_inv during decryption) + if($m == 0x0e) + return self::$_gm14[$pos]; + } + + + /** + * Each time this function is called, it XORs the 16 bytes of $text + * with the next 16 bytes from the $this->xkey. The expanded key + * never has the same bytes used twice. Note that the first time + * addRoundKey() is called, it will be outside of the rounds, so no + * $round is given. Every call after that will be inside the rounds. + * + * @param string $text The text to encrypt/decrypt + * @param integer $round The round we are on inside of rijndael() + * @return void + */ + private function addRoundKey(&$text, $round) + { + // length of the xkey + $ek_len = strlen($this->xkey); + $len = $this->blockSize(); + + if($this->operation() == parent::ENCRYPT) + $offset = $round * $len; + else + $offset = ($ek_len - ($round * $len)) - $len; + + for($i = 0; $i < $len; ++$i) + $text[$i] = $text[$i] ^ $this->xkey[$offset + $i]; + } + + + /** + * Applies the Sbox to each byte of the string passed in + * This is used in key expansione + * + * @param string $text The string to peform the byte subsitution + * @return void + */ + private function byteSub(&$text) + { + $max = strlen($text); + for($i = 0; $i < $max; ++$i) + { + // the sbox is arrange in a 16 x 16 grid, where each row + // and column is numbered in hex (from 0 - f) + $hex = parent::str2Hex($text[$i]); + $row = parent::hex2Dec($hex[0]); + $col = parent::hex2Dec($hex[1]); + $pos = ($row * 16) + $col; + + // return the corresponding value from the sbox + if($this->operation() == parent::ENCRYPT) + $text[$i] = chr(self::$_s[$pos]); + else // parent::DECRYPT uses the inverse sbox + $text[$i] = chr(self::$_s_inv[$pos]); + } + } + + + /** + * This function is hard to explain, the easiest way to understand it is to read + * http://www.net-security.org/dl/articles/AESbyExample.pdf, Section 5.4 + * + * @param string $t The string to multiply bytes by the Galois Multiplication lookup tables + * @return void + */ + private function mixColumn(&$t) + { + $tmp = $t; + + // the matrix we use depends on if we are encrypting or decrypting + if($this->operation() == parent::ENCRYPT) + $m = self::$_matrix_mult; + else // parent::DECRYPT + $m = self::$_matrix_mult_inv; + + // the number of rounds we make depends on the block size of the text + // used during encryption/decryption + // 128 has a 4x4 matrix, loop 4 times + // 192 has a 4x6 matrix, loop 6 times + // 256 has a 4x8 matrix, loop 8 times + $max_col = ($this->blockSize() * 8) / 32; + + // loop through each column of the matrix + for($col = 0; $col < $max_col; ++$col) + { + $pos = $col * 4; + + $a = $this->mixColumnMultiply($m[0], ord($tmp[$pos + 0])); + $b = $this->mixColumnMultiply($m[4], ord($tmp[$pos + 1])); + $c = $this->mixColumnMultiply($m[8], ord($tmp[$pos + 2])); + $d = $this->mixColumnMultiply($m[12], ord($tmp[$pos + 3])); + $t[$pos + 0] = chr($a ^ $b ^ $c ^ $d); + + $a = $this->mixColumnMultiply($m[1], ord($tmp[$pos + 0])); + $b = $this->mixColumnMultiply($m[5], ord($tmp[$pos + 1])); + $c = $this->mixColumnMultiply($m[9], ord($tmp[$pos + 2])); + $d = $this->mixColumnMultiply($m[13], ord($tmp[$pos + 3])); + $t[$pos + 1] = chr($a ^ $b ^ $c ^ $d); + + $a = $this->mixColumnMultiply($m[2], ord($tmp[$pos + 0])); + $b = $this->mixColumnMultiply($m[6], ord($tmp[$pos + 1])); + $c = $this->mixColumnMultiply($m[10], ord($tmp[$pos + 2])); + $d = $this->mixColumnMultiply($m[14], ord($tmp[$pos + 3])); + $t[$pos + 2] = chr($a ^ $b ^ $c ^ $d); + + $a = $this->mixColumnMultiply($m[3], ord($tmp[$pos + 0])); + $b = $this->mixColumnMultiply($m[7], ord($tmp[$pos + 1])); + $c = $this->mixColumnMultiply($m[11], ord($tmp[$pos + 2])); + $d = $this->mixColumnMultiply($m[15], ord($tmp[$pos + 3])); + $t[$pos + 3] = chr($a ^ $b ^ $c ^ $d); + } + } + + + /** + * Convert the 16, 24, or 32 bytes of $text into a matrix, and shift each row + * n-bytes left for encryptiong, n-bytes right if we are decrypting. + * Row shifts depend on the bit size of the block $text. + * Rijndael-128/AES: 4x4 matrix + * Rijndael-192: 6x4 matrix + * Rijndael-256: 8x4 matrix + * + * @param string $text A 16, 24, or 32 byte string + * @return void + */ + private function shiftRow(&$text) + { + /* + * Rijndael-128 / AES + */ + if($this->blockSize() == 16) + { + if($this->operation() == parent::ENCRYPT) + { + // create a 4x4 matrix + // row 0 is unchanged, + // shift row 1 left 1 byte + // shift row 2 left 2 bytes + // shift row 3 left 3 bytes + $text = $text[0].$text[5].$text[10].$text[15].$text[4].$text[9]. + $text[14].$text[3].$text[8].$text[13].$text[2].$text[7]. + $text[12].$text[1].$text[6].$text[11]; + } + else // parent::DECRYPT + { + // create a 4x4 matrix + // row 0 is unchanged, + // shift row 1 right 1 byte + // shift row 2 right 2 bytes + // shift row 3 right 3 bytes + $text = $text[0].$text[13].$text[10].$text[7].$text[4].$text[1]. + $text[14].$text[11].$text[8].$text[5].$text[2].$text[15]. + $text[12].$text[9].$text[6].$text[3]; + } + } + + /* + * Rijndael-192 + */ + if($this->blockSize() == 24) + { + if($this->operation() == parent::ENCRYPT) + { + // create a 6x4 matrix + // row 0 is unchanged + // shift row 1 left 1 byte + // shift row 2 left 2 bytes + // shift row 3 left 3 bytes + $text = $text[0].$text[5].$text[10].$text[15].$text[4].$text[9]. + $text[14].$text[19].$text[8].$text[13].$text[18].$text[23]. + $text[12].$text[17].$text[22].$text[3].$text[16].$text[21]. + $text[2].$text[7].$text[20].$text[1].$text[6].$text[11]; + + } + else // parent::DECRYPT + { + // create a 6x4 matrix + // row 0 is unchanged + // shift row 1 right 1 byte + // shift row 2 right 2 bytes + // shift row 3 right 3 bytes + $text = $text[0].$text[21].$text[18].$text[15].$text[4].$text[1]. + $text[22].$text[19].$text[8].$text[5].$text[2].$text[23]. + $text[12].$text[9].$text[6].$text[3].$text[16].$text[13]. + $text[10].$text[7].$text[20].$text[17].$text[14].$text[11]; + } + } + + /* + * Rijndael-256 + */ + if($this->blockSize() == 32) + { + if($this->operation() == parent::ENCRYPT) + { + // create an 8x4 matrix + // row 0 is unchanged + // shift row 1 left 1 byte + // shift row 2 left 3 bytes + // shift row 3 left 4 bytes + $text = $text[0].$text[5].$text[14].$text[19].$text[4].$text[9].$text[18]. + $text[23].$text[8].$text[13].$text[22].$text[27].$text[12].$text[17]. + $text[26].$text[31].$text[16].$text[21].$text[30].$text[3].$text[20]. + $text[25].$text[2].$text[7].$text[24].$text[29].$text[6].$text[11]. + $text[28].$text[1].$text[10].$text[15]; + } + else // parent::DECRYPT + { + // create an 8x4 matrix + // row 0 is unchanged + // shift row 1 right 1 byte + // shift row 2 right 3 bytes + // shift row 3 right 4 bytes + $text = $text[0].$text[29].$text[22].$text[19].$text[4].$text[1].$text[26]. + $text[23].$text[8].$text[5].$text[30].$text[27].$text[12].$text[9]. + $text[2].$text[31].$text[16].$text[13].$text[6].$text[3].$text[20]. + $text[17].$text[10].$text[7].$text[24].$text[21].$text[14].$text[11]. + $text[28].$text[25].$text[18].$text[15]; + } + } + } + + + /** + * Applies the Sbox to each byte of the string passed in. + * This is similar to subByte(), but Unlike subByte() we do not use + * the _s_inv[] table. This function is only used in expandKey(), + * which is implemented by the class that inherits this class + * + * @param string $text The string to peform the byte subsitution + * @return string The string with the subsituted bytes + */ + private function subWord(&$text) + { + $max = strlen($text); + for($i = 0; $i < $max; ++$i) + { + // the sbox is arrange in a 16 x 16 grid, where each row + // and column is numbered in hex (from 0 - f) + $hex = parent::str2Hex($text[$i]); + $row = parent::hex2Dec($hex[0]); + $col = parent::hex2Dec($hex[1]); + $pos = ($row * 16) + $col; + + $text[$i] = chr(self::$_s[$pos]); + } + } + + + /** + * Rotate a 4 byte block of the key, moving the first byte to + * to the end, and shifting everything left + * Used in key Expandsion + * + * @param string $key_block A 4 byte string + * @return string The shifted 4 byte string + */ + private function rotWord($key_block) + { + return substr($key_block, 1, 3).$key_block[0]; + } + + + /** + * Returns 4 bytes from the expanded key starting at the given offset + * Used during expandKey() + * + * @param integer $offset The offset within $this->xkey to grab the 4 bytes + * @return string A 4 byte string from the key + */ + private function ek($offset) + { + return substr($this->xkey, $offset, 4); + } + + + /** + * Returns 4 bytes of the original key from the given offset + * Used during expandKey() + * + * @param integer $offset The offset within $this->key to grab the 4 bytes + * @return string A 4 byte string from the key + */ + private function k($offset) + { + return substr($this->key(), $offset, 4); + } + + + /** + * Return the 4 byte round constant used during expandKey(). + * Gets the 1 byte value from self::$_rcon and multiplies it by + * 0x01000000 to create a 4 byte value + * + * @param integer $pos The position in self::$_rcon array to grab 1 byte + * @return integer A 4 byte value + */ + private function rcon($pos) + { + return (self::$_rcon[$pos] * 0x01000000); + } + + + /** + * Expands the key + * The key expands based on the block size as well as the key size + * + * @return void + */ + protected function expandKey() + { + if($this->keySize() == 16) + return $this->expandKey128(); + else if($this->keySize() == 24) + return $this->expandKey192(); + else if($this->keySize() == 32) + return $this->expandKey256(); + } + + + /** + * Expand a 16 byte key, the size it is expanded to varies + * based on the block size of the Rijndael implementation chosen + * + * @return void + */ + private function expandKey128() + { + // clear the xkey, we're creating a new one + $this->xkey = ""; + $max = 0; + + // the number of rounds we make depends on the block size of the text + // used during encryption/decryption + if($this->blockSize() == 16) + $max = 44; + if($this->blockSize() == 24) + $max = 78; + if($this->blockSize() == 32) + $max = 120; + + // 16 byte key expands to 176 bytes + for($i = 0; $i < $max; ++$i) + { + if($i >= 0 && $i <= 3) + $this->xkey .= $this->k($i * 4); + else if(($i % 4) == 0) + { + // rotate the 4 bytes + $subword = $this->rotWord($this->ek(($i - 1) * 4)); + + // apply the sbox + $this->subWord($subword); + + // return 4 byte value based on self::$_rcon table + //$rcon = $this->rcon(($i / 4) - 1); + $rcon = $this->rcon(($i / 4)); + + // grab 4 bytes from $this->extended_key + $ek = $this->ek(($i - 4) * 4); + + $h1 = parent::str2Hex($subword); + $h2 = parent::dec2Hex($rcon); + $h3 = parent::str2Hex($ek); + $res = parent::xorHex($h1, $h2, $h3); + $this->xkey .= parent::hex2Str($res); + } + else + { + $h1 = parent::str2Hex($this->ek(($i - 1) * 4)); + $h2 = parent::str2Hex($this->ek(($i - 4) * 4)); + $res = parent::xorHex($h1, $h2); + $this->xkey .= parent::hex2Str($res); + } + } + + return true; + } + + + /** + * Expand a 24 byte key, the size it is expanded to varies + * based on the block size of the Rijndael implementation chosen + * + * @return void + */ + private function expandKey192() + { + // clear the xkey, we're creating a new one + $this->xkey = ""; + $max = 0; + + // the number of rounds we make depends on the block size of the text + // used during encryption/decryption + if($this->blockSize() == 16) + $max = 52; + if($this->blockSize() == 24) + $max = 78; + if($this->blockSize() == 32) + $max = 120; + + // 24 byte key expands to 208 bytes + for($i = 0; $i < $max; ++$i) + { + if($i >= 0 && $i <= 5) + $this->xkey .= $this->k($i * 4); + else if(($i % 6) == 0) + { + // rotate the 4 bytes + $subword = $this->rotWord($this->ek(($i - 1) * 4)); + + // apply the sbox + $this->subWord($subword); + + // return 4 byte value based on self::$_rcon table + //$rcon = $this->rcon(($i / 6) - 1); + $rcon = $this->rcon(($i / 6)); + + // grab 4 bytes from $this->extended_key + $ek = $this->ek(($i - 6) * 4); + + $h1 = parent::str2Hex($subword); + $h2 = parent::dec2Hex($rcon); + $h3 = parent::str2Hex($ek); + $res = parent::xorHex($h1, $h2, $h3); + $this->xkey .= parent::hex2Str($res); + } + else + { + $h1 = parent::str2Hex($this->ek(($i - 1) * 4)); + $h2 = parent::str2Hex($this->ek(($i - 6) * 4)); + $res = parent::xorHex($h1, $h2); + $this->xkey .= parent::hex2Str($res); + } + } + + return true; + } + + + /** + * Expand a 32 byte key, the size it is expanded to varies + * based on the block size of the Rijndael implementation chosen + * + * @return void + */ + private function expandKey256() + { + // clear the xkey, we're creating a new one + $this->xkey = ""; + $max = 0; + + // the number of rounds we make depends on the block size of the text + // used during encryption/decryption + if($this->blockSize() == 16) + $max = 60; + if($this->blockSize() == 24) + $max = 90; + if($this->blockSize() == 32) + $max = 120; + + // 32 byte key expands to 240 bytes + for($i = 0; $i < $max; ++$i) + { + if($i >= 0 && $i <= 7) + $this->xkey .= $this->k($i * 4); + else if($i % 8 == 0) + { + // rotate the 4 bytes + $subword = $this->rotWord($this->ek(($i - 1) * 4)); + + // apply the sbox + $this->subWord($subword); + + // return 4 byte value based on self::$_rcon table + $rcon = $this->rcon(($i / 8)); + + // grab 4 bytes from $this->extended_key + $ek = $this->ek(($i - 8) * 4); + + $h1 = parent::str2Hex($subword); + $h2 = parent::dec2Hex($rcon); + $h3 = parent::str2Hex($ek); + $res = parent::xorHex($h1, $h2, $h3); + $this->xkey .= parent::hex2Str($res); + } + else if($i % 4 == 0) + { + // get the subsitution from the s-box + $subword = $this->ek(($i - 1) * 4); + $this->subWord($subword); + + // get the extended key part + $ek = $this->ek(($i - 8) * 4); + + // xor the two parts + $h1 = parent::str2Hex($subword); + $h2 = parent::str2Hex($ek); + $res = parent::xorHex($h1, $h2); + $this->xkey .= parent::hex2Str($res); + } + else + { + $h1 = parent::str2Hex($this->ek(($i - 1) * 4)); + $h2 = parent::str2Hex($this->ek(($i - 8) * 4)); + $res = parent::xorHex($h1, $h2); + $this->xkey .= parent::hex2Str($res); + } + } + + return true; + } + + + /** + * Initalizes the tables used for Rijndael/AES encryption + * + * @return void + */ + private function initTables() + { + // the sbox used for encryption + self::$_s = array( + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 + ); + + // the inverse sbox used for decryption + self::$_s_inv = array( + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d + ); + + // used in mixColumn() during encryption + self::$_matrix_mult = array( + 0x02, 0x01, 0x01, 0x03, + 0x03, 0x02, 0x01, 0x01, + 0x01, 0x03, 0x02, 0x01, + 0x01, 0x01, 0x03, 0x02 + ); + + // used in mixColumn() during decryption + self::$_matrix_mult_inv = array( + 0x0e, 0x09, 0x0d, 0x0b, + 0x0b, 0x0e, 0x09, 0x0d, + 0x0d, 0x0b, 0x0e, 0x09, + 0x09, 0x0d, 0x0b, 0x0e + ); + + // The round constants, each round is a 1 byte value which should be multiplied by 0x01000000 + // to create a 4 byte value before being used in expandKey(). This is done in rcon() + // NOTE: AES only needs the first row of values, since AES only uses 16 byte blocks, + // the other values are used for larger block/key combinations supported by Rijndael + // NOTE: self::$_rcon[0] is never used + self::$_rcon = array( + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, + 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, + 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, + 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, + 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, + 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, + 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, + 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, + 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, + 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, + 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, + 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, + 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, + 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d + ); + + /* + * Galois Multiplication lookup tables + * See http://en.wikipedia.org/wiki/Rijndael_mix_columns#InverseMixColumns + */ + + // multiply a byte by 2 (the value 2 will come from self::$_matrix_mult) + self::$_gm2 = array( + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, + 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, + 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, + 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, + 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, + 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, + 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, + 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, + 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, + 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, + 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, + 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, + 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, + 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, + 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, + 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5 + ); + + // multiply a byte by 3 (the value 3 will come from self::$_matrix_mult) + self::$_gm3 = array( + 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11, + 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, + 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, + 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41, + 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, + 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1, + 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1, + 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, + 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a, + 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba, + 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea, + 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda, + 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a, + 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a, + 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a, + 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a + ); + + // multiply a byte by 9 (the value 9 will come from self::$_matrix_mult_inv) + self::$_gm9 = array( + 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, + 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, + 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, + 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, + 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, + 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, + 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, + 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, + 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, + 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, + 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, + 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, + 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, + 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, + 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, + 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46 + ); + + // multiply a byte by 11 (the value 11 will come from self::$_matrix_mult_inv) + self::$_gm11 = array( + 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, + 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, + 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, + 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, + 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, + 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, + 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, + 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, + 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, + 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, + 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, + 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, + 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, + 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, + 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, + 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3 + ); + + // multiply a byte by 13 (the value 13 will come from self::$_matrix_mult_inv) + self::$_gm13 = array( + 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, + 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, + 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, + 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, + 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, + 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, + 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, + 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, + 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, + 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, + 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, + 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, + 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, + 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, + 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, + 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97 + ); + + // multiply a byte by 14 (the value 14 will come from self::$_matrix_mult_inv) + self::$_gm14 = array( + 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, + 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, + 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, + 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, + 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, + 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, + 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, + 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, + 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, + 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, + 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, + 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, + 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, + 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, + 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, + 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d + ); + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/Rijndael128.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/Rijndael128.php new file mode 100644 index 0000000000..8b0bfe0ebb --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/Rijndael128.php @@ -0,0 +1,98 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/Rijndael.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implement Rijndael with a 16 bytes (128 bits) data block + * Key sizes can be 16, 24, 32 bytes (128, 192, 256 bits) + * References used to implement this cipher: + * http://www.net-security.org/dl/articles/AESbyExample.pdf + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Cipher_Rijndael_128 extends Cipher_Rijndael +{ + /** @type integer BITS_BLOCK The size of the block, in bits */ + const BYTES_BLOCK = 16; + + //const BITS_KEY = 0; + + + /** + * Constructor + * Sets the key used for encryption. Also sets the requied block size + * This should only be used when calling this class directly, for classes + * that extend this class, they should call __construct1() + * + * @param string $key string containing the user supplied encryption key + * @return void + */ + public function __construct($key) + { + // Set up the key + parent::__construct(PHP_Crypt::CIPHER_RIJNDAEL_128, $key); + + // required block size in bits + $this->blockSize(self::BYTES_BLOCK); + + // expand the key + $this->expandKey(); + } + + + /** + * Constructor, used only by classes that extend this class + * + * @param string $cipher_name The pre-defined cipher name of the child class + * @param string $key The key used for encryption/decryption + * @param integer $req_key_len The required key length, in bits + * @return void + */ + protected function __construct1($cipher_name, $key, $req_key_len) + { + parent::__construct($cipher_name, $key, $req_key_len); + + // required block size in bits + $this->blockSize(self::BYTES_BLOCK); + + // expand the key + $this->expandKey(); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } +} \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/Rijndael192.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/Rijndael192.php new file mode 100644 index 0000000000..4d65fc3fba --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/Rijndael192.php @@ -0,0 +1,76 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/Rijndael.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implement Rijndael with a 192 bit data block + * Key sizes can be 128, 192, or 256 + * References used to implement this cipher: + * http://www.net-security.org/dl/articles/AESbyExample.pdf + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Cipher_Rijndael_192 extends Cipher_Rijndael +{ + /** @type integer BYTES_BLOCK The size of the block, in bytes */ + const BYTES_BLOCK = 24; // 192 bits + + //const BITS_KEY = 0; + + + /** + * Constructor + * Sets the key used for encryption. Also sets the requied block size + * + * @param string $key string containing the user supplied encryption key + * @return void + */ + public function __construct($key) + { + // Set up the key + parent::__construct(PHP_CRYPT::CIPHER_RIJNDAEL_192, $key); + + // required block size in bits + $this->blockSize(self::BYTES_BLOCK); + + // expand the key now that we know the key size, and the bit size + $this->expandKey(); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } +} \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/Rijndael256.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/Rijndael256.php new file mode 100644 index 0000000000..4487e069b4 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/Rijndael256.php @@ -0,0 +1,76 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/Rijndael.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implement Rijndael with a 256 bit data block + * Key sizes can be 128, 192, or 256 + * References used to implement this cipher: + * http://www.net-security.org/dl/articles/AESbyExample.pdf + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Cipher_Rijndael_256 extends Cipher_Rijndael +{ + /** @type integer BYTES_BLOCK The size of the block, in bytes */ + const BYTES_BLOCK = 32; // 256 bits + + //const BITS_KEY = 0; + + + /** + * Constructor + * Sets the key used for encryption. Also sets the requied block size + * + * @param string $key string containing the user supplied encryption key + * @return void + */ + public function __construct($key) + { + // Set up the key + parent::__construct(PHP_Crypt::CIPHER_RIJNDAEL_256, $key); + + // required block size in bits + $this->blockSize(self::BYTES_BLOCK); + + // expand the key now that we know the key size, and the bit size + $this->expandKey(); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } +} \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/SimpleXOR.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/SimpleXOR.php new file mode 100644 index 0000000000..157195fbea --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/SimpleXOR.php @@ -0,0 +1,145 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * An example class that implements a simple Exclusive OR (XOR) encryption + * cipher using the user supplied key. + * + * A SimpleXOR cipher is the same as a One Time Pad when the key length + * is the same as the data length, and the key is changed after every round + * of encryption. + * + * XOR encryption is very difficult to break, however it can be susceptible + * to patterns. Thus it is not recommended to use this Cipher for very + * sensitive data, instead use one of the more secure ciphers (AES, 3DES, + * Blowfish, etc) + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2005 Ryan Gilfether + */ +class Cipher_Simple_XOR extends Cipher +{ + /** @type integer BYTES_BLOCK The size of the block, in bytes */ + const BYTES_BLOCK = 1; // 8 bits + + + /** + * Constructor + * Sets the key used for encryption. Also sets the requied block size + * + * @param string $key string containing the user supplied encryption key + * @return void + */ + public function __construct($key) + { + // SimpleXOR does not have a key size requirement + parent::__construct(PHP_Crypt::CIPHER_SIMPLEXOR, $key); + + // required block size in bits + $this->blockSize(self::BYTES_BLOCK); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypts data using an XOR encryption scheme + * + * @param string $text A string to encrypt + * @return boolean Always returns true + */ + public function encrypt(&$text) + { + $this->operation(parent::ENCRYPT); + return $this->simpleXOR($text); + } + + + /** + * Decrypts data encrypted with SimpleXOR::Encrypt() + * + * @param string $text An encrypted string to decrypt + * @return boolean Always returns true + */ + public function decrypt(&$text) + { + $this->operation(parent::DECRYPT); + return $this->simpleXOR($text); + } + + + /** + * Because XOR Encryption uses the same algorithm to encrypt and decrypt, + * this function contains the code to do both. The SimpleXOR::Encrypt() + * and SimpleXOR::Decrypt() function above just call this function + * + * @param string $input + * @return boolean Always returns true + */ + private function simpleXOR(&$text) + { + $pos = 0; + $max = strlen($text); + $key = $this->key(); + + for($i = 0; $i < $max; ++$i) + { + // if the current position in the key reaches the end of the key, + // start over at position 0 of the key + if($pos >= $this->keySize()) + $pos = 0; + + $text[$i] = $text[$i] ^ $key[$pos]; + ++$pos; + } + + return true; + } + + + /** + * Indicates that this is stream cipher + * + * @return integer Returns Cipher::STREAM + */ + public function type() + { + return parent::STREAM; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/Skipjack.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/Skipjack.php new file mode 100644 index 0000000000..8c9bc842bf --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/Skipjack.php @@ -0,0 +1,391 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements Skipjack Encryption + * Resources used to implement this algorithm: + * csrc.nist.gov/groups/ST/toolkit/documents/skipjack/skipjack.pdf + * http://calccrypto.wikidot.com/algorithms:skipjack + * http://www.quadibloc.com/crypto/co040303.htm + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Cipher_Skipjack extends Cipher +{ + /** @type integer BYTES_BLOCK The size of the block, in bytes */ + const BYTES_BLOCK = 8; // 64 bits + + /** @type integer BYTES_KEY The size of the key, in bytes */ + const BYTES_KEY = 10; // 80 bits + + /** @type string $expanded_key The expanded key */ + private $expanded_key = ""; + + /** @type array $_f The Skipjack F-Table, this is a constant */ + private static $_f = array(); + + + /** + * Constructor + * + * @param string $key The key used for Encryption/Decryption + * @return void + */ + public function __construct($key) + { + // set the Skipjack key + parent::__construct(PHP_Crypt::CIPHER_SKIPJACK, $key, self::BYTES_KEY); + + // initialize variables + $this->initTables(); + + // set the block size used + $this->blockSize(self::BYTES_BLOCK); + + // expand the key from 10 bytes to 128 bytes + $this->expandKey(); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypt plain text data using Skipjack + * + * @param string $data A plain text string, 8 bytes long + * @return boolean Returns true + */ + public function encrypt(&$text) + { + $this->operation(parent::ENCRYPT); + + for($i = 1; $i <= 32; ++$i) + { + $pos = (4 * $i) - 4; + $subkey = substr($this->expanded_key, $pos, 4); + + if($i >= 1 && $i <= 8) + $this->ruleA($text, $subkey, $i); + + if($i >= 9 && $i <= 16) + $this->ruleB($text, $subkey, $i); + + if($i >= 17 && $i <= 24) + $this->ruleA($text, $subkey, $i); + + if($i >= 25 && $i <= 32) + $this->ruleB($text, $subkey, $i); + } + + return true; + } + + + /** + * Decrypt a Skipjack encrypted string + * + * @param string $encrypted A Skipjack encrypted string, 8 bytes long + * @return boolean Returns true + */ + public function decrypt(&$text) + { + $this->operation(parent::DECRYPT); + + for($i = 32; $i >= 1; --$i) + { + $pos = ($i - 1) * 4; + $subkey = substr($this->expanded_key, $pos, 4); + + if($i <= 32 && $i >= 25) + $this->ruleB($text, $subkey, $i); + + if($i <= 24 && $i >= 17) + $this->ruleA($text, $subkey, $i); + + if($i <= 16 && $i >= 9) + $this->ruleB($text, $subkey, $i); + + if($i <= 8 && $i >= 1) + $this->ruleA($text, $subkey, $i); + } + + return true; + } + + + /** + * For the G Permutations, the input data is 2 Bytes The first byte is + * the left side and the second is the right side.The round key is 4 bytes + * long (Indices 8*i-8 to 8*i), which is split as 4 pieces: K0, K1, K2, K3 + * + * @param string $bytes A 2 byte string + * @param string $key 4 bytes of $this->expanded_key + * @return string A 2 byte string, the G Permutation of $bytes + */ + private function gPermutation($bytes, $key) + { + $left = ord($bytes[0]); + $right = ord($bytes[1]); + + if($this->operation() == parent::ENCRYPT) + { + for($i = 0; $i < 4; ++$i) + { + if($i == 0 || $i == 2) + { + $pos = $right ^ $this->str2Dec($key[$i]); + $left = $left ^ self::$_f[$pos]; + } + else + { + $pos = $left ^ $this->str2Dec($key[$i]); + $right = $right ^ self::$_f[$pos]; + } + } + } + else // parent::DECRYPT + { + // we do the same as in encryption, but apply the key backwards, + // from key[3] to key[0] + for($i = 3; $i >= 0; --$i) + { + if($i == 0 || $i == 2) + { + $pos = $right ^ $this->str2Dec($key[$i]); + $left = $left ^ self::$_f[$pos]; + } + else + { + $pos = $left ^ $this->str2Dec($key[$i]); + $right = $right ^ self::$_f[$pos]; + } + } + } + + return $this->dec2Str($left).$this->dec2Str($right); + } + + + /** + * Perform SkipJacks RuleA function. Split the data into 4 parts, + * 2 bytes each: W0, W1, W2, W3. + * + * @param string $bytes An 8 byte string + * @param string $key 4 bytes of $this->expanded_key + * @param integer $i The round number + * @return void + */ + private function ruleA(&$bytes, $key, $i) + { + $w = str_split($bytes, 2); + + if($this->operation() == parent::ENCRYPT) + { + /* + * Set the W3 as the old W2 + * Set the W2 as the old W1 + * Set the W1 as the G(W0) + * Set the W0 as the W1 xor W4 xor i + */ + + $w[4] = $w[3]; + $w[3] = $w[2]; + $w[2] = $w[1]; + $w[1] = $this->gPermutation($w[0], $key); + + $hex1 = $this->str2Hex($w[1]); + $hex4 = $this->str2Hex($w[4]); + $hexi = $this->dec2Hex($i); + $w[0] = $this->xorHex($hex1, $hex4, $hexi); + $w[0] = $this->hex2Str($w[0]); + } + else // parent::DECRYPT + { + /* + * Set W4 as W0 xor W1 xor i + * Set W0 as Inverse G(W1) + * Set W1 as the old W2 + * Set W2 as the old W3 + * Set W3 as W4 + */ + + $hex0 = $this->str2Hex($w[0]); + $hex1 = $this->str2Hex($w[1]); + $hexi = $this->dec2Hex($i); + $w[4] = $this->xorHex($hex0, $hex1, $hexi); + $w[4] = $this->hex2Str($w[4]); + + $w[0] = $this->gPermutation($w[1], $key); + $w[1] = $w[2]; + $w[2] = $w[3]; + $w[3] = $w[4]; + } + + // glue all the pieces back together + $bytes = $w[0].$w[1].$w[2].$w[3]; + } + + + /** + * Perform SkipJacks RuleB function. Split the data into 4 parts, + * 2 bytes each: W0, W1, W2, W3. + * + * @param string $bytes An 8 bytes string + * @param string $key 4 bytes of $this->expanded_key + * @param integer $i The round number + * @return void + */ + private function ruleB(&$bytes, $key, $i) + { + $w = str_split($bytes, 2); + + if($this->operation() == parent::ENCRYPT) + { + /* + * Set the new W3 as the old W2 + * Set the new W2 as the old W0 xor old W1 xor i + * Set the new W1 as G(old W0) + * Set the new W0 as the old W3 + */ + + $w[4] = $w[3]; + $w[3] = $w[2]; + + $hex0 = $this->str2Hex($w[0]); + $hex1 = $this->str2Hex($w[1]); + $hexi = $this->dec2Hex($i); + $w[2] = $this->xorHex($hex0, $hex1, $hexi); + $w[2] = $this->hex2Str($w[2]); + + $w[1] = $this->gPermutation($w[0], $key); + $w[0] = $w[4]; + } + else // parent::DECRYPT + { + /* + * Set W4 as the old W0 + * Set new W0 as Inverse G(old W1) + * Set new W1 as Inverse G(old W1) xor old W2 xor i + * Set new W2 as the old W3 + * Set new W0 as the old W4 + */ + + $w[4] = $w[0]; + $w[0] = $this->gPermutation($w[1], $key); + + $hex0 = $this->str2Hex($w[0]); + $hex2 = $this->str2Hex($w[2]); + $hexi = $this->dec2Hex($i); + $w[1] = $this->xorHex($hex0, $hex2, $hexi); + $w[1] = $this->hex2Str($w[1]); + + $w[2] = $w[3]; + $w[3] = $w[4]; + } + + $bytes = $w[0].$w[1].$w[2].$w[3]; + } + + + /** + * Expands the key from 10 bytes, to 128 bytes + * This is done by copying the key 1 byte at a time and + * appending it to $this->expanded_key, when we reach the + * end of the key, we start over at position 0 and continue + * until we reach 128 bytes + * + * @return void + */ + private function expandKey() + { + $this->expanded_key = ""; + $key_bytes = $this->keySize(); + $key = $this->key(); + $pos = 0; + + for($i = 0; $i < 128; ++$i) + { + if($pos == $key_bytes) + $pos = 0; + + $this->expanded_key .= $key[$pos]; + ++$pos; + } + } + + + /** + * Initialize all the tables, this function is called inside the constructor + * + * @return void + */ + private function initTables() + { + self::$_f = array( + 0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4, 0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9, + 0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e, 0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28, + 0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68, 0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53, + 0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19, 0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2, + 0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b, 0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8, + 0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0, 0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90, + 0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69, 0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76, + 0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20, 0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d, + 0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43, 0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18, + 0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa, 0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4, + 0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87, 0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40, + 0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b, 0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5, + 0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0, 0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2, + 0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1, 0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8, + 0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5, 0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac, + 0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3, 0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46 + ); + } + + + /** + * Indicates that this is a block cipher + * + * @return integer Returns Cipher::BLOCK + */ + public function type() + { + return parent::BLOCK; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/ciphers/Vigenere.php b/plugin/advancedsubscription/resources/phpcrypt/ciphers/Vigenere.php new file mode 100644 index 0000000000..0718fbf92a --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/ciphers/Vigenere.php @@ -0,0 +1,249 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements the Vigenere Cipher + * The Vigenere Cipher encrypts alphabetic text using a series of + * different Caesar ciphers based on letters of a keyword. + * This cipher was first described in 1553 in the book + * "La cifra del. Sig. Giovan Battista Bellaso". This cipher + * is intended only for use for fun or for historical purposes and + * is not secure by modern standards. Only works with ASCII. + * + * Resources used to implement this algorithm: + * http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Cipher_Vigenere extends Cipher +{ + /** @type array $_vtable The Vigenere table */ + private static $_vtable = null; + + + /** + * Constructor + * + * @param string $key The key used for Encryption/Decryption + * @return void + */ + public function __construct($key) + { + // set the key + parent::__construct(PHP_Crypt::CIPHER_VIGENERE, $key); + + $this->initTables(); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypt plain text data using Vigenere cipher + * + * @param string $data A plain text string + * @return boolean Returns true + */ + public function encrypt(&$text) + { + $this->operation(parent::ENCRYPT); + + // convert to uppercase, and remove any non alphabetic characters + $text = strtoupper($text); + $text = preg_replace("/[^A-Z]/", "", $text); + $len = strlen($text); + + // prepare the key for the cipher + $this->keyPrep($len); + + // loop through each letter of the message + for($i = 0; $i < $len; ++$i) + { + // get the Cipher letter from the Vigenere table, using the + // current letter from the key as the row, and the current letter + // from the text, as the column, subtract 65 because ascii upper case + // letters start at 65 + $row = ord($this->expanded_key[$i]) - 65; + $col = ord($text[$i]) - 65; + $pos = ($row * 26) + $col; + + // convert the plain text to cipher text + $text[$i] = self::$_vtable[$pos]; + } + + return true; + } + + + /** + * Decrypt a Vigenere encrypted string + * + * @param string $encrypted A Vigenere encrypted string + * @return boolean Returns true + */ + public function decrypt(&$text) + { + $this->operation(parent::DECRYPT); + + // ensure the cipher text is all uppercase + $text = strtoupper($text); + $len = strlen($text); + + // prepare the key for the cipher + $this->keyPrep($len); + + // go to the row corresponding to the letter from the key + for($i = 0; $i < $len; ++$i) + { + // find the row from the current character of the key, we subtract 65 + // because uppercase letters start at ASCII 65 + $row = (ord($this->expanded_key[$i]) - 65) * 26; + + // loop throw the entire row in the table until we find the letter + // that matches the letter from the encrypted text + for($j = 0; $j < 26; ++$j) + { + // save the position we are in in the row + $pos = $row + $j; + + // compare the letter from the table to the letter in the cipher text + if(self::$_vtable[$pos] == $text[$i]) + { + // bingo, we found it. The plain text is the letter associated with + // with the column position, again add 65 because ascii capital + // letters start at 65 + $text[$i] = chr($j + 65); + break; + } + } + } + + return true; + } + + + /** + * Prepare the key. The key can only contain uppercase letters. + * All other characters are stripped out. The key length must match + * The length of the message + * + * @param integer $len The length of message + * @return void + */ + private function keyPrep($len) + { + // we never modify the actual key, so we save it into another variable + $this->expanded_key = $this->key(); + $this->expanded_key = strtoupper($this->expanded_key); + $this->expanded_key = preg_replace("/[^A-Z]/", "", $this->expanded_key); + $keylen = strlen($this->expanded_key); + + // The key must be prepared so that it is the same length as the + // message. If it is longer or shorter we need to modify it + // to make it the correct length + if($keylen > $len) + $this->expanded_key = substr($this->expanded_key, 0, $len); + else if($len > $keylen) + { + // if the key is shorter than the message, then we need pad the key + // by repeating it until it is the correct length + $diff = $len - $keylen; + $pos = 0; + + for($i = 0; $i < $diff; ++$i) + { + if($pos >= $keylen) + $pos = 0; + + $this->expanded_key .= $this->expanded_key[$pos]; + ++$pos; + } + } + } + + + /** + * Initialize the Vigenere table used for encryption & decryption + * + * @return void + */ + private function initTables() + { + self::$_vtable = array( + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z', + 'B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A', + 'C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B', + 'D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C', + 'E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D', + 'F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D','E', + 'G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D','E','F', + 'H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D','E','F','G', + 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D','E','F','G','H', + 'J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D','E','F','G','H','I', + 'K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D','E','F','G','H','I','J', + 'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D','E','F','G','H','I','J','K', + 'M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D','E','F','G','H','I','J','K','L', + 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D','E','F','G','H','I','J','K','L','M', + 'O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D','E','F','G','H','I','J','K','L','M','N', + 'P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O', + 'Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', + 'R','S','T','U','V','W','X','Y','Z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q', + 'S','T','U','V','W','X','Y','Z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R', + 'T','U','V','W','X','Y','Z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S', + 'U','V','W','X','Y','Z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T', + 'V','W','X','Y','Z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U', + 'W','X','Y','Z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V', + 'X','Y','Z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W', + 'Y','Z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X', + 'Z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y' + ); + } + + + /** + * Indicates that this is a stream cipher + * + * @return integer Returns Cipher::STREAM + */ + public function type() + { + return parent::STREAM; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/examples/aes_256_example.php b/plugin/advancedsubscription/resources/phpcrypt/examples/aes_256_example.php new file mode 100644 index 0000000000..2e9fc4c956 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/examples/aes_256_example.php @@ -0,0 +1,36 @@ +createIV(); +$encrypt = $crypt->encrypt($text); + +$crypt->IV($iv); +$decrypt = $crypt->decrypt($encrypt); + +print "CIPHER: ".$crypt->cipherName()."\n"; +print "MODE: ".$crypt->modeName()."\n"; +print "PLAIN TEXT: $text\n"; +print "PLAIN TEXT HEX: ".bin2hex($text)."\n"; +print "ENCRYPTED HEX: ".bin2hex($encrypt)."\n"; +print "DECRYPTED: $decrypt\n"; +print "DECRYPTED HEX: ".bin2hex($decrypt)."\n"; +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/examples/arc4_stream_example.php b/plugin/advancedsubscription/resources/phpcrypt/examples/arc4_stream_example.php new file mode 100644 index 0000000000..63c22a93f7 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/examples/arc4_stream_example.php @@ -0,0 +1,28 @@ +createIV(); // STREAM CIPHERS DO NOT REQUIRE AN IV FOR THE STREAM MODE +$encrypt = $crypt->encrypt($text); +$decrypt = $crypt->decrypt($encrypt); + +print "CIPHER: ".$crypt->cipherName()."\n"; +print "MODE: ".$crypt->modeName()."\n"; +print "PLAIN TEXT: $text\n"; +print "PLAIN TEXT HEX: ".bin2hex($text)."\n"; +print "ENCRYPTED HEX: ".bin2hex($encrypt)."\n"; +print "DECRYPTED: $decrypt\n"; +print "DECRYPTED HEX: ".bin2hex($decrypt)."\n"; +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/examples/basic_example.php b/plugin/advancedsubscription/resources/phpcrypt/examples/basic_example.php new file mode 100644 index 0000000000..989e58673b --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/examples/basic_example.php @@ -0,0 +1,33 @@ +encrypt($text); +$decrypt = $crypt->decrypt($encrypt); + +print "CIPHER: ".$crypt->cipherName()."\n"; +print "MODE: ".$crypt->modeName()."\n"; +print "PLAIN TEXT: $text\n"; +print "PLAIN TEXT HEX: ".bin2hex($text)."\n"; +print "ENCRYPTED HEX: ".bin2hex($encrypt)."\n"; +print "DECRYPTED: $decrypt\n"; +print "DECRYPTED HEX: ".bin2hex($decrypt)."\n"; +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/examples/basic_example_secure.php b/plugin/advancedsubscription/resources/phpcrypt/examples/basic_example_secure.php new file mode 100644 index 0000000000..ddf1ee42e1 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/examples/basic_example_secure.php @@ -0,0 +1,32 @@ +createIV(); +$encrypt = $crypt->encrypt($text); + +$crypt->IV($iv); +$decrypt = $crypt->decrypt($encrypt); + +print "CIPHER: ".$crypt->cipherName()."\n"; +print "MODE: ".$crypt->modeName()."\n"; +print "PLAIN TEXT: $text\n"; +print "PLAIN TEXT HEX: ".bin2hex($text)."\n"; +print "ENCRYPTED HEX: ".bin2hex($encrypt)."\n"; +print "DECRYPTED: $decrypt\n"; +print "DECRYPTED HEX: ".bin2hex($decrypt)."\n"; +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/examples/create_key_example.php b/plugin/advancedsubscription/resources/phpcrypt/examples/create_key_example.php new file mode 100644 index 0000000000..5bd766d4f7 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/examples/create_key_example.php @@ -0,0 +1,61 @@ +createIV(); +$encrypt = $crypt->encrypt($text); + +$crypt->IV($iv); +$decrypt = $crypt->decrypt($encrypt); + +print "CIPHER: ".$crypt->cipherName()."\n"; +print "MODE: ".$crypt->modeName()."\n"; +print "PLAIN TEXT: $text\n"; +print "PLAIN TEXT HEX: ".bin2hex($text)."\n"; +print "ENCRYPTED HEX: ".bin2hex($encrypt)."\n"; +print "DECRYPTED: $decrypt\n"; +print "DECRYPTED HEX: ".bin2hex($decrypt)."\n"; +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/examples/file.txt b/plugin/advancedsubscription/resources/phpcrypt/examples/file.txt new file mode 100644 index 0000000000..16b071aa86 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/examples/file.txt @@ -0,0 +1,20 @@ +BEGIN + +This is a test file to test encryption & decription. It contains 20 lines. +The text below is taken from http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation + +In cryptography, modes of operation is the procedure of enabling the repeated and secure use of a block cipher under a single key.[1][2] +A block cipher by itself allows encryption only of a single data block of the cipher's block length. When targeting a variable-length +message, the data must first be partitioned into separate cipher blocks. Typically, the last block must also be extended to match the +cipher's block length using a suitable padding scheme. A mode of operation describes the process of encrypting each of these blocks, and +generally uses randomization based on an additional input value, often called an initialization vector, to allow doing so safely.[1] + +Modes of operation have primarily been defined for encryption and authentication.[1][3] Historically, encryption modes have been studied +extensively in regard to their error propagation properties under various scenarios of data modification. Later development regarded +integrity protection as an entirely separate cryptographic goal from encryption. Some modern modes of operation combine encryption and +authentication in an efficient way, and are known as authenticated encryption modes.[2] + +While modes of operation are commonly associated with symmetric encryption,[2] they may also be applied to public-key encryption primitives +such as RSA in principle (though in practice public-key encryption of longer messages is generally realized using hybrid encryption).[1] + +END \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/examples/file_encryption_example.php b/plugin/advancedsubscription/resources/phpcrypt/examples/file_encryption_example.php new file mode 100644 index 0000000000..6544e99c60 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/examples/file_encryption_example.php @@ -0,0 +1,66 @@ +cipherBlockSize(); // in bytes +$encrypt = ""; +$decrypt = ""; +$result = ""; + + +print "Encrypting file.txt using:\n"; +print "CIPHER: ".$crypt->cipherName()."\n"; +print "MODE: ".$crypt->modeName()."\n"; + + +/* + * DO THE ENCRYPTION + */ +$rhandle = fopen("file.txt", "r"); +$whandle = fopen("file.encrypted.txt", "w+b"); +print "Creating file.encrypted.txt\n"; + +// CFB mode requires an IV, create it +$iv = $crypt->createIV(); + +while (!feof($rhandle)) +{ + $bytes = fread($rhandle, $cipher_block_sz); + $result = $crypt->encrypt($bytes); + fwrite($whandle, $result); +} +fclose($rhandle); +fclose($whandle); + + +/* + * DO THE DECRYPTION + */ +$rhandle = fopen("file.encrypted.txt", "rb"); +$whandle = fopen("file.decrypted.txt", "w+"); +print "Creating file.decrypted.txt\n"; + +// we need to set the IV to the same IV used for encryption +$crypt->IV($iv); + +while (!feof($rhandle)) +{ + $bytes = fread($rhandle, $cipher_block_sz); + $result = $crypt->decrypt($bytes); + fwrite($whandle, $result); +} +fclose($rhandle); +fclose($whandle); + +print "Finished.\n"; +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/examples/mode_iv_examples.php b/plugin/advancedsubscription/resources/phpcrypt/examples/mode_iv_examples.php new file mode 100644 index 0000000000..8833ac3ee7 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/examples/mode_iv_examples.php @@ -0,0 +1,61 @@ +createIV(PHP_Crypt::RAND); // The default, uses PHP's mt_rand() + * $iv = $crypt->createIV(PHP_Crypt::RAND_DEV_RAND); // unix only, uses /dev/random + * $iv = $crypt->createIV(PHP_Crypt::RAND_DEV_URAND);// unix only, uses /dev/urandom + * $iv = $crypt->createIV(PHP_Crypt::RAND_WIN_COM); // Windows only, uses the com_dotnet extension + * + * In the case where you are given an encrypted string, along with the key and IV + * to decrypt the string, you don't need to call createIV() since the IV has already + * been created for you. Set the IV by calling $crypt->IV($iv) as shown below. + */ + +// by default createIV() uses PHP_Crypt::RAND which uses PHP's mt_rand() +$iv = $crypt->createIV(); +$encrypt = $crypt->encrypt($text); + +// we need to use the same IV for decryption as used during encryption +$crypt->IV($iv); +$decrypt = $crypt->decrypt($encrypt); + +print "CIPHER: ".$crypt->cipherName()."\n"; +print "MODE: ".$crypt->modeName()."\n"; +print "PLAIN TEXT: $text\n"; +print "PLAIN TEXT HEX: ".bin2hex($text)."\n"; +print "ENCRYPTED HEX: ".bin2hex($encrypt)."\n"; +print "DECRYPTED: $decrypt\n"; +print "DECRYPTED HEX: ".bin2hex($decrypt)."\n"; +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/examples/padding_examples.php b/plugin/advancedsubscription/resources/phpcrypt/examples/padding_examples.php new file mode 100644 index 0000000000..beaf7d612c --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/examples/padding_examples.php @@ -0,0 +1,88 @@ +padding(PHP_Crypt::PAD_ANSI_X923); + */ + + +//$iv = $crypt->createIV(); // ECB Mode does not require an IV +$encrypt = $crypt->encrypt($text); +$decrypt = $crypt->decrypt($encrypt); + +print "CIPHER: ".$crypt->cipherName()."\n"; +print "MODE: ".$crypt->modeName()."\n"; +print "PLAIN TEXT: $text\n"; +print "PLAIN TEXT HEX: ".bin2hex($text)."\n"; +print "ENCRYPTED HEX: ".bin2hex($encrypt)."\n"; +print "DECRYPTED: $decrypt\n"; +print "DECRYPTED HEX: ".bin2hex($decrypt)."\n"; +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/examples/phpcrypt_vs_mcrypt.php b/plugin/advancedsubscription/resources/phpcrypt/examples/phpcrypt_vs_mcrypt.php new file mode 100644 index 0000000000..1526fe16f4 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/examples/phpcrypt_vs_mcrypt.php @@ -0,0 +1,97 @@ +cipherName()." - ".$phpcrypt->modeName()."\n\n"; + + +/** + * ENCRYPT USING mCrypt + * DECRYPT USING phpCrypt + */ + +// MCRYPT: ENCRYPT +mcrypt_generic_init($td, $key, $iv); +$ts_start = microtime(true); +$encrypt = mcrypt_generic($td, $text); +$m_time = number_format((microtime(true) - $ts_start), 5); +mcrypt_generic_deinit($td); + +// PHPCRYPT: DECRYPT +$phpcrypt->IV($iv); +$ts_start = microtime(true); +$decrypt = $phpcrypt->decrypt($encrypt); +$p_time = number_format((microtime(true) - $ts_start), 5); + +// OUTPUT +print "MCRYPT ENCRYPTED (HEX): ".bin2hex($encrypt)." (length=".strlen($encrypt).", time=$m_time)\n"; +print "PHPCRYPT DECRYPTED: $decrypt (length=".strlen($decrypt).", time=$p_time)\n"; +print "PHPCRYPT DECRYPTED (HEX): ".bin2hex($decrypt)."\n"; + + +print "\n\n"; + + +/** + * ENCRYPT USING phpCrypt + * DECRYPT USING mCrypt + */ + +// PHPCRYPT: ENCRYPT +$phpcrypt->IV($iv); +$ts_start = microtime(true); +$encrypt = $phpcrypt->encrypt($text); +$p_time = number_format((microtime(true) - $ts_start), 5); + + +// MCRYPT: DECRYPT +mcrypt_generic_init($td, $key, $iv); +$ts_start = microtime(true); +$decrypt = mdecrypt_generic($td, $encrypt); +$m_time = number_format((microtime(true) - $ts_start), 5); +mcrypt_generic_deinit($td); + +// OUTPUT +print "PHPCRYPT ENCRYPTED (HEX): ".bin2hex($encrypt)." (length=".strlen($encrypt).", time=$p_time)\n"; +print "MCRYPT DECRYPTED: $decrypt (length=".strlen($decrypt).", time=$m_time)\n"; +print "MCRYPT DECRYPTED (HEX): ".bin2hex($decrypt)."\n"; + +// close mcrypt +mcrypt_module_close($td); +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/licenses/ECCN_5D002.txt b/plugin/advancedsubscription/resources/phpcrypt/licenses/ECCN_5D002.txt new file mode 100644 index 0000000000..4972fad371 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/licenses/ECCN_5D002.txt @@ -0,0 +1,7 @@ +phpCrypt is self classified under ECCN 5D002 in the United States as freely +available encryption source code. Both BIS and the NSA were notified of +phpCrypt and the URLs which host the phpCrypt source code as required under +740.13(e) of the EAR on July 30, 2013 at the following email addresses: + +crypt@bis.doc.gov +enc@nsa.gov \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/licenses/GPL.txt b/plugin/advancedsubscription/resources/phpcrypt/licenses/GPL.txt new file mode 100644 index 0000000000..94a9ed024d --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/licenses/GPL.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/plugin/advancedsubscription/resources/phpcrypt/modes/CBC.php b/plugin/advancedsubscription/resources/phpcrypt/modes/CBC.php new file mode 100644 index 0000000000..49204f15a1 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/modes/CBC.php @@ -0,0 +1,167 @@ +. + */ + +namespace PHP_Crypt; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../Mode.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements Cipher-Block Chaining (CBC) block cipher mode + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Mode_CBC extends Mode +{ + /** + * Constructor + * Sets the cipher object that will be used for encryption + * + * @param object $cipher one of the phpCrypt encryption cipher objects + * @return void + */ + function __construct($cipher) + { + parent::__construct(PHP_Crypt::MODE_CBC, $cipher); + + // this works with only block Ciphers + if($cipher->type() != Cipher::BLOCK) + trigger_error("CBC mode requires a block cipher", E_USER_WARNING); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypts an the entire string $plain_text using the cipher passed + * to the constructor in CBC mode + * The steps to encrypt using CBC are as follows + * 1) Get a block of plain text data to use in the Cipher + * 2) XOR the block with IV (if it's the first round) or the previous + * round's encrypted result + * 3) Encrypt the block using the cipher + * 4) Save the encrypted block to use in the next round + * + * @param string $text the string to be encrypted in CBC mode + * @return boolean Returns true + */ + public function encrypt(&$text) + { + $this->pad($text); + $blocksz = $this->cipher->blockSize(); + + $max = strlen($text) / $blocksz; + for($i = 0; $i < $max; ++$i) + { + // get the current position in $text + $pos = $i * $blocksz; + + // grab a block of plain text + $block = substr($text, $pos, $blocksz); + + // xor the block with the register + for($j = 0; $j < $blocksz; ++$j) + $block[$j] = $block[$j] ^ $this->register[$j]; + + // encrypt the block, and save it back to the register + $this->cipher->encrypt($block); + $this->register = $block; + + // replace the plain text block with the cipher text + $text = substr_replace($text, $this->register, $pos, $blocksz); + } + + return true; + } + + + /** + * Decrypts an the entire string $plain_text using the cipher passed + * to the constructor in CBC mode + * The decryption algorithm requires the following steps + * 1) Get the first block of encrypted text, save it + * 2) Decrypt the block + * 3) XOR the decrypted block (if it's the first pass use the IV, + * else use the encrypted block from step 1 + * 4) the result from the XOR will be a plain text block, save it + * 5) assign the encrypted block from step 1 to use in the next round + * + * @param string $text the string to be decrypted in CBC mode + * @return boolean Returns true + */ + public function decrypt(&$text) + { + $blocksz = $this->cipher->blockSize(); + + $max = strlen($text) / $blocksz; + for($i = 0; $i < $max; ++$i) + { + // get the current position in $text + $pos = $i * $blocksz; + + // grab a block of cipher text, and save it for use later + $block = substr($text, $pos, $blocksz); + $tmp_block = $block; + + // decrypt the block of cipher text + $this->cipher->decrypt($block); + + // xor the block with the register + for($j = 0; $j < $blocksz; ++$j) + $block[$j] = $block[$j] ^ $this->register[$j]; + + // replace the block of cipher text with plain text + $text = substr_replace($text, $block, $pos, $blocksz); + + // save the cipher text block to the register + $this->register = $tmp_block; + } + + $this->strip($text); + return true; + } + + + /** + * This mode requires an IV + * + * @return boolean Returns True + */ + public function requiresIV() + { + return true; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/modes/CFB.php b/plugin/advancedsubscription/resources/phpcrypt/modes/CFB.php new file mode 100644 index 0000000000..978f33e5ae --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/modes/CFB.php @@ -0,0 +1,130 @@ +. + */ + +namespace PHP_Crypt; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../Mode.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements Cipher Feedback (CFB) block cipher mode + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Mode_CFB extends Mode +{ + /** + * Constructor + * Sets the cipher object that will be used for encryption + * + * @param object $cipher one of the phpCrypt encryption cipher objects + * @return void + */ + public function __construct($cipher) + { + parent::__construct(PHP_Crypt::MODE_CFB, $cipher); + + // this works with only block Ciphers + if($cipher->type() != Cipher::BLOCK) + trigger_error("CFB mode requires a block cipher", E_USER_WARNING); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypts an the entire string $plain_text using the cipher passed + * + * @param string $text The string to be encrypted in CFB mode + * @return boolean Returns true + */ + public function encrypt(&$text) + { + $max = strlen($text); + for($i = 0; $i < $max; ++$i) + { + // copy the register, and then encrypt it + $this->enc_register = $this->register; + $this->cipher->encrypt($this->enc_register); + + // encrypt the byte + $text[$i] = $text[$i] ^ $this->enc_register[0]; + + // left shift the register and push the encrypted byte onto register + $this->register = substr($this->register, 1); + $this->register .= $text[$i]; + } + + return true; + } + + + /** + * Decrypts an the entire string $plain_text using the cipher passed + * + * @param string $text the string to be decrypted in CFB mode + * @return boolean Returns true + */ + public function decrypt(&$text) + { + $max = strlen($text); + for($i = 0; $i < $max; ++$i) + { + $this->enc_register = $this->register; + $this->cipher->encrypt($this->enc_register); + + // left shift the register and push the encrypted byte onto register + $this->register = substr($this->register, 1); + $this->register .= $text[$i]; + + // decrypt the byte + $text[$i] = $text[$i] ^ $this->enc_register[0]; + } + + return true; + } + + + /** + * This mode requires an IV + * + * @return boolean True + */ + public function requiresIV() + { + return true; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/modes/CTR.php b/plugin/advancedsubscription/resources/phpcrypt/modes/CTR.php new file mode 100644 index 0000000000..4730b7b058 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/modes/CTR.php @@ -0,0 +1,202 @@ +. + */ + +namespace PHP_Crypt; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../Mode.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements Counter (CTR) block cipher mode + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Mode_CTR extends Mode +{ + /** + * Constructor + * Sets the cipher object that will be used for encryption + * + * @param object $cipher one of the phpCrypt encryption cipher objects + * @return void + */ + function __construct($cipher) + { + parent::__construct(PHP_CRYPT::MODE_CTR, $cipher); + + // this works with only block Ciphers + if($cipher->type() != Cipher::BLOCK) + trigger_error("CTR mode requires a block cipher", E_USER_WARNING); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypts an encrypted string + * + * @param string $text the string to be encrypted + * @return boolean Returns true + */ + public function encrypt(&$text) + { + $len = strlen($text); + $blocksz = $this->cipher->blockSize(); + + $max = $len / $blocksz; + for($i = 0; $i < $max; ++$i) + { + // get the current position in $text + $pos = $i * $blocksz; + + // make sure we don't extend past the length of $text + $byte_len = $blocksz; + if(($pos + $byte_len) > $len) + $byte_len -= ($pos + $byte_len) - $len; + + // encrypt the register + $this->enc_register = $this->register; + $this->cipher->encrypt($this->enc_register); + + // grab a block of plain text + $block = substr($text, $pos, $byte_len); + + // xor the block + for($j = 0; $j < $byte_len; ++$j) + $block[$j] = $block[$j] ^ $this->enc_register[$j]; + + // replace the plain text block with the encrypted block + $text = substr_replace($text, $block, $pos, $byte_len); + + // increment the counter + $this->counter(); + } + + return true; + } + + + /** + * Decrypt an encrypted string + * + * @param string $text The string to be decrypted + * @return boolean Returns true + */ + public function decrypt(&$text) + { + $len = strlen($text); + $blocksz = $this->cipher->blockSize(); + + $max = $len / $blocksz; + for($i = 0; $i < $max; ++$i) + { + // get the current position in $text + $pos = $i * $blocksz; + + // make sure we don't extend past the length of $text + $byte_len = $blocksz; + if(($pos + $byte_len) > $len) + $byte_len -= ($pos + $byte_len) - $len; + + // encrypt the register + $this->enc_register = $this->register; + $this->cipher->encrypt($this->enc_register); + + // grab a block of plain text + $block = substr($text, $pos, $byte_len); + + // xor the block with the register (which contains the IV) + for($j = 0; $j < $byte_len; ++$j) + $block[$j] = $block[$j] ^ $this->enc_register[$j]; + + // replace the encrypted block with the plain text + $text = substr_replace($text, $block, $pos, $byte_len); + + // increment the counter + $this->counter(); + } + + return true; + } + + + /** + * This mode requires an IV + * + * @return boolean True + */ + public function requiresIV() + { + return true; + } + + + /** + * Increments the counter (which is initially the IV) by one byte starting at the + * last byte. Once that byte has reached 0xff, it is then set to 0x00, and the + * next byte is then incremented. On the following incrementation, the last byte + * is incremented again. An example: + * PASS 1: 2037e9ae63f73dfe + * PASS 2: 2037e9ae63f73dff + * PASS 3: 2037e9ae63f73e00 + * PASS 4: 2037e9ae63f73e01 + * ... + * PASS N: 2100000000000001 + * PASS N+1: 2100000000000002 + * + * @return void + */ + private function counter() + { + $pos = $this->cipher->blockSize() - 1; + + // starting at the last byte, loop through each byte until + // we find one that can be incremented + for($i = $pos; $i >= 0; --$i) + { + // if we reached the last byte, set it to 0x00, then + // loop one more time to increment the next byte + if(ord($this->register[$i]) == 0xff) + $this->register[$i] = chr(0x00); + else + { + // now increment the byte by 1 + $this->register[$i] = chr(ord($this->register[$i]) + 1); + break; + } + } + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/modes/ECB.php b/plugin/advancedsubscription/resources/phpcrypt/modes/ECB.php new file mode 100644 index 0000000000..d3981a9c27 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/modes/ECB.php @@ -0,0 +1,142 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../Mode.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements Electronic Code Book (ECB) block cipher mode + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2005 Ryan Gilfether + */ +class Mode_ECB extends Mode +{ + /** + * Constructor + * Sets the cipher object that will be used for encryption + * + * @param object $cipher one of the phpCrypt encryption cipher objects + * @param int $block_size The size of blocks (in bits) used for encryption + * @return void + */ + public function __construct($cipher) + { + parent::__construct(PHP_Crypt::MODE_ECB, $cipher); + + // this works with only block Ciphers + if($cipher->type() != Cipher::BLOCK) + trigger_error("ECB mode requires a block cipher", E_USER_WARNING); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypts an the entire string $plain_text using the cipher passed + * to the constructor in ECB mode + * + * @param string $text The string to be encrypted in ECB mode + * @return boolean Returns true + */ + public function encrypt(&$text) + { + $this->pad($text); + $blocksz = $this->cipher->blockSize(); + + $max = strlen($text) / $blocksz; + for($i = 0; $i < $max; ++$i) + { + // get the current position within $text + $pos = $i * $blocksz; + + // grab a block of text + $block = substr($text, $pos, $blocksz); + + // encrypt the block + $this->cipher->encrypt($block); + + // replace the plain text with the cipher text + $text = substr_replace($text, $block, $pos, $blocksz); + } + + return true; + } + + + /** + * Decrypts an the entire string $plain_text using the cipher passed + * to the constructor in ECB mode + * + * @param string $text The string to be decrypted in ECB mode + * @return boolean Returns true + */ + public function decrypt(&$text) + { + $blocksz = $this->cipher->blockSize(); + + $max = strlen($text) / $blocksz; + for($i = 0; $i < $max; ++$i) + { + // get the current position within $text + $pos = $i * $blocksz; + + // get a block of cipher text + $block = substr($text, $pos, $blocksz); + + // decrypt the block + $this->cipher->decrypt($block); + + // replace the block of cipher text with plain text + $text = substr_replace($text, $block, $pos, $blocksz); + } + + $this->strip($text); + return true; + } + + + /** + * This mode does not require an IV + * + * @return boolean Returns false + */ + public function requiresIV() + { + return false; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/modes/NCFB.php b/plugin/advancedsubscription/resources/phpcrypt/modes/NCFB.php new file mode 100644 index 0000000000..59c36ed2a3 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/modes/NCFB.php @@ -0,0 +1,171 @@ +. + */ + +namespace PHP_Crypt; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../Mode.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements N Cipher Feedback (CFB) block cipher mode, same as CFB + * but N = the block size requirement of the cipher + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Mode_NCFB extends Mode +{ + /** + * The constructor, Sets the cipher object that will be used for encryption + * + * @param object $cipher one of the phpCrypt encryption cipher objects + * @return void + */ + public function __construct($cipher) + { + parent::__construct(PHP_Crypt::MODE_NCFB, $cipher); + + // this works with only block Ciphers + if($cipher->type() != Cipher::BLOCK) + trigger_error("NCFB mode requires a block cipher", E_USER_WARNING); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypts an the entire string $plain_text using the cipher passed + * + * @param string $text the string to be encrypted + * @return boolean True + */ + public function encrypt(&$text) + { + $blocksz = $this->cipher->blockSize(); + + // first we need to pad the string so its the correct length for the cipher + $len = strlen($text); + + // if $len is less than blockSize() this will still work, as even + // a fraction is greater than 0 + $max = $len / $blocksz; + for($i = 0; $i < $max; ++$i) + { + // current position in the text + $pos = $i * $blocksz; + + // make sure we don't extend past the length of $text + $byte_len = $blocksz; + + if(($pos + $byte_len) > $len) + $byte_len -= ($pos + $byte_len) - $len; + + // encrypt the register + $this->enc_register = $this->register; + $this->cipher->encrypt($this->enc_register); + + // encrypt the block by xoring it with the encrypted register + $block = substr($text, $pos, $byte_len); + + // xor the block + for($j = 0; $j < $byte_len; ++$j) + $block[$j] = $block[$j] ^ $this->enc_register[$j]; + + // replace the plain text block with the encrypted block + $text = substr_replace($text, $block, $pos, $byte_len); + + // shift the register left n-bytes, append n-bytes of encrypted register + $this->register = substr($this->register, $blocksz); + $this->register .= $block; + } + + return true; + } + + + /** + * Decrypts an the entire string $plain_text using the cipher passed + * + * @param string $text the string to be decrypted + * @return bool Returns True + */ + public function decrypt(&$text) + { + $blocksz = $this->cipher->blockSize(); + $len = strlen($text); + + // if $len is less than blockSize() this will still work, as even + // a fraction is greater than 0 + $max = $len / $blocksz; + for($i = 0; $i < $max; ++$i) + { + // get the current position in text + $pos = $i * $blocksz; + + // make sure we don't extend past the length of $text + $byte_len = $blocksz; + if(($pos + $byte_len) > $len) + $byte_len -= ($pos + $byte_len) - $len; + + // encrypt the register + $this->enc_register = $this->register; + $this->cipher->encrypt($this->enc_register); + + // shift the register left, push the encrypted byte onto the end + $block = substr($text, $pos, $byte_len); + $this->register = $block; + + // xor the block + for($j = 0; $j < $byte_len; ++$j) + $block[$j] = $block[$j] ^ $this->enc_register[$j]; + + // replace the encrypted block with the plain text block + $text = substr_replace($text, $block, $pos, $byte_len); + } + + return true; + } + + + /** + * This mode requires an IV + * + * @return boolean true + */ + public function requiresIV() + { + return true; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/modes/NOFB.php b/plugin/advancedsubscription/resources/phpcrypt/modes/NOFB.php new file mode 100644 index 0000000000..bfac1c1e62 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/modes/NOFB.php @@ -0,0 +1,164 @@ +. + */ + +namespace PHP_Crypt; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../Mode.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements N Output Feedback (NOFB) block cipher mode, same as OFB + * but N = the block size requirement of the cipher + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Mode_NOFB extends Mode +{ + /** + * Constructor + * Sets the cipher object that will be used for encryption + * + * @param object $cipher one of the phpCrypt encryption cipher objects + * @return void + */ + public function __construct($cipher) + { + parent::__construct(PHP_Crypt::MODE_NOFB, $cipher); + + // this works with only block Ciphers + if($cipher->type() != Cipher::BLOCK) + trigger_error("NOFB mode requires a block cipher", E_USER_WARNING); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypts an the entire string $plain_text using the cipher passed + * + * @param string $text the string to be encrypted + * @return boolean Returns true + */ + public function encrypt(&$text) + { + $len = strlen($text); + $blocksz = $this->cipher->blockSize(); + + $max = $len / $blocksz; + for($i = 0; $i < $max; ++$i) + { + // current position in the text + $pos = $i * $blocksz; + + // make sure we don't extend past the length of $text + $byte_len = $blocksz; + if(($pos + $blocksz) > $len) + $byte_len -= ($pos + $blocksz) - $len; + + // encrypt the register + $this->enc_register = $this->register; + $this->cipher->encrypt($this->enc_register); + + // now grab a block of text and a block of from the register, and XOR them + $block = substr($text, $pos, $byte_len); + for($j = 0; $j < $byte_len; ++$j) + $block[$j] = $block[$j] ^ $this->enc_register[$j]; + + // replace the plain text block with encrypted text + $text = substr_replace($text, $block, $pos, $byte_len); + + // shift the register left n-bytes, append n-bytes of encrypted register + $this->register = substr($this->register, $byte_len); + $this->register .= substr($this->enc_register, 0, $byte_len); + } + + return true; + } + + + /** + * Decrypts an the entire string $plain_text using the cipher passed + * + * @param string $text the string to be decrypted + * @return boolean Returns true + */ + public function decrypt(&$text) + { + $len = strlen($text); + $blocksz = $this->cipher->blockSize(); + + $max = $len / $blocksz; + for($i = 0; $i < $max; ++$i) + { + // current position within $text + $pos = $i * $blocksz; + + // make sure we don't extend past the length of $text + $byte_len = $blocksz; + if(($pos + $byte_len) > $len) + $byte_len -= ($pos + $byte_len) - $len; + + // encrypt the register + $this->enc_register = $this->register; + $this->cipher->encrypt($this->enc_register); + + // shift the register left n-bytes, append n-bytes of encrypted register + $this->register = substr($this->register, $byte_len); + $this->register .= substr($this->enc_register, 0, $byte_len); + + // now grab a block of text and xor with the register + $block = substr($text, $pos, $byte_len); + for($j = 0; $j < $byte_len; ++$j) + $block[$j] = $block[$j] ^ $this->enc_register[$j]; + + // replace the encrypted block with plain text + $text = substr_replace($text, $block, $pos, $byte_len); + } + + return true; + } + + + /** + * This mode requires an IV + * + * @return boolean true + */ + public function requiresIV() + { + return true; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/modes/OFB.php b/plugin/advancedsubscription/resources/phpcrypt/modes/OFB.php new file mode 100644 index 0000000000..0ea3fd2250 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/modes/OFB.php @@ -0,0 +1,126 @@ +. + */ + +namespace PHP_Crypt; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../Mode.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements Output Feedback (OFB) block cipher mode + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Mode_OFB extends Mode +{ + /** + * Constructor + * Sets the cipher object that will be used for encryption + * + * @param object $cipher one of the phpCrypt encryption cipher objects + * @return void + */ + public function __construct($cipher) + { + parent::__construct(PHP_Crypt::MODE_OFB, $cipher); + + // this works with only block Ciphers + if($cipher->type() != Cipher::BLOCK) + trigger_error("OFB mode requires a block cipher", E_USER_WARNING); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypts an the entire string $plain_text using the cipher passed + * + * @param string $text the string to be encrypted + * @return boolean Returns true + */ + public function encrypt(&$text) + { + $max = strlen($text); + for($i = 0; $i < $max; ++$i) + { + $this->enc_register = $this->register; + $this->cipher->encrypt($this->enc_register); + $text[$i] = $text[$i] ^ $this->enc_register[0]; + + // shift the register left + $this->register = substr($this->register, 1); + $this->register .= $this->enc_register[0]; + } + + return true; + } + + + /** + * Decrypts an the entire string $plain_text using the cipher passed + * + * @param string $text the string to be decrypted + * @return boolean Returns true + */ + public function decrypt(&$text) + { + $max = strlen($text); + for($i = 0; $i < $max; ++$i) + { + $this->enc_register = $this->register; + $this->cipher->encrypt($this->enc_register); + + // shift the register left + $this->register = substr($this->register, 1); + $this->register .= $this->enc_register[0]; + + $text[$i] = $text[$i] ^ $this->enc_register[0]; + } + + return true; + } + + + /** + * This mode requires an IV + * + * @return boolean true + */ + public function requiresIV() + { + return true; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/modes/PCBC.php b/plugin/advancedsubscription/resources/phpcrypt/modes/PCBC.php new file mode 100644 index 0000000000..6e1d98f30d --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/modes/PCBC.php @@ -0,0 +1,159 @@ +. + */ + +namespace PHP_Crypt; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../Mode.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Implements Propagating Cipher-Block Chaining (PCBC) block cipher mode + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Mode_PCBC extends Mode +{ + /** + * Constructor + * Sets the cipher object that will be used for encryption + * + * @param object $cipher one of the phpCrypt encryption cipher objects + * @return void + */ + function __construct($cipher) + { + parent::__construct(PHP_Crypt::MODE_PCBC, $cipher); + + // this works with only block Ciphers + if($cipher->type() != Cipher::BLOCK) + trigger_error("PCBC mode requires a block cipher", E_USER_WARNING); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypts an the entire string $plain_text using the cipher + * + * @param string $text the string to be encrypted + * @return boolean Returns true + */ + public function encrypt(&$text) + { + $this->pad($text); + $blocksz = $this->cipher->blockSize(); + + $max = strlen($text) / $blocksz; + for($i = 0; $i < $max; ++$i) + { + // current position in the text + $pos = $i * $blocksz; + + // get a block of plain text, and make a copy + $block = substr($text, $pos, $blocksz); + $plain_block = $block; + + // xor the register with plain text + for($j = 0; $j < $blocksz; ++$j) + $block[$j] = $this->register[$j] ^ $block[$j]; + + // encrypt the block creating the cipher text + $this->cipher->encrypt($block); + + // xor the encrypted block with the plain text block to create + // the register in the next round + for($j = 0; $j < $blocksz; ++$j) + $this->register[$j] = $block[$j] ^ $plain_block[$j]; + + // copy the encrypted block back to $text + $text = substr_replace($text, $block, $pos, $blocksz); + } + + return true; + } + + + /** + * Decrypts an the entire string $plain_text using the cipher + * + * @param string $text the string to be decrypted + * @return boolean Returns true + */ + public function decrypt(&$text) + { + $blocksz = $this->cipher->blockSize(); + + $max = strlen($text) / $blocksz; + for($i = 0; $i < $max; ++$i) + { + // current position in the text + $pos = $i * $blocksz; + + // get a block of encrypted text, and make a copy + $block = substr($text, $pos, $blocksz); + $enc_block = $block; + + // decrypt the block + $this->cipher->decrypt($block); + + // xor the decrypted block with the register, to create + // the plain text block + for($j = 0; $j < $blocksz; ++$j) + $block[$j] = $this->register[$j] ^ $block[$j]; + + // now xor the $enc_block with the unencrypted $block + for($j = 0; $j < $blocksz; ++$j) + $this->register[$j] = $block[$j] ^ $enc_block[$j]; + + // copy the plain text block back to $text + $text = substr_replace($text, $block, $pos, $blocksz); + } + + $this->strip($text); + return true; + } + + + /** + * This mode requires an IV + * + * @return boolean Returns true + */ + public function requiresIV() + { + return true; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/modes/Raw.php b/plugin/advancedsubscription/resources/phpcrypt/modes/Raw.php new file mode 100644 index 0000000000..7eaaaaa52a --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/modes/Raw.php @@ -0,0 +1,116 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../Mode.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); + + +/** + * Allows Raw encryption of block or stream cipher, this does not use any + * mode, rather is simply calls the Encryption/Decryption method of the + * Cipher selected. The data encrypted/decrypted must be the same length + * as required by the Cipher. No padding is used. + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Mode_Raw extends Mode +{ + /** + * Constructor + * Sets the cipher object that will be used for encryption + * + * @param object $cipher one of the phpCrypt encryption cipher objects + * @return void + */ + public function __construct($cipher) + { + parent::__construct(PHP_Crypt::MODE_RAW, $cipher); + } + + + /** + * Constructor used by classes that extend this class + * Used by Mode_Stream, which extends this class + * + * @param object $cipher One of phpCrypts cipher objects + * @param integer $mode The mode constant identifier + * @return void + */ + protected function __construct1($mode, $cipher) + { + parent::__construct($mode, $cipher); + } + + + /** + * Destructor + */ + public function __destruct() + { + parent::__destruct(); + } + + + /** + * Encrypts an the string using the Cipher with no Mode + * NOTE: The data in $text must be the exact length required by the Cipher + * + * @param string $str the string to be encrypted + * @return boolean Always returns false + */ + public function encrypt(&$text) + { + $this->cipher->encrypt($text); + return true; + } + + + /** + * Decrypts one block of cipher text, not using any mode. + * NOTE: The data in $text must be the exact length required by the Cipher + * + * @param string $str the string to be decrypted + * @return boolean Always returns false + */ + public function decrypt(&$text) + { + $this->cipher->decrypt($text); + return true; + } + + + /** + * This mode does not require an IV + * + * @return boolean false + */ + public function requiresIV() + { + return false; + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/modes/Stream.php b/plugin/advancedsubscription/resources/phpcrypt/modes/Stream.php new file mode 100644 index 0000000000..ee11b10b60 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/modes/Stream.php @@ -0,0 +1,69 @@ +. + */ + +namespace PHP_CRYPT; +require_once(dirname(__FILE__)."/../Cipher.php"); +require_once(dirname(__FILE__)."/../phpCrypt.php"); +require_once(dirname(__FILE__)."/Raw.php"); + + +/** + * Used only on Stream Ciphers, this isn't really a mode, it's + * just a way to apply the stream cipher to the data being encrypted + * Since it's basically the same as the Mode_Raw, we just extend from Mode_Raw + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2013 Ryan Gilfether + */ +class Mode_Stream extends Mode_Raw +{ + /** + * Constructor + * Sets the cipher object that will be used for encryption + * + * @param object $cipher one of the phpCrypt encryption cipher objects + * @return void + */ + public function __construct($cipher) + { + // call the secondary 'constructor' from the parent + parent::__construct1(PHP_Crypt::MODE_STREAM, $cipher); + + // this works with only stream Ciphers + if($cipher->type() != Cipher::STREAM) + trigger_error("Stream mode requires a stream cipher", E_USER_WARNING); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + parent::__destruct(); + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/resources/phpcrypt/phpCrypt.php b/plugin/advancedsubscription/resources/phpcrypt/phpCrypt.php new file mode 100644 index 0000000000..a03fdd8e76 --- /dev/null +++ b/plugin/advancedsubscription/resources/phpcrypt/phpCrypt.php @@ -0,0 +1,457 @@ +. + */ + +namespace PHP_Crypt; + +require_once(dirname(__FILE__)."/Core.php"); +require_once(dirname(__FILE__)."/Includes.inc.php"); + +/** + * The phpCrypt class, a front end to all the Ciphers and Modes phpCrypt supports + * + * @author Ryan Gilfether + * @link http://www.gilfether.com/phpcrypt + * @copyright 2005 Ryan Gilfether + */ +class PHP_Crypt +{ + // Ciphers + const CIPHER_3DES = "3DES"; + const CIPHER_3WAY = "3-Way"; + const CIPHER_AES_128 = "AES-128"; + const CIPHER_AES_192 = "AES-192"; + const CIPHER_AES_256 = "AES-256"; + const CIPHER_ARC4 = "ARC4"; // Alternative RC4 + const CIPHER_BLOWFISH = "Blowfish"; + const CIPHER_CAST_128 = "CAST-128"; + const CIPHER_CAST_256 = "CAST-256"; + const CIPHER_DES = "DES"; + const CIPHER_ENIGMA = "Enigma"; + const CIPHER_GOST = "GOST"; + const CIPHER_RC2 = "RC2"; + const CIPHER_RIJNDAEL_128 = "Rijndael-128"; + const CIPHER_RIJNDAEL_192 = "Rijndael-192"; + const CIPHER_RIJNDAEL_256 = "Rijndael-256"; + const CIPHER_SKIPJACK = "Skipjack"; + const CIPHER_SIMPLEXOR = "SimpleXOR"; + const CIPHER_VIGENERE = "Vigenere"; // historical + + // Modes + const MODE_CBC = "CBC"; + const MODE_CFB = "CFB"; // 8 bit cfb mode + const MODE_CTR = "CTR"; + const MODE_ECB = "ECB"; + const MODE_NCFB = "NCFB"; // blocksize cfb mode + const MODE_NOFB = "NOFB"; // blocksize ofb mode + const MODE_OFB = "OFB"; // 8 bit ofb mode + const MODE_PCBC = "PCBC"; + const MODE_RAW = "Raw"; // raw encryption, with no mode + const MODE_STREAM = "Stream"; // used only for stream ciphers + + // The source of random data used to create keys and IV's + // Used for PHP_Crypt::createKey(), PHP_Crypt::createIV() + const RAND = "rand"; // uses mt_rand(), windows & unix + const RAND_DEV_RAND = "/dev/random"; // unix only + const RAND_DEV_URAND= "/dev/urandom";// unix only + const RAND_WIN_COM = "wincom"; // windows only, COM extension + const RAND_DEFAULT_SZ = 32; // the default number of bytes returned + + // Padding types + const PAD_ZERO = 0; + const PAD_ANSI_X923 = 1; + const PAD_ISO_10126 = 2; + const PAD_PKCS7 = 3; + const PAD_ISO_7816_4 = 4; + + + /** @type object $cipher An instance of the cipher object selected */ + private $cipher = null; + + /** @type object $mode An instance of the mode object selected */ + private $mode = null; + + + /** + * Constructor + * + * @param string $key The key to use for the selected Cipher + * @param string $cipher The type of cipher to use + * @param string $mode The encrypt mode to use with the cipher + * @param string $padding The padding type to use. Defaults to PAD_ZERO + * @return void + */ + public function __construct($key, $cipher = self::CIPHER_AES_128, $mode = self::MODE_ECB, $padding = self::PAD_ZERO) + { + /* + * CIPHERS + */ + switch($cipher) + { + case self::CIPHER_3DES: + $this->cipher = new Cipher_3DES($key); + break; + + case self::CIPHER_3WAY: + $this->cipher = new Cipher_3WAY($key); + break; + + case self::CIPHER_AES_128: + $this->cipher = new Cipher_AES_128($key); + break; + + case self::CIPHER_AES_192: + $this->cipher = new Cipher_AES_192($key); + break; + + case self::CIPHER_AES_256: + $this->cipher = new Cipher_AES_256($key); + break; + + case self::CIPHER_ARC4: // an alternative to RC4 + $this->cipher = new Cipher_ARC4($key); + break; + + case self::CIPHER_BLOWFISH: + $this->cipher = new Cipher_Blowfish($key); + break; + + case self::CIPHER_CAST_128: + $this->cipher = new Cipher_CAST_128($key); + break; + + case self::CIPHER_CAST_256: + $this->cipher = new Cipher_CAST_256($key); + break; + + case self::CIPHER_DES: + $this->cipher = new Cipher_DES($key); + break; + + case self::CIPHER_ENIGMA: + $this->cipher = new Cipher_Enigma($key); + break; + + case self::CIPHER_GOST: + $this->cipher = new Cipher_GOST($key); + break; + + case self::CIPHER_RC2: + $this->cipher = new Cipher_RC2($key); + break; + + case self::CIPHER_RIJNDAEL_128: + $this->cipher = new Cipher_Rijndael_128($key); + break; + + case self::CIPHER_RIJNDAEL_192: + $this->cipher = new Cipher_Rijndael_192($key); + break; + + case self::CIPHER_RIJNDAEL_256: + $this->cipher = new Cipher_Rijndael_256($key); + break; + + case self::CIPHER_SIMPLEXOR: + $this->cipher = new Cipher_Simple_XOR($key); + break; + + case self::CIPHER_SKIPJACK: + $this->cipher = new Cipher_Skipjack($key); + break; + + case self::CIPHER_VIGENERE: + $this->cipher = new Cipher_Vigenere($key); + break; + + default: + trigger_error("$cipher is not a valid cipher", E_USER_WARNING); + } + + + /* + * MODES + */ + switch($mode) + { + case self::MODE_CBC: + $this->mode = new Mode_CBC($this->cipher); + break; + + case self::MODE_CFB: + $this->mode = new Mode_CFB($this->cipher); + break; + + case self::MODE_CTR: + $this->mode = new Mode_CTR($this->cipher); + break; + + case self::MODE_ECB: + $this->mode = new Mode_ECB($this->cipher); + break; + + case self::MODE_NCFB: + $this->mode = new Mode_NCFB($this->cipher); + break; + + case self::MODE_NOFB: + $this->mode = new Mode_NOFB($this->cipher); + break; + + case self::MODE_OFB: + $this->mode = new Mode_OFB($this->cipher); + break; + + case self::MODE_PCBC: + $this->mode = new Mode_PCBC($this->cipher); + break; + + case self::MODE_RAW: + $this->mode = new Mode_RAW($this->cipher); + break; + + case self::MODE_STREAM: + $this->mode = new Mode_Stream($this->cipher); + break; + + default: + trigger_error("$mode is not a valid mode", E_USER_WARNING); + } + + // set the default padding + $this->padding($padding); + } + + + /** + * Destructor + * + * @return void + */ + public function __destruct() + { + + } + + + /** + * Encrypt a plain text message using the Mode and Cipher selected. + * Some stream modes require this function to be called in a loop + * which requires the use of $result parameter to retrieve + * the decrypted data. + * + * @param string $text The plain text string + * @return string The encrypted string + */ + public function encrypt($text) + { + // check that an iv is set, if required by the mode + $this->mode->checkIV(); + + // the encryption is done inside the mode + $this->mode->encrypt($text); + return $text; + } + + + /** + * Decrypt an encrypted message using the Mode and Cipher selected. + * Some stream modes require this function to be called in a loop + * which requires the use of $result parameter to retrieve + * the decrypted data. + * + * @param string $text The encrypted string + * @return string The decrypted string + */ + public function decrypt($text) + { + // check that an iv is set, if required by the mode + $this->mode->checkIV(); + + // the decryption is done inside the mode + $this->mode->decrypt($text); + return $text; + } + + + /** + * Return the cipher object being used + * + * @return object The Cipher object + */ + public function cipher() + { + return $this->cipher; + } + + + /** + * Return the mode object being used + * + * @return object The Mode object + */ + public function mode() + { + return $this->mode; + } + + + /** + * Returns the name of the cipher being used + * + * @return string The name of the cipher currently in use, + * it will be one of the predefined phpCrypt cipher constants + */ + public function cipherName() + { + return $this->cipher->name(); + } + + + /** + * Return the name of the mode being used + * + * @return string The name of the mode in use, it will + * be one of the predefined phpCrypt mode constants + */ + public function modeName() + { + return $this->mode->name(); + } + + + /** + * Returns Ciphers required block size in bytes + * + * @return integer The cipher data block size, in bytes + */ + public function cipherBlockSize() + { + return $this->cipher->blockSize(); + } + + + /** + * Returns the cipher's required key size, in bytes + * + * @return integer The cipher's key size requirement, in bytes + */ + public function cipherKeySize() + { + return $this->cipher->keySize(); + } + + + /** + * Sets and/or returns the key to be used. Normally you set + * the key in the phpCrypt constructor. This can be usefully + * if you need to change the key on the fly and don't want + * to create a new instance of phpCrypt. + * + * If the $key parameter is not given, this function will simply + * return the key currently in use. + * + * @param string $key Optional, The key to set + * @return string The key being used + */ + public function cipherKey($key = "") + { + return $this->cipher->key($key); + } + + + /** + * A helper function which will create a random key. Calls + * Core::randBytes(). By default it will use PHP_Crypt::RAND for + * the random source of bytes, and return a PHP_Crypt::RAND_DEFAULT_SZ + * byte string. There are 4 ways to create a random byte string by + * setting the $src parameter: + * PHP_Crypt::RAND - Default, uses mt_rand() + * PHP_Crypt::RAND_DEV_RAND - Unix only, uses /dev/random + * PHP_Crypt::RAND_DEV_URAND - Unix only, uses /dev/urandom + * PHP_Crypt::RAND_WIN_COM - Windows only, uses Microsoft's CAPICOM SDK + * + * @param string $src Optional, The source to use to create random bytes + * @param integer $len Optional, The number of random bytes to return + * @return string A random string of bytes + */ + public static function createKey($src = self::RAND, $len = self::RAND_DEFAULT_SZ) + { + return Core::randBytes($src, $len); + } + + + /** + * Sets the IV to use. Note that you do not need to call + * this function if creating an IV using createIV(). This + * function is used when an IV has already been created + * outside of phpCrypt and needs to be set. Alternatively + * you can just pass the $iv parameter to the encrypt() + * or decrypt() functions + * + * When the $iv parameter is not given, the function will + * return the current IV being used. See createIV() if you + * need to create an IV. + * + * @param string $iv Optional, The IV to use during Encryption/Decryption + * @return void + */ + public function IV($iv = "") + { + return $this->mode->IV($iv); + } + + + /** + * Creates an IV for the the Cipher selected, if one is required. + * If you already have an IV to use, this function does not need + * to be called, instead set it with setIV(). If you create an + * IV with createIV(), you do not need to set it with setIV(), + * as it is automatically set in this function + * + * $src values are: + * PHP_Crypt::RAND - Default, uses mt_rand() + * PHP_Crypt::RAND_DEV_RAND - Unix only, uses /dev/random + * PHP_Crypt::RAND_DEV_URAND - Unix only, uses /dev/urandom + * PHP_Crypt::RAND_WIN_COM - Windows only, uses Microsoft's CAPICOM SDK + * + * @param string $src Optional, how the IV is generated + * @return string The IV that was created, and set for the mode + */ + public function createIV($src = self::RAND) + { + return $this->mode->createIV($src); + } + + + /** + * Sets the type of padding to be used within the specified Mode + * + * @param string $type One of the predefined padding types + * @return void + */ + public function padding($type = "") + { + return $this->mode->padding($type); + } +} +?> \ No newline at end of file diff --git a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php new file mode 100644 index 0000000000..78d5ac5e2c --- /dev/null +++ b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php @@ -0,0 +1,629 @@ + 'boolean', + 'yearly_cost_limit' => 'text', + 'yearly_hours_limit' => 'text', + 'yearly_cost_unit_converter' => 'text', + 'courses_count_limit' => 'text', + 'course_session_credit_year_start_date' => 'text', + 'ws_url' => 'text', + 'min_profile_percentage' => 'text', + 'check_induction' => 'boolean', + 'confirmation_message' => 'wysiwyg' + ); + + parent::__construct('1.0', 'Imanol Losada, Daniel Barreto', $parameters); + } + + /** + * Instance the plugin + * @staticvar null $result + * @return AdvancedSubscriptionPlugin + */ + static function create() + { + static $result = null; + + return $result ? $result : $result = new self(); + } + + /** + * Install the plugin + * @return void + */ + public function install() + { + $this->installDatabase(); + $this->installHook(); + } + + /** + * Uninstall the plugin + * @return void + */ + public function uninstall() + { + $this->uninstallHook(); + $this->uninstallDatabase(); + } + + /** + * Create the database tables for the plugin + * @return void + */ + private function installDatabase() + { + $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); + $pAdvSubMailTable = Database::get_main_table(TABLE_ADV_SUB_MAIL); + $pAdvSubMailTypeTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_TYPE); + $pAdvSubMailStatusTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_STATUS); + + $sql = "CREATE TABLE IF NOT EXISTS $pAdvSubQueueTable (" . + "id int UNSIGNED NOT NULL AUTO_INCREMENT, " . + "session_id int UNSIGNED NOT NULL, " . + "user_id int UNSIGNED NOT NULL, " . + "status int UNSIGNED NOT NULL, " . + "created_at datetime NOT NULL, " . + "updated_at datetime NULL, " . + "PRIMARY KEY PK_tour_log (id)); "; + Database::query($sql); + + $sql = "CREATE TABLE $pAdvSubMailTypeTable ( " . + "id int UNSIGNED NOT NULL AUTO_INCREMENT, " . + "description char(20), " . + "PRIMARY KEY PK_advsub_mail_type (id) " . + "); "; + + Database::query($sql); + $sql = "CREATE TABLE $pAdvSubMailTable ( " . + "id int UNSIGNED NOT NULL AUTO_INCREMENT, " . + "message_id, mail_type_id, mail_status_id, " . + "PRIMARY KEY PK_advsub_mail (id) " . + "); "; + Database::query($sql); + + $sql = "CREATE TABLE $pAdvSubMailStatusTable ( " . + "id int UNSIGNED NOT NULL AUTO_INCREMENT, " . + "description char(20), " . + "PRIMARY KEY PK_advsub_mail_status (id) " . + "); "; + Database::query($sql); + } + + /** + * Drop the database tables for the plugin + * @return void + */ + private function uninstallDatabase() + { + /* Drop plugin tables */ + $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); + $pAdvSubMailTable = Database::get_main_table(TABLE_ADV_SUB_MAIL); + $pAdvSubMailTypeTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_TYPE); + $pAdvSubMailStatusTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_STATUS); + + $sql = "DROP TABLE IF EXISTS $pAdvSubQueueTable; "; + Database::query($sql); + $sql = "DROP TABLE IF EXISTS $pAdvSubMailTable; "; + Database::query($sql); + $sql = "DROP TABLE IF EXISTS $pAdvSubMailTypeTable; "; + Database::query($sql); + $sql = "DROP TABLE IF EXISTS $pAdvSubMailStatusTable; "; + Database::query($sql); + + /* Delete settings */ + $tSettings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT); + Database::query("DELETE FROM $tSettings WHERE subkey = 'advancedsubscription'"); + } + + /** + * Return true if user is able to be added to queue for session subscription + * @param int $userId + * @param array $params MUST have keys: + * "is_connected" Indicate if the user is online on external web + * "profile_completed" Percentage of completed profile, given by WS + * @throws Exception + * @return bool + */ + public function isAbleToRequest($userId, $params = array()) + { + if (isset($params['is_connected']) && isset($params['profile_completed'])) { + $isAble = false; + $advSubPlugin = self::create(); + $wsUrl = $advSubPlugin->get('ws_url'); + // @TODO: Get connection status from user by WS + $isConnected = $params['is_connected']; + if ($isConnected) { + $profileCompletedMin = (float) $advSubPlugin->get('min_profile_percentage'); + // @TODO: Get completed profile percentage by WS + $profileCompleted = (float) $params['profile_completed']; + if ($profileCompleted > $profileCompletedMin) { + $checkInduction = $advSubPlugin->get('check_induction'); + // @TODO: check if user have completed at least one induction session + $completedInduction = true; + if (!$checkInduction || $completedInduction) { + $uitMax = $advSubPlugin->get('yearly_cost_unit_converter'); + $uitMax *= $advSubPlugin->get('yearly_cost_limit'); + // @TODO: Get UIT completed by user this year by WS + $uitUser = 0; + if ($uitMax > $uitUser) { + $expendedTimeMax = $advSubPlugin->get('yearly_hours_limit'); + // @TODO: Get Expended time from user data + $expendedTime = 0; + if ($expendedTimeMax > $expendedTime) { + $expendedNumMax = $advSubPlugin->get('courses_count_limit'); + // @TODO: Get Expended num from user + $expendedNum = 0; + if ($expendedNumMax > $expendedNum) { + $isAble = true; + } else { + throw new \Exception(get_lang('AdvancedSubscriptionCourseXLimitReached')); + } + } else { + throw new \Exception(get_lang('AdvancedSubscriptionTimeXLimitReached')); + } + } else { + throw new \Exception(get_lang('AdvancedSubscriptionCostXLimitReached')); + } + } else { + throw new \Exception(get_lang('AdvancedSubscriptionIncompleteInduction')); + } + } else { + throw new \Exception(get_lang('AdvancedSubscriptionProfileIncomplete')); + } + } else { + throw new \Exception(get_lang('AdvancedSubscriptionNotConnected')); + } + + return $isAble; + } else { + throw new \Exception($this->get_lang('AdvancedSubscriptionIncompleteParams')); + } + + } + + /** + * @param $userId + * @param $sessionId + * @return bool|int + */ + public function addToQueue($userId, $sessionId) + { + $now = api_get_utc_datetime(); + $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); + $attributes = array( + 'session_id' => $sessionId, + 'user_id' => $userId, + 'status' => 0, + 'created_at' => $now, + 'updated_at' => null, + ); + + $id = Database::insert($pAdvSubQueueTable, $attributes); + + return $id; + } + + /** + * @param $userId + * @param $sessionId + * @return bool|string + */ + public function startSubscription($userId, $sessionId, $params) + { + $result = false; + if (isset($params['accept']) && !empty($sessionId) && !empty($userId)) { + $advSub = self::create(); + try { + if ($advSub->isAbleToRequest($userId, $params)) { + $result = (bool) $advSub->addToQueue($userId, $sessionId); + } else { + throw new \Exception(get_lang('AdvancedSubscriptionNotMoreAble')); + } + } catch (Exception $e) { + $result = $e->getMessage(); + } + } else { + $result = 'Params not found'; + } + + return $result; + } + + /** + * Check if session is open for subscription + * @param $sessionId + * @param string $fieldVariable + * @return bool + */ + public function isSessionOpen($sessionId, $fieldVariable = 'es_abierta') + { + $sessionId = (int) $sessionId; + $fieldVariable = Database::escape_string($fieldVariable); + $isOpen = false; + if ($sessionId > 0 && !empty($fieldVariable)) { + $sfTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD); + $sfvTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES); + $joinTable = $sfvTable . ' sfv INNER JOIN ' . $sfTable . ' sf ON sfv.field_id = sf.id '; + $row = Database::select( + 'sfv.field_value as field_value', + $joinTable, + array( + 'where' => array( + 'sfv.session_id = ? AND ' => $sessionId, + 'sf.field_variable = ?' => $fieldVariable, + ) + ) + ); + if (isset($row[0]) && is_array($row[0])) { + $isOpen = (bool) $row[0]['field_value']; + } + } + + return $isOpen; + } + + public function updateQueueStatus($params, $newStatus) + { + if (isset($params['queue']['id'])) { + $where = array( + 'id' => $params['queue']['id'], + ); + } elseif(isset($params['user']['id']) && isset($params['session']['id'])) { + $where = array( + 'user_id' => $params['user']['id'], + 'session_id' => $params['session']['id'], + ); + } + if (isset($where)) { + $res = Database::update( + Database::get_main_table(TABLE_ADV_SUB_QUEUE), + array( + 'unsigned' => $newStatus, + ), + $where + ); + } else { + $res = false; + } + + return $res; + } + + /** + * @param $userId + * @param $relationType + */ + public function sendMail($data, $actionType) + { + global $_configuration; // @TODO: Add $_configuration['no_reply_user_id'] to configuration file + $tpl= new Template($this->get_lang('plugin_title')); + $tpl->assign('data', $data); + $tplParams = array('user', 'student', 'students','superior', 'admin', 'session', 'signature', '_p', ); + foreach ($tplParams as $tplParam) { + if (isset($data['superior'])) { + $tpl->assign($tplParam, $data[$tplParam]); + } + } + switch ($actionType) { + case ADV_SUB_ACTION_STUDENT_REQUEST: + // Mail to student + MessageManager::send_message( + $data['student']['id'], + $this->get_lang('MailStudentRequest'), + $tpl->fetch('/advancedsubscription/views/advsub_request_received.tpl'), + null, + null, + null, + null, + null, + null, + $_configuration['no_reply_user_id'] + ); + // Mail to superior + MessageManager::send_message( + $data['superior']['id'], + $this->get_lang('MailStudentRequest'), + $tpl->fetch('/advancedsubscription/views/advsub_request_superior.tpl'), + null, + null, + null, + null, + null, + null, + $_configuration['no_reply_user_id'] + ); + break; + case ADV_SUB_ACTION_SUPERIOR_APPROVE: + // Mail to student + MessageManager::send_message( + $data['student']['id'], + $this->get_lang('MailStudentRequest'), + $tpl->fetch('/advancedsubscription/views/advsub_request_superior_approved.tpl'), + null, + null, + null, + null, + null, + null, + $_configuration['no_reply_user_id'] + ); + // Mail to superior + MessageManager::send_message( + $data['superior']['id'], + $this->get_lang('MailStudentRequest'), + $tpl->fetch('/advancedsubscription/views/advsub_approve_confirmed.tpl'), + null, + null, + null, + null, + null, + null, + $_configuration['no_reply_user_id'] + ); + // Mail to admin + MessageManager::send_message( + $data['admin']['id'], + $this->get_lang('MailStudentRequest'), + $tpl->fetch('/advancedsubscription/views/advsub_request_approved_info_admin.tpl'), + null, + null, + null, + null, + null, + null, + $_configuration['no_reply_user_id'] + ); + break; + case ADV_SUB_ACTION_SUPERIOR_DISAPPROVE: + // Mail to student + MessageManager::send_message( + $data['student']['id'], + $this->get_lang('MailStudentRequest'), + $tpl->fetch('/advancedsubscription/views/advsub_request_superior_disapproved.tpl'), + null, + null, + null, + null, + null, + null, + $_configuration['no_reply_user_id'] + ); + // Mail to superior + MessageManager::send_message( + $data['superior']['id'], + $this->get_lang('MailStudentRequest'), + $tpl->fetch('/advancedsubscription/views/advsub_disapprove_confirmed.tpl'), + null, + null, + null, + null, + null, + null, + $_configuration['no_reply_user_id'] + ); + break; + case ADV_SUB_ACTION_SUPERIOR_SELECT: + // Mail to student + MessageManager::send_message( + $data['student']['id'], + $this->get_lang('MailStudentRequest'), + $tpl->fetch('/advancedsubscription/views/advsub_request_received.tpl'), + null, + null, + null, + null, + null, + null, + $_configuration['no_reply_user_id'] + ); + // Mail to superior + MessageManager::send_message( + $data['superior']['id'], + $this->get_lang('MailStudentRequest'), + $tpl->fetch('/advancedsubscription/views/advsub_request_superior.tpl'), + null, + null, + null, + null, + null, + null, + $_configuration['no_reply_user_id'] + ); + break; + case ADV_SUB_ACTION_ADMIN_APPROVE: + // Mail to student + MessageManager::send_message( + $data['student']['id'], + $this->get_lang('MailStudentRequest'), + $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_accepted_notice_student.tpl'), + null, + null, + null, + null, + null, + null, + $_configuration['no_reply_user_id'] + ); + // Mail to superior + MessageManager::send_message( + $data['superior']['id'], + $this->get_lang('MailStudentRequest'), + $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_accepted_notice_superior.tpl'), + null, + null, + null, + null, + null, + null, + $_configuration['no_reply_user_id'] + ); + // Mail to admin + MessageManager::send_message( + $data['admin']['id'], + $this->get_lang('MailStudentRequest'), + $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl'), + null, + null, + null, + null, + null, + null, + $_configuration['no_reply_user_id'] + ); + break; + case ADV_SUB_ACTION_ADMIN_DISAPPROVE: + // Mail to student + MessageManager::send_message( + $data['student']['id'], + $this->get_lang('MailStudentRequest'), + $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_rejected_notice_student.tpl'), + null, + null, + null, + null, + null, + null, + $_configuration['no_reply_user_id'] + ); + // Mail to superior + MessageManager::send_message( + $data['superior']['id'], + $this->get_lang('MailStudentRequest'), + $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_rejected_notice_superior.tpl'), + null, + null, + null, + null, + null, + null, + $_configuration['no_reply_user_id'] + ); + // Mail to admin + MessageManager::send_message( + $data['admin']['id'], + $this->get_lang('MailStudentRequest'), + $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_rejected_notice_admin.tpl'), + null, + null, + null, + null, + null, + null, + $_configuration['no_reply_user_id'] + ); + break; + default: + break; + } + } + + /** + * Count the users in queue filtered by params (sessions, status) + * @param array $params Input array containing the set of + * session and status to count from queue + * e.g: + * array('sessions' => array(215, 218, 345, 502), + * 'status' => array(0, 1, 2)) + * @return int + */ + public function countQueueByParams($params) + { + $count = 0; + if (!empty($params) && is_array($params)) { + $advsubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); + $where['1 = ? '] = 1; + if (isset($params['sessions']) && is_array($params['sessions'])) { + $where['AND session_id IN ( ? ) '] = implode($params['sessions']); + } + if (isset($params['status']) && is_array($params['status'])) { + $where['AND status IN ( ? ) '] = implode($params['status']); + } + $where['where'] = $where; + $count = Database::select('COUNT(*)', $advsubQueueTable, $where); + $count = $count[0]; + } + return $count; + } + + /** + * This method will call the Hook management insertHook to add Hook observer from this plugin + * @return int + */ + public function installHook() + { + if (HookEvent::isHookPluginActive()) { + $hookObserver = HookAdvancedSubscription::create(); + HookAdminBlock::create()->attach($hookObserver); + HookWSRegistration::create()->attach($hookObserver); + } else { + // Hook management plugin is not enabled + } + } + + /** + * This method will call the Hook management deleteHook to disable Hook observer from this plugin + * @return int + */ + public function uninstallHook() + { + $hookObserver = HookAdvancedSubscription::create(); + HookAdminBlock::create()->detach($hookObserver); + HookWSRegistration::create()->detach($hookObserver); + } + + /** + * Use AES-256 Encryption and url encoded + * Return the message encrypted + * @param mixed $data + * @return string + */ + public function encrypt($data) + { + global $_config; + $key = sha1($_config['secret_key']); + $crypt = new PHP_Crypt($key, PHP_Crypt::CIPHER_AES_256, PHP_Crypt::MODE_CTR); + $encrypted = $crypt->createIV(); + $encrypted .= $crypt->encrypt(serialize($data)); + $encrypted = urlencode($encrypted); + + return $encrypted; + } + + /** + * Decrypt a message decoding as url an then decrypt AES-256 method + * Return the message decrypted + * @param $encrypted + * @return mixed + */ + public function decrypt($encrypted) + { + global $_config; + $encrypted = urldecode($encrypted); + $key = sha1($_config['secret_key']); + $crypt = new PHP_Crypt($key, PHP_Crypt::CIPHER_AES_256, PHP_Crypt::MODE_CTR); + $iv = substr($encrypted, 0, 16); + $crypt->IV($iv); + $data = unserialize($crypt->decrypt(substr($encrypted, 16))); + + return $data; + } +} diff --git a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php new file mode 100644 index 0000000000..a5a7f95bf8 --- /dev/null +++ b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php @@ -0,0 +1,204 @@ +getEventData(); + if ($data['type'] === HOOK_TYPE_PRE) { + // Nothing to do + } elseif ($data['type'] === HOOK_TYPE_POST) { + if (isset($data['blocks'])) { + $data['blocks']['sessions']['items'][] = array( + 'url' => 'configure_plugin.php?name=advancedsubscription', + 'label' => get_plugin_lang('plugin_title', 'AdvancedSubscriptionPlugin'), + ); + } + } else { + // Hook type is not valid + // Nothing to do + } + + return $data; + } + + /** + * @param HookWSRegistrationEventInterface $hook + * @return int + */ + public function hookWSRegistration(HookWSRegistrationEventInterface $hook) + { + $data = $hook->getEventData(); + if ($data['type'] === HOOK_TYPE_PRE) { + + } elseif ($data['type'] === HOOK_TYPE_POST) { + /** @var \nusoap_server $server */ + $server = &$data['server']; + + /** WSSessionListInCategory */ + + // Output params for WSSessionListInCategory + $server->wsdl->addComplexType( + 'sessionBrief', + 'complexType', + 'struct', + 'all', + '', + array( + 'name' => array('name' => 'name', 'type' => 'xsd:string'), //Course string code + 'description' => array('name' => 'description', 'type' => 'xsd:string'), //Chamilo user_id + 'date_start' => array('name' => 'start_date', 'type' => 'xsd:string'), + 'date_end' => array('name' => 'end_date', 'type' => 'xsd:string'), + ) + ); + + $server->wsdl->addComplexType( + 'sessionBriefList', + 'complexType', + 'array', + '', + 'SOAP-ENC:Array', + array(), + array( + array('ref'=>'SOAP-ENC:arrayType', + 'wsdl:arrayType'=>'tns:sessionBrief[]') + ), + 'tns:sessionBrief' + ); + + // Input params for editing users + $server->wsdl->addComplexType( + 'sessionCategoryInput', + 'complexType', + 'struct', + 'all', + '', + array( + 'id' => array('name' => 'id', 'type' => 'xsd:string'), //Course string code + 'name' => array('name' => 'name', 'type' => 'xsd:string'), //Chamilo user_id + 'secret_key' => array('name' => 'secret_key', 'type' => 'xsd:string') + ) + ); + + // Register the method to expose + $server->register('HookAdvancedSubscription..WSSessionListInCategory', // method name + array('sessionCategoryInput' => 'tns:sessionCategoryInput'), // input parameters + array('return' => 'tns:sessionBriefList'), // output parameters + 'urn:WSRegistration', // namespace + 'urn:WSRegistration#WSSessionListInCategory', // soapaction + 'rpc', // style + 'encoded', // use + 'This service checks if user assigned to course' // documentation + ); + + $server->register('HookAdvancedSubscription..WSAdvsubEncrypt', // method name + array('sessionCategoryInput' => 'xsd:string'), // input parameters + array('return' => 'xsd:string'), // output parameters + 'urn:WSRegistration', // namespace + 'urn:WSRegistration#WSAdvsubEncrypt', // soapaction + 'rpc', // style + 'encoded', // use + 'This service encrpyt data to be used later in urls' // documentation + ); + + return $data; + } else { + // Nothing to do + } + } + + /** + * @param $params + * @return null|soap_fault + */ + public static function WSSessionListInCategory($params) { + global $debug; + + if ($debug) error_log('WSUserSubscribedInCourse'); + if ($debug) error_log('Params '. print_r($params, 1)); + if (!WSHelperVerifyKey($params)) { + + return return_error(WS_ERROR_SECRET_KEY); + } + // Check if category ID is set + if (!empty($params['id']) && empty($params['category_name'])) { + $sessionCategoryId = $params['id']; + } elseif (!empty($params['category_name'])) { + // Check if category name is set + $sessionCategoryId = SessionManager::getSessionCategoryIdByName($params['category_name']); + if (is_array($sessionCategoryId)) { + $sessionCategoryId = current($sessionCategoryId); + } + } else { + // Return soap fault Not valid input params + + return return_error(WS_ERROR_INVALID_INPUT); + } + + // Get the session brief List by category + + $sessionList = SessionManager::getSessionBriefListByCategory($sessionCategoryId); + + if (empty($sessionList)) { + + return return_error(WS_ERROR_NOT_FOUND_RESULT); + } + + return $sessionList; + } + + /** + * @param $data + * @return null|soap_fault|string + */ + public static function WSAdvsubEncrypt($data) + { + global $debug; + + if ($debug) error_log('WSUserSubscribedInCourse'); + if ($debug) error_log('Params '. print_r($data, 1)); + if (!WSHelperVerifyKey($data)) { + + //return return_error(WS_ERROR_SECRET_KEY); + } + // Check if data is a string + if (is_string($data)) { + $enc = AdvancedSubscriptionPlugin::create()->encrypt($data); + if (is_string($enc) && strlen($enc) > 16) { + $result = $enc; + } else { + $result = return_error(WS_ERROR_INVALID_INPUT); + } + } else { + // Return soap fault Not valid input params + + $result = return_error(WS_ERROR_INVALID_INPUT); + } + + return $result; + } + +} \ No newline at end of file diff --git a/plugin/advancedsubscription/src/advanced_subscription_plugin.class.php b/plugin/advancedsubscription/src/advanced_subscription_plugin.class.php deleted file mode 100644 index 334d8ecff5..0000000000 --- a/plugin/advancedsubscription/src/advanced_subscription_plugin.class.php +++ /dev/null @@ -1,333 +0,0 @@ - 'boolean', - 'yearly_cost_limit' => 'text', - 'yearly_hours_limit' => 'text', - 'yearly_cost_unit_converter' => 'text', - 'courses_count_limit' => 'text', - 'course_session_credit_year_start_date' => 'text', - 'ws_url' => 'text', - 'min_profile_percentage' => 'text', - 'check_induction' => 'boolean', - 'confirmation_message' => 'wysiwyg' - ); - - parent::__construct('1.0', 'Imanol Losada, Daniel Barreto', $parameters); - } - - /** - * Instance the plugin - * @staticvar null $result - * @return AdvancedSubscriptionPlugin - */ - static function create() - { - static $result = null; - - return $result ? $result : $result = new self(); - } - - /** - * Install the plugin - * @return void - */ - public function install() - { - $this->installDatabase(); - } - - /** - * Uninstall the plugin - * @return void - */ - public function uninstall() - { - $this->uninstallDatabase(); - } - - /** - * Create the database tables for the plugin - * @return void - */ - private function installDatabase() - { - $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); - $pAdvSubMailTable = Database::get_main_table(TABLE_ADV_SUB_MAIL); - $pAdvSubMailTypeTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_TYPE); - $pAdvSubMailStatusTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_STATUS); - - $sql = "CREATE TABLE IF NOT EXISTS $pAdvSubQueueTable (" . - "id int UNSIGNED NOT NULL AUTO_INCREMENT, " . - "session_id varchar(255) NOT NULL, " . - "user_id int UNSIGNED NOT NULL, " . - "status int UNSIGNED NOT NULL, " . - "created_at datetime NOT NULL, " . - "updated_at datetime NULL, " . - "PRIMARY KEY PK_tour_log (id)); "; - - $sql .= "CREATE TABLE $pAdvSubMailTypeTable ( " . - "id int UNSIGNED NOT NULL AUTO_INCREMENT, " . - "description char(20), " . - "PRIMARY KEY PK_advsub_mail_type (id) " . - "); "; - $sql .= "CREATE TABLE $pAdvSubMailTable ( " . - "id int UNSIGNED NOT NULL AUTO_INCREMENT, " . - "message_id, mail_type_id, mail_status_id, " . - "PRIMARY KEY PK_advsub_mail (id) " . - "); "; - - $sql .= "CREATE TABLE $pAdvSubMailStatusTable ( " . - "id int UNSIGNED NOT NULL AUTO_INCREMENT, " . - "description char(20), " . - "PRIMARY KEY PK_advsub_mail_status (id) " . - "); "; - - echo $sql; - //Database::query($sql); - } - - /** - * Drop the database tables for the plugin - * @return void - */ - private function uninstallDatabase() - { - /* Drop plugin tables */ - $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); - $pAdvSubMailTable = Database::get_main_table(TABLE_ADV_SUB_MAIL); - $pAdvSubMailTypeTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_TYPE); - $pAdvSubMailStatusTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_STATUS); - - $sql = "DROP TABLE IF EXISTS $pAdvSubQueueTable; "; - $sql .= "DROP TABLE IF EXISTS $pAdvSubMailTable; "; - $sql .= "DROP TABLE IF EXISTS $pAdvSubMailTypeTable; "; - $sql .= "DROP TABLE IF EXISTS $pAdvSubMailStatusTable; "; - - Database::query($sql); - - /* Delete settings */ - $tSettings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT); - Database::query("DELETE FROM $tSettings WHERE subkey = 'advancedsubscription'"); - } - - /** - * Return true if user is able to be added to queue for session subscription - * @param int $userId - * @param array $params MUST have keys: - * "is_connected" Indicate if the user is online on external web - * "profile_completed" Percentage of completed profile, given by WS - * @throws Exception - * @return bool - */ - public function isAbleToRequest($userId, $params = array()) - { - if (isset($params['is_connected']) && isset($params['profile_completed'])) { - $isAble = false; - $advSubPlugin = self::create(); - $wsUrl = $advSubPlugin->get('ws_url'); - // @TODO: Get connection status from user by WS - $isConnected = $params['is_connected']; - if ($isConnected) { - $profileCompletedMin = $advSubPlugin->get('min_profile_percentage'); - // @TODO: Get completed profile percentage by WS - $profileCompleted = (float) $params['profile_completed']; - if ($profileCompleted > $profileCompletedMin) { - $checkInduction = $advSubPlugin->get('check_induction'); - // @TODO: check if user have completed at least one induction session - $completedInduction = true; - if (!$checkInduction || $completedInduction) { - $uitMax = $advSubPlugin->get('yearly_cost_unit_converter'); - $uitMax *= $advSubPlugin->get('yearly_cost_limit'); - // @TODO: Get UIT completed by user this year by WS - $uitUser = 0; - if ($uitMax > $uitUser) { - $expendedTimeMax = $advSubPlugin->get('yearly_hours_limit'); - // @TODO: Get Expended time from user data - $expendedTime = 0; - if ($expendedTimeMax > $expendedTime) { - $expendedNumMax = $advSubPlugin->get('courses_count_limit'); - // @TODO: Get Expended num from user - $expendedNum = 0; - if ($expendedNumMax > $expendedNum) { - $isAble = true; - } else { - throw new \Exception(get_lang('AdvancedSubscriptionCourseXLimitReached')); - } - } else { - throw new \Exception(get_lang('AdvancedSubscriptionTimeXLimitReached')); - } - } else { - throw new \Exception(get_lang('AdvancedSubscriptionCostXLimitReached')); - } - } else { - throw new \Exception(get_lang('AdvancedSubscriptionIncompleteInduction')); - } - } else { - throw new \Exception(get_lang('AdvancedSubscriptionProfileIncomplete')); - } - } else { - throw new \Exception(get_lang('AdvancedSubscriptionNotConnected')); - } - - return $isAble; - } else { - throw new \Exception($this->get_lang('AdvancedSubscriptionIncompleteParams')); - } - - } - - /** - * @param $userId - * @param $sessionId - */ - public function addToQueue($userId, $sessionId) - { - $now = api_get_utc_datetime(); - $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); - $sql = "INSERT INTO $pAdvSubQueueTable ( " . - "session_id, user_id, status, created_at, updated_at " . - ") VALUES ( " . - "$sessionId, $userId, 0, $now, NULL "; - "); "; - - } - - /** - * @param $userId - * @param $sessionId - * @return bool|string - */ - public function startSubscription($userId, $sessionId) - { - $result = false; - $advSub = self::create(); - try { - if ($advSub->isAbleToRequest($userId)) { - $advSub->addToQueue($userId, $sessionId); - $result = true; - } else { - throw new \Exception(get_lang('AdvancedSubscriptionNotMoreAble')); - } - } catch (Exception $e) { - $result = $e->getMessage(); - } - - return $result; - } - - /** - * Check if session is open for subscription - * @param $sessionId - * @param string $fieldVariable - * @return bool - */ - public function isSessionOpen($sessionId, $fieldVariable = 'es_abierta') - { - $sessionId = (int) $sessionId; - $fieldVariable = Database::escape_string($fieldVariable); - $isOpen = false; - if ($sessionId > 0 && !empty($fieldVariable)) { - $sfTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD); - $sfvTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES); - $joinTable = $sfvTable . ' sfv INNER JOIN ' . $sfTable . ' sf ON sfv.field_id = sf.id '; - $row = Database::select( - 'sfv.field_value as field_value', - $joinTable, - array( - 'where' => array( - 'sfv.session_id = ? AND ' => $sessionId, - 'sf.field_variable = ?' => $fieldVariable, - ) - ) - ); - if (isset($row[0]) && is_array($row[0])) { - $isOpen = (bool) $row[0]['field_value']; - } - } - - return $isOpen; - } - - public function approvedByBoss() - { - - } - - public function disapprovedByBoss() - { - - } - - public function approvedByAdmin() - { - - } - - public function disapprovedByAdmin() - { - - } - - public function confirmTermsAndConditions() - { - - } - - public function checkToken() - { - - } - - public function sendMail() - { - - } - - /** - * Count the users in queue filtered by params (sessions, status) - * @param array $params Input array containing the set of - * session and status to count from queue - * e.g: - * array('sessions' => array(215, 218, 345, 502), - * 'status' => array(0, 1, 2)) - * @return int - */ - public function countQueueByParams($params) - { - $count = 0; - if (!empty($params) && is_array($params)) { - $advsubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); - $where['1 = ? '] = 1; - if (isset($params['sessions']) && is_array($params['sessions'])) { - $where['AND session_id IN ( ? ) '] = implode($params['sessions']); - } - if (isset($params['status']) && is_array($params['status'])) { - $where['AND status IN ( ? ) '] = implode($params['status']); - } - $where['where'] = $where; - $count = Database::select('COUNT(*)', $advsubQueueTable, $where); - $count = $count[0]; - } - return $count; - } -} diff --git a/plugin/advancedsubscription/src/index.php b/plugin/advancedsubscription/src/index.php index 1c6ecb8580..6180e3be48 100644 --- a/plugin/advancedsubscription/src/index.php +++ b/plugin/advancedsubscription/src/index.php @@ -7,25 +7,59 @@ /** * */ -$plugin = AdvancedSubscriptionPlugin::create(); - -if (api_is_platform_admin()) { - $isAdmin = api_is_platform_admin(); - $title = $plugin->get_lang('CourseListOnSale'); - $templateName = $plugin->get_lang('BuyCourses'); - $tpl = new Template($templateName); - $tpl->assign('isAdmin', $isAdmin); - $tpl->assign('title', $title); - $tpl->assign('BuySessions', $plugin->get_lang('BuySessions')); - $tpl->assign('BuyCourses', $templateName); - $tpl->assign('ConfigurationOfSessionsAndPrices', $plugin->get_lang('ConfigurationOfSessionsAndPrices')); - $tpl->assign('ConfigurationOfCoursesAndPrices', $plugin->get_lang('ConfigurationOfCoursesAndPrices')); - $tpl->assign('ConfigurationOfPayments', $plugin->get_lang('ConfigurationOfPayments')); - $tpl->assign('OrdersPendingOfPayment', $plugin->get_lang('OrdersPendingOfPayment')); - $listing_tpl = 'buycourses/view/index.tpl'; - $content = $tpl->fetch($listing_tpl); - $tpl->assign('content', $content); - // If the user is NOT an administrator, redirect it to course/session buy list - $isAdmin ? $tpl->display_one_col_template() : header('Location: src/list.php'); +require_once __DIR__ . '/../config.php'; +$plugin = AdvancedSubscriptionPlugin::create(); +$data = isset($_REQUEST['data']) ? + strlen($_REQUEST['data']) > 16 ? + $plugin->decrypt($_REQUEST['data']) : + null : + null; +if (isset($data)) { + if (is_string($data)) { + $data = unserialize($data); + } + if (is_array($data)) { + if (isset($data['template'])) { + $template = '/advancedsubscription/views/' . $data['template']; + $templateName = $plugin->get_lang('plugin_title'); + $tpl = new Template($templateName); + $tplParams = array('user', 'student', 'students','superior', 'admin', 'session', 'signature', '_p', ); + foreach ($tplParams as $tplParam) { + if (isset($data['superior'])) { + $tpl->assign($tplParam, $data[$tplParam]); + } + } + $content = $tpl->fetch($template); + $tpl->assign('content', $content); + $tpl->display_one_col_template(); + } elseif ($data['action']) { + switch($data['action']) { + case ADV_SUB_ACTION_STUDENT_REQUEST: + $plugin->startSubscription($data['user']['id'], $data['session']['id'], $data); + $plugin->sendMail($data, $data['action']); + break; + case ADV_SUB_ACTION_SUPERIOR_APPROVE: + $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_APPROVED); + $plugin->sendMail($data, $data['action']); + break; + case ADV_SUB_ACTION_SUPERIOR_DISAPPROVE: + $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED); + $plugin->sendMail($data, $data['action']); + break; + case ADV_SUB_ACTION_SUPERIOR_SELECT: + $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_APPROVED); + $plugin->sendMail($data, $data['action']); + break; + case ADV_SUB_ACTION_ADMIN_APPROVE: + $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED); + $plugin->sendMail($data, $data['action']); + break; + case ADV_SUB_ACTION_ADMIN_DISAPPROVE: + $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED); + $plugin->sendMail($data, $data['action']); + break; + } + } + } } diff --git a/plugin/advancedsubscription/test.php b/plugin/advancedsubscription/test.php new file mode 100644 index 0000000000..087ffeb0c7 --- /dev/null +++ b/plugin/advancedsubscription/test.php @@ -0,0 +1,23 @@ +install(); +*/ \ No newline at end of file diff --git a/plugin/advancedsubscription/views/index.tpl b/plugin/advancedsubscription/views/index.tpl new file mode 100644 index 0000000000..e69de29bb2 From 484a6fed2351e12ae252005b81fc12151699d331 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Wed, 14 Jan 2015 17:12:01 -0500 Subject: [PATCH 09/72] Update templates, update send mail method - refs BT#9092 --- plugin/advancedsubscription/config.php | 10 +- .../src/AdvancedSubscriptionPlugin.class.php | 246 +++++++++--------- plugin/advancedsubscription/src/index.php | 22 +- plugin/advancedsubscription/test.php | 10 +- ...b_approval_admin_accepted_notice_admin.tpl | 85 ++++++ ...approval_admin_accepted_notice_student.tpl | 85 ++++++ ...pproval_admin_accepted_notice_superior.tpl | 85 ++++++ ...b_approval_admin_rejected_notice_admin.tpl | 85 ++++++ ...approval_admin_rejected_notice_student.tpl | 85 ++++++ ...pproval_admin_rejected_notice_superior.tpl | 85 ++++++ .../advsub_request_approve_confirmed.tpl | 85 ++++++ .../advsub_request_approved_info_admin.tpl | 85 ++++++ .../advsub_request_approved_reminder.tpl | 85 ++++++ .../advsub_request_disapprove_confirmed.tpl | 85 ++++++ .../views/advsub_request_received.tpl | 86 ++++++ .../advsub_request_received_reminder.tpl | 86 ++++++ .../views/advsub_request_superior.tpl | 94 +++++++ .../advsub_request_superior_approved.tpl | 85 ++++++ .../advsub_request_superior_disapproved.tpl | 85 ++++++ .../advsub_request_superior_reminder.tpl | 100 +++++++ .../advsub_request_superior_reminder_max.tpl | 101 +++++++ .../views/img/aprobar.png | Bin 0 -> 1482 bytes .../advancedsubscription/views/img/avatar.png | Bin 0 -> 4710 bytes .../views/img/desaprobar.png | Bin 0 -> 1901 bytes .../advancedsubscription/views/img/footer.png | Bin 0 -> 270 bytes .../advancedsubscription/views/img/header.png | Bin 0 -> 267 bytes .../advancedsubscription/views/img/line.png | Bin 0 -> 283 bytes .../views/img/logo-minedu.png | Bin 0 -> 8409 bytes 28 files changed, 1634 insertions(+), 141 deletions(-) create mode 100644 plugin/advancedsubscription/views/advsub_request_superior_reminder_max.tpl create mode 100644 plugin/advancedsubscription/views/img/aprobar.png create mode 100644 plugin/advancedsubscription/views/img/avatar.png create mode 100644 plugin/advancedsubscription/views/img/desaprobar.png create mode 100644 plugin/advancedsubscription/views/img/footer.png create mode 100644 plugin/advancedsubscription/views/img/header.png create mode 100644 plugin/advancedsubscription/views/img/line.png create mode 100644 plugin/advancedsubscription/views/img/logo-minedu.png diff --git a/plugin/advancedsubscription/config.php b/plugin/advancedsubscription/config.php index 924b1b1208..a9a298ec41 100644 --- a/plugin/advancedsubscription/config.php +++ b/plugin/advancedsubscription/config.php @@ -18,14 +18,22 @@ define('ADV_SUB_ACTION_SUPERIOR_SELECT', 3); define('ADV_SUB_ACTION_ADMIN_APPROVE', 4); define('ADV_SUB_ACTION_ADMIN_DISAPPROVE', 5); - define('ADV_SUB_QUEUE_STATUS_START', 0); define('ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED', 1); define('ADV_SUB_QUEUE_STATUS_BOSS_APPROVED', 2); define('ADV_SUB_QUEUE_STATUS_ADMIN_DISAPPROVED', 3); define('ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED', 10); +define('ADV_SUB_MAIL_TYPE_A', 1); +define('ADV_SUB_MAIL_TYPE_B', 2); +define('ADV_SUB_MAIL_TYPE_C', 3); + +define('ADV_SUB_MAIL_STATUS_MAIL_SENT', 1); +define('ADV_SUB_MAIL_STATUS_MAIL_ANSWERED', 2); +define('ADV_SUB_MAIL_STATUS_MAIL_EXPIRED', 3); + require_once __DIR__ . '/../../main/inc/global.inc.php'; +require_once api_get_path(LIBRARY_PATH) . 'plugin.class.php'; require_once __DIR__ . '/resources/phpcrypt/phpCrypt.php'; require_once api_get_path(LIBRARY_PATH) . 'plugin.class.php'; require_once api_get_path(PLUGIN_PATH) . 'advancedsubscription/src/AdvancedSubscriptionPlugin.class.php'; diff --git a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php index 78d5ac5e2c..e247bf7ba8 100644 --- a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php +++ b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php @@ -81,6 +81,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface "session_id int UNSIGNED NOT NULL, " . "user_id int UNSIGNED NOT NULL, " . "status int UNSIGNED NOT NULL, " . + "last_message_id UNSIGNED NOT NULL, " . "created_at datetime NOT NULL, " . "updated_at datetime NULL, " . "PRIMARY KEY PK_tour_log (id)); "; @@ -223,8 +224,65 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface } /** + * Register a message type + * @param $description + * @return bool|int + */ + public function addMessageType($description) + { + $pAdvSubMessageTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_TYPE); + $attributes = array( + 'description' => $description, + ); + + $id = Database::insert($pAdvSubMessageTable, $attributes); + + return $id; + } + + /** + * Register a message status + * @param $description + * @return bool|int + */ + public function addMessageStatus($description) + { + $pAdvSubMessageTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_STATUS); + $attributes = array( + 'description' => $description, + ); + + $id = Database::insert($pAdvSubMessageTable, $attributes); + + return $id; + } + + /** + * Register message with type and status + * @param $mailId + * @param $mailTypeId + * @param $mailStatusId + * @return bool|int + */ + public function addMessage($mailId, $mailTypeId, $mailStatusId) + { + $pAdvSubMessageTable = Database::get_main_table(TABLE_ADV_SUB_MAIL); + $attributes = array( + 'message_id' => $mailId, + 'mail_type_id' => $mailTypeId, + 'mail_status_id' => $mailStatusId, + ); + + $id = Database::insert($pAdvSubMessageTable, $attributes); + + return $id; + } + + /** + * Check for requirements and register user into queue * @param $userId * @param $sessionId + * @param $params * @return bool|string */ public function startSubscription($userId, $sessionId, $params) @@ -248,6 +306,31 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface return $result; } + public function sendMailMessage($studentId, $subject, $content, $type = '') + { + global $_configuration; // @TODO: Add $_configuration['no_reply_user_id'] to configuration file + + $mailId = MessageManager::send_message( + $studentId, + $subject, + $content, + null, + null, + null, + null, + null, + null, + $_configuration['no_reply_user_id'] + ); + + if (!empty($mailId)) { + // Save as sent message + $mailId = $this->addMessage($mailId, $type, ADV_SUB_MAIL_STATUS_MAIL_SENT); + } + + return $mailId; + } + /** * Check if session is open for subscription * @param $sessionId @@ -294,7 +377,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface ); } if (isset($where)) { - $res = Database::update( + $res = (bool) Database::update( Database::get_main_table(TABLE_ADV_SUB_QUEUE), array( 'unsigned' => $newStatus, @@ -309,13 +392,14 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface } /** - * @param $userId - * @param $relationType + * Render and send mail by defined advanced subscription action + * @param $data + * @param $actionType + * @return array */ public function sendMail($data, $actionType) { - global $_configuration; // @TODO: Add $_configuration['no_reply_user_id'] to configuration file - $tpl= new Template($this->get_lang('plugin_title')); + $tpl = new Template($this->get_lang('plugin_title')); $tpl->assign('data', $data); $tplParams = array('user', 'student', 'students','superior', 'admin', 'session', 'signature', '_p', ); foreach ($tplParams as $tplParam) { @@ -326,214 +410,126 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface switch ($actionType) { case ADV_SUB_ACTION_STUDENT_REQUEST: // Mail to student - MessageManager::send_message( + $mailIds[] = $this->sendMailMessage( $data['student']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_received.tpl'), - null, - null, - null, - null, - null, - null, - $_configuration['no_reply_user_id'] + ADV_SUB_MAIL_TYPE_A ); // Mail to superior - MessageManager::send_message( + $mailIds[] = $this->sendMailMessage( $data['superior']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_superior.tpl'), - null, - null, - null, - null, - null, - null, - $_configuration['no_reply_user_id'] + ADV_SUB_MAIL_TYPE_B ); break; case ADV_SUB_ACTION_SUPERIOR_APPROVE: // Mail to student - MessageManager::send_message( + $mailIds[] = $this->sendMailMessage( $data['student']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_superior_approved.tpl'), - null, - null, - null, - null, - null, - null, - $_configuration['no_reply_user_id'] + ADV_SUB_MAIL_TYPE_A ); // Mail to superior - MessageManager::send_message( + $mailIds[] = $this->sendMailMessage( $data['superior']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approve_confirmed.tpl'), - null, - null, - null, - null, - null, - null, - $_configuration['no_reply_user_id'] + ADV_SUB_MAIL_TYPE_B ); // Mail to admin - MessageManager::send_message( + $mailIds[] = $this->sendMailMessage( $data['admin']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_approved_info_admin.tpl'), - null, - null, - null, - null, - null, - null, - $_configuration['no_reply_user_id'] + ADV_SUB_MAIL_TYPE_C ); break; case ADV_SUB_ACTION_SUPERIOR_DISAPPROVE: // Mail to student - MessageManager::send_message( + $mailIds[] = $this->sendMailMessage( $data['student']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_superior_disapproved.tpl'), - null, - null, - null, - null, - null, - null, - $_configuration['no_reply_user_id'] + ADV_SUB_MAIL_TYPE_A ); // Mail to superior - MessageManager::send_message( + $mailIds[] = $this->sendMailMessage( $data['superior']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_disapprove_confirmed.tpl'), - null, - null, - null, - null, - null, - null, - $_configuration['no_reply_user_id'] + ADV_SUB_MAIL_TYPE_B ); break; case ADV_SUB_ACTION_SUPERIOR_SELECT: // Mail to student - MessageManager::send_message( + $mailIds[] = $this->sendMailMessage( $data['student']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_received.tpl'), - null, - null, - null, - null, - null, - null, - $_configuration['no_reply_user_id'] + ADV_SUB_MAIL_TYPE_A ); // Mail to superior - MessageManager::send_message( + $mailIds[] = $this->sendMailMessage( $data['superior']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_superior.tpl'), - null, - null, - null, - null, - null, - null, - $_configuration['no_reply_user_id'] + ADV_SUB_MAIL_TYPE_B ); break; case ADV_SUB_ACTION_ADMIN_APPROVE: // Mail to student - MessageManager::send_message( + $mailIds[] = $this->sendMailMessage( $data['student']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_accepted_notice_student.tpl'), - null, - null, - null, - null, - null, - null, - $_configuration['no_reply_user_id'] + ADV_SUB_MAIL_TYPE_A ); // Mail to superior - MessageManager::send_message( + $mailIds[] = $this->sendMailMessage( $data['superior']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_accepted_notice_superior.tpl'), - null, - null, - null, - null, - null, - null, - $_configuration['no_reply_user_id'] + ADV_SUB_MAIL_TYPE_B ); // Mail to admin - MessageManager::send_message( + $mailIds[] = $this->sendMailMessage( $data['admin']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl'), - null, - null, - null, - null, - null, - null, - $_configuration['no_reply_user_id'] + ADV_SUB_MAIL_TYPE_C ); break; case ADV_SUB_ACTION_ADMIN_DISAPPROVE: // Mail to student - MessageManager::send_message( + $mailIds[] = $this->sendMailMessage( $data['student']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_rejected_notice_student.tpl'), - null, - null, - null, - null, - null, - null, - $_configuration['no_reply_user_id'] + ADV_SUB_MAIL_TYPE_A ); // Mail to superior - MessageManager::send_message( + $mailIds[] = $this->sendMailMessage( $data['superior']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_rejected_notice_superior.tpl'), - null, - null, - null, - null, - null, - null, - $_configuration['no_reply_user_id'] + ADV_SUB_MAIL_TYPE_B ); // Mail to admin - MessageManager::send_message( + $mailIds[] = $this->sendMailMessage( $data['admin']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_rejected_notice_admin.tpl'), - null, - null, - null, - null, - null, - null, - $_configuration['no_reply_user_id'] + ADV_SUB_MAIL_TYPE_C ); break; default: break; } + + return $mailIds; } /** diff --git a/plugin/advancedsubscription/src/index.php b/plugin/advancedsubscription/src/index.php index 6180e3be48..69bd7b366b 100644 --- a/plugin/advancedsubscription/src/index.php +++ b/plugin/advancedsubscription/src/index.php @@ -36,30 +36,28 @@ if (isset($data)) { } elseif ($data['action']) { switch($data['action']) { case ADV_SUB_ACTION_STUDENT_REQUEST: - $plugin->startSubscription($data['user']['id'], $data['session']['id'], $data); - $plugin->sendMail($data, $data['action']); + $res = $plugin->startSubscription($data['user']['id'], $data['session']['id'], $data); break; case ADV_SUB_ACTION_SUPERIOR_APPROVE: - $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_APPROVED); - $plugin->sendMail($data, $data['action']); + $res = $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_APPROVED); break; case ADV_SUB_ACTION_SUPERIOR_DISAPPROVE: - $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED); - $plugin->sendMail($data, $data['action']); + $res = $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED); break; case ADV_SUB_ACTION_SUPERIOR_SELECT: - $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_APPROVED); - $plugin->sendMail($data, $data['action']); + $res = $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_APPROVED); break; case ADV_SUB_ACTION_ADMIN_APPROVE: - $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED); - $plugin->sendMail($data, $data['action']); + $res = $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED); break; case ADV_SUB_ACTION_ADMIN_DISAPPROVE: - $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED); - $plugin->sendMail($data, $data['action']); + $res = $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED); break; } + + if ($res === true) { + $plugin->sendMail($data, $data['action']); + } } } } diff --git a/plugin/advancedsubscription/test.php b/plugin/advancedsubscription/test.php index 087ffeb0c7..b5a8b6ab44 100644 --- a/plugin/advancedsubscription/test.php +++ b/plugin/advancedsubscription/test.php @@ -3,6 +3,7 @@ require_once '/var/www/chamilo-lms/main/inc/global.inc.php'; require_once __DIR__ . '/config.php'; +/* MessageManager::send_message( 18, get_lang('MailStudentRequest'), @@ -15,9 +16,12 @@ MessageManager::send_message( null, 17 ); +*/ + //api_mail_html('RECIPIENT', '9leinad0@gmail.com', 'TEST!', 'ESTOY TESTEANDO D:!', 'Dan', 'dbarreto@kabuto.com'); -/* + $advSub = AdvancedSubscriptionPlugin::create(); -$advSub->install(); -*/ \ No newline at end of file +$tpl = new Template('Hi'); +$body = $tpl->fetch('/advancedsubscription/views/advsub_request_received.tpl'); +$advSub->sendMailMessage(18, 'TEST', $body); diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl index 8b13789179..adfd3e03a5 100644 --- a/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl +++ b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl @@ -1 +1,86 @@ + + + + + Solicitud recibida para el curso {{ session.title }} + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ministerio de Educación 
   
   
 Información: Validación de inscripción recibida  
   
   
 

Estimado:

+

{{ admin.name }}

+

Hemos recibido y registrado su validación de la inscripción de {{ student.name }} ({{ student.official_code }}) al curso {{ session.title }}

+

Gracias.

+

{{ signature }}

 
   
 
+ + diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_student.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_student.tpl index 8b13789179..7524b181ef 100644 --- a/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_student.tpl +++ b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_student.tpl @@ -1 +1,86 @@ + + + + + Solicitud recibida para el curso {{ session.title }} + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ministerio de Educación 
   
   
 Aprobada: su inscripción al curso {{ session.title }} fue confirmada!  
   
   
 

Estimado:

+

{{ student.name }}

+

Nos complace informarle que su inscripción al curso {{ session.title }} iniciando el {{ session.start_date }} fue validada por los administradores rechazada por falta de cupos. Esperamos mantenga todo su ánimo y participe en otro curso o, en otra oportunidad, a este mismo curso.

+

Gracias.

+

{{ signature }}

 
   
 
+ + diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_superior.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_superior.tpl index 8b13789179..a41f120275 100644 --- a/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_superior.tpl +++ b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_superior.tpl @@ -1 +1,86 @@ + + + + + Solicitud recibida para el curso {{ session.title }} + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ministerio de Educación 
   
   
 Información: Validación de inscripción de {{ student.name }} al curso {{ session.title }}  
   
   
 

Estimado:

+

{{ superior.name }}

+

La inscripción de {{ student.name }} al curso {{ session.title }} iniciando el {{ session.start_date }}, que estaba pendiente de validación por los organizadores del curso, fue validada hacen unos minutos. Esperamos nos ayude en asegurar la completa disponibilidad de su colaborador(a) para la duración completa del curso.

+

Gracias.

+

{{ signature }}

 
   
 
+ + diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_admin.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_admin.tpl index 8b13789179..5ac7ca7362 100644 --- a/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_admin.tpl +++ b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_admin.tpl @@ -1 +1,86 @@ + + + + + Solicitud recibida para el curso {{ session.title }} + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ministerio de Educación 
   
   
 Información: rechazo de inscripción recibido  
   
   
 

Estimado:

+

{{ admin.name }}

+

Hemos recibido y registrado su rechazo de la inscripción de {{ student.name }} ({{ student.official_code }}) al curso {{ session.title }}

+

Gracias.

+

{{ signature }}

 
   
 
+ + diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_student.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_student.tpl index 8b13789179..49ea885fa0 100644 --- a/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_student.tpl +++ b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_student.tpl @@ -1 +1,86 @@ + + + + + Solicitud recibida para el curso {{ session.title }} + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ministerio de Educación 
   
   
 Rechazamos su inscripción al curso {{ session.title }}  
   
   
 

Estimado:

+

{{ student.name }}

+

Lamentamos informarle que su inscripción al curso {{ session.title }} iniciando el {{ session.start_date }} fue rechazada por falta de cupos. Esperamos mantenga todo su ánimo y participe en otro curso o, en otra oportunidad, a este mismo curso.

+

Gracias.

+

{{ signature }}

 
   
 
+ + diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_superior.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_superior.tpl index 8b13789179..eba308cff8 100644 --- a/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_superior.tpl +++ b/plugin/advancedsubscription/views/advsub_approval_admin_rejected_notice_superior.tpl @@ -1 +1,86 @@ + + + + + Solicitud recibida para el curso {{ session.title }} + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ministerio de Educación 
   
   
 Información: Rechazo de inscripción de {{ student.name }} al curso {{ session.title }}  
   
   
 

Estimado:

+

{{ admin.name }}

+

La inscripción de {{ student.name }} al curso {{ session.title }}, que había aprobado anteriormente, fue rechazada por falta de cupos. Les presentamos nuestras disculpas sinceras.

+

Gracias.

+

{{ signature }}

 
   
 
+ + diff --git a/plugin/advancedsubscription/views/advsub_request_approve_confirmed.tpl b/plugin/advancedsubscription/views/advsub_request_approve_confirmed.tpl index 8b13789179..896a67741c 100644 --- a/plugin/advancedsubscription/views/advsub_request_approve_confirmed.tpl +++ b/plugin/advancedsubscription/views/advsub_request_approve_confirmed.tpl @@ -1 +1,86 @@ + + + + + Solicitud recibida para el curso {{ session.title }} + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ministerio de Educación 
   
   
 Confirmación: Aprobación recibida para {{ student.name }}  
   
   
 

Estimado:

+

{{ student.name }}

+

Lamentamos informarle que, en esta oportunidad, su inscripción al curso {{ session.title }} NO ha sido aprobada. Esperamos mantenga todo su ánimo y participe en otro curso o, en otra oportunidad, a este mismo curso.

+

Gracias.

+

{{ signature }}

 
   
 
+ + diff --git a/plugin/advancedsubscription/views/advsub_request_approved_info_admin.tpl b/plugin/advancedsubscription/views/advsub_request_approved_info_admin.tpl index 8b13789179..8f4388c495 100644 --- a/plugin/advancedsubscription/views/advsub_request_approved_info_admin.tpl +++ b/plugin/advancedsubscription/views/advsub_request_approved_info_admin.tpl @@ -1 +1,86 @@ + + + + + Solicitud recibida para el curso {{ session.title }} + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ministerio de Educación 
   
   
 Aprobación de {{ student.name }} al curso {{ session.title }}  
   
   
 

Estimado:

+

{{ admin.name }}

+

La inscripción del alumno {{ student.name }} ({{ student.offical_code }}) al curso {{ session.title }} ha sido aprobada por su superior. Puede gestionar las inscripciones al curso aquí

+

Gracias.

+

{{ signature }}

 
   
 
+ + diff --git a/plugin/advancedsubscription/views/advsub_request_approved_reminder.tpl b/plugin/advancedsubscription/views/advsub_request_approved_reminder.tpl index 8b13789179..736de423ea 100644 --- a/plugin/advancedsubscription/views/advsub_request_approved_reminder.tpl +++ b/plugin/advancedsubscription/views/advsub_request_approved_reminder.tpl @@ -1 +1,86 @@ + + + + + Solicitud recibida para el curso {{ session.title }} + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ministerio de Educación 
   
   
 Inscripciones a {{ session.title }} pendiente de confirmación 
   
   
 

Estimado:

+

{{ admin.name }}

+

Las inscripciones siguientes al curso {{ session.title }} están pendientes de validación para ser efectivas. Por favor, dirigese al la página de administración para validarlos.

+

Gracias.

+

{{ signature }}

 
   
 
+ + diff --git a/plugin/advancedsubscription/views/advsub_request_disapprove_confirmed.tpl b/plugin/advancedsubscription/views/advsub_request_disapprove_confirmed.tpl index 8b13789179..f6a63ff2cd 100644 --- a/plugin/advancedsubscription/views/advsub_request_disapprove_confirmed.tpl +++ b/plugin/advancedsubscription/views/advsub_request_disapprove_confirmed.tpl @@ -1 +1,86 @@ + + + + + Solicitud recibida para el curso {{ session.title }} + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ministerio de Educación 
   
   
 Confirmación: Desaprobación recibida para {{ student.name }}  
   
   
 

Estimado:

+

{{ superior.name }}

+

Hemos recibido y registrado su decisión de desaprobar el curso {{ session.title }} para su colaborador {{ student.name }}

+

Gracias por su colaboración

+

{{ signature }}

 
   
 
+ + diff --git a/plugin/advancedsubscription/views/advsub_request_received.tpl b/plugin/advancedsubscription/views/advsub_request_received.tpl index 8b13789179..816c871eba 100644 --- a/plugin/advancedsubscription/views/advsub_request_received.tpl +++ b/plugin/advancedsubscription/views/advsub_request_received.tpl @@ -1 +1,87 @@ + + + + + Solicitud recibida para el curso {{ session.title }} + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ministerio de Educación 
   
   
 Solicitud recibida para el curso {{ sesion.title }} 
   
   
 

Estimado:

+

{{ user.name }}

+

Hemos recibido y registrado su solicitud de inscripción al curso {{ sesion.title }} para iniciarse el {{ session.start_date }}.

+

Su inscripción es pendiente primero de la aprobación de su superior, y luego de la disponibilidad de cupos. Un correo ha sido enviado a su superior para revisión y aprobación de su solicitud.

+

Gracias.

+

Equipo Forge

 
   
 
+ + diff --git a/plugin/advancedsubscription/views/advsub_request_received_reminder.tpl b/plugin/advancedsubscription/views/advsub_request_received_reminder.tpl index 8b13789179..76048ffe49 100644 --- a/plugin/advancedsubscription/views/advsub_request_received_reminder.tpl +++ b/plugin/advancedsubscription/views/advsub_request_received_reminder.tpl @@ -1 +1,87 @@ + + + + + Solicitud recibida para el curso {{ session.title }} + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ministerio de Educación 
   
   
 Información: Solicitud pendiente de aprobación para el curso {{ session.title }} 
   
   
 

Estimado:

+

{{ user.name }}

+

Este correo es para confirmar que hemos recibido y registrado su solicitud de inscripción al curso {{ session.title }}, por iniciarse el {{ session.start_date }}.

+

Su inscripción todavía no ha sido aprobada por su superior, por lo que hemos vuelto a enviarle un correo electrónico de recordatorio.

+

Gracias por su paciencia.

+

Equipo Forge

 
   
 
+ + diff --git a/plugin/advancedsubscription/views/advsub_request_superior.tpl b/plugin/advancedsubscription/views/advsub_request_superior.tpl index 8b13789179..4f12fe78a3 100644 --- a/plugin/advancedsubscription/views/advsub_request_superior.tpl +++ b/plugin/advancedsubscription/views/advsub_request_superior.tpl @@ -1 +1,95 @@ + + + + + Solicitud recibida para el curso {{ session.title }} + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ministerio de Educación 
   
   
 Solicitud de consideración de curso para un colaborador 
   
   
 

Estimado:

+

{{ superior.name }}

+

Hemos recibido una solicitud de inscripción de {{ student.name }} al curso {{ session.title }}, por iniciarse el {{ session.start_date }}. Detalles del curso: {{ sesion.description }}.

+

Le invitamos a aprobar o desarprobar esta inscripción, dando clic en el botón correspondiente a continuación.

+ + + + + + + +

{{ student.name }}

+

Gracias.

+

Equipo Forge

 
   
 
+ + diff --git a/plugin/advancedsubscription/views/advsub_request_superior_approved.tpl b/plugin/advancedsubscription/views/advsub_request_superior_approved.tpl index 8b13789179..1a43cbe411 100644 --- a/plugin/advancedsubscription/views/advsub_request_superior_approved.tpl +++ b/plugin/advancedsubscription/views/advsub_request_superior_approved.tpl @@ -1 +1,86 @@ + + + + + Solicitud recibida para el curso {{ session.title }} + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ministerio de Educación 
   
   
 Aprobado: Su inscripción al curso {{ session.title }} ha sido aprobada por su superior  
   
   
 

Estimado:

+

{{ student.name }}

+

Nos complace informarle que su inscripción al curso {{ session.title }} ha sido aprobada por su superior. Su inscripción ahora solo se encuentra pendiente de disponibilidad de cupos. Le avisaremos tan pronto como se confirme este último paso.

+

Gracias.

+

{{ signature }}

 
   
 
+ + diff --git a/plugin/advancedsubscription/views/advsub_request_superior_disapproved.tpl b/plugin/advancedsubscription/views/advsub_request_superior_disapproved.tpl index 8b13789179..352a2750d7 100644 --- a/plugin/advancedsubscription/views/advsub_request_superior_disapproved.tpl +++ b/plugin/advancedsubscription/views/advsub_request_superior_disapproved.tpl @@ -1 +1,86 @@ + + + + + Solicitud recibida para el curso {{ session.title }} + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ministerio de Educación 
   
   
 Información: Su inscripción al curso {{ session.title }} ha sido rechazada  
   
   
 

Estimado:

+

{{ student.name }}

+

Lamentamos informarle que, en esta oportunidad, su inscripción al curso {{ session.title }} NO ha sido aprobada. Esperamos mantenga todo su ánimo y participe en otro curso o, en otra oportunidad, a este mismo curso.

+

Gracias.

+

{{ signature }}

 
   
 
+ + diff --git a/plugin/advancedsubscription/views/advsub_request_superior_reminder.tpl b/plugin/advancedsubscription/views/advsub_request_superior_reminder.tpl index 8b13789179..0fc3388adb 100644 --- a/plugin/advancedsubscription/views/advsub_request_superior_reminder.tpl +++ b/plugin/advancedsubscription/views/advsub_request_superior_reminder.tpl @@ -1 +1,101 @@ + + + + + Solicitud recibida para el curso {{ session.title }} + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ministerio de Educación 
   
   
 Solicitud de consideración de curso para un colaborador 
   
   
 

Estimado:

+

{{ superior.name }}

+

Le recordamos que hemos recibido las siguientes solicitudes de suscripción al curso {{ session.title }} de parte de sus colaboradores. El curso se iniciará el {{ session.start_date }}. Detalles del curso: {{ sesion.description }}.

+

Le invitamos a aprobar o desarprobar las suscripciones, dando clic en el botón correspondiente a continuación para cada colaborador.

+ + + + + + + + + + + + + +

{{ student.name }}

{{ student.name }}

+

Gracias.

+

Equipo Forge

 
   
 
+ + diff --git a/plugin/advancedsubscription/views/advsub_request_superior_reminder_max.tpl b/plugin/advancedsubscription/views/advsub_request_superior_reminder_max.tpl new file mode 100644 index 0000000000..871b093b46 --- /dev/null +++ b/plugin/advancedsubscription/views/advsub_request_superior_reminder_max.tpl @@ -0,0 +1,101 @@ + + + + +Solicitud recibida para el curso {{ session.title }} + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ministerio de Educación 
   
   
 Recordatorio: Solicitud de consideración de curso para colaborador(es) 
   
   
 

Estimado:

+

{{ superior.name }}

+

Le recordamos que hemos recibido las siguientes solicitudes de suscripción al curso {{ session.title }} de parte de sus colaboradores. El curso se iniciará el {{ session.start_date }}. Detalles del curso: {{ sesion.description }}.

+

Este curso tiene una cantidad de cupos limitados y ha recibido una alta tasa de solicitudes de inscripción, por lo que recomendamos que cada área apruebe un máximo de {{ session.recommended_subscription_limit }} candidatos. Le invitamos a aprobar o desaprobar las suscripciones, dando clic en el botón correspondiente a continuación para cada colaborador.

+ + + + + + + + + + + + + +

{{ student.name }}

{{ student.name }}

+

Gracias.

+

{{ signature }}

 
   
 
+ + diff --git a/plugin/advancedsubscription/views/img/aprobar.png b/plugin/advancedsubscription/views/img/aprobar.png new file mode 100644 index 0000000000000000000000000000000000000000..90250ca75277a5c1d5db591d3a1325e88f262d3b GIT binary patch literal 1482 zcmV;*1vUDKP)X1^@s6v1B>G00004b3#c}2nYxW zd>|G0X8>q!`G~g8Jvi+1S#bZSBoa~1G`~kh*&Fl(4${`KoAQ#) z6!~97mK?;D5MAB-X*$0HWqdT5-ynN<_`%QdxR;?QVNNx^NpIi~PWu8D%-e;@ma{rhiGWrMqC-8ymSkG-+KBkA0ZO$!|&U`$5ec2*Y@dt|eG4rNraI=yew6RJ@DDT#QaMU^eArwUn@E{$3ne4mXZ{^ z;ozUt*01I8PfLg^AwVD}``Wvcs*ZEA;T4Y5E~CBk3rhT(065#coyNaDk1b)25Q0|3a9BRQ8x!p#7Lue49*5vM!@#v(n$<3S`T3!}k{ZAJwP=k1>S!Bxh` zqsf}DCp_BDz|aW|)JR3sj?Q*1MV9OU6y`t2y!&<}1-jblQ(-X|0}zc~o^m~|giuul zm=GO6(p@_cW3ho7e2fMUl9V+OHx^*_taq?lO1N<8YrZ>NNz?fqx4XUngr*&x=bd=k z7#OOjZE`-FOg`pTypPRV&J0Ug(pHik6X-vN!H|7JTvb)*AFLzW zwUn}=SBWbjN()~CAQ);Q5)CA6O~wMeo+l_S*a$!@KFr|o@06Erz8VdqF&DS9TFb59 z6wQPdMTy*;Cjq$F{S7^VgOe))vr1mWAiMG9t|1m10>Es{XHnJONgI`OEjtN~woWND zKtt2pR9EfA>sf)KKJy$Zi?1AgBI z!lUh4ZT*%IzCDnyY7t1MGvmmb2TUAv*FSREW>g|ec4F}%+>UDIR(`;6uz}M}Z(%hT z5e%IpJlYCO99~(r*{JF`14H#GIYiNb$F&r*serLaH~oXZOdg~YQ965uKn2qBPCf(3*D zD=?8EvIek3QN*~j2q8vid>z~1nP;v}0=d7n!P{@Wfr%m@ewdUJYc0kYthE!L4Id(e zKq-aex@aeXRvPU%D5bc+waNB_EgpL0QIcMoR4PTM(?SYCv)Le<$s?qo*=V30hoqN6 zN{O){#+VV9aS%fVDCr=CI0*!6kwOrS32uy;cs~SSjES`gg9k~hu?V2mtP@3sgM%{F zN(DzL{{8zu;NakZuYc{U6iWq^b~rq&;%G(v@Q}5eHz`b)SXq6TLZLL$`fz`p_ANGV5PwByG2MiDpPf0qlF9->h_i(V|#0Z$b_t{UP6c??T^REP_g4yI|k(BF$6O_gpfx*sx_{g zz*?}zQf=(>+AFUjEL5sB`t3GB5K`VRQ_AO=$!FQ#-6xZDP(qMSdsHeF`n?{m)a;h4 ztpE5G9)J1?jJ2$+u1eLTlOs}6@POSjuY^!psvTl9j6*+Q0F%EgZi&0Yvm#LUbrOH0cL z1eVDZcbX+m0EwwpPJkHxI7TjzGNxIj6prIyt>vfx`4irG`yHalAWVP|inC|t@e(ez zW{srlF+Vp;y}FN^PEoBl@r~fznK`r)L?&Xt-lEy)?CzDRG}l*Ch(a;3uFL4{H_&HY-1jvufzKTX0>G@Ahj z^%hcTB0t2{n#jWX<_1@J5hY!W>;nUOAM=#)*Ao_rO)>-`C(J1a8QYpTiz}s&%E5J$ z+`W63opKo|1-{=$3d_0K0@KAD`?V(ZcAwA+ly)elJkqWr3POS~KuaiQlH@!GrN9qE z)^6QqYjYE&6k5fJbtw2ysiz%dt|gI5!oVs@X&mh$g+hopF0`Y^zEfZg?|t|&&2}HG zA*&T%e)tT}t2u80PIawesSy`H7HJj68l+Ssi#dbRBlc5C7)7)@JyNd5h9Td0 z_A&nQ+usB~px^KF$@&JLKG^5ML5+iEhjP8aVJG0D^*y@2PiPIsf-*gf4as;Zq9|f_ zcL%K$5Ly8u0tZJ`Sv%y z%+lHONNe%C9ab-_((Co8R;%3G*x=sw9`E11&sL?uP6HY}A0ai}Fr?KBaGZ#g@{2L9Jbi4x7ew-*s3(yJnRsfkU~C-wHD>* zICLXJ7>0vNW0I{-b*-Vm<7OKIvDS`~pw(%$4#~J3Y3mO|Cp7`QDG;CgG*I_N8lRrQ>uc71r1Z*|1{d zMJIqrB}e`@tTe5)IF2)TFGc|;rQ%?JhbZt#IFhMi0TK2Pn0TFpgOn~-N(A7@UhLln z(zzVnZj&?#T4VRLf1Xv=pQha*n&Pc&hD}+4C8$;Gor^Sd660IGuU^!}L;_Eog#1@HZ zcx`Qsa^;XhHpNb*$#OBx%*-?(&}ghq#)J`A5Sscyg>Ju(lP!@$;3Mb+7U4%A6`8^` z22DaaET22ilTZB);h?!1#i`b#Yilj`vseqnM5!`lEGYyQ141B`qS>rda3xPJ&GY`| z19I6EFJJp2sZ5cB@*#KLd7olwhO=jvajk`3hjz0`uh(IEp@>4#tT)iAi|Z+jlRzbs zw7YFe#XJDYafp0>JMoI5j%2}An*9_?CJW@aEbEYug7jJ6+Q0Bv&p! zLJ$SGu4Za>W@L#8MJtJkKoDUDUFxYZa#Uj}5Edy_oG9bW2t%M!P`r4FQnO4+Se|?K zDU9nN3}k1fdFIjQcw_5(w0G{YWICLG>|s_fuCl-VfFHg2OFr4HvtDTsTFFC;b6mN6 z36(37%X~->L|nUeZ7^|}%olbD2!%X0$U355Ay87q&5Qs!##rObHKgBmZk8n(@|CZ= z$l3WBR3uPRbNSh;bjt^P=ZlxP_i=y-Bd-1aw^(}o8QQP?2e01TAel^&F3#{^dmFDb zgOHX&#v_->@Y2gKQ!Gvqh9M!rMA^BBc22U>|mZrwKm(YK%c@hrMQ(M^;y9)hiGggmf^G zAe}1m$fHjqv_=%?z#2r*r`M|U{F9GTl#<8<_)Z96o2BVR_Ummj=?s}{7Gn+892JJc zL_O?}#^d+|5UhY9Bgn}lczn(zL=5KUb_IWXhv`z5sOKYG1%8AH`iLk*ragoVu>AYg{1-mxnhxgsfZ&b`;8h9(X3W! z9h3=sU7mdQg}C4FG6by-UNViXHTcy>Yb+M?l!_%(p}>siarNn|gO)ZNwALb?33HSN zkg>Z-F&RS>Ku+r*M*%iAB#W!hcu?aeJf45yB|1SHr6i#VNSCtAojpsh?cY5NGuNY4>BYAF-3xIKkti z?~WMl%<>BL^>-=cawNSB39WhO{SU|%W|%&InMBEQ{mq|q{ni>=hjj`IP0n0cWpm>m zPOncQ3Q6V*_>sXxgAve};t)12pM=1gfiguLr{c8PFT@nAkf*xVxJHKTA%q~A%3!DF zXtnF)lT)60@uF&yGl28APqX?ag%x#RR*R z13ay%ZC7b*-p8?$Rc{JsDaoz%Psn7Fq;pxO7B5hkTO#!RIDJV;7={yqj!)soK^#9O zCyhfe#)4#mJ&v0-zRmK?l}8D0zk}-}P{y*myT{7X3fsFoBpu1^UYQT>Y|#lqax*jR z)vA=HOQbSc_BJ;N{NN}ij>$JZKZs8-6Lr?-lqf@g6oVf`L+u!g9k|fYQWq~?Le_S< zfA<4sX6HG(aE6c8ZnLwy!^+}$riwE>n=Wx-b(`Dk>oh_G35C#_f|ulj_dcZCZsK^U zxOp248HT0OaVs2Gd zve`VBAG*Z#4?d*TXz{61)N3`AcIbp5jc$h^G>Be@8#fL(JZ#WzHA!n1N6Uf6hjU$t z5atAc)8@XXyVjsbAK!u-z78403dQr!K8I;n`1LP;%H?wl1VKPDkzl28o|&0>UVr0t ze)3;$Q*ZlZGa0NGDsb!FUvcXQ0Db+m&U z1F=}VRE8^8zQDN)s{~;{dG`Tfr^QD%*SNAg#j4*U3a-=7hdA}uioU$$_29d0s!f3j(WXHK9|FWA?;?1q?ejV z)}IT+nh3DWFD`QV@)IPzBuYqvemo7dShnuo=H4g2A(_t5sMpCA`~2B=|AAls>p#+H zG*D8bv`b_x`{i9)jT#bgJQt0Hb|;<=hL%72tH0r$8`pW|hd;m~$d{&h>gsb`y8Jk) zRF+nwNg|mf=_yPYAhkxwNlKpRPwe38#`SlYnVBb@&SIhnrQ+r(ioy}M`@T=BUS)f0 zgI=$TwU8_1kWrtz|MpMh^I3!y^m+mPFrw3G)9?0>68g<1Hi$^1Gswa;FaP!5@%P{T zTlRLhiIl?keZnvzmCo?k6HhWXH^=ns{Lx&?TD)``l*ae_BQp4tKmOB6i#+_u723@f zQ5c{dg&_VX#IUUuKqBGd&Mx3(vUJ;B0>6h oGL@$9_fEIS|M%m!=Kos%4Y4D~QNi~*`Tzg`07*qoM6N<$g6CZI$N&HU literal 0 HcmV?d00001 diff --git a/plugin/advancedsubscription/views/img/desaprobar.png b/plugin/advancedsubscription/views/img/desaprobar.png new file mode 100644 index 0000000000000000000000000000000000000000..1d73cd739ee151bbb18b6d7628674accc8e163b8 GIT binary patch literal 1901 zcmV-z2a@=SP)X1^@s6v1B>G00004b3#c}2nYxW zd{Q3{hh;`vWJ;$@87nvrw$d_CI|5q75$KFn>j-p2+Xib8fyl1_ z0g?+jlHBgy?Y{kE(}NU`hCvbs^ZDmy_kG^?`M%$M?%BPY6&LDe3_+@;O0WP3Gr$)~ zyHKph5i9g=lOOGGMK>s6C3sXwh3u~60j?uTus|}~95M6$Xs%BlIf`3SR(` z|26kODKNWG7tW)SW?yK#Zs-%IppTn`bK)?`zisWCoL3su%E#kh^mNaYj!k<1hgh$@ zh|_%RdTP6FXeA>tYVIT*7zBM}bgx@SYWEIOAH0p~>OiloA@HMLA_ot-EKYd+AVijI z612~`wn88Rq3rW6i9=ppw-Y}9{}0NxrqmGrUg+utSFGquv9_&4bzMLVE+F{$ZxDkE z@XlRC;>G141fJVx}R_v4v17cnRoWhO}1zlZhbwWzL+%$`JW5dMWr(Z|=K(kZMh z&y(8wS7cEc{zXqCBT?66J59P_FXqduQSlg_sdF%<&c;6U5l&Mh#y9W7eEC`IL;JG& zchxsT)pm~L-~R%DHhe4q#*}a4om+?MIFGq`4fe^;Fsi5Fo%J9hCqm%izClJ9QAX*-8jJ|5q^C9V-(A2Jd}yJ-ws*=STpJHq3|bI&}q zVHKbo$Ve0!iQ-?p0&PSk!XLsjbq?NH4}zwVeCrid>isuyP8=q!d(g^8qmQd4wPz<7UI3hvjif)`OLFHQ5uq@u zqn*xW3lX{bXeA>Nx`CWL6Ro7YM?RXAOA3umn zS_B?{1_0~zKakq>2B|$e2|l?FeZpi!ZhmG?x?wMg7oI}+{Df9+1;c|jY9i@>zDw7y z79$Iakws;QoWbbhYA@Gywh43dbExwzs0(dhywM`B&^0_BLsApz2cd;a2|Hk zXV@nWqm_)rJEsosoI32I2QW9T1i-&=DOyF9yI#_ACuZxJO5vP5f{a8F;k+J0srucJ zvOr2?ZUF$!>7(xFxs#bVSx|iWvStD&){M+ALgwZn3ySbR^c1pqc=zJny0o6UoY)!c zgY{Wl>d93bEka?8+PeU-8$X6r5@nePpP$6K<=Bl4JtsIeUBCV@#-thOqb8zN)}WP* z#&gH_QRiFGDyp!LeM;hmpCKbd2rOBB#r$%}PykdsO9eR&D$$7ugb=|TSF<;e8CD(V zFW-~Lm$|X4cpIL3=Oc@Uldj)|`O+%%${Kw0pXil8+32;=o_l|Y&<*slw;*!!QSGf* zul)`H`;!mQtG7Or4F>+MFp2r?na9Ow+}6 zbMw(FYcOi>c5l*2i}b;L=--%jQCCg`t>Wh1+LV>v8-3fXOmh3ve__7zJWlHw0L)Em z@Q1=^@2RC{aI#;=u(L>88UH-Kt8i{1Ed zl$k&lmZA+E0lok#c9!(PdPt|-9Dxw}_*+r&HtZw&kwZrUU?19tQ9TXc{3mc)PLcTS zGGt*XPV;e`Q%Bsn9v^a8g&TkPBlp*9MvRVLQH3lh#%XWGKC}FSZ*LsrY;X`@aTNXhUviRva@1lAzFDg{p4~iSX$&;j;mX!(pyD+u6^slX!a(ON z;f!NoxWuB*z>wJ_&d^|Tkek6_)&o`s1>X-$3=`A{DtlXZFaJBxLlMUg!*sr7f4P{= V_r;&f&w(~Ec)I$ztaD0e0st0QQ1$=- literal 0 HcmV?d00001 diff --git a/plugin/advancedsubscription/views/img/header.png b/plugin/advancedsubscription/views/img/header.png new file mode 100644 index 0000000000000000000000000000000000000000..45580646798ece8b4c4ef716cf5bb427bf16ba2c GIT binary patch literal 267 zcmeAS@N?(olHy`uVBq!ia0y~yVA=y@i*T?3$^5K$FM$+Gv6E*A2N2Y7q;vrJoCO|{ z#X$AfL734=V|E2lP_o1|q9iy!t)x7$D3zhSyj(9cFS|H7u^?41zbJk7I~ysWq7F|N z$B>FSZ*MqqG8hW596a6GThA^ns(2wpb4I#xcG@#$hK3dYzXDb6@ch8UFhQ+?k-aSRNXSo9efGMmI18cYsyGdRq8z{;TDOPsRYw|k#|gcyqV(DCY@~pSW_Y?d zhE&XXd(DxTK|$bv!GZnHommwlqgbo+&Y#g?VCb;g&&!~1@0aAyU#bq~zub+S&7j=f-I=WHZCp%@9L<;z9W?&QrXXo>QJJQ(Bpa zyi@e~KulD84gob<;$NRQET^XlqYSO5|6$~QQ9#8f7UTF`BHAY&b{}Nl{g!RHi!O8Z zcv6qj>OPchfe!T}gHKXLW#*H8T*zibM8xOH%F2mZ68Rp56wc3d13~tKzI{d;I@UdF z?VjvTPEP2}lK6hifq{XH$c5%~W&hiiV&Sy(K%7A=ghxdu!|$2P-X`1Yr1yV++5CtH z0wt>SJHn!(23A+o-rrs}FIOQiCgZXR>(cWIXUqFRZ$2p1+~{I@nE8=wlRGsvBK_^# z{yk~9JmQL$;9n-H0im)+1oYw6W-&muP}bEl_ZGaa)#RGJHNXq(iMvp zMhAA(;6xjzYWwdb3vcnp!tlAB>*>Sl=xNw?xZiK@ZJIhPY;74XnICLyupoQ1ZQhSe z$;y(~Fvk%T6o7VgcB2OGSG7M}_~0<3w(JWup05e<@$k=p7gFB%{p~dD@y1w=Z(!Ys z7bJAlF^P#MhvO*H<|$Naw_li_R_DSMXQwhF3M|m4_)qfTQDg9%(peiCTt{S3X?Cso zpkTstqH#_9S9*j)qDVQZ3YIws1|)w*A4SiXI5VvAuK_%gJ2((>pwKBSoUd!s_N65y zYo;A2`?y|z>pU!~OiahK7b&^yO*d}NC_=n|(Vh-;aBv`zQMo6hsf0$v2MgG8CjC3+ zs@?9l#}N^Vu34}dkdgxDO2bZjRkLU6NuHvmHE|LZ9evOn?4s6+=QN=ovsS)F{S=B$ zLVe<(3UcB|;xG{>=c+(}m5z~&=jqQ9R`k5lztsr}2~A!7?hm`AnzuD~bhvysK~rsk zE7?$byLD?E{Ukh;iv3}DvBq0E3)2b&<(L)9hX>zMqw~b{}r~ z2PbuWF^AIzrQvO}TgE>7$>Vl~zWj|zq5Tz$_=+46_O`>%m0w`g;>`G|4DR3n=iwpT z65{vM@D=6R4n+A~cf`>xRKJcaMcoiw&Sw95%H=4=C@owsY&Z%n6|E={Z+eDxb}Hqb zo5W;BP-P9-<;_Y}8&4jB1kXb{1BE2Js8nohhc{wTo7>t{bOGbu%pbwa-Z428zo3TQ zSo^qIKtimC$`S*m$piR;6(Pbf71m}{a!}u&ZwG6rNn+%Y2rE^y`P#`?MwoZCiqx1g zev$4hV$UtkV-Y$1-aM!nk{m;0t|Bj_qwsK%!4KqYLE&DpgY zA%F*^OBW$iB2zjx10wF{JwXLjv0H{E){)bQ1tG%lb}Y%o5;=$e0s}B%>(P-8wl?)8 z=zx@Hbv@SFaGh~Fyz0LQ&jCcvyZj~^CVeLXzLs<$nA&wAPP>Dw&PyT(G3yGhjYOVT z87jd0{} z-|WGrN2ok$$_uSc?{3I)V)cMt)MqtWs!?`U%rgA(bQqR#yd*{3f4KXw{P?Df%ybk4 z*xEVyE#0->d_PGI2r&Uu#r@1Mn7&UR>h5{(uSUseSpMqM3bN3I2dg%vDhLvgd*71M z3u1ftSjYzh5$V1()u7uvn#?={G=6_&IX}|+HEJ#T-6{(-R1lHOa`7&dV2m4YF~46} z20Oyl@lC})eB;iFloEy~)#XdoohsteGa6z~@%hcSH?Ys3Lz+^}4${|<&n4~#6287f zO1i^RgE zJb_D5)IJl?BsN^5SIhFs`~R)Q9rT4>c0p7oxpRwDXHMbqpNLTqnME}ng69#(ddD|w26Zuvxx2=fM8xRi8RdPnpqvon%MP6vAFE@G2MfRgH!;ed% z!NJvF*E+$a8tbn&)VF(T{HO4obAn>D(BVnZFuNO*Ae1|?RRBp~JasKItk`+T(yKJb zD=83>@;RfNm1yNNqrA9CZY(LjcI9^(l{Jj}{M*I8^qR)Ql^Pjf@jWWCNLbsYouMJ= z_V%_y24BO#Yd`>0Z(pD1ZWK4v(aC|7hsPt)d>1)Sv!Yor2G0tAeal4>h|O%2sNquO zpz#3n^XJc$)kAraAD>6eJQPv+Z*Rlvr~8HgS$`|sB0nRGH+6?=CVWJd+4F+vMfGnMjefDoiTI&{y?*=aNs&1#P{a3$#|sPm6!lCp&O5yf#H^ow znlfu$KFm>Dh-2$XFB0l-4>f|-{`F4vb=R*i7FFsSG%3}S(PpfWcieY%xz;Sfkjf7E zh`aQf8gcUKEPjL+PZ#_%-o@lqGwGN(y!PL<2}N;YhQbewXNMEp^$kQEh`AC0YUCKV zqnf;C{Xdsonv5dwliw0(l+53r@3`+s(lavB@)MIa9Z&j4xaJxEkg`*JI_Ii1)c3tp z&$PT87T(aBE4*fmON<*C!J_edxQoGTdMlKNg4Xgh|Hi~5&D)h3u!d<`36;~I$AarX zBG`$_ohLU0+Z?h|NG6I%oAiw8O2?}mAEwg*J$2MJ!^)mPDUQ(YrKK`HrXJ%nmh>*9zT-_2r_Lsah|Uki(>DDr{eDa=F~_?T zbwVN{Cue7JPEPd<3scknYNNiesBo1g(sOICG&pIwk@rssD{DBuf*t%;UJ+-)9szF% ztA10`DXW*P1RAyt(twou$=}2Cm2)u*@HrCUBG3{N_@v;3rv`~EF{5#thIb$JIkbXl z^3Iho#(OL%3|d4-BAG@v>`=L#@EPUGW4N|dQ~u&b#BM%LDj<-aolQCzMXyx|33C$g;LJ8bLPD48sKcb0`($ZLEw8pkq2y0OcZ$MO$PS=CA zg@kmZ;DyM)N-GH*S9I~JHcxj!?B$Fl2y_>1jH;w`%MDrHtgteacPXWyDrEUQZ+6rT zI+z`-9Xw}ni)NN+5Rcp0H|~2?O-%%8Y3Vx)$VuP(jWbtClKpdH!tpV|V11sjvlL)mn0 z+bS;~YOTQ3Q1DO1ukj5H4Nh)u=9`_q75Z&XyHajvYoe}-oR^IHC}NzSHe~V&1q1~% zPJ8v5`w~`((hHrCiGUCiC1--TW2HSz#EyZ=Z6{e^^kXx7CtG1VltmyOs;awuTLDi zbl*TlMF=pvXG8$fQn`&MFz`w2&jwNISE&H3tV9YMprf%qB-%UR`Y!H_HRQemek&h~ zGY+B*Ra=nA-M_AtTP6z{t?~4!>GLRhO(Q6d9=X9ORq|u2SjJO z(6X~*JU%{dZf0Ew8IQu6Zhx~s*s9&$%%0pun#1;>DNs!N@|{Hu+2dDYdi z)6>&Q^w!OtI!*Sl@bIMxf&v1LZqD`qj)LIbV5rvTQb8MSFRz4KU+)LjW2J=0tsr#m z*0Z=A^`5h}fv7pM_gI6!Gf7$D?lnf%&cv!FV66s?+$y_Z^#dv|bt>f?v+*5}ndRvb zAk#NRiw?J#n}cF(8XqH_w-r}QU2I@q)zaWOs(31*+UZh0lcRgx2CC!b-t73#=8^|1 zI#Pb~(iSj1#>X7?zAVZ3V>ikB0~Xc;$CSJ(F`GptLziyji9)k*qP--0Z>0xBZ7_LK zzGrUMDm|db96)+Lu}Hh&@^7Q*1x>5VPcQ<9(HKHUw*h_%=9HbRxjI4_%mcnmlnXiu6W@ct{ za|`RC(xfA3Ps(rJPbsRptGJ>!!X2dEcQ1Q+nLvX|M<-FP@fBO;S@c84@MEy}gc(j$3``!h5m~m*&5h ziy0zfVjS4YygWP%Ee#zt&yRK%_LJ()@+8W{UDCr1X0SW=dnbHEJJVw%@0XeLEk-*?d>X zdgvqrwts}pXr_v<)%{RGXxBR{+aQ8*D&z(VF-cw1zLHGuw$~`0ucH61_tOQIxpek3 zwoXqY$|C3?L4LP_(#>YC=>Ll>Exd z=;GZWosP|o4(}8;Gvo+dX7iDqf#DFY+sjRZ3PUfT)g7~emKMY&5`|PGDKj%Vw>x*b zkZ$->Tivvv!Aw339pzz1BIWp;$*nMb3)co_ohGBl_Ni@%kFw%iRznzI0U9P46Yyag zag5sv^rw(Hwu}~G`%Xdf2InyI(pEJmhGb}Gr)V}1q?-LoT*{;;id^k+)mochNl8N2 z?b!W~dI2j?Vrm^O7I?-x`sTRY74HnEJfRjf4FB-A(b2aiyLCsZYhN4zef!{IFa(tV zQNJ;AB8@vCA#E%iJ~ZI*(SvY>AA^`Ux}kv+5)pc9tSU5Nf zg^dsx#As&#L4ShBz`+?j%<`S=4gMS+7UsdAUrT99ufNU9yS%irQX))4MYVl$BB!_9 z*57$eqbgr@R>-GI+z{BQ_ix^ zyM<(ZF@r)@iOtd#NgG;@$%}XQHAUE-ctWqE(QbMC53as#gQ|t?*~)DrbCW?Y%L#WR zc;UW@j_TNx3zO(2nlZ_SC+Tm-O5V_WhyWGQJKpd4{1Qm!YU3yn`)j%BlX#2}rQiqo zVl<&RjF-|+u+@;pE#I$$$c8?<-~osbv^0_SsT+dzB&E#8hd(lo=gV+sW@adYc#YgX+>@bIMbZy-19x_TCHBy5x$B<2rLh-!gfg;I+ppN4BX3LbX3LTu z&+HkTtHk;(*zbpebQxI5sD(qFsLj)lY(rOrIi~H1=@GNDi<{2{I~Qe+GB(@wtm+Jk zNY6B&d%w;V9tJ_xS-jD0+|iQ`Yq$UX!QTkBdWqTddEy1Rxg;kSFX4id`UR9xs$)*7~5DZ3W%o~C%MBR=@Qv@ zgUpgK0GJ83qgXhJJdNyPn*7+8Op82e#_}pwa8mH__3R`2tLj{Y0y#sSd;0wnB<4#m z#NUq63#vzvD{LAF`PxY=9uAtu$E}G~E+5DPUQu=E1U*_4oqwk@cS?;d)egM=t-}>X z9*vfY_XX>#!#t%elo6sLj}ZWk;%DwRyAwj9u^cZk3ks)oXd-lm%j{vr=v^6z7 zosfZnVS0XEy-5B#4iJcesX4_~|037ks(rIvE?{e0{ENMRzb#M?_; zapIi%YByU`!(!5V<{Jqzm)3Qr+kCYh1}{G$X1AruAzoi!SJ%{#QBlF=U_87sm>V5& zX=A}4?Nz+R@b$~FC5!N)?QExL zmFyk$_zkPk&v-KNRxHV}muhFZC9FH5CeN%$Es}GWplS9U3(iPE>PkY9vVUVIC?^JbuR6|YFvz;j$ z>tCCVOi6J4#xnt{W5e&$men_TFJPiUeqUmd0D$vkh=tL;XHh< zIaIx!z~leU5Co4(F36ZsTWh1s=blvA^?onx#Snw8TJ%GmzuIBFwLz;hG!y}gTEVb8 z02-oO)j{$}vAzqxk`iTF#8jd`ABg^=V`FJnIzutuXt1^)$26{~Sy?1vxk93|C8{(q z`iR}`Va(ZVaXz;*(zJM}ngAjP89mUMgmTDl}gAe)C5br@mN7qCb%FN7!RqzQUX?*P_ zaOjkMxj*N1zb8EH((&K?>QKRC2KH*XS}W(JR78id6ZOUQmP0NpCg6vLAy*-8qG9O_ z2%zn`JtP_~z398SG-q3D1GT@}4x-c?zRtV#`3Eo-w77de_9~oYSeP_$7DXo1A@^6!L=-@?7N);e})pbwhUWcPX}M0ZdyF9$a}bn ztnY7cDJd!ce0o9ucMDbm7r0nJ${AMy0YQ74&-Jy9#z)gRinIB^{K9<4f}Z9suRH5} zAS@i5ioX72B%b1j8&P^j>ilY_ulF6w>DHErj0_@#Pup*25G7%nr}p8r0F<__1F1IVj{gJ1i6M@F1wVv z-rvHMlvAQ$U|>L8cK9T|w_m*P&x~SY&?7cH5g>;~m3~w~0Tl!@#5bn{n7dx%>*qMk z5hlzhQaPK}RX0&9kPpCBU9!D@3yy$EImM;aUD-*ZNXx+BiXoO6sB`9s>C`Gpmb&;d zNwnrwNs1$dgL&9??=}p#>44sNYoI!=Q*|A+rd7=QEnB7DG=)tl4w@%bDV2u9r}z(} z=nHi9Z?FGQ?alVT@oCN0Gy?%Ps(-}dFXpa|%upx3h;;eAA)=vCQ&YnSJl!1Lj4^i= zkKLZHCO0?pXoQx-ZvlJ++T6~KC)0Vq5fG?qXe@|L#78qRG5oB~*7{*-NvjC}94%In zKuTiBCwF>(^@K`d)EPt7F&V7>m#5^x$k))>8et34CY+@ZJxlB?+tv_I@i6NgDUpHuB};0ZyKB*De0|mJlBc`;{pYtI;Cn6>o0yAo^U`$vA;BAxXRpZ0#zuZtDCn|_ zrwn=M9Yg0wH?-@UCb()t#s31x<@plrb4VibBplk5grf~GOwjn#Qo|*~5;0ZuF3HG* zTAp`WjMDp&+utpcRYp_}I?Iymp~8ZHdqL)N<;?&12YY`J>nMqtVj-%cLfk2q#=f~Q zeHY1(V@G6fKzp-yz2O4_RsN~g$?hOgZ>TWfanLq#R-`C-r{ksAviUk(5O zM0nb%m^Y}afXjad#Y-Uu=H!sM-ZkAv>9>2Zeu76K<)sTZiHjo?c1mZmFSU#U$ko@^ zU&y3rxby{H5zK(Ws-Jg1*f4a{V8QOg7zdqC$fN!heMM5(1|mh}`seq#>Ws&3B7r>0 zW0rIxz(86AN~dUZk4mTf6FKac!$nrQ21HHRN-=C))xY>^pMSSXNi+ZXYNjU><6I6Wzx*?X%FJBcELdr#Y4?m>>hc$cbU07mifU?D z|JTx(m@WbbSUdBAY)l3tduWc4>nx@U?HzdffbrYGrC(}TtJOOz=yFn8ZVeh@{~%Kh z$ZM+XU-UcqGL9#lTBE-OST0Pgo808Q%Q`AQ%jjbzU!Y)6~^(B7_@pv6Y0}*ald~311xnf z*Z?JiK*P~Q{Qs`5$T&EFCUHYyk&zHzk2q6(&xPvX#thsZr!XJ_Lp4L0*u1qB5s zc~0nJJUXt%U7YdsbR|CS;y?R^e4kmo#x3VdkjOwcizDOjLh0kj&_{YQQkU0M3(qlI z3I4uF07u?qHi%qOP+IzTusFv4!d{_Oo=Qn4V~IrlVlI4rXb6Fxp5ED5*y;bb8~Z!w?{KLU0aaJ(aFiibtgPL{Nu}usy3iECk@Tr{b(8*LUd?^ zJR%Ukk627gO=Yv5qn!nV!y_ZxE5MLimFOF!5{Zk8Yg#th)Un_1_rv|Yj2~YlEvVS^ z7J7AiLtcerdo#*2I~3&a>+SDL#reBrTV?wpi|MIDrYG_+b9+RkZ`s^b3|G+3NA>2& z(86!i9@0?X?R~>ifX@4Hz`=avpDzAP@@h$x4CyxqI&O+Lg{S#@`)GpjIo3R5wMig9 z49NZeF918Su7V__QNI>1Ej(%PS%!}IGF+>U$m6UfMtd1S(!`zEV8+&m4D&-AmlgFx thgkgoX8MeD-O&F%bqNZHIe|Z~!e8Geb6XyK`5{)JWF>z{REin?{twddW3~VQ literal 0 HcmV?d00001 From bf4641869d4b2f0694299f36fea3e80db02df760 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Thu, 15 Jan 2015 16:21:01 -0500 Subject: [PATCH 10/72] Add extra fields to Webservice, add "publico_objetivo" - refs BT#9092 --- main/inc/lib/sessionmanager.lib.php | 25 +++++++++++++------ main/webservices/registration.soap.php | 10 +++++--- .../src/HookAdvancedSubscription.class.php | 20 +++++++++++---- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/main/inc/lib/sessionmanager.lib.php b/main/inc/lib/sessionmanager.lib.php index fb2bea0b9a..081907f594 100755 --- a/main/inc/lib/sessionmanager.lib.php +++ b/main/inc/lib/sessionmanager.lib.php @@ -5442,10 +5442,10 @@ class SessionManager * Returns the list of session (name, short description, start date, end date) from category. * The short description is an extra field value * @param $categoryId + * @param $publicoObjetivo * @return mixed */ - public static function getSessionBriefListByCategory($categoryId) - { + public static function getSessionBriefListByCategory($categoryId, $publicoObjetivo) { $categoryId = (int) $categoryId; $sessionList = array(); if ($categoryId > 0) { @@ -5463,11 +5463,11 @@ class SessionManager ) ); $sessionFieldValueList = Database::select( - 'sfv.session_id AS id, sfv.field_value AS description', + 'sfv.session_id AS id, sfv.field_value AS description,', $joinTable, array( 'where' => array( - 'sf.field_variable = ?' => 'as_description' + 'sf.field_variable IN ( ? ) OR' => 'modalidad, duracion, cupos, horario, publico_objetivo', ) ) ); @@ -5475,9 +5475,20 @@ class SessionManager } foreach ($sessionList as $id => &$session) { - $session['description'] = isset($sessionFieldValueList[$id]) ? - $sessionFieldValueList[$id]['description'] : - ''; + if ($publicoObjetivo == $session['publico_objetivo']) { + $session['modalidad'] = isset($sessionFieldValueList[$id]) ? + $sessionFieldValueList[$id]['modalidad'] : + ''; + $session['duracion'] = isset($sessionFieldValueList[$id]) ? + $sessionFieldValueList[$id]['duracion'] : + ''; + $session['cupos'] = isset($sessionFieldValueList[$id]) ? + $sessionFieldValueList[$id]['cupos'] : + ''; + $session['horario'] = isset($sessionFieldValueList[$id]) ? + $sessionFieldValueList[$id]['horario'] : + ''; + } } return $sessionList; diff --git a/main/webservices/registration.soap.php b/main/webservices/registration.soap.php index 26f0497439..0937631d05 100755 --- a/main/webservices/registration.soap.php +++ b/main/webservices/registration.soap.php @@ -15,6 +15,7 @@ $debug = false; define('WS_ERROR_SECRET_KEY', 1); define('WS_ERROR_NOT_FOUND_RESULT', 2); define('WS_ERROR_INVALID_INPUT', 3); +define('WS_ERROR_SETTING', 4); function return_error($code) { @@ -22,13 +23,16 @@ function return_error($code) { switch ($code) { case WS_ERROR_SECRET_KEY: $fault = new soap_fault('Server', '', 'Secret key is not correct or params are not correctly set'); - break; + break; case WS_ERROR_NOT_FOUND_RESULT: $fault = new soap_fault('Server', '', 'Not found any result from the query'); - break; + break; case WS_ERROR_INVALID_INPUT: $fault = new soap_fault('Server', '', 'The input variables are invalid o are not correctly set'); - break; + break; + case WS_ERROR_SETTING: + $fault = new soap_fault('Server', '', 'Please check the configuration and installation for this webservice'); + break; } return $fault; } diff --git a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php index a5a7f95bf8..693cbe0443 100644 --- a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php +++ b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php @@ -70,8 +70,12 @@ class HookAdvancedSubscription extends HookObserver implements array( 'name' => array('name' => 'name', 'type' => 'xsd:string'), //Course string code 'description' => array('name' => 'description', 'type' => 'xsd:string'), //Chamilo user_id + 'modality' => array('name' => 'start_date', 'type' => 'xsd:string'), 'date_start' => array('name' => 'start_date', 'type' => 'xsd:string'), 'date_end' => array('name' => 'end_date', 'type' => 'xsd:string'), + 'duration' => array('name' => 'date_end', 'type' => 'xsd:string'), + 'quota' => array('name' => 'quota', 'type' => 'xsd:string'), + 'schedule' => array('name' => 'schedule', 'type' => 'xsd:string'), ) ); @@ -97,8 +101,9 @@ class HookAdvancedSubscription extends HookObserver implements 'all', '', array( - 'id' => array('name' => 'id', 'type' => 'xsd:string'), //Course string code - 'name' => array('name' => 'name', 'type' => 'xsd:string'), //Chamilo user_id + 'id' => array('name' => 'id', 'type' => 'xsd:string'), // Course string code + 'name' => array('name' => 'name', 'type' => 'xsd:string'), // Chamilo user_id + 'target' => array('name' => 'target', 'type' => 'xsd:string'), // Publico objetivo 'secret_key' => array('name' => 'secret_key', 'type' => 'xsd:string') ) ); @@ -121,7 +126,7 @@ class HookAdvancedSubscription extends HookObserver implements 'urn:WSRegistration#WSAdvsubEncrypt', // soapaction 'rpc', // style 'encoded', // use - 'This service encrpyt data to be used later in urls' // documentation + 'This service encrypt data to be used later in urls' // documentation ); return $data; @@ -160,9 +165,14 @@ class HookAdvancedSubscription extends HookObserver implements // Get the session brief List by category - $sessionList = SessionManager::getSessionBriefListByCategory($sessionCategoryId); + $sessionList = SessionManager::getSessionBriefListByCategory($sessionCategoryId, $params['publico_objetivo']); - if (empty($sessionList)) { + $extraFieldSession = new ExtraFieldValue('session'); + $hasExtraField = $extraFieldSession->get_values_by_handler_and_field_variable(1, 'publico_objetivo'); + if ($hasExtraField != false) { + // Has session extra fields, Nothing to do + } else { + // No session extra fields return return_error(WS_ERROR_NOT_FOUND_RESULT); } From 169d82dfd3a1e3432d3fa44bcdde75c6bd4fff20 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Thu, 15 Jan 2015 17:01:40 -0500 Subject: [PATCH 11/72] Add description to brief sessions - refs BT#9092 --- main/inc/lib/sessionmanager.lib.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/main/inc/lib/sessionmanager.lib.php b/main/inc/lib/sessionmanager.lib.php index 081907f594..6a93a350b8 100755 --- a/main/inc/lib/sessionmanager.lib.php +++ b/main/inc/lib/sessionmanager.lib.php @@ -5467,7 +5467,7 @@ class SessionManager $joinTable, array( 'where' => array( - 'sf.field_variable IN ( ? ) OR' => 'modalidad, duracion, cupos, horario, publico_objetivo', + 'sf.field_variable IN ( ? ) OR' => 'as_description, modalidad, duracion, cupos, horario, publico_objetivo', ) ) ); @@ -5479,6 +5479,9 @@ class SessionManager $session['modalidad'] = isset($sessionFieldValueList[$id]) ? $sessionFieldValueList[$id]['modalidad'] : ''; + $session['descripcion'] = isset($sessionFieldValueList[$id]) ? + $sessionFieldValueList[$id]['as_description'] : + ''; $session['duracion'] = isset($sessionFieldValueList[$id]) ? $sessionFieldValueList[$id]['duracion'] : ''; From 6a0902d39a1f722e6b17f38a7e2496af2c458f41 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Thu, 15 Jan 2015 20:54:21 -0500 Subject: [PATCH 12/72] Fix, tested WS session list by category from BT#9167 - refs BT#9092 --- main/inc/lib/sessionmanager.lib.php | 30 ++++++++++--------- .../src/HookAdvancedSubscription.class.php | 10 +++++-- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/main/inc/lib/sessionmanager.lib.php b/main/inc/lib/sessionmanager.lib.php index 6a93a350b8..fd05c29605 100755 --- a/main/inc/lib/sessionmanager.lib.php +++ b/main/inc/lib/sessionmanager.lib.php @@ -5463,33 +5463,35 @@ class SessionManager ) ); $sessionFieldValueList = Database::select( - 'sfv.session_id AS id, sfv.field_value AS description,', + 'CONCAT(sfv.session_id, sf.field_variable) AS id, sfv.field_value AS field_value', $joinTable, array( 'where' => array( - 'sf.field_variable IN ( ? ) OR' => 'as_description, modalidad, duracion, cupos, horario, publico_objetivo', + 'sf.field_variable IN ( ?, ?, ?, ?, ?, ? )' => array( + 'as_description', 'modalidad', 'duracion', 'cupos', 'brochure', 'publico_objetivo', + ) ) ) ); - } + foreach ($sessionList as $id => &$session) { - if ($publicoObjetivo == $session['publico_objetivo']) { - $session['modalidad'] = isset($sessionFieldValueList[$id]) ? - $sessionFieldValueList[$id]['modalidad'] : + if ($publicoObjetivo == $sessionFieldValueList[$id . 'publico_objetivo']['field_value']) { + $session['modalidad'] = isset($sessionFieldValueList[$id . 'modalidad']) ? + $sessionFieldValueList[$id . 'modalidad']['field_value'] : ''; - $session['descripcion'] = isset($sessionFieldValueList[$id]) ? - $sessionFieldValueList[$id]['as_description'] : + $session['descripcion'] = isset($sessionFieldValueList[$id . 'modalidad']) ? + $sessionFieldValueList[$id . 'modalidad']['field_value'] : ''; - $session['duracion'] = isset($sessionFieldValueList[$id]) ? - $sessionFieldValueList[$id]['duracion'] : + $session['duracion'] = isset($sessionFieldValueList[$id . 'duracion']) ? + $sessionFieldValueList[$id . 'duracion']['field_value'] : ''; - $session['cupos'] = isset($sessionFieldValueList[$id]) ? - $sessionFieldValueList[$id]['cupos'] : + $session['cupos'] = isset($sessionFieldValueList[$id . 'cupos']) ? + $sessionFieldValueList[$id . 'cupos']['field_value'] : ''; - $session['horario'] = isset($sessionFieldValueList[$id]) ? - $sessionFieldValueList[$id]['horario'] : + $session['horario'] = isset($sessionFieldValueList[$id . 'horario']) ? + $sessionFieldValueList[$id . 'horario']['field_value'] : ''; } } diff --git a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php index 693cbe0443..b878d5a0f9 100644 --- a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php +++ b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php @@ -139,7 +139,8 @@ class HookAdvancedSubscription extends HookObserver implements * @param $params * @return null|soap_fault */ - public static function WSSessionListInCategory($params) { + public static function WSSessionListInCategory($params) + { global $debug; if ($debug) error_log('WSUserSubscribedInCourse'); @@ -165,10 +166,12 @@ class HookAdvancedSubscription extends HookObserver implements // Get the session brief List by category - $sessionList = SessionManager::getSessionBriefListByCategory($sessionCategoryId, $params['publico_objetivo']); + $sessionList = SessionManager::getSessionBriefListByCategory($sessionCategoryId, $params['target']); + /* $extraFieldSession = new ExtraFieldValue('session'); - $hasExtraField = $extraFieldSession->get_values_by_handler_and_field_variable(1, 'publico_objetivo'); + $hasExtraField = $extraFieldSession->get_values_by_handler_and_field_variable(key($sessionList), 'publico_objetivo'); + var_dump($hasExtraField); if ($hasExtraField != false) { // Has session extra fields, Nothing to do } else { @@ -176,6 +179,7 @@ class HookAdvancedSubscription extends HookObserver implements return return_error(WS_ERROR_NOT_FOUND_RESULT); } + */ return $sessionList; } From c3124e879133962a96483e027f335d082eb6885a Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Mon, 19 Jan 2015 18:05:51 -0500 Subject: [PATCH 13/72] Add Webservice for session details BT#9168 - refs BT#9092 --- plugin/advancedsubscription/config.php | 1 + plugin/advancedsubscription/lang/english.php | 9 ++ .../src/AdvancedSubscriptionPlugin.class.php | 122 +++++++++++++++++- .../src/HookAdvancedSubscription.class.php | 118 +++++++++++++++++ 4 files changed, 248 insertions(+), 2 deletions(-) diff --git a/plugin/advancedsubscription/config.php b/plugin/advancedsubscription/config.php index a9a298ec41..8f015ff0bc 100644 --- a/plugin/advancedsubscription/config.php +++ b/plugin/advancedsubscription/config.php @@ -18,6 +18,7 @@ define('ADV_SUB_ACTION_SUPERIOR_SELECT', 3); define('ADV_SUB_ACTION_ADMIN_APPROVE', 4); define('ADV_SUB_ACTION_ADMIN_DISAPPROVE', 5); +define('ADV_SUB_QUEUE_STATUS_NO_QUEUE', -1); define('ADV_SUB_QUEUE_STATUS_START', 0); define('ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED', 1); define('ADV_SUB_QUEUE_STATUS_BOSS_APPROVED', 2); diff --git a/plugin/advancedsubscription/lang/english.php b/plugin/advancedsubscription/lang/english.php index 5c61d55318..942a3c77b3 100644 --- a/plugin/advancedsubscription/lang/english.php +++ b/plugin/advancedsubscription/lang/english.php @@ -19,3 +19,12 @@ $strings['AdvancedSubscriptionCostXLimitReached'] = "Lo sentimos, usted ya ha al $strings['AdvancedSubscriptionTimeXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s horas para los cursos que ha seguido este año"; $strings['AdvancedSubscriptionCourseXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s cursos que ha seguido este año"; $strings['AdvancedSubscriptionNotMoreAble'] = "Lo sentimos, usted ya no cumple con las condiciones iniciales para poder inscribirse al curso"; + +$strings['AdvancedSubscriptionNoQueue'] = "Usted no está inscrito en este curso."; +$strings['AdvancedSubscriptionNoQueueIsAble'] = "Usted no está inscrito, pero está calificado para este curso."; +$strings['AdvancedSubscriptionQueueStart'] = "Su inscripción está en espera de aprobación por parte de su jefe, por favor este atento."; +$strings['AdvancedSubscriptionQueueBossDisapproved'] = "Lo sentimos, su inscripción ha sido desaprobada por su jefe."; +$strings['AdvancedSubscriptionQueueBossApproved'] = "Su inscripción ha sido aprobada por su jefe, y está en espera de aprobación del Administrador."; +$strings['AdvancedSubscriptionQueueAdminDisapproved'] = "Lo sentimos, su inscripción ha sido desaprobada por el administrador."; +$strings['AdvancedSubscriptionQueueAdminApproved'] = "Felicitaciones, Su inscripción ha sido aprobada por el administrador."; +$strings['AdvancedSubscriptionQueueDefaultX'] = "Ha ocurrido un problema, el estado en cola, %d no está definido en el sistema."; diff --git a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php index e247bf7ba8..5b7dfe249f 100644 --- a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php +++ b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php @@ -351,8 +351,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $joinTable, array( 'where' => array( - 'sfv.session_id = ? AND ' => $sessionId, - 'sf.field_variable = ?' => $fieldVariable, + 'sfv.session_id = ? AND sf.field_variable = ?' => array($sessionId, $fieldVariable), ) ) ); @@ -622,4 +621,123 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface return $data; } + + /** + * Return the status from user in queue to session subscription + * @param int $userId + * @param int $sessionId + * @return bool|int + */ + public function getQueueStatus($userId, $sessionId) + { + if (!empty($userId) && !empty($sessionId)) { + $queueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); + $row = Database::select( + 'status', + $queueTable, + array( + 'where' => array( + 'user_id = ? AND session_id = ?' => array($userId, $sessionId), + ) + ) + ); + + if (count($row) == 1) { + + return $row['status']; + } else { + + return ADV_SUB_QUEUE_STATUS_NO_QUEUE; + } + } + + return false; + } + + /** + * Return the remaining vacancy + * @param $sessionId + * @return bool|int + */ + public function getVacancy($sessionId) + { + if (!empty($sessionId)) { + $extra = new ExtraFieldValue('session'); + $vacancy = $extra->get_values_by_handler_and_field_variable($sessionId, 'vacantes'); + $vacancy -= $this->countQueueByParams(array('sessions' => $sessionId, 'status' => ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED)); + + if ($vacancy >= 0) { + + return $vacancy; + } + } + + return false; + } + + /** + * Return the session details data from session extra field value + * @param $sessionId + * @return bool|mixed + */ + public function getSessionDetails($sessionId) + { + if (!empty($sessionId)) { + $extra = new ExtraFieldValue('session'); + $data['id'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'id'); + $data['cost'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'costo'); + $data['place'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'lugar'); + $data['allow_visitors'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'permitir_visitantes'); + $data['class_hours'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'horas_lectivas'); + $data['brochure'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'brochure'); + $data['banner'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'banner'); + $data['description'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'descripcion'); + $data['class_hours'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'horas_lectivas'); + + return $data; + } + + return false; + } + + /** + * Get status message + * @param int $status + * @param bool $isAble + * @return string + */ + public function getStatusMessage($status, $isAble = true) + { + $message = ''; + switch ($status) + { + case ADV_SUB_QUEUE_STATUS_NO_QUEUE: + if ($isAble) { + $message = $this->get_lang('AdvancedSubscriptionNoQueueIsAble'); + } else { + $message = $this->get_lang('AdvancedSubscriptionNoQueue'); + } + break; + case ADV_SUB_QUEUE_STATUS_START: + $message = $this->get_lang('AdvancedSubscriptionQueueStart'); + break; + case ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED: + $message = $this->get_lang('AdvancedSubscriptionQueueBossDisapproved'); + break; + case ADV_SUB_QUEUE_STATUS_BOSS_APPROVED: + $message = $this->get_lang('AdvancedSubscriptionQueueBossApproved'); + break; + case ADV_SUB_QUEUE_STATUS_ADMIN_DISAPPROVED: + $message = $this->get_lang('AdvancedSubscriptionQueueAdminDisapproved'); + break; + case ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED: + $message = $this->get_lang('AdvancedSubscriptionQueueAdminApproved'); + break; + default: + $message = sprintf($this->get_lang('AdvancedSubscriptionQueueDefault'), $status); + + } + + return $message; + } } diff --git a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php index b878d5a0f9..376d74b69f 100644 --- a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php +++ b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php @@ -108,6 +108,44 @@ class HookAdvancedSubscription extends HookObserver implements ) ); + // Input params for get session Details + $server->wsdl->addComplexType( + 'advsubSessionDetailInput', + 'complexType', + 'struct', + 'all', + '', + array( + 'user_id' => array('name' => 'id', 'type' => 'xsd:int'), // Chamilo user_id + 'session_id' => array('name' => 'name', 'type' => 'xsd:int'), // Chamilo session_id + 'secret_key' => array('name' => 'secret_key', 'type' => 'xsd:string'), + 'profile_completed' => array('name' => 'profile_completed', 'type' => 'xsd:float'), + 'is_connected' => array('name' => 'secret_key', 'type' => 'xsd:boolean'), + ) + ); + + // Output params for get session Details + $server->wsdl->addComplexType( + 'advsubSessionDetail', + 'complexType', + 'struct', + 'all', + '', + array( + 'id' => array('name' => 'id', 'type' => 'xsd:string'), + 'cost' => array('name' => 'cost', 'type' => 'xsd:string'), + 'place' => array('name' => 'place', 'type' => 'xsd:string'), + 'visitors' => array('name' => 'visitors', 'type' => 'xsd:string'), + 'duration' => array('name' => 'duration', 'type' => 'xsd:int'), + 'brochure' => array('name' => 'brochure', 'type' => 'xsd:string'), + 'banner' => array('name' => 'banner', 'type' => 'xsd:string'), + 'description_full' => array('name' => 'description_full', 'type' => 'xsd:string'), + 'status' => array('name' => 'status', 'type' => 'xsd:string'), + 'action_url' => array('name' => 'action_url', 'type' => 'xsd:string'), + 'message' => array('name' => 'error_message', 'type' => 'xsd:string'), + ) + ); + // Register the method to expose $server->register('HookAdvancedSubscription..WSSessionListInCategory', // method name array('sessionCategoryInput' => 'tns:sessionCategoryInput'), // input parameters @@ -129,6 +167,16 @@ class HookAdvancedSubscription extends HookObserver implements 'This service encrypt data to be used later in urls' // documentation ); + $server->register('HookAdvancedSubscription..WSSessionGetDetailsByUser', // method name + array('input' => 'xsd:string'), // input parameters + array('return' => 'tns:advsubSessionDetail'), // output parameters + 'urn:WSRegistration', // namespace + 'urn:WSRegistration#WSSessionGetDetailsByUser', // soapaction + 'rpc', // style + 'encoded', // use + 'This service encrypt data to be used later in urls' // documentation + ); + return $data; } else { // Nothing to do @@ -215,4 +263,74 @@ class HookAdvancedSubscription extends HookObserver implements return $result; } + /** + * @param $params + * @return null|soap_fault + */ + public function WSSessionGetDetailsByUser($params) + { + global $debug; + + if ($debug) error_log('WSUserSubscribedInCourse'); + if ($debug) error_log('Params '. print_r($params, 1)); + if (!WSHelperVerifyKey($params)) { + + //return return_error(WS_ERROR_SECRET_KEY); + } + $result = return_error(WS_ERROR_NOT_FOUND_RESULT); + // Check params + if (is_array($params) && !empty($params['session_id']) && !empty($params['user_id'])) { + $userId = (int) $params['user_id']; + $sessionId = (int) $params['session_id']; + // Check if student is already subscribed + + $advsubPlugin = AdvancedSubscriptionPlugin::create(); + $isOpen = $advsubPlugin->isSessionOpen($sessionId); + $status = $advsubPlugin->getQueueStatus($userId, $sessionId); + $vacancy = $advsubPlugin->getVacancy($sessionId); + $data = $advsubPlugin->getSessionDetails($sessionId); + if (!empty($data) && is_array($data)) { + + $data['status'] = $status; + // 5 Cases: + if ($isOpen) { + // Go to Course session + $data['action_url'] = $advsubPlugin->getSessionUrl($sessionId); + } else { + try { + $isAble = $advsubPlugin->isAbleToRequest($userId, $params); + $data['message'] = $advsubPlugin->getStatusMessage($status, $isAble); + } catch (\Exception $e) { + $data['message'] = $e->getMessage(); + } + if ($vacancy > 0) { + // Check conditions + if ($status === ADV_SUB_QUEUE_STATUS_NO_QUEUE) { + // No in Queue, require queue subscription url action + } elseif ($status === ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED) { + // send url action + $data['action_url'] = $advsubPlugin->getSessionUrl($sessionId); + } else { + // In queue, output status message, no more info. + } + } else { + if ($status === ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED) { + + } else { + // in Queue or not, cannot be subscribed to session + } + + } + + } + $result = $data; + } + } else { + // Return soap fault Not valid input params + $result = return_error(WS_ERROR_INVALID_INPUT); + } + + return $result; + } + } \ No newline at end of file From a5986290a2eea737b3d143c4c4bf428e0ca487a8 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Tue, 20 Jan 2015 13:58:46 -0500 Subject: [PATCH 14/72] Fix, tested Session detail Webservice BT#9168 - refs BT#9092 --- .../advancedsubscription/ajax/advsub.ajax.php | 2 +- .../src/AdvancedSubscriptionPlugin.class.php | 72 +++++++++---------- .../src/HookAdvancedSubscription.class.php | 7 +- 3 files changed, 39 insertions(+), 42 deletions(-) diff --git a/plugin/advancedsubscription/ajax/advsub.ajax.php b/plugin/advancedsubscription/ajax/advsub.ajax.php index c0e251e771..6764ffe64f 100644 --- a/plugin/advancedsubscription/ajax/advsub.ajax.php +++ b/plugin/advancedsubscription/ajax/advsub.ajax.php @@ -11,7 +11,7 @@ require_once '../config.php'; $plugin = AdvancedSubscriptionPlugin::create(); $data = isset($_REQUEST['data']) ? strlen($_REQUEST['data']) > 16 ? - $plugin->decrypt(Security::remove_XSS($_REQUEST['data'])) : + $plugin->decrypt($_REQUEST['data']) : null : null; // Get data diff --git a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php index 5b7dfe249f..b7028e8285 100644 --- a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php +++ b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php @@ -72,40 +72,17 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface private function installDatabase() { $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); - $pAdvSubMailTable = Database::get_main_table(TABLE_ADV_SUB_MAIL); - $pAdvSubMailTypeTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_TYPE); - $pAdvSubMailStatusTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_STATUS); $sql = "CREATE TABLE IF NOT EXISTS $pAdvSubQueueTable (" . "id int UNSIGNED NOT NULL AUTO_INCREMENT, " . "session_id int UNSIGNED NOT NULL, " . "user_id int UNSIGNED NOT NULL, " . "status int UNSIGNED NOT NULL, " . - "last_message_id UNSIGNED NOT NULL, " . + "last_message_id int UNSIGNED NOT NULL, " . "created_at datetime NOT NULL, " . "updated_at datetime NULL, " . - "PRIMARY KEY PK_tour_log (id)); "; - Database::query($sql); - - $sql = "CREATE TABLE $pAdvSubMailTypeTable ( " . - "id int UNSIGNED NOT NULL AUTO_INCREMENT, " . - "description char(20), " . - "PRIMARY KEY PK_advsub_mail_type (id) " . - "); "; - - Database::query($sql); - $sql = "CREATE TABLE $pAdvSubMailTable ( " . - "id int UNSIGNED NOT NULL AUTO_INCREMENT, " . - "message_id, mail_type_id, mail_status_id, " . - "PRIMARY KEY PK_advsub_mail (id) " . - "); "; - Database::query($sql); - - $sql = "CREATE TABLE $pAdvSubMailStatusTable ( " . - "id int UNSIGNED NOT NULL AUTO_INCREMENT, " . - "description char(20), " . - "PRIMARY KEY PK_advsub_mail_status (id) " . - "); "; + "PRIMARY KEY PK_advsub_queue (id), " . + "UNIQUE KEY UK_advsub_queue (user_id, session_id)); "; Database::query($sql); } @@ -117,18 +94,9 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface { /* Drop plugin tables */ $pAdvSubQueueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); - $pAdvSubMailTable = Database::get_main_table(TABLE_ADV_SUB_MAIL); - $pAdvSubMailTypeTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_TYPE); - $pAdvSubMailStatusTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_STATUS); $sql = "DROP TABLE IF EXISTS $pAdvSubQueueTable; "; Database::query($sql); - $sql = "DROP TABLE IF EXISTS $pAdvSubMailTable; "; - Database::query($sql); - $sql = "DROP TABLE IF EXISTS $pAdvSubMailTypeTable; "; - Database::query($sql); - $sql = "DROP TABLE IF EXISTS $pAdvSubMailStatusTable; "; - Database::query($sql); /* Delete settings */ $tSettings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT); @@ -165,15 +133,18 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $uitMax *= $advSubPlugin->get('yearly_cost_limit'); // @TODO: Get UIT completed by user this year by WS $uitUser = 0; - if ($uitMax > $uitUser) { + $extra = new ExtraFieldValue('session'); + $uitUser += $extra->get_values_by_handler_and_field_variable($params['session_id'], 'costo'); + if ($uitMax >= $uitUser) { $expendedTimeMax = $advSubPlugin->get('yearly_hours_limit'); // @TODO: Get Expended time from user data $expendedTime = 0; - if ($expendedTimeMax > $expendedTime) { + $expendedTime += $extra->get_values_by_handler_and_field_variable($params['session_id'], 'duracion'); + if ($expendedTimeMax >= $expendedTime) { $expendedNumMax = $advSubPlugin->get('courses_count_limit'); // @TODO: Get Expended num from user $expendedNum = 0; - if ($expendedNumMax > $expendedNum) { + if ($expendedNumMax >= $expendedNum) { $isAble = true; } else { throw new \Exception(get_lang('AdvancedSubscriptionCourseXLimitReached')); @@ -689,8 +660,12 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $data['place'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'lugar'); $data['allow_visitors'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'permitir_visitantes'); $data['class_hours'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'horas_lectivas'); + // Get brochure URL $data['brochure'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'brochure'); + $data['brochure'] = api_get_path(WEB_CODE_PATH) . $data['brochure']['field_value']; + // Get banner URL $data['banner'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'banner'); + $data['banner'] = api_get_path(WEB_CODE_PATH) . $data['banner']['field_value']; $data['description'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'descripcion'); $data['class_hours'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'horas_lectivas'); @@ -740,4 +715,25 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface return $message; } + + public function getSessionUrl($sessionId) + { + $url = api_get_path(WEB_CODE_PATH) . 'session/?session_id=' . $sessionId; + return $url; + } + + public function getQueueUrl($params) + { + $data = array( + 'a' => 'second', + 'u' => $params['user_id'], + 's' => $params['session_id'], + 'is_connected' => $params['is_connected'], + 'profile_completed' => $params['profile_completed'], + 'accept' => $params['accept'], + ); + $data = $this->encrypt($data); + $url = api_get_path(WEB_PLUGIN_PATH) . 'advancedsubscription/ajax/advsub.ajax.php?data=' . $data; + return $url; + } } diff --git a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php index 376d74b69f..bcc658cc4a 100644 --- a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php +++ b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php @@ -168,7 +168,7 @@ class HookAdvancedSubscription extends HookObserver implements ); $server->register('HookAdvancedSubscription..WSSessionGetDetailsByUser', // method name - array('input' => 'xsd:string'), // input parameters + array('advsubSessionDetailInput' => 'tns:advsubSessionDetailInput'), // input parameters array('return' => 'tns:advsubSessionDetail'), // output parameters 'urn:WSRegistration', // namespace 'urn:WSRegistration#WSSessionGetDetailsByUser', // soapaction @@ -290,7 +290,6 @@ class HookAdvancedSubscription extends HookObserver implements $vacancy = $advsubPlugin->getVacancy($sessionId); $data = $advsubPlugin->getSessionDetails($sessionId); if (!empty($data) && is_array($data)) { - $data['status'] = $status; // 5 Cases: if ($isOpen) { @@ -307,6 +306,7 @@ class HookAdvancedSubscription extends HookObserver implements // Check conditions if ($status === ADV_SUB_QUEUE_STATUS_NO_QUEUE) { // No in Queue, require queue subscription url action + $data['action_url'] = $advsubPlugin->getQueueUrl($params); } elseif ($status === ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED) { // send url action $data['action_url'] = $advsubPlugin->getSessionUrl($sessionId); @@ -315,9 +315,10 @@ class HookAdvancedSubscription extends HookObserver implements } } else { if ($status === ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED) { - + $data['action_url'] = $advsubPlugin->getSessionUrl($sessionId); } else { // in Queue or not, cannot be subscribed to session + $data['action_url'] = $advsubPlugin->getQueueUrl($params); } } From c0d2a46f5fdcde818d5471f12a9177b73b0a646d Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Tue, 20 Jan 2015 15:30:55 -0500 Subject: [PATCH 15/72] Fix for mail table delete - refs BT#9092 --- plugin/advancedsubscription/config.php | 11 -- .../src/AdvancedSubscriptionPlugin.class.php | 113 ++++++++---------- 2 files changed, 53 insertions(+), 71 deletions(-) diff --git a/plugin/advancedsubscription/config.php b/plugin/advancedsubscription/config.php index 8f015ff0bc..e8d7b3faf2 100644 --- a/plugin/advancedsubscription/config.php +++ b/plugin/advancedsubscription/config.php @@ -7,9 +7,6 @@ */ define('TABLE_ADV_SUB_QUEUE', 'plugin_advsub_queue'); -define('TABLE_ADV_SUB_MAIL', 'plugin_advsub_mail'); -define('TABLE_ADV_SUB_MAIL_TYPE', 'plugin_advsub_mail_type'); -define('TABLE_ADV_SUB_MAIL_STATUS', 'plugin_advsub_mail_status'); define('ADV_SUB_ACTION_STUDENT_REQUEST', 0); define('ADV_SUB_ACTION_SUPERIOR_APPROVE', 1); @@ -25,14 +22,6 @@ define('ADV_SUB_QUEUE_STATUS_BOSS_APPROVED', 2); define('ADV_SUB_QUEUE_STATUS_ADMIN_DISAPPROVED', 3); define('ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED', 10); -define('ADV_SUB_MAIL_TYPE_A', 1); -define('ADV_SUB_MAIL_TYPE_B', 2); -define('ADV_SUB_MAIL_TYPE_C', 3); - -define('ADV_SUB_MAIL_STATUS_MAIL_SENT', 1); -define('ADV_SUB_MAIL_STATUS_MAIL_ANSWERED', 2); -define('ADV_SUB_MAIL_STATUS_MAIL_EXPIRED', 3); - require_once __DIR__ . '/../../main/inc/global.inc.php'; require_once api_get_path(LIBRARY_PATH) . 'plugin.class.php'; require_once __DIR__ . '/resources/phpcrypt/phpCrypt.php'; diff --git a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php index b7028e8285..3f42f097b6 100644 --- a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php +++ b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php @@ -173,6 +173,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface } /** + * Register a user into a queue for a session * @param $userId * @param $sessionId * @return bool|int @@ -194,59 +195,27 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface return $id; } - /** - * Register a message type - * @param $description - * @return bool|int - */ - public function addMessageType($description) - { - $pAdvSubMessageTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_TYPE); - $attributes = array( - 'description' => $description, - ); - - $id = Database::insert($pAdvSubMessageTable, $attributes); - - return $id; - } - - /** - * Register a message status - * @param $description - * @return bool|int - */ - public function addMessageStatus($description) - { - $pAdvSubMessageTable = Database::get_main_table(TABLE_ADV_SUB_MAIL_STATUS); - $attributes = array( - 'description' => $description, - ); - - $id = Database::insert($pAdvSubMessageTable, $attributes); - - return $id; - } - /** * Register message with type and status * @param $mailId - * @param $mailTypeId - * @param $mailStatusId + * @param $userId + * @param $sessionId * @return bool|int */ - public function addMessage($mailId, $mailTypeId, $mailStatusId) + public function saveLastMessage($mailId, $userId, $sessionId) { - $pAdvSubMessageTable = Database::get_main_table(TABLE_ADV_SUB_MAIL); + $queueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); $attributes = array( - 'message_id' => $mailId, - 'mail_type_id' => $mailTypeId, - 'mail_status_id' => $mailStatusId, + 'last_message_id' => $mailId, ); - $id = Database::insert($pAdvSubMessageTable, $attributes); + $num = Database::update( + $queueTable, + $attributes, + array('user_id = ? AND session_id = ?' => array($userId, $sessionId)) + ); - return $id; + return $num; } /** @@ -277,7 +246,15 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface return $result; } - public function sendMailMessage($studentId, $subject, $content, $type = '') + /** + * Send message for the student subscription approval to a specific session + * @param $studentId + * @param $subject + * @param $content + * @param $sessionId + * @return bool|int + */ + public function sendMailMessage($studentId, $subject, $content, $sessionId) { global $_configuration; // @TODO: Add $_configuration['no_reply_user_id'] to configuration file @@ -296,7 +273,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface if (!empty($mailId)) { // Save as sent message - $mailId = $this->addMessage($mailId, $type, ADV_SUB_MAIL_STATUS_MAIL_SENT); + $mailId = $this->saveLastMessage($mailId, $studentId, $sessionId); } return $mailId; @@ -334,6 +311,12 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface return $isOpen; } + /** + * Update the queue status for subscription approval rejected or accepted + * @param $params + * @param $newStatus + * @return bool + */ public function updateQueueStatus($params, $newStatus) { if (isset($params['queue']['id'])) { @@ -384,14 +367,14 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $data['student']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_received.tpl'), - ADV_SUB_MAIL_TYPE_A + $data['session_id'] ); // Mail to superior $mailIds[] = $this->sendMailMessage( $data['superior']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_superior.tpl'), - ADV_SUB_MAIL_TYPE_B + $data['session_id'] ); break; case ADV_SUB_ACTION_SUPERIOR_APPROVE: @@ -400,21 +383,21 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $data['student']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_superior_approved.tpl'), - ADV_SUB_MAIL_TYPE_A + $data['session_id'] ); // Mail to superior $mailIds[] = $this->sendMailMessage( $data['superior']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approve_confirmed.tpl'), - ADV_SUB_MAIL_TYPE_B + $data['session_id'] ); // Mail to admin $mailIds[] = $this->sendMailMessage( $data['admin']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_approved_info_admin.tpl'), - ADV_SUB_MAIL_TYPE_C + $data['session_id'] ); break; case ADV_SUB_ACTION_SUPERIOR_DISAPPROVE: @@ -423,14 +406,14 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $data['student']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_superior_disapproved.tpl'), - ADV_SUB_MAIL_TYPE_A + $data['session_id'] ); // Mail to superior $mailIds[] = $this->sendMailMessage( $data['superior']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_disapprove_confirmed.tpl'), - ADV_SUB_MAIL_TYPE_B + $data['session_id'] ); break; case ADV_SUB_ACTION_SUPERIOR_SELECT: @@ -439,14 +422,14 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $data['student']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_received.tpl'), - ADV_SUB_MAIL_TYPE_A + $data['session_id'] ); // Mail to superior $mailIds[] = $this->sendMailMessage( $data['superior']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_superior.tpl'), - ADV_SUB_MAIL_TYPE_B + $data['session_id'] ); break; case ADV_SUB_ACTION_ADMIN_APPROVE: @@ -455,21 +438,21 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $data['student']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_accepted_notice_student.tpl'), - ADV_SUB_MAIL_TYPE_A + $data['session_id'] ); // Mail to superior $mailIds[] = $this->sendMailMessage( $data['superior']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_accepted_notice_superior.tpl'), - ADV_SUB_MAIL_TYPE_B + $data['session_id'] ); // Mail to admin $mailIds[] = $this->sendMailMessage( $data['admin']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl'), - ADV_SUB_MAIL_TYPE_C + $data['session_id'] ); break; case ADV_SUB_ACTION_ADMIN_DISAPPROVE: @@ -478,21 +461,21 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $data['student']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_rejected_notice_student.tpl'), - ADV_SUB_MAIL_TYPE_A + $data['session_id'] ); // Mail to superior $mailIds[] = $this->sendMailMessage( $data['superior']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_rejected_notice_superior.tpl'), - ADV_SUB_MAIL_TYPE_B + $data['session_id'] ); // Mail to admin $mailIds[] = $this->sendMailMessage( $data['admin']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_rejected_notice_admin.tpl'), - ADV_SUB_MAIL_TYPE_C + $data['session_id'] ); break; default: @@ -716,12 +699,22 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface return $message; } + /** + * Return the url to go to session + * @param $sessionId + * @return string + */ public function getSessionUrl($sessionId) { $url = api_get_path(WEB_CODE_PATH) . 'session/?session_id=' . $sessionId; return $url; } + /** + * Return the url to enter to subscription queue to session + * @param $params + * @return string + */ public function getQueueUrl($params) { $data = array( From 2a404a6a577eab0e202f921f65bee0d264a1a6e5 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Wed, 21 Jan 2015 17:47:04 -0500 Subject: [PATCH 16/72] Add Admin view for advanced subscription plugin - refs BT#9092 --- .../advancedsubscription/ajax/advsub.ajax.php | 15 ++++- .../src/AdvancedSubscriptionPlugin.class.php | 60 ++++++++++++++++++ plugin/advancedsubscription/views/index.tpl | 62 +++++++++++++++++++ 3 files changed, 134 insertions(+), 3 deletions(-) diff --git a/plugin/advancedsubscription/ajax/advsub.ajax.php b/plugin/advancedsubscription/ajax/advsub.ajax.php index 6764ffe64f..d0a3af1bf4 100644 --- a/plugin/advancedsubscription/ajax/advsub.ajax.php +++ b/plugin/advancedsubscription/ajax/advsub.ajax.php @@ -6,7 +6,7 @@ * Time: 01:51 PM */ -require_once '../config.php'; +require_once __DIR__ . '/../config.php'; $plugin = AdvancedSubscriptionPlugin::create(); $data = isset($_REQUEST['data']) ? @@ -73,7 +73,6 @@ if (!empty($a) && !empty($u)) { } break; case 'third': // Encrypt - $plugin = AdvancedSubscriptionPlugin::create(); $res = $plugin->encrypt($data); if (!empty($res) && strlen($res) > 16) { $result['error'] = false; @@ -88,9 +87,19 @@ if (!empty($a) && !empty($u)) { $result['pass'] = false; } break; + case 'admin': + $studentList = $plugin->listAllStudentsInQueueBySession($s); + $sessionList = $plugin->listAllSessions(); + $tpl = new Template('TESTING'); + $tpl->assign('session', $studentList['session']); + $tpl->assign('sessionItems', $sessionList); + $tpl->assign('students', $studentList['students']); + $content = $tpl->fetch('/advancedsubscription/views/index.tpl'); + $tpl->assign('content', $content); + $tpl->display_one_col_template(); + exit; default: $result['errorMessage'] = 'Action do not exist!'; - break; } } diff --git a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php index 3f42f097b6..917c123a12 100644 --- a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php +++ b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php @@ -729,4 +729,64 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $url = api_get_path(WEB_PLUGIN_PATH) . 'advancedsubscription/ajax/advsub.ajax.php?data=' . $data; return $url; } + + /** + * Return the list of student, in queue used by admin view + * @param int $sessionId + * @return array + */ + public function listAllStudentsInQueueBySession($sessionId) + { + $return = array(); + $extraSession = new ExtraFieldValue('session'); + $session = api_get_session_info($sessionId); + $session['publico_objetivo'] = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'publico_objetivo'); + $session['fin_publicacion'] = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'fin_publicacion'); + $session['modalidad'] = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'modalidad'); + $session['participantes_recomendados'] = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'numero_recomendado_participantes'); + $session['vacantes'] = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'vacantes'); + $queueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); + $userTable = Database::get_main_table(TABLE_MAIN_USER); + $userJoinTable = $queueTable . ' q INNER JOIN ' . $userTable . ' u ON q.user_id = u.user_id'; + $where = array('where' => array('session_id = ?' => $sessionId)); + $select = 'u.user_id, u.firstname, u.lastname, q.created_at, q.updated_at, q.status'; + $students = Database::select($select, $userJoinTable, $where); + foreach ($students as &$student) { + $status = intval($student['status']); + switch($status) { + case ADV_SUB_QUEUE_STATUS_NO_QUEUE: + case ADV_SUB_QUEUE_STATUS_START: + $student['validation'] = ''; + break; + case ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED: + case ADV_SUB_QUEUE_STATUS_ADMIN_DISAPPROVED: + $student['validation'] = get_lang('No'); + break; + case ADV_SUB_QUEUE_STATUS_BOSS_APPROVED: + case ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED: + $student['validation'] = get_lang('Yes'); + break; + default: + error_log(__FILE__ . ' ' . __FUNCTION__ . ' Student status no detected'); + } + } + $return = array( + 'session' => $session, + 'students' => $students, + ); + + return $return; + + } + + /** + * List all session (id, name) for select input + * @return array + */ + public function listAllSessions() + { + $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION); + $columns = 'id, name'; + return Database::select($columns, $sessionTable); + } } diff --git a/plugin/advancedsubscription/views/index.tpl b/plugin/advancedsubscription/views/index.tpl index e69de29bb2..73f5f9e073 100644 --- a/plugin/advancedsubscription/views/index.tpl +++ b/plugin/advancedsubscription/views/index.tpl @@ -0,0 +1,62 @@ + \ No newline at end of file From 89ee9656e34eafec8c477f0f77c8c15894dd5211 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Thu, 22 Jan 2015 11:13:53 -0500 Subject: [PATCH 17/72] Fix extra field value method use - refs BT#9092 --- .../src/AdvancedSubscriptionPlugin.class.php | 63 ++++++++++++------- .../src/HookAdvancedSubscription.class.php | 2 +- 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php index 917c123a12..dd9728c18e 100644 --- a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php +++ b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php @@ -134,12 +134,14 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface // @TODO: Get UIT completed by user this year by WS $uitUser = 0; $extra = new ExtraFieldValue('session'); - $uitUser += $extra->get_values_by_handler_and_field_variable($params['session_id'], 'costo'); + $var = $extra->get_values_by_handler_and_field_variable($params['session_id'], 'costo'); + $uitUser += $var['field_value']; if ($uitMax >= $uitUser) { $expendedTimeMax = $advSubPlugin->get('yearly_hours_limit'); // @TODO: Get Expended time from user data $expendedTime = 0; - $expendedTime += $extra->get_values_by_handler_and_field_variable($params['session_id'], 'duracion'); + $var = $extra->get_values_by_handler_and_field_variable($params['session_id'], 'duracion'); + $expendedTime += $var['field_value']; if ($expendedTimeMax >= $expendedTime) { $expendedNumMax = $advSubPlugin->get('courses_count_limit'); // @TODO: Get Expended num from user @@ -508,7 +510,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface } $where['where'] = $where; $count = Database::select('COUNT(*)', $advsubQueueTable, $where); - $count = $count[0]; + $count = $count[0]['COUNT(*)']; } return $count; } @@ -617,12 +619,15 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface { if (!empty($sessionId)) { $extra = new ExtraFieldValue('session'); - $vacancy = $extra->get_values_by_handler_and_field_variable($sessionId, 'vacantes'); - $vacancy -= $this->countQueueByParams(array('sessions' => $sessionId, 'status' => ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED)); + $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'vacantes'); + $vacancy = intval($var['field_value']); + if (!empty($vacancy)) { + $vacancy -= $this->countQueueByParams(array('sessions' => $sessionId, 'status' => ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED)); - if ($vacancy >= 0) { + if ($vacancy >= 0) { - return $vacancy; + return $vacancy; + } } } @@ -638,19 +643,26 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface { if (!empty($sessionId)) { $extra = new ExtraFieldValue('session'); - $data['id'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'id'); - $data['cost'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'costo'); - $data['place'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'lugar'); - $data['allow_visitors'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'permitir_visitantes'); - $data['class_hours'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'horas_lectivas'); + $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'id'); + $data['id'] = $var['field_value']; + $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'costo'); + $data['cost'] = $var['field_value']; + $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'lugar'); + $data['place'] = $var['field_value']; + $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'permitir_visitantes'); + $data['allow_visitors'] = $var['field_value']; + $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'horas_lectivas'); + $data['class_hours'] = $var['field_value']; // Get brochure URL - $data['brochure'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'brochure'); - $data['brochure'] = api_get_path(WEB_CODE_PATH) . $data['brochure']['field_value']; + $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'brochure'); + $data['brochure'] = api_get_path(WEB_CODE_PATH) . $var['field_value']; // Get banner URL - $data['banner'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'banner'); - $data['banner'] = api_get_path(WEB_CODE_PATH) . $data['banner']['field_value']; - $data['description'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'descripcion'); - $data['class_hours'] = $extra->get_values_by_handler_and_field_variable($sessionId, 'horas_lectivas'); + $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'banner'); + $data['banner'] = api_get_path(WEB_CODE_PATH) . $var['field_value']; + $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'descripcion'); + $data['description'] = $var['field_value']; + $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'horas_lectivas'); + $data['class_hours'] = $var['field_value']; return $data; } @@ -740,11 +752,16 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $return = array(); $extraSession = new ExtraFieldValue('session'); $session = api_get_session_info($sessionId); - $session['publico_objetivo'] = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'publico_objetivo'); - $session['fin_publicacion'] = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'fin_publicacion'); - $session['modalidad'] = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'modalidad'); - $session['participantes_recomendados'] = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'numero_recomendado_participantes'); - $session['vacantes'] = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'vacantes'); + $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'publico_objetivo'); + $session['publico_objetivo'] = $var['field_value']; + $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'fin_publicacion'); + $session['fin_publicacion'] = $var['field_value']; + $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'modalidad'); + $session['modalidad'] = $var['field_value']; + $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'numero_recomendado_participantes'); + $session['participantes_recomendados'] = $var['field_value']; + $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'vacantes'); + $session['vacantes'] = $var['field_value']; $queueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); $userTable = Database::get_main_table(TABLE_MAIN_USER); $userJoinTable = $queueTable . ' q INNER JOIN ' . $userTable . ' u ON q.user_id = u.user_id'; diff --git a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php index bcc658cc4a..4aad7dcab3 100644 --- a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php +++ b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php @@ -133,7 +133,7 @@ class HookAdvancedSubscription extends HookObserver implements '', array( 'id' => array('name' => 'id', 'type' => 'xsd:string'), - 'cost' => array('name' => 'cost', 'type' => 'xsd:string'), + 'cost' => array('name' => 'cost', 'type' => 'xsd:float'), 'place' => array('name' => 'place', 'type' => 'xsd:string'), 'visitors' => array('name' => 'visitors', 'type' => 'xsd:string'), 'duration' => array('name' => 'duration', 'type' => 'xsd:int'), From 80a036ef54f62b23e21778a5c14708a8b772e6c8 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Wed, 3 Dec 2014 15:19:18 -0500 Subject: [PATCH 18/72] WSListSessionDetailsByCategory from BT9090 - refs BT#9092 Conflicts: main/inc/lib/sessionmanager.lib.php main/webservices/registration.soap.php --- main/inc/lib/sessionmanager.lib.php | 158 ++++++++++- .../src/HookAdvancedSubscription.class.php | 247 ++++++++++++++++++ 2 files changed, 402 insertions(+), 3 deletions(-) diff --git a/main/inc/lib/sessionmanager.lib.php b/main/inc/lib/sessionmanager.lib.php index fd05c29605..baba3e8a0c 100755 --- a/main/inc/lib/sessionmanager.lib.php +++ b/main/inc/lib/sessionmanager.lib.php @@ -5233,8 +5233,8 @@ class SessionManager $sessionId = intval($sessionId); $userId = intval($userId); - $sql = "SELECT COUNT(1) AS qty FROM $sessionRelUserTable - WHERE id_session = $sessionId AND id_user = $userId AND relation_type = 0"; + $sql = "SELECT COUNT(1) AS qty FROM $sessionRelUserTable " + . "WHERE id_session = $sessionId AND id_user = $userId AND relation_type = 0"; $result = Database::fetch_assoc(Database::query($sql)); @@ -5314,7 +5314,6 @@ class SessionManager * Check if the course belongs to the session * @param int $sessionId The session id * @param string $courseCode The course code - * * @return bool */ public static function sessionHasCourse($sessionId, $courseCode) @@ -5498,4 +5497,157 @@ class SessionManager return $sessionList; } + + /** + * Return the Session Category id searched by name + * @param string $categoryName Name attribute of session category used for search query + * @param bool $force boolean used to get even if something is wrong (e.g not unique name) + * @return int|array If success, return category id (int), else it will return an array + * with the next structure: + * array('error' => true, 'errorMessage' => ERROR_MESSAGE) + */ + public static function getSessionCategoryIdByName($categoryName, $force = false) + { + // Start error result + $errorResult = array('error' => true, 'errorMessage' => 'There was an error'); + $categoryName = Database::escape_string($categoryName); + // Check if is not empty category name + if (!empty($categoryName)) { + $sessionCategoryTable = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY); + // Get all session category with same name + $result = Database::select( + 'id', + $sessionCategoryTable, + array( + 'where' => array( + 'name = ?' => $categoryName, + ) + ) + ); + // Check the result + if ($result < 1) { + // If not found any result, update error message + $errorResult['errorMessage'] = 'Not found any session category name ' . $categoryName; + } elseif (count($result) > 1 && !$force) { + // If found more than one result and force is disabled, update error message + $errorResult['errorMessage'] = 'Found many session categories'; + } elseif (count($result) == 1 || $force) { + // If found just one session category or force option is enabled + + return key($result); + } + } else { + // category name is empty, update error message + $errorResult['errorMessage'] = 'Not valid category name'; + } + + return $errorResult; + } + + /** + * Return all data from sessions (plus extra field, course and coach data) by category id + * @param int $sessionCategoryId session category id used to search sessions + * @return array + */ + public static function getSessionListAndExtraByCategoryId($sessionCategoryId) + { + // Start error result + $errorResult = array('error' => true, 'errorMessage' => 'There was an error'); + $sessionCategoryId = intval($sessionCategoryId); + // Check if sesssion category id is valid + if ($sessionCategoryId > 0) { + // Get table names + $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION); + $sessionFieldTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD); + $sessionFieldValueTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES); + $sessionCourseUserTable = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER); + $userTable = Database::get_main_table(TABLE_MAIN_USER); + $courseTable = Database::get_main_table(TABLE_MAIN_COURSE); + + // Get all data from all sessions whit the session category specified + $sessionList = Database::select( + '*', + $sessionTable, + array( + 'where' => array( + 'session_category_id = ?' => $sessionCategoryId + ) + ) + ); + // Check if session list query had result + if (!empty($sessionList)) { + // implode all session id + $sessionIdsString = '(' . implode(', ', array_keys($sessionList)) . ')'; + // Get all field variables + $sessionFieldList = Database::select('id, field_variable', $sessionFieldTable); + // Get all field values + $sessionFieldValueList = Database::select( + 'session_id, field_id, field_value', + $sessionFieldValueTable, + array('where' => array('session_id IN ?' => $sessionIdsString)) + ); + // Check if session field values had result + if (!empty($sessionFieldValueList)) { + $sessionFieldValueListBySession = array(); + foreach ($sessionFieldValueList as $key => $sessionFieldValue) { + // Create an array to index ids to session id + $sessionFieldValueListBySession[$sessionFieldValue['session_id']][] = $key; + } + } + // Query used to find course-coaches from sessions + $sql = "SELECT scu.id_session AS session_id, c.id AS course_id, c.code AS course_code," . + " c.title AS course_title, u.username AS coach_username, u.firstname AS coach_firstname, " . + " u.lastname AS coach_lastname " . + "FROM $courseTable c " . + "INNER JOIN $sessionCourseUserTable scu ON c.code = scu.course_code " . + "INNER JOIN $userTable u ON scu.id_user = u.user_id " . + "WHERE scu.status = 2 AND scu.id_session IN $sessionIdsString " . + "ORDER BY scu.id_session ASC "; + $res = Database::query($sql); + $sessionCourseList = Database::store_result($res, 'ASSOC'); + // Check if course list had result + if (!empty($sessionCourseList)) { + $sessionCourseListBySession = array(); + foreach ($sessionCourseList as $key => $sessionCourse) { + // Create an array to index ids to session_id + $sessionCourseListBySession[$sessionCourse['session_id']][] = $key; + } + } + // Join lists + if (is_array($sessionList)) { + foreach ($sessionList as $id => &$row) { + if (is_array($sessionFieldValueListBySession[$id])) { + // If have an index array for session extra fields, use it to join arrays + foreach ($sessionFieldValueListBySession[$id] as $key) { + $row['extra'][$key] = array( + 'field_name' => $sessionFieldList[$sessionFieldValueList[$key]['field_id']]['field_variable'], + 'field_value' => $sessionFieldValueList[$key]['field_value'], + ); + } + } + if (is_array($sessionCourseListBySession[$id])) { + // If have an index array for session course coach, use it to join arrays + foreach ($sessionCourseListBySession[$id] as $key) { + $row['course'][$key] = array( + 'course_id' => $sessionCourseList[$key]['course_id'], + 'course_code' => $sessionCourseList[$key]['course_code'], + 'course_title' => $sessionCourseList[$key]['course_title'], + 'coach_username' => $sessionCourseList[$key]['coach_username'], + 'coach_firstname' => $sessionCourseList[$key]['coach_firstname'], + 'coach_lastname' => $sessionCourseList[$key]['coach_lastname'], + ); + } + } + } + } + + return $sessionList; + } else { + // Not found result, update error message + $errorResult['errorMessage'] = 'Not found any session for session category id ' . $sessionCategoryId; + } + + return $errorResult; + } + } } diff --git a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php index 4aad7dcab3..67466afb82 100644 --- a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php +++ b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php @@ -146,6 +146,175 @@ class HookAdvancedSubscription extends HookObserver implements ) ); + /** WSListSessionsDetailsByCategory **/ + + $server->wsdl->addComplexType( + 'listSessionsDetailsByCategory', + 'complexType', + 'struct', + 'all', + '', + array( + 'id' => array('name' => 'id', 'type' => 'xsd:string'), // session_category.id + 'category_name' => array('name' => 'category_name', 'type' => 'xsd:string'), // session_category.name + 'access_url_id' => array('name' => 'access_url_id', 'type' => 'xsd:int'), // session_category.access_url_id + 'secret_key' => array('name' => 'secret_key', 'type' => 'xsd:string') // secret key + ), + array(), + 'tns:listSessionsDetailsByCategory' + ); + + $server->wsdl->addComplexType( + 'sessionDetailsCourse', + 'complexType', + 'struct', + 'all', + '', + array( + 'course_id' => array('name' => 'course_id', 'type' => 'xsd:int'), // course.id + 'course_code' => array('name' => 'course_code', 'type' => 'xsd:string'), // course.code + 'course_title' => array('name' => 'course_title', 'type' => 'xsd:string'), // course.title + 'coach_username' => array('name' => 'coach_username', 'type' => 'xsd:string'), // user.username + 'coach_firstname' => array('name' => 'coach_firstname', 'type' => 'xsd:string'), // user.firstname + 'coach_lastname' => array('name' => 'coach_lastname', 'type' => 'xsd:string'), // user.lastname + ) + ); + + + $server->wsdl->addComplexType( + 'sessionDetailsCourseList', + 'complexType', + 'array', + '', + 'SOAP-ENC:Array', + array(), + array( + array( + 'ref' => 'SOAP-ENC:arrayType', + 'wsdl:arrayType' => 'tns:sessionDetailsCourse[]', + ) + ), + 'tns:sessionDetailsCourse' + ); + + $server->wsdl->addComplexType( + 'sessionDetails', + 'complexType', + 'struct', + 'all', + '', + array( + // session.id + 'id' => array( + 'name' => 'id', + 'type' => 'xsd:int' + ), + // session.id_coach + 'coach_id' => array( + 'name' => 'coach_id', + 'type' => 'xsd:int' + ), + // session.name + 'name' => array( + 'name' => 'name', + 'type' => 'xsd:string' + ), + // session.nbr_courses + 'courses_num' => array( + 'name' => 'courses_num', + 'type' => 'xsd:int' + ), + // session.nbr_users + 'users_num' => array( + 'name' => 'users_num', + 'type' => 'xsd:int' + ), + // session.nbr_classes + 'classes_num' => array( + 'name' => 'classes_num', + 'type' => 'xsd:int' + ), + // session.date_start + 'date_start' => array( + 'name' => 'date_start', + 'type' => 'xsd:string' + ), + // session.date_end + 'date_end' => array( + 'name' => 'date_end', + 'type' => 'xsd:string' + ), + // session.nb_days_access_before_beginning + 'access_days_before_num' => array( + 'name' => 'access_days_before_num', + 'type' => 'xsd:int' + ), + // session.nb_days_access_after_end + 'access_days_after_num' => array( + 'name' => 'access_days_after_num', + 'type' => 'xsd:int' + ), + // session.session_admin_id + 'session_admin_id' => array( + 'name' => 'session_admin_id', + 'type' => 'xsd:int' + ), + // session.visibility + 'visibility' => array( + 'name' => 'visibility', + 'type' => 'xsd:int' + ), + // session.session_category_id + 'session_category_id' => array( + 'name' => 'session_category_id', + 'type' => 'xsd:int' + ), + // session.promotion_id + 'promotion_id' => array( + 'name' => 'promotion_id', + 'type' => 'xsd:int' + ), + // session.number of registered users validated + 'validated_user_num' => array( + 'name' => 'validated_user_num', + 'type' => 'xsd:int' + ), + // session.number of registered users from waiting queue + 'waiting_user_num' => array( + 'name' => 'waiting_user_num', + 'type' => 'xsd:int' + ), + // extra fields + // Array(field_name, field_value) + 'extra' => array( + 'name' => 'extra', + 'type' => 'tns:extrasList' + ), + // course and coaches data + // Array(course_id, course_code, course_title, coach_username, coach_firstname, coach_lastname) + 'course' => array( + 'name' => 'courses', + 'type' => 'tns:sessionDetailsCourseList' + ), + ) + ); + + $server->wsdl->addComplexType( + 'sessionDetailsList', + 'complexType', + 'array', + '', + 'SOAP-ENC:Array', + array(), + array( + array( + 'ref' => 'SOAP-ENC:arrayType', + 'wsdl:arrayType' => 'tns:sessionDetails[]', + ) + ), + 'tns:sessionDetails' + ); + // Register the method to expose $server->register('HookAdvancedSubscription..WSSessionListInCategory', // method name array('sessionCategoryInput' => 'tns:sessionCategoryInput'), // input parameters @@ -177,6 +346,17 @@ class HookAdvancedSubscription extends HookObserver implements 'This service encrypt data to be used later in urls' // documentation ); + $server->register( + 'HookAdvancedSubscription..WSListSessionsDetailsByCategory', // method name + array('name' => 'tns:listSessionsDetailsByCategory'), // input parameters + array('return' => 'tns:sessionDetailsList'), // output parameters + 'urn:WSRegistration', // namespace + 'urn:WSRegistration#WSListSessionsDetailsByCategory', // soapaction + 'rpc', // style + 'encoded', // use + 'This service returns a list of detailed sessions by a category' // documentation + ); + return $data; } else { // Nothing to do @@ -334,4 +514,71 @@ class HookAdvancedSubscription extends HookObserver implements return $result; } + /** + * Get a list of sessions (id, coach_id, name, courses_num, users_num, classes_num, + * date_start, date_end, access_days_before_num, session_admin_id, visibility, + * session_category_id, promotion_id, + * validated_user_num, waiting_user_num, + * extra, course) the validated_usernum and waiting_user_num are + * used when have the plugin for advance incsription enables. + * The extra data (field_name, field_value) + * The course data (course_id, course_code, course_title, + * coach_username, coach_firstname, coach_lastname) + * @param array List of parameters (id, category_name, access_url_id, secret_key) + * @return array|soap_fault Sessions list (id=>[title=>'title',url='http://...',date_start=>'...',date_end=>'']) + */ + function WSListSessionsDetailsByCategory($params) + { + global $debug; + + if ($debug) error_log('WSListSessionsDetailsByCategory'); + if ($debug) error_log('Params '. print_r($params, 1)); + $secretKey = $params['secret_key']; + + // Check if secret key is valid + if(!WSHelperVerifyKey($secretKey)) { + + //return return_error(WS_ERROR_SECRET_KEY); + } + + // Check if category ID is set + if (!empty($params['id']) && empty($params['category_name'])) { + $sessionCategoryId = $params['id']; + } elseif (!empty($params['category_name'])) { + // Check if category name is set + $sessionCategoryId = SessionManager::getSessionCategoryIdByName($params['category_name']); + if (is_array($sessionCategoryId)) { + $sessionCategoryId = current($sessionCategoryId); + } + } else { + // Return soap fault Not valid input params + + return return_error(WS_ERROR_INVALID_INPUT); + } + + // Get the session List by category + $sessionList = SessionManager::getSessionListAndExtraByCategoryId($sessionCategoryId); + + if (empty($sessionList)) { + // If not found any session, return error + + return return_error(WS_ERROR_NOT_FOUND_RESULT); + } + //@TODO: Not implemented yet, see BT#9092 + // Check if advanced inscription plugin is enabled + $isAdvancedInscriptionEnabled = false; + if ($isAdvancedInscriptionEnabled) { + // Get validated and waiting queue users count for each session + foreach ($sessionList as &$session) {; + // Add validated and queue users count + $session['validated_user_num'] = 0; + $session['waiting_user_num'] = 0; + } + } else { + // Set -1 to validated and waiting queue users count + } + + return $sessionList; + } + } \ No newline at end of file From c778dedc1879249c4735e39799ec7b8d5465c8e2 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Thu, 22 Jan 2015 16:40:17 -0500 Subject: [PATCH 19/72] Fix webservices, change vaiables names - refs BT#9092 --- main/inc/lib/sessionmanager.lib.php | 57 +++++++++---------- .../src/AdvancedSubscriptionPlugin.class.php | 8 +-- .../src/HookAdvancedSubscription.class.php | 41 +++++-------- 3 files changed, 45 insertions(+), 61 deletions(-) diff --git a/main/inc/lib/sessionmanager.lib.php b/main/inc/lib/sessionmanager.lib.php index baba3e8a0c..e663ba42a5 100755 --- a/main/inc/lib/sessionmanager.lib.php +++ b/main/inc/lib/sessionmanager.lib.php @@ -5451,47 +5451,46 @@ class SessionManager $sTable = Database::get_main_table(TABLE_MAIN_SESSION); $sfTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD); $sfvTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES); + $joinSSfvTable = $sTable . ' o INNER JOIN ' . $sfvTable . ' q ON s.id = sfv.session_id'; $joinTable = $sfTable . ' sf INNER JOIN ' . $sfvTable . ' sfv ON sf.id = sfv.field_id'; + $fieldsArray = array( + 'as_description', 'modalidad', 'duracion', 'vacantes', 'brochure', 'publico_objetivo', 'horario' + ); $sessionList = Database::select( 'id, name, date_start, date_end', $sTable, array( 'where' => array( - 'session_category_id = ?' => $categoryId - ) - ) - ); - $sessionFieldValueList = Database::select( - 'CONCAT(sfv.session_id, sf.field_variable) AS id, sfv.field_value AS field_value', - $joinTable, - array( - 'where' => array( - 'sf.field_variable IN ( ?, ?, ?, ?, ?, ? )' => array( - 'as_description', 'modalidad', 'duracion', 'cupos', 'brochure', 'publico_objetivo', - ) + "session_category_id = ? AND id IN ( + SELECT sfv.session_id FROM $joinTable WHERE + sfv.session_id = session.id + AND sf.field_variable = 'publico_objetivo' + AND sfv.field_value = ? + );" => array($categoryId, $publicoObjetivo) ) ) ); - } + $extraField = new ExtraField('session'); + $fieldList = $extraField->get_all(array( + 'field_variable IN ( ?, ?, ?, ?, ?, ?, ? )' => $fieldsArray + )); + foreach ($fieldList as $field) { + $fields[$field['id']] = $field['field_variable']; + } + $extra = new ExtraFieldValue('session'); + $sessionFieldValueList = $extra->get_all(array('field_id IN ( ?, ?, ?, ?, ?, ?, ? )' => array_keys($fields))); + } foreach ($sessionList as $id => &$session) { - if ($publicoObjetivo == $sessionFieldValueList[$id . 'publico_objetivo']['field_value']) { - $session['modalidad'] = isset($sessionFieldValueList[$id . 'modalidad']) ? - $sessionFieldValueList[$id . 'modalidad']['field_value'] : - ''; - $session['descripcion'] = isset($sessionFieldValueList[$id . 'modalidad']) ? - $sessionFieldValueList[$id . 'modalidad']['field_value'] : - ''; - $session['duracion'] = isset($sessionFieldValueList[$id . 'duracion']) ? - $sessionFieldValueList[$id . 'duracion']['field_value'] : - ''; - $session['cupos'] = isset($sessionFieldValueList[$id . 'cupos']) ? - $sessionFieldValueList[$id . 'cupos']['field_value'] : - ''; - $session['horario'] = isset($sessionFieldValueList[$id . 'horario']) ? - $sessionFieldValueList[$id . 'horario']['field_value'] : - ''; + foreach ($sessionFieldValueList as $sessionFieldValue) { + if ($sessionFieldValue['session_id'] == $id) { + if (isset($fields[$sessionFieldValue['field_id']])) { + $var = $fields[$sessionFieldValue['field_id']]; + $val = $sessionFieldValue['field_value']; + $session[$var] = $val; + } + } } } diff --git a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php index dd9728c18e..20e600f2ac 100644 --- a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php +++ b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php @@ -600,7 +600,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface if (count($row) == 1) { - return $row['status']; + return $row[0]['status']; } else { return ADV_SUB_QUEUE_STATUS_NO_QUEUE; @@ -650,9 +650,9 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'lugar'); $data['place'] = $var['field_value']; $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'permitir_visitantes'); - $data['allow_visitors'] = $var['field_value']; + $data['visitors'] = $var['field_value']; $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'horas_lectivas'); - $data['class_hours'] = $var['field_value']; + $data['duration'] = $var['field_value']; // Get brochure URL $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'brochure'); $data['brochure'] = api_get_path(WEB_CODE_PATH) . $var['field_value']; @@ -661,8 +661,6 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $data['banner'] = api_get_path(WEB_CODE_PATH) . $var['field_value']; $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'descripcion'); $data['description'] = $var['field_value']; - $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'horas_lectivas'); - $data['class_hours'] = $var['field_value']; return $data; } diff --git a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php index 67466afb82..72aeb16905 100644 --- a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php +++ b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php @@ -69,13 +69,13 @@ class HookAdvancedSubscription extends HookObserver implements '', array( 'name' => array('name' => 'name', 'type' => 'xsd:string'), //Course string code - 'description' => array('name' => 'description', 'type' => 'xsd:string'), //Chamilo user_id - 'modality' => array('name' => 'start_date', 'type' => 'xsd:string'), + 'as_description' => array('name' => 'description', 'type' => 'xsd:string'), //Chamilo user_id + 'modalidad' => array('name' => 'start_date', 'type' => 'xsd:string'), 'date_start' => array('name' => 'start_date', 'type' => 'xsd:string'), 'date_end' => array('name' => 'end_date', 'type' => 'xsd:string'), - 'duration' => array('name' => 'date_end', 'type' => 'xsd:string'), - 'quota' => array('name' => 'quota', 'type' => 'xsd:string'), - 'schedule' => array('name' => 'schedule', 'type' => 'xsd:string'), + 'duracion' => array('name' => 'date_end', 'type' => 'xsd:string'), + 'vacantes' => array('name' => 'quota', 'type' => 'xsd:string'), + 'horario' => array('name' => 'schedule', 'type' => 'xsd:string'), ) ); @@ -316,7 +316,8 @@ class HookAdvancedSubscription extends HookObserver implements ); // Register the method to expose - $server->register('HookAdvancedSubscription..WSSessionListInCategory', // method name + $server->register( + 'HookAdvancedSubscription..WSSessionListInCategory', // method name array('sessionCategoryInput' => 'tns:sessionCategoryInput'), // input parameters array('return' => 'tns:sessionBriefList'), // output parameters 'urn:WSRegistration', // namespace @@ -326,8 +327,9 @@ class HookAdvancedSubscription extends HookObserver implements 'This service checks if user assigned to course' // documentation ); - $server->register('HookAdvancedSubscription..WSAdvsubEncrypt', // method name - array('sessionCategoryInput' => 'xsd:string'), // input parameters + $server->register( + 'HookAdvancedSubscription..WSAdvsubEncrypt', // method name + array('data' => 'xsd:string'), // input parameters array('return' => 'xsd:string'), // output parameters 'urn:WSRegistration', // namespace 'urn:WSRegistration#WSAdvsubEncrypt', // soapaction @@ -336,7 +338,8 @@ class HookAdvancedSubscription extends HookObserver implements 'This service encrypt data to be used later in urls' // documentation ); - $server->register('HookAdvancedSubscription..WSSessionGetDetailsByUser', // method name + $server->register( + 'HookAdvancedSubscription..WSSessionGetDetailsByUser', // method name array('advsubSessionDetailInput' => 'tns:advsubSessionDetailInput'), // input parameters array('return' => 'tns:advsubSessionDetail'), // output parameters 'urn:WSRegistration', // namespace @@ -375,7 +378,7 @@ class HookAdvancedSubscription extends HookObserver implements if ($debug) error_log('Params '. print_r($params, 1)); if (!WSHelperVerifyKey($params)) { - return return_error(WS_ERROR_SECRET_KEY); + //return return_error(WS_ERROR_SECRET_KEY); } // Check if category ID is set if (!empty($params['id']) && empty($params['category_name'])) { @@ -393,22 +396,8 @@ class HookAdvancedSubscription extends HookObserver implements } // Get the session brief List by category - $sessionList = SessionManager::getSessionBriefListByCategory($sessionCategoryId, $params['target']); - /* - $extraFieldSession = new ExtraFieldValue('session'); - $hasExtraField = $extraFieldSession->get_values_by_handler_and_field_variable(key($sessionList), 'publico_objetivo'); - var_dump($hasExtraField); - if ($hasExtraField != false) { - // Has session extra fields, Nothing to do - } else { - // No session extra fields - - return return_error(WS_ERROR_NOT_FOUND_RESULT); - } - */ - return $sessionList; } @@ -500,9 +489,7 @@ class HookAdvancedSubscription extends HookObserver implements // in Queue or not, cannot be subscribed to session $data['action_url'] = $advsubPlugin->getQueueUrl($params); } - } - } $result = $data; } @@ -569,7 +556,7 @@ class HookAdvancedSubscription extends HookObserver implements $isAdvancedInscriptionEnabled = false; if ($isAdvancedInscriptionEnabled) { // Get validated and waiting queue users count for each session - foreach ($sessionList as &$session) {; + foreach ($sessionList as &$session) { // Add validated and queue users count $session['validated_user_num'] = 0; $session['waiting_user_num'] = 0; From 452837194f4fd6ca92d257ab890a439a5821045f Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Fri, 23 Jan 2015 15:36:16 -0500 Subject: [PATCH 20/72] Add data to advanced subscription mails - refs BT#9092 --- .../advancedsubscription/ajax/advsub.ajax.php | 27 ++++++++++++++++ .../src/AdvancedSubscriptionPlugin.class.php | 31 ++++++++++++------- .../src/HookAdvancedSubscription.class.php | 27 +++++++++------- .../views/advsub_request_received.tpl | 2 +- .../advsub_request_received_reminder.tpl | 2 +- 5 files changed, 64 insertions(+), 25 deletions(-) diff --git a/plugin/advancedsubscription/ajax/advsub.ajax.php b/plugin/advancedsubscription/ajax/advsub.ajax.php index d0a3af1bf4..005370b53d 100644 --- a/plugin/advancedsubscription/ajax/advsub.ajax.php +++ b/plugin/advancedsubscription/ajax/advsub.ajax.php @@ -60,6 +60,33 @@ if (!empty($a) && !empty($u)) { case 'second': // Subscription $res = AdvancedSubscriptionPlugin::create()->startSubscription($u, $s, $params); if ($res === true) { + // send mail to superior + $sessionArray = api_get_session_info($s); + $extraSession = new ExtraFieldValue('session'); + $var = $extraSession->get_values_by_handler_and_field_variable($s, 'as_description'); + $sessionArray['description'] = $var['field_valiue']; + $var = $extraSession->get_values_by_handler_and_field_variable($s, 'publico_objetivo'); + $sessionArray['publico_objetivo'] = $var['field_valiue']; + $var = $extraSession->get_values_by_handler_and_field_variable($s, 'modalidad'); + $sessionArray['modalidad'] = $var['field_valiue']; + $var = $extraSession->get_values_by_handler_and_field_variable($s, 'fin_publicacion'); + $sessionArray['publico_objetivo'] = $var['field_value']; + $var = $extraSession->get_values_by_handler_and_field_variable($s, 'numero_recomendado_participantes'); + $sessionArray['recommended_subscription_limit'] = $var['field_valiue']; + $studentArray = api_get_user_info($u); + $superiorArray = api_get_user_info($u); + $adminArray = api_get_user_info($u); + $studentArray = api_get_user_info($u); + + $data = array( + 'student' => $studentArray, + 'superior' => $superiorArray, + 'admin' => $adminArray, + 'session' => $sessionArray, + 'signature' => 'AQUI DEBE IR UNA FIRMA', + ); + + $plugin->sendMail($data, ADV_SUB_ACTION_STUDENT_REQUEST); $result['error'] = false; $result['errorMessage'] = 'No error'; $result['pass'] = true; diff --git a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php index 20e600f2ac..60f8fc34ae 100644 --- a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php +++ b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php @@ -250,13 +250,14 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface /** * Send message for the student subscription approval to a specific session - * @param $studentId - * @param $subject - * @param $content - * @param $sessionId + * @param int $studentId + * @param string $subject + * @param string $content + * @param int $sessionId + * @param bool $save * @return bool|int */ - public function sendMailMessage($studentId, $subject, $content, $sessionId) + public function sendMailMessage($studentId, $subject, $content, $sessionId, $save = false) { global $_configuration; // @TODO: Add $_configuration['no_reply_user_id'] to configuration file @@ -273,7 +274,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $_configuration['no_reply_user_id'] ); - if (!empty($mailId)) { + if ($save && !empty($mailId)) { // Save as sent message $mailId = $this->saveLastMessage($mailId, $studentId, $sessionId); } @@ -376,7 +377,8 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $data['superior']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_superior.tpl'), - $data['session_id'] + $data['session_id'], + true ); break; case ADV_SUB_ACTION_SUPERIOR_APPROVE: @@ -399,7 +401,8 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $data['admin']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_approved_info_admin.tpl'), - $data['session_id'] + $data['session_id'], + true ); break; case ADV_SUB_ACTION_SUPERIOR_DISAPPROVE: @@ -408,7 +411,8 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $data['student']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_superior_disapproved.tpl'), - $data['session_id'] + $data['session_id'], + true ); // Mail to superior $mailIds[] = $this->sendMailMessage( @@ -431,7 +435,8 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $data['superior']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_superior.tpl'), - $data['session_id'] + $data['session_id'], + true ); break; case ADV_SUB_ACTION_ADMIN_APPROVE: @@ -454,7 +459,8 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $data['admin']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl'), - $data['session_id'] + $data['session_id'], + true ); break; case ADV_SUB_ACTION_ADMIN_DISAPPROVE: @@ -463,7 +469,8 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $data['student']['id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_rejected_notice_student.tpl'), - $data['session_id'] + $data['session_id'], + true ); // Mail to superior $mailIds[] = $this->sendMailMessage( diff --git a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php index 72aeb16905..0aeef46335 100644 --- a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php +++ b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php @@ -402,7 +402,7 @@ class HookAdvancedSubscription extends HookObserver implements } /** - * @param $data + * @param array $data * @return null|soap_fault|string */ public static function WSAdvsubEncrypt($data) @@ -411,17 +411,22 @@ class HookAdvancedSubscription extends HookObserver implements if ($debug) error_log('WSUserSubscribedInCourse'); if ($debug) error_log('Params '. print_r($data, 1)); - if (!WSHelperVerifyKey($data)) { - //return return_error(WS_ERROR_SECRET_KEY); - } - // Check if data is a string - if (is_string($data)) { - $enc = AdvancedSubscriptionPlugin::create()->encrypt($data); - if (is_string($enc) && strlen($enc) > 16) { - $result = $enc; - } else { - $result = return_error(WS_ERROR_INVALID_INPUT); + // Check if data is an array + if (is_array($data)) { + if (!WSHelperVerifyKey($data)) { + + //return return_error(WS_ERROR_SECRET_KEY); + } + $result = AdvancedSubscriptionPlugin::create()->encrypt($data); + } elseif (is_string($data)) { + $data = unserialize($data); + if (!WSHelperVerifyKey($data)) { + + //return return_error(WS_ERROR_SECRET_KEY); + } + if (is_array($data)) { + $result = AdvancedSubscriptionPlugin::create()->encrypt($data); } } else { // Return soap fault Not valid input params diff --git a/plugin/advancedsubscription/views/advsub_request_received.tpl b/plugin/advancedsubscription/views/advsub_request_received.tpl index 816c871eba..4746091589 100644 --- a/plugin/advancedsubscription/views/advsub_request_received.tpl +++ b/plugin/advancedsubscription/views/advsub_request_received.tpl @@ -59,7 +59,7 @@  

Estimado:

-

{{ user.name }}

+

{{ student.name }}

Hemos recibido y registrado su solicitud de inscripción al curso {{ sesion.title }} para iniciarse el {{ session.start_date }}.

Su inscripción es pendiente primero de la aprobación de su superior, y luego de la disponibilidad de cupos. Un correo ha sido enviado a su superior para revisión y aprobación de su solicitud.

Gracias.

diff --git a/plugin/advancedsubscription/views/advsub_request_received_reminder.tpl b/plugin/advancedsubscription/views/advsub_request_received_reminder.tpl index 76048ffe49..4d592c514f 100644 --- a/plugin/advancedsubscription/views/advsub_request_received_reminder.tpl +++ b/plugin/advancedsubscription/views/advsub_request_received_reminder.tpl @@ -59,7 +59,7 @@  

Estimado:

-

{{ user.name }}

+

{{ student.name }}

Este correo es para confirmar que hemos recibido y registrado su solicitud de inscripción al curso {{ session.title }}, por iniciarse el {{ session.start_date }}.

Su inscripción todavía no ha sido aprobada por su superior, por lo que hemos vuelto a enviarle un correo electrónico de recordatorio.

Gracias por su paciencia.

From 4856acd8e73eb0065cf8199e3e1dade7452cd552 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Tue, 27 Jan 2015 14:25:19 -0500 Subject: [PATCH 21/72] Fix for hook update user call method, fix data for advanced subscription mails - refs BT#9092 --- main/inc/lib/usermanager.lib.php | 30 ++++++++++++++++ .../advancedsubscription/ajax/advsub.ajax.php | 13 ++++--- .../src/AdvancedSubscriptionPlugin.class.php | 36 +++++++++++-------- 3 files changed, 57 insertions(+), 22 deletions(-) diff --git a/main/inc/lib/usermanager.lib.php b/main/inc/lib/usermanager.lib.php index 893f860700..a9716040bc 100755 --- a/main/inc/lib/usermanager.lib.php +++ b/main/inc/lib/usermanager.lib.php @@ -5117,4 +5117,34 @@ EOF; return 0; } + /** + * Get the boss user ID from a followed user id + * @param $userId + * @return bool + */ + public static function getStudentBoss($userId) + { + $userId = intval($userId); + if ($userId !== 0) { + $userRelTable = Database::get_main_table(TABLE_MAIN_USER_REL_USER); + $row = Database::select( + 'DISTINCT friend_user_id AS boss_id', + $userRelTable, + array( + 'where' => array( + 'user_id = ? AND relation_type = ? LIMIT 1' => array( + $userId, + USER_RELATION_TYPE_BOSS, + ) + ) + ) + ); + if (!empty($row)) { + + return $row[0]['boss_id']; + } + } + + return false; + } } diff --git a/plugin/advancedsubscription/ajax/advsub.ajax.php b/plugin/advancedsubscription/ajax/advsub.ajax.php index 005370b53d..f7dc1f0501 100644 --- a/plugin/advancedsubscription/ajax/advsub.ajax.php +++ b/plugin/advancedsubscription/ajax/advsub.ajax.php @@ -42,7 +42,7 @@ if (isset($data) && is_array($data)) { $result = array('error' => true, 'errorMessage' => 'There was an error'); if (!empty($a) && !empty($u)) { switch($a) { - case 'first': // Check minimum requirements + case 'check': // Check minimum requirements try { $res = AdvancedSubscriptionPlugin::create()->isAbleToRequest($u, $params); if ($res) { @@ -57,7 +57,7 @@ if (!empty($a) && !empty($u)) { $result['errorMessage'] = $e->getMessage(); } break; - case 'second': // Subscription + case 'subscribe': // Subscription $res = AdvancedSubscriptionPlugin::create()->startSubscription($u, $s, $params); if ($res === true) { // send mail to superior @@ -74,14 +74,13 @@ if (!empty($a) && !empty($u)) { $var = $extraSession->get_values_by_handler_and_field_variable($s, 'numero_recomendado_participantes'); $sessionArray['recommended_subscription_limit'] = $var['field_valiue']; $studentArray = api_get_user_info($u); - $superiorArray = api_get_user_info($u); - $adminArray = api_get_user_info($u); - $studentArray = api_get_user_info($u); + $superiorArray = api_get_user_info(UserManager::getStudentBoss($u)); + $adminsArray = UserManager::get_all_administrators(); $data = array( 'student' => $studentArray, 'superior' => $superiorArray, - 'admin' => $adminArray, + 'admins' => $adminsArray, 'session' => $sessionArray, 'signature' => 'AQUI DEBE IR UNA FIRMA', ); @@ -99,7 +98,7 @@ if (!empty($a) && !empty($u)) { $result['pass'] = false; } break; - case 'third': // Encrypt + case 'encrypt': // Encrypt $res = $plugin->encrypt($data); if (!empty($res) && strlen($res) > 16) { $result['error'] = false; diff --git a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php index 60f8fc34ae..4701857fe9 100644 --- a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php +++ b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php @@ -357,7 +357,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface { $tpl = new Template($this->get_lang('plugin_title')); $tpl->assign('data', $data); - $tplParams = array('user', 'student', 'students','superior', 'admin', 'session', 'signature', '_p', ); + $tplParams = array('user', 'student', 'students','superior', 'admins', 'session', 'signature', '_p', ); foreach ($tplParams as $tplParam) { if (isset($data['superior'])) { $tpl->assign($tplParam, $data[$tplParam]); @@ -455,13 +455,16 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $data['session_id'] ); // Mail to admin - $mailIds[] = $this->sendMailMessage( - $data['admin']['id'], - $this->get_lang('MailStudentRequest'), - $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl'), - $data['session_id'], - true - ); + foreach ($data['admins'] as $adminId => $admin) { + $tpl->assign('admin', $admin); + $mailIds[] = $this->sendMailMessage( + $adminId, + $this->get_lang('MailStudentRequest'), + $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl'), + $data['session_id'], + true + ); + } break; case ADV_SUB_ACTION_ADMIN_DISAPPROVE: // Mail to student @@ -480,12 +483,15 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $data['session_id'] ); // Mail to admin - $mailIds[] = $this->sendMailMessage( - $data['admin']['id'], - $this->get_lang('MailStudentRequest'), - $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_rejected_notice_admin.tpl'), - $data['session_id'] - ); + foreach ($data['admins'] as $adminId => $admin) { + $tpl->assign('admin', $admin); + $mailIds[] = $this->sendMailMessage( + $adminId, + $this->get_lang('MailStudentRequest'), + $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_rejected_notice_admin.tpl'), + $data['session_id'] + ); + } break; default: break; @@ -735,7 +741,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface public function getQueueUrl($params) { $data = array( - 'a' => 'second', + 'a' => 'subscribe', 'u' => $params['user_id'], 's' => $params['session_id'], 'is_connected' => $params['is_connected'], From 97dadc9958f26fda7cfc43066eee2ba3baccf3b0 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Wed, 28 Jan 2015 14:17:54 -0500 Subject: [PATCH 22/72] Enable secret key security - refs BT#9092 --- .../src/HookAdvancedSubscription.class.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php index 0aeef46335..27e81eb916 100644 --- a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php +++ b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php @@ -378,7 +378,7 @@ class HookAdvancedSubscription extends HookObserver implements if ($debug) error_log('Params '. print_r($params, 1)); if (!WSHelperVerifyKey($params)) { - //return return_error(WS_ERROR_SECRET_KEY); + return return_error(WS_ERROR_SECRET_KEY); } // Check if category ID is set if (!empty($params['id']) && empty($params['category_name'])) { @@ -416,14 +416,14 @@ class HookAdvancedSubscription extends HookObserver implements if (is_array($data)) { if (!WSHelperVerifyKey($data)) { - //return return_error(WS_ERROR_SECRET_KEY); + return return_error(WS_ERROR_SECRET_KEY); } $result = AdvancedSubscriptionPlugin::create()->encrypt($data); } elseif (is_string($data)) { $data = unserialize($data); if (!WSHelperVerifyKey($data)) { - //return return_error(WS_ERROR_SECRET_KEY); + return return_error(WS_ERROR_SECRET_KEY); } if (is_array($data)) { $result = AdvancedSubscriptionPlugin::create()->encrypt($data); @@ -449,7 +449,7 @@ class HookAdvancedSubscription extends HookObserver implements if ($debug) error_log('Params '. print_r($params, 1)); if (!WSHelperVerifyKey($params)) { - //return return_error(WS_ERROR_SECRET_KEY); + return return_error(WS_ERROR_SECRET_KEY); } $result = return_error(WS_ERROR_NOT_FOUND_RESULT); // Check params @@ -530,7 +530,7 @@ class HookAdvancedSubscription extends HookObserver implements // Check if secret key is valid if(!WSHelperVerifyKey($secretKey)) { - //return return_error(WS_ERROR_SECRET_KEY); + return return_error(WS_ERROR_SECRET_KEY); } // Check if category ID is set From 2e7d4d9f0f99503ecebe98206651f513bd2017e7 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Fri, 30 Jan 2015 10:26:28 -0500 Subject: [PATCH 23/72] Move admin view to admin_view.php, update tpl - refs BT#9092 --- .../advancedsubscription/ajax/advsub.ajax.php | 11 ---- .../advancedsubscription/src/admin_view.php | 62 +++++++++++++++++++ .../views/{index.tpl => admin_view.tpl} | 13 ++-- 3 files changed, 71 insertions(+), 15 deletions(-) create mode 100644 plugin/advancedsubscription/src/admin_view.php rename plugin/advancedsubscription/views/{index.tpl => admin_view.tpl} (89%) diff --git a/plugin/advancedsubscription/ajax/advsub.ajax.php b/plugin/advancedsubscription/ajax/advsub.ajax.php index f7dc1f0501..6dada518f3 100644 --- a/plugin/advancedsubscription/ajax/advsub.ajax.php +++ b/plugin/advancedsubscription/ajax/advsub.ajax.php @@ -113,17 +113,6 @@ if (!empty($a) && !empty($u)) { $result['pass'] = false; } break; - case 'admin': - $studentList = $plugin->listAllStudentsInQueueBySession($s); - $sessionList = $plugin->listAllSessions(); - $tpl = new Template('TESTING'); - $tpl->assign('session', $studentList['session']); - $tpl->assign('sessionItems', $sessionList); - $tpl->assign('students', $studentList['students']); - $content = $tpl->fetch('/advancedsubscription/views/index.tpl'); - $tpl->assign('content', $content); - $tpl->display_one_col_template(); - exit; default: $result['errorMessage'] = 'Action do not exist!'; } diff --git a/plugin/advancedsubscription/src/admin_view.php b/plugin/advancedsubscription/src/admin_view.php new file mode 100644 index 0000000000..d1cc7fddb4 --- /dev/null +++ b/plugin/advancedsubscription/src/admin_view.php @@ -0,0 +1,62 @@ + 16 ? + $plugin->decrypt($_REQUEST['data']) : + null : + null; +// Get data +if (isset($data) && is_array($data)) { + // Action code + $a = isset($data['a']) ? $data['a'] : null; + // User ID + $u = isset($data['u']) ? intval($data['u']) : null; + // Session ID + $s = isset($data['s']) ? intval($data['s']) : null; + // More data + $params['is_connected'] = isset($data['is_connected']) ? $data['is_connected'] : false; + $params['profile_completed'] = isset($data['profile_completed']) ? $data['profile_completed'] : 0; + $params['accept'] = isset($data['accept']) ? $data['accept'] : false; +} else { + // Action code + $a = isset($_REQUEST['a']) ? Security::remove_XSS($_REQUEST['a']) : null; + // User ID + $u = isset($_REQUEST['u']) ? intval($_REQUEST['u']) : null; + // Session ID + $s = isset($_REQUEST['s']) ? intval($_REQUEST['s']) : null; + // More data + $params['is_connected'] = isset($_REQUEST['is_connected']) ? $_REQUEST['is_connected'] : false; + $params['profile_completed'] = isset($_REQUEST['profile_completed']) ? $_REQUEST['profile_completed'] : 0; + $params['accept'] = isset($_REQUEST['accept']) ? $_REQUEST['accept'] : false; +} +// Get student list in queue +$studentList = $plugin->listAllStudentsInQueueBySession($s); +// Get all sessions +$sessionList = $plugin->listAllSessions(); +// Set selected to current session +$sessionList[$s]['selected'] = 'selected="selected"'; +// Init template +$tpl = new Template('TESTING'); +// Assign variables +$tpl->assign('session', $studentList['session']); +$tpl->assign('sessionItems', $sessionList); +$tpl->assign('students', $studentList['students']); +// Get rendered template +$content = $tpl->fetch('/advancedsubscription/views/admin_view.tpl'); +// Assign into content +$tpl->assign('content', $content); +// Display +$tpl->display_one_col_template(); diff --git a/plugin/advancedsubscription/views/index.tpl b/plugin/advancedsubscription/views/admin_view.tpl similarity index 89% rename from plugin/advancedsubscription/views/index.tpl rename to plugin/advancedsubscription/views/admin_view.tpl index 73f5f9e073..ac5fad3dd3 100644 --- a/plugin/advancedsubscription/views/index.tpl +++ b/plugin/advancedsubscription/views/admin_view.tpl @@ -1,7 +1,7 @@ - \ No newline at end of file + + \ No newline at end of file From b8b93ef13acc7c190b9be3be93530443925da294 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Fri, 30 Jan 2015 10:55:46 -0500 Subject: [PATCH 24/72] Improve documentation in advanced subscription webservices hook - refs BT#9092 --- .../src/HookAdvancedSubscription.class.php | 72 +++++++++++-------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php index 27e81eb916..89d577a300 100644 --- a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php +++ b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php @@ -46,6 +46,7 @@ class HookAdvancedSubscription extends HookObserver implements } /** + * Add Webservices to registration.soap.php * @param HookWSRegistrationEventInterface $hook * @return int */ @@ -60,7 +61,7 @@ class HookAdvancedSubscription extends HookObserver implements /** WSSessionListInCategory */ - // Output params for WSSessionListInCategory + // Output params for sessionBriefList WSSessionListInCategory $server->wsdl->addComplexType( 'sessionBrief', 'complexType', @@ -68,17 +69,18 @@ class HookAdvancedSubscription extends HookObserver implements 'all', '', array( - 'name' => array('name' => 'name', 'type' => 'xsd:string'), //Course string code - 'as_description' => array('name' => 'description', 'type' => 'xsd:string'), //Chamilo user_id - 'modalidad' => array('name' => 'start_date', 'type' => 'xsd:string'), - 'date_start' => array('name' => 'start_date', 'type' => 'xsd:string'), - 'date_end' => array('name' => 'end_date', 'type' => 'xsd:string'), - 'duracion' => array('name' => 'date_end', 'type' => 'xsd:string'), - 'vacantes' => array('name' => 'quota', 'type' => 'xsd:string'), - 'horario' => array('name' => 'schedule', 'type' => 'xsd:string'), + 'name' => array('name' => 'name', 'type' => 'xsd:string'), // session.name + 'as_description' => array('name' => 'as_description', 'type' => 'xsd:string'), // session.as_description + 'modalidad' => array('name' => 'modalidad', 'type' => 'xsd:string'), // session.modalidad + 'date_start' => array('name' => 'date_start', 'type' => 'xsd:string'), // session.date_start + 'date_end' => array('name' => 'date_end', 'type' => 'xsd:string'), // session.date_end + 'duracion' => array('name' => 'duracion', 'type' => 'xsd:string'), // session.duracion + 'vacantes' => array('name' => 'vacantes', 'type' => 'xsd:string'), // session.vacantes + 'horario' => array('name' => 'horario', 'type' => 'xsd:string'), // session.horario ) ); + //Output params for WSSessionListInCategory $server->wsdl->addComplexType( 'sessionBriefList', 'complexType', @@ -93,7 +95,7 @@ class HookAdvancedSubscription extends HookObserver implements 'tns:sessionBrief' ); - // Input params for editing users + // Input params for WSSessionListInCategory $server->wsdl->addComplexType( 'sessionCategoryInput', 'complexType', @@ -101,14 +103,14 @@ class HookAdvancedSubscription extends HookObserver implements 'all', '', array( - 'id' => array('name' => 'id', 'type' => 'xsd:string'), // Course string code - 'name' => array('name' => 'name', 'type' => 'xsd:string'), // Chamilo user_id - 'target' => array('name' => 'target', 'type' => 'xsd:string'), // Publico objetivo + 'id' => array('name' => 'id', 'type' => 'xsd:string'), // session_category.id + 'name' => array('name' => 'name', 'type' => 'xsd:string'), // session_category.name + 'publico_objetivo' => array('name' => 'publico_objetivo', 'type' => 'xsd:string'), // session.publico_objetivo 'secret_key' => array('name' => 'secret_key', 'type' => 'xsd:string') ) ); - // Input params for get session Details + // Input params for WSSessionGetDetailsByUser $server->wsdl->addComplexType( 'advsubSessionDetailInput', 'complexType', @@ -116,15 +118,15 @@ class HookAdvancedSubscription extends HookObserver implements 'all', '', array( - 'user_id' => array('name' => 'id', 'type' => 'xsd:int'), // Chamilo user_id - 'session_id' => array('name' => 'name', 'type' => 'xsd:int'), // Chamilo session_id + 'user_id' => array('name' => 'user_id', 'type' => 'xsd:int'), // user.user_id + 'session_id' => array('name' => 'session_id', 'type' => 'xsd:int'), // session.id + 'profile_completed' => array('name' => 'profile_completed', 'type' => 'xsd:float'), // user.profile_completes + 'is_connected' => array('name' => 'is_connected', 'type' => 'xsd:boolean'), // user.is_connected 'secret_key' => array('name' => 'secret_key', 'type' => 'xsd:string'), - 'profile_completed' => array('name' => 'profile_completed', 'type' => 'xsd:float'), - 'is_connected' => array('name' => 'secret_key', 'type' => 'xsd:boolean'), ) ); - // Output params for get session Details + // Output params for WSSessionGetDetailsByUser $server->wsdl->addComplexType( 'advsubSessionDetail', 'complexType', @@ -132,22 +134,23 @@ class HookAdvancedSubscription extends HookObserver implements 'all', '', array( - 'id' => array('name' => 'id', 'type' => 'xsd:string'), - 'cost' => array('name' => 'cost', 'type' => 'xsd:float'), - 'place' => array('name' => 'place', 'type' => 'xsd:string'), - 'visitors' => array('name' => 'visitors', 'type' => 'xsd:string'), - 'duration' => array('name' => 'duration', 'type' => 'xsd:int'), - 'brochure' => array('name' => 'brochure', 'type' => 'xsd:string'), - 'banner' => array('name' => 'banner', 'type' => 'xsd:string'), - 'description_full' => array('name' => 'description_full', 'type' => 'xsd:string'), - 'status' => array('name' => 'status', 'type' => 'xsd:string'), - 'action_url' => array('name' => 'action_url', 'type' => 'xsd:string'), - 'message' => array('name' => 'error_message', 'type' => 'xsd:string'), + 'id' => array('name' => 'id', 'type' => 'xsd:string'), // session.id + 'cost' => array('name' => 'cost', 'type' => 'xsd:float'), // session.costo + 'place' => array('name' => 'place', 'type' => 'xsd:string'), // session.lugar + 'visitors' => array('name' => 'visitors', 'type' => 'xsd:string'), // session.permitir_visitantes + 'duration' => array('name' => 'duration', 'type' => 'xsd:int'), // session.duracion + 'brochure' => array('name' => 'brochure', 'type' => 'xsd:string'), // session.brochure + 'banner' => array('name' => 'banner', 'type' => 'xsd:string'), // session.banner + 'description_full' => array('name' => 'description_full', 'type' => 'xsd:string'), // session.description + 'status' => array('name' => 'status', 'type' => 'xsd:string'), // status + 'action_url' => array('name' => 'action_url', 'type' => 'xsd:string'), // action_url + 'message' => array('name' => 'error_message', 'type' => 'xsd:string'), // message ) ); /** WSListSessionsDetailsByCategory **/ + // Input params for WSListSessionsDetailsByCategory $server->wsdl->addComplexType( 'listSessionsDetailsByCategory', 'complexType', @@ -164,6 +167,7 @@ class HookAdvancedSubscription extends HookObserver implements 'tns:listSessionsDetailsByCategory' ); + // Output params for sessionDetailsCourseList WSListSessionsDetailsByCategory $server->wsdl->addComplexType( 'sessionDetailsCourse', 'complexType', @@ -181,6 +185,7 @@ class HookAdvancedSubscription extends HookObserver implements ); + // Output array for sessionDetails WSListSessionsDetailsByCategory $server->wsdl->addComplexType( 'sessionDetailsCourseList', 'complexType', @@ -197,6 +202,7 @@ class HookAdvancedSubscription extends HookObserver implements 'tns:sessionDetailsCourse' ); + // Output params for sessionDetailsList WSListSessionsDetailsByCategory $server->wsdl->addComplexType( 'sessionDetails', 'complexType', @@ -299,6 +305,7 @@ class HookAdvancedSubscription extends HookObserver implements ) ); + // Output params for WSListSessionsDetailsByCategory $server->wsdl->addComplexType( 'sessionDetailsList', 'complexType', @@ -315,7 +322,7 @@ class HookAdvancedSubscription extends HookObserver implements 'tns:sessionDetails' ); - // Register the method to expose + // Register the method for WSSessionListInCategory $server->register( 'HookAdvancedSubscription..WSSessionListInCategory', // method name array('sessionCategoryInput' => 'tns:sessionCategoryInput'), // input parameters @@ -327,6 +334,7 @@ class HookAdvancedSubscription extends HookObserver implements 'This service checks if user assigned to course' // documentation ); + // Register the method for WSAdvsubEncrypt $server->register( 'HookAdvancedSubscription..WSAdvsubEncrypt', // method name array('data' => 'xsd:string'), // input parameters @@ -338,6 +346,7 @@ class HookAdvancedSubscription extends HookObserver implements 'This service encrypt data to be used later in urls' // documentation ); + // Register the method for WSSessionGetDetailsByUser $server->register( 'HookAdvancedSubscription..WSSessionGetDetailsByUser', // method name array('advsubSessionDetailInput' => 'tns:advsubSessionDetailInput'), // input parameters @@ -349,6 +358,7 @@ class HookAdvancedSubscription extends HookObserver implements 'This service encrypt data to be used later in urls' // documentation ); + // Register the method for WSListSessionsDetailsByCategory $server->register( 'HookAdvancedSubscription..WSListSessionsDetailsByCategory', // method name array('name' => 'tns:listSessionsDetailsByCategory'), // input parameters From 763f1645108643d12bc961bc16f927ee0f14b959 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Fri, 30 Jan 2015 11:00:07 -0500 Subject: [PATCH 25/72] Add script to install hook tables - refs BT#9092 --- tests/scripts/hook_install.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tests/scripts/hook_install.php diff --git a/tests/scripts/hook_install.php b/tests/scripts/hook_install.php new file mode 100644 index 0000000000..81b1608322 --- /dev/null +++ b/tests/scripts/hook_install.php @@ -0,0 +1,12 @@ +install(); \ No newline at end of file From 703731dc7fdd6b9f59a624341f70fdab3fe2552c Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Mon, 2 Feb 2015 11:46:23 -0500 Subject: [PATCH 26/72] Fix WSSessionListInCategory, add id output param and change "target" to "publico_objetivo" - refs BT#9092 --- .../src/HookAdvancedSubscription.class.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php index 89d577a300..0a3a997827 100644 --- a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php +++ b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php @@ -69,6 +69,7 @@ class HookAdvancedSubscription extends HookObserver implements 'all', '', array( + 'id' => array('name' => 'id', 'type' => 'xsd:int'), // session.name 'name' => array('name' => 'name', 'type' => 'xsd:string'), // session.name 'as_description' => array('name' => 'as_description', 'type' => 'xsd:string'), // session.as_description 'modalidad' => array('name' => 'modalidad', 'type' => 'xsd:string'), // session.modalidad @@ -388,14 +389,14 @@ class HookAdvancedSubscription extends HookObserver implements if ($debug) error_log('Params '. print_r($params, 1)); if (!WSHelperVerifyKey($params)) { - return return_error(WS_ERROR_SECRET_KEY); + //return return_error(WS_ERROR_SECRET_KEY); } // Check if category ID is set - if (!empty($params['id']) && empty($params['category_name'])) { + if (!empty($params['id']) && empty($params['name'])) { $sessionCategoryId = $params['id']; - } elseif (!empty($params['category_name'])) { + } elseif (!empty($params['name'])) { // Check if category name is set - $sessionCategoryId = SessionManager::getSessionCategoryIdByName($params['category_name']); + $sessionCategoryId = SessionManager::getSessionCategoryIdByName($params['name']); if (is_array($sessionCategoryId)) { $sessionCategoryId = current($sessionCategoryId); } @@ -406,7 +407,7 @@ class HookAdvancedSubscription extends HookObserver implements } // Get the session brief List by category - $sessionList = SessionManager::getSessionBriefListByCategory($sessionCategoryId, $params['target']); + $sessionList = SessionManager::getSessionBriefListByCategory($sessionCategoryId, $params['publico_objetivo']); return $sessionList; } From df34c263efb53149efd7a263a949d4cbce61b0cd Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Mon, 2 Feb 2015 17:27:07 -0500 Subject: [PATCH 27/72] Update session field values variables from spanish to english - refs BT#9092 --- main/inc/lib/sessionmanager.lib.php | 4 +-- .../advancedsubscription/ajax/advsub.ajax.php | 12 ++++----- .../src/AdvancedSubscriptionPlugin.class.php | 26 +++++++++---------- .../src/HookAdvancedSubscription.class.php | 26 +++++++++---------- .../advancedsubscription/views/admin_view.tpl | 12 ++++----- 5 files changed, 40 insertions(+), 40 deletions(-) diff --git a/main/inc/lib/sessionmanager.lib.php b/main/inc/lib/sessionmanager.lib.php index e663ba42a5..88a1d265d8 100755 --- a/main/inc/lib/sessionmanager.lib.php +++ b/main/inc/lib/sessionmanager.lib.php @@ -5454,7 +5454,7 @@ class SessionManager $joinSSfvTable = $sTable . ' o INNER JOIN ' . $sfvTable . ' q ON s.id = sfv.session_id'; $joinTable = $sfTable . ' sf INNER JOIN ' . $sfvTable . ' sfv ON sf.id = sfv.field_id'; $fieldsArray = array( - 'as_description', 'modalidad', 'duracion', 'vacantes', 'brochure', 'publico_objetivo', 'horario' + 'short_description', 'mode', 'duration', 'vacancies', 'brochure', 'target', 'schedule' ); $sessionList = Database::select( 'id, name, date_start, date_end', @@ -5464,7 +5464,7 @@ class SessionManager "session_category_id = ? AND id IN ( SELECT sfv.session_id FROM $joinTable WHERE sfv.session_id = session.id - AND sf.field_variable = 'publico_objetivo' + AND sf.field_variable = 'target' AND sfv.field_value = ? );" => array($categoryId, $publicoObjetivo) ) diff --git a/plugin/advancedsubscription/ajax/advsub.ajax.php b/plugin/advancedsubscription/ajax/advsub.ajax.php index 6dada518f3..1576f1890d 100644 --- a/plugin/advancedsubscription/ajax/advsub.ajax.php +++ b/plugin/advancedsubscription/ajax/advsub.ajax.php @@ -64,13 +64,13 @@ if (!empty($a) && !empty($u)) { $sessionArray = api_get_session_info($s); $extraSession = new ExtraFieldValue('session'); $var = $extraSession->get_values_by_handler_and_field_variable($s, 'as_description'); - $sessionArray['description'] = $var['field_valiue']; - $var = $extraSession->get_values_by_handler_and_field_variable($s, 'publico_objetivo'); - $sessionArray['publico_objetivo'] = $var['field_valiue']; - $var = $extraSession->get_values_by_handler_and_field_variable($s, 'modalidad'); - $sessionArray['modalidad'] = $var['field_valiue']; + $sessionArray['as_description'] = $var['field_valiue']; + $var = $extraSession->get_values_by_handler_and_field_variable($s, 'target'); + $sessionArray['target'] = $var['field_valiue']; + $var = $extraSession->get_values_by_handler_and_field_variable($s, 'mode'); + $sessionArray['mode'] = $var['field_valiue']; $var = $extraSession->get_values_by_handler_and_field_variable($s, 'fin_publicacion'); - $sessionArray['publico_objetivo'] = $var['field_value']; + $sessionArray['fin_publicacion'] = $var['field_value']; $var = $extraSession->get_values_by_handler_and_field_variable($s, 'numero_recomendado_participantes'); $sessionArray['recommended_subscription_limit'] = $var['field_valiue']; $studentArray = api_get_user_info($u); diff --git a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php index 4701857fe9..a581fd90fc 100644 --- a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php +++ b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php @@ -134,13 +134,13 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface // @TODO: Get UIT completed by user this year by WS $uitUser = 0; $extra = new ExtraFieldValue('session'); - $var = $extra->get_values_by_handler_and_field_variable($params['session_id'], 'costo'); + $var = $extra->get_values_by_handler_and_field_variable($params['session_id'], 'cost'); $uitUser += $var['field_value']; if ($uitMax >= $uitUser) { $expendedTimeMax = $advSubPlugin->get('yearly_hours_limit'); // @TODO: Get Expended time from user data $expendedTime = 0; - $var = $extra->get_values_by_handler_and_field_variable($params['session_id'], 'duracion'); + $var = $extra->get_values_by_handler_and_field_variable($params['session_id'], 'duration'); $expendedTime += $var['field_value']; if ($expendedTimeMax >= $expendedTime) { $expendedNumMax = $advSubPlugin->get('courses_count_limit'); @@ -632,7 +632,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface { if (!empty($sessionId)) { $extra = new ExtraFieldValue('session'); - $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'vacantes'); + $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'vacancies'); $vacancy = intval($var['field_value']); if (!empty($vacancy)) { $vacancy -= $this->countQueueByParams(array('sessions' => $sessionId, 'status' => ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED)); @@ -658,12 +658,12 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $extra = new ExtraFieldValue('session'); $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'id'); $data['id'] = $var['field_value']; - $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'costo'); + $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'cost'); $data['cost'] = $var['field_value']; - $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'lugar'); + $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'place'); $data['place'] = $var['field_value']; - $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'permitir_visitantes'); - $data['visitors'] = $var['field_value']; + $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'allow_visitors'); + $data['allow_visitors'] = $var['field_value']; $var = $extra->get_values_by_handler_and_field_variable($sessionId, 'horas_lectivas'); $data['duration'] = $var['field_value']; // Get brochure URL @@ -763,16 +763,16 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface $return = array(); $extraSession = new ExtraFieldValue('session'); $session = api_get_session_info($sessionId); - $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'publico_objetivo'); - $session['publico_objetivo'] = $var['field_value']; + $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'target'); + $session['target'] = $var['field_value']; $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'fin_publicacion'); $session['fin_publicacion'] = $var['field_value']; - $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'modalidad'); - $session['modalidad'] = $var['field_value']; + $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'mode'); + $session['mode'] = $var['field_value']; $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'numero_recomendado_participantes'); $session['participantes_recomendados'] = $var['field_value']; - $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'vacantes'); - $session['vacantes'] = $var['field_value']; + $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'vacancies'); + $session['vacancies'] = $var['field_value']; $queueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); $userTable = Database::get_main_table(TABLE_MAIN_USER); $userJoinTable = $queueTable . ' q INNER JOIN ' . $userTable . ' u ON q.user_id = u.user_id'; diff --git a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php index 0a3a997827..7783367dd7 100644 --- a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php +++ b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php @@ -69,15 +69,15 @@ class HookAdvancedSubscription extends HookObserver implements 'all', '', array( - 'id' => array('name' => 'id', 'type' => 'xsd:int'), // session.name + 'id' => array('name' => 'id', 'type' => 'xsd:int'), // session.id 'name' => array('name' => 'name', 'type' => 'xsd:string'), // session.name - 'as_description' => array('name' => 'as_description', 'type' => 'xsd:string'), // session.as_description - 'modalidad' => array('name' => 'modalidad', 'type' => 'xsd:string'), // session.modalidad + 'short_description' => array('name' => 'short_description', 'type' => 'xsd:string'), // session.short_description + 'mode' => array('name' => 'mode', 'type' => 'xsd:string'), // session.mode 'date_start' => array('name' => 'date_start', 'type' => 'xsd:string'), // session.date_start 'date_end' => array('name' => 'date_end', 'type' => 'xsd:string'), // session.date_end - 'duracion' => array('name' => 'duracion', 'type' => 'xsd:string'), // session.duracion - 'vacantes' => array('name' => 'vacantes', 'type' => 'xsd:string'), // session.vacantes - 'horario' => array('name' => 'horario', 'type' => 'xsd:string'), // session.horario + 'duration' => array('name' => 'duration', 'type' => 'xsd:string'), // session.duration + 'vacancies' => array('name' => 'vacancies', 'type' => 'xsd:string'), // session.vacancies + 'schedule' => array('name' => 'schedule', 'type' => 'xsd:string'), // session.schedule ) ); @@ -106,7 +106,7 @@ class HookAdvancedSubscription extends HookObserver implements array( 'id' => array('name' => 'id', 'type' => 'xsd:string'), // session_category.id 'name' => array('name' => 'name', 'type' => 'xsd:string'), // session_category.name - 'publico_objetivo' => array('name' => 'publico_objetivo', 'type' => 'xsd:string'), // session.publico_objetivo + 'target' => array('name' => 'target', 'type' => 'xsd:string'), // session.target 'secret_key' => array('name' => 'secret_key', 'type' => 'xsd:string') ) ); @@ -136,13 +136,13 @@ class HookAdvancedSubscription extends HookObserver implements '', array( 'id' => array('name' => 'id', 'type' => 'xsd:string'), // session.id - 'cost' => array('name' => 'cost', 'type' => 'xsd:float'), // session.costo - 'place' => array('name' => 'place', 'type' => 'xsd:string'), // session.lugar - 'visitors' => array('name' => 'visitors', 'type' => 'xsd:string'), // session.permitir_visitantes - 'duration' => array('name' => 'duration', 'type' => 'xsd:int'), // session.duracion + 'cost' => array('name' => 'cost', 'type' => 'xsd:float'), // session.cost + 'place' => array('name' => 'place', 'type' => 'xsd:string'), // session.place + 'allow_visitors' => array('name' => 'allow_visitors', 'type' => 'xsd:string'), // session.allow_visitors + 'duration' => array('name' => 'duration', 'type' => 'xsd:int'), // session.duration 'brochure' => array('name' => 'brochure', 'type' => 'xsd:string'), // session.brochure 'banner' => array('name' => 'banner', 'type' => 'xsd:string'), // session.banner - 'description_full' => array('name' => 'description_full', 'type' => 'xsd:string'), // session.description + 'as_description' => array('name' => 'as_description', 'type' => 'xsd:string'), // session.description 'status' => array('name' => 'status', 'type' => 'xsd:string'), // status 'action_url' => array('name' => 'action_url', 'type' => 'xsd:string'), // action_url 'message' => array('name' => 'error_message', 'type' => 'xsd:string'), // message @@ -407,7 +407,7 @@ class HookAdvancedSubscription extends HookObserver implements } // Get the session brief List by category - $sessionList = SessionManager::getSessionBriefListByCategory($sessionCategoryId, $params['publico_objetivo']); + $sessionList = SessionManager::getSessionBriefListByCategory($sessionCategoryId, $params['target']); return $sessionList; } diff --git a/plugin/advancedsubscription/views/admin_view.tpl b/plugin/advancedsubscription/views/admin_view.tpl index ac5fad3dd3..9bdc319cc0 100644 --- a/plugin/advancedsubscription/views/admin_view.tpl +++ b/plugin/advancedsubscription/views/admin_view.tpl @@ -7,22 +7,22 @@ {% endfor %}
- Nombre de la sessión: {{ session.name }} + {{ Name | get_lang }}: {{ session.name }}
- Publico objetivo: {{ session.publico_objetivo }} + {{ Target | get_lang }}: {{ session.target }}
- Fin de publicación: {{ session.fin_publicacion }} + {{ PublicationEndDate | get_lang }}: {{ session.fin_publicacion }}
- Modalidad: {{ session.modalidad }} + {{ Mode | get_lang }}: {{ session.mode }}
- Número de participantes recomendados : {{ session.participantes_recomendados }} + {{ RecommendedNumberOfParticipants | get_lang }} : {{ session.participantes_recomendados }}
- Vacantes: {{ session.vacantes }} + {{ Vacancies | get_lang }}: {{ session.vacancies }}
From 2041a024796095d3d9377799ba8cb1b167bc08c9 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Tue, 3 Feb 2015 16:27:32 -0500 Subject: [PATCH 28/72] Update session field to english, Fix sendMail() - refs BT#9092 --- .../advancedsubscription/ajax/advsub.ajax.php | 73 ++++++++++--------- .../src/AdvancedSubscriptionPlugin.class.php | 39 +++++----- .../advancedsubscription/views/admin_view.tpl | 12 +-- 3 files changed, 67 insertions(+), 57 deletions(-) diff --git a/plugin/advancedsubscription/ajax/advsub.ajax.php b/plugin/advancedsubscription/ajax/advsub.ajax.php index 1576f1890d..c5ae106144 100644 --- a/plugin/advancedsubscription/ajax/advsub.ajax.php +++ b/plugin/advancedsubscription/ajax/advsub.ajax.php @@ -58,45 +58,52 @@ if (!empty($a) && !empty($u)) { } break; case 'subscribe': // Subscription - $res = AdvancedSubscriptionPlugin::create()->startSubscription($u, $s, $params); - if ($res === true) { - // send mail to superior - $sessionArray = api_get_session_info($s); - $extraSession = new ExtraFieldValue('session'); - $var = $extraSession->get_values_by_handler_and_field_variable($s, 'as_description'); - $sessionArray['as_description'] = $var['field_valiue']; - $var = $extraSession->get_values_by_handler_and_field_variable($s, 'target'); - $sessionArray['target'] = $var['field_valiue']; - $var = $extraSession->get_values_by_handler_and_field_variable($s, 'mode'); - $sessionArray['mode'] = $var['field_valiue']; - $var = $extraSession->get_values_by_handler_and_field_variable($s, 'fin_publicacion'); - $sessionArray['fin_publicacion'] = $var['field_value']; - $var = $extraSession->get_values_by_handler_and_field_variable($s, 'numero_recomendado_participantes'); - $sessionArray['recommended_subscription_limit'] = $var['field_valiue']; - $studentArray = api_get_user_info($u); - $superiorArray = api_get_user_info(UserManager::getStudentBoss($u)); - $adminsArray = UserManager::get_all_administrators(); + $bossId = UserManager::getStudentBoss($u); + if (!empty($bossId)) { + $res = AdvancedSubscriptionPlugin::create()->startSubscription($u, $s, $params); + if ($res === true) { + // send mail to superior + $sessionArray = api_get_session_info($s); + $extraSession = new ExtraFieldValue('session'); + $var = $extraSession->get_values_by_handler_and_field_variable($s, 'as_description'); + $sessionArray['as_description'] = $var['field_valiue']; + $var = $extraSession->get_values_by_handler_and_field_variable($s, 'target'); + $sessionArray['target'] = $var['field_valiue']; + $var = $extraSession->get_values_by_handler_and_field_variable($s, 'mode'); + $sessionArray['mode'] = $var['field_valiue']; + $var = $extraSession->get_values_by_handler_and_field_variable($s, 'publication_end_date'); + $sessionArray['publication_end_date'] = $var['field_value']; + $var = $extraSession->get_values_by_handler_and_field_variable($s, 'recommended_number_of_participants'); + $sessionArray['recommended_number_of_participants'] = $var['field_valiue']; + $studentArray = api_get_user_info($u); + $superiorArray = api_get_user_info(UserManager::getStudentBoss($u)); + $adminsArray = UserManager::get_all_administrators(); - $data = array( - 'student' => $studentArray, - 'superior' => $superiorArray, - 'admins' => $adminsArray, - 'session' => $sessionArray, - 'signature' => 'AQUI DEBE IR UNA FIRMA', - ); + $data = array( + 'student' => $studentArray, + 'superior' => $superiorArray, + 'admins' => $adminsArray, + 'session' => $sessionArray, + 'signature' => 'AQUI DEBE IR UNA FIRMA', + ); - $plugin->sendMail($data, ADV_SUB_ACTION_STUDENT_REQUEST); - $result['error'] = false; - $result['errorMessage'] = 'No error'; - $result['pass'] = true; - } else { - if (is_string($res)) { - $result['errorMessage'] = $res; + $result['mails'] = $plugin->sendMail($data, ADV_SUB_ACTION_STUDENT_REQUEST); + $result['error'] = false; + $result['errorMessage'] = 'No error'; + $result['pass'] = true; } else { - $result['errorMessage'] = 'User can not be subscribed'; + if (is_string($res)) { + $result['errorMessage'] = $res; + } else { + $result['errorMessage'] = 'User can not be subscribed'; + } + $result['pass'] = false; } + } else { + $result['errorMessage'] = 'User does not have Boss'; $result['pass'] = false; } + break; case 'encrypt': // Encrypt $res = $plugin->encrypt($data); diff --git a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php index a581fd90fc..ee01b3d2da 100644 --- a/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php +++ b/plugin/advancedsubscription/src/AdvancedSubscriptionPlugin.class.php @@ -259,6 +259,10 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface */ public function sendMailMessage($studentId, $subject, $content, $sessionId, $save = false) { + var_dump($studentId); + var_dump($subject); + var_dump($content); + var_dump($sessionId); global $_configuration; // @TODO: Add $_configuration['no_reply_user_id'] to configuration file $mailId = MessageManager::send_message( @@ -367,14 +371,14 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface case ADV_SUB_ACTION_STUDENT_REQUEST: // Mail to student $mailIds[] = $this->sendMailMessage( - $data['student']['id'], + $data['student']['user_id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_received.tpl'), $data['session_id'] ); // Mail to superior $mailIds[] = $this->sendMailMessage( - $data['superior']['id'], + $data['superior']['user_id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_superior.tpl'), $data['session_id'], @@ -384,21 +388,21 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface case ADV_SUB_ACTION_SUPERIOR_APPROVE: // Mail to student $mailIds[] = $this->sendMailMessage( - $data['student']['id'], + $data['student']['user_id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_superior_approved.tpl'), $data['session_id'] ); // Mail to superior $mailIds[] = $this->sendMailMessage( - $data['superior']['id'], + $data['superior']['user_id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approve_confirmed.tpl'), $data['session_id'] ); // Mail to admin $mailIds[] = $this->sendMailMessage( - $data['admin']['id'], + $data['admin']['user_id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_approved_info_admin.tpl'), $data['session_id'], @@ -408,7 +412,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface case ADV_SUB_ACTION_SUPERIOR_DISAPPROVE: // Mail to student $mailIds[] = $this->sendMailMessage( - $data['student']['id'], + $data['student']['user_id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_superior_disapproved.tpl'), $data['session_id'], @@ -416,7 +420,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface ); // Mail to superior $mailIds[] = $this->sendMailMessage( - $data['superior']['id'], + $data['superior']['user_id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_disapprove_confirmed.tpl'), $data['session_id'] @@ -425,14 +429,14 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface case ADV_SUB_ACTION_SUPERIOR_SELECT: // Mail to student $mailIds[] = $this->sendMailMessage( - $data['student']['id'], + $data['student']['user_id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_received.tpl'), $data['session_id'] ); // Mail to superior $mailIds[] = $this->sendMailMessage( - $data['superior']['id'], + $data['superior']['user_id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_request_superior.tpl'), $data['session_id'], @@ -442,14 +446,14 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface case ADV_SUB_ACTION_ADMIN_APPROVE: // Mail to student $mailIds[] = $this->sendMailMessage( - $data['student']['id'], + $data['student']['user_id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_accepted_notice_student.tpl'), $data['session_id'] ); // Mail to superior $mailIds[] = $this->sendMailMessage( - $data['superior']['id'], + $data['superior']['user_id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_accepted_notice_superior.tpl'), $data['session_id'] @@ -469,7 +473,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface case ADV_SUB_ACTION_ADMIN_DISAPPROVE: // Mail to student $mailIds[] = $this->sendMailMessage( - $data['student']['id'], + $data['student']['user_id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_rejected_notice_student.tpl'), $data['session_id'], @@ -477,7 +481,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface ); // Mail to superior $mailIds[] = $this->sendMailMessage( - $data['superior']['id'], + $data['superior']['user_id'], $this->get_lang('MailStudentRequest'), $tpl->fetch('/advancedsubscription/views/advsub_approval_admin_rejected_notice_superior.tpl'), $data['session_id'] @@ -760,17 +764,16 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface */ public function listAllStudentsInQueueBySession($sessionId) { - $return = array(); $extraSession = new ExtraFieldValue('session'); $session = api_get_session_info($sessionId); $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'target'); $session['target'] = $var['field_value']; - $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'fin_publicacion'); - $session['fin_publicacion'] = $var['field_value']; + $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'publication_end_date'); + $session['publication_end_date'] = $var['field_value']; $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'mode'); $session['mode'] = $var['field_value']; - $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'numero_recomendado_participantes'); - $session['participantes_recomendados'] = $var['field_value']; + $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'recommended_number_of_participants'); + $session['recommended_number_of_participants'] = $var['field_value']; $var = $extraSession->get_values_by_handler_and_field_variable($sessionId, 'vacancies'); $session['vacancies'] = $var['field_value']; $queueTable = Database::get_main_table(TABLE_ADV_SUB_QUEUE); diff --git a/plugin/advancedsubscription/views/admin_view.tpl b/plugin/advancedsubscription/views/admin_view.tpl index 9bdc319cc0..4abd8c01ce 100644 --- a/plugin/advancedsubscription/views/admin_view.tpl +++ b/plugin/advancedsubscription/views/admin_view.tpl @@ -7,22 +7,22 @@ {% endfor %}
- {{ Name | get_lang }}: {{ session.name }} + {{ "Name" | get_lang }}: {{ session.name }}
- {{ Target | get_lang }}: {{ session.target }} + {{ "Target" | get_lang }}: {{ session.target }}
- {{ PublicationEndDate | get_lang }}: {{ session.fin_publicacion }} + {{ "PublicationEndDate" | get_lang }}: {{ session.publication_end_date }}
- {{ Mode | get_lang }}: {{ session.mode }} + {{ "Mode" | get_lang }}: {{ session.mode }}
- {{ RecommendedNumberOfParticipants | get_lang }} : {{ session.participantes_recomendados }} + {{ "RecommendedNumberOfParticipants" | get_lang }} : {{ session.recommended_number_of_participants }}
- {{ Vacancies | get_lang }}: {{ session.vacancies }} + {{ "Vacancies" | get_lang }}: {{ session.vacancies }}
From 7586e9032333b90c2e26cc28d1ceea616cb4bc5a Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Tue, 3 Feb 2015 16:38:03 -0500 Subject: [PATCH 29/72] Fix admin block url, fix admin_view when session id is empty - refs BT#9092 --- .../src/HookAdvancedSubscription.class.php | 2 +- .../advancedsubscription/src/admin_view.php | 22 ++++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php index 7783367dd7..dab276ea3d 100644 --- a/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php +++ b/plugin/advancedsubscription/src/HookAdvancedSubscription.class.php @@ -33,7 +33,7 @@ class HookAdvancedSubscription extends HookObserver implements } elseif ($data['type'] === HOOK_TYPE_POST) { if (isset($data['blocks'])) { $data['blocks']['sessions']['items'][] = array( - 'url' => 'configure_plugin.php?name=advancedsubscription', + 'url' => '../../plugin/advancedsubscription/src/admin_view.php', 'label' => get_plugin_lang('plugin_title', 'AdvancedSubscriptionPlugin'), ); } diff --git a/plugin/advancedsubscription/src/admin_view.php b/plugin/advancedsubscription/src/admin_view.php index d1cc7fddb4..c339fc2702 100644 --- a/plugin/advancedsubscription/src/admin_view.php +++ b/plugin/advancedsubscription/src/admin_view.php @@ -42,18 +42,24 @@ if (isset($data) && is_array($data)) { $params['profile_completed'] = isset($_REQUEST['profile_completed']) ? $_REQUEST['profile_completed'] : 0; $params['accept'] = isset($_REQUEST['accept']) ? $_REQUEST['accept'] : false; } -// Get student list in queue -$studentList = $plugin->listAllStudentsInQueueBySession($s); -// Get all sessions -$sessionList = $plugin->listAllSessions(); -// Set selected to current session -$sessionList[$s]['selected'] = 'selected="selected"'; + // Init template $tpl = new Template('TESTING'); + +if (!empty($s)) { + // Get student list in queue + $studentList = $plugin->listAllStudentsInQueueBySession($s); + // Set selected to current session + $sessionList[$s]['selected'] = 'selected="selected"'; + // Assign variables + $tpl->assign('session', $studentList['session']); + $tpl->assign('students', $studentList['students']); +} + +// Get all sessions +$sessionList = $plugin->listAllSessions(); // Assign variables -$tpl->assign('session', $studentList['session']); $tpl->assign('sessionItems', $sessionList); -$tpl->assign('students', $studentList['students']); // Get rendered template $content = $tpl->fetch('/advancedsubscription/views/admin_view.tpl'); // Assign into content From ca5faba0f7280b498c6e584c2bf1788931fc31a4 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Wed, 4 Feb 2015 14:23:00 -0500 Subject: [PATCH 30/72] Fix mail template data - refs BT#9092 --- .../advancedsubscription/views/admin_view.tpl | 4 +-- ...b_approval_admin_accepted_notice_admin.tpl | 16 ++++----- ...approval_admin_accepted_notice_student.tpl | 18 +++++----- ...pproval_admin_accepted_notice_superior.tpl | 18 +++++----- ...b_approval_admin_rejected_notice_admin.tpl | 16 ++++----- ...approval_admin_rejected_notice_student.tpl | 18 +++++----- ...pproval_admin_rejected_notice_superior.tpl | 18 +++++----- .../advsub_request_approve_confirmed.tpl | 18 +++++----- .../advsub_request_approved_info_admin.tpl | 18 +++++----- .../advsub_request_approved_reminder.tpl | 18 +++++----- .../advsub_request_disapprove_confirmed.tpl | 18 +++++----- .../views/advsub_request_received.tpl | 18 +++++----- .../advsub_request_received_reminder.tpl | 18 +++++----- .../views/advsub_request_superior.tpl | 24 ++++++------- .../advsub_request_superior_approved.tpl | 18 +++++----- .../advsub_request_superior_disapproved.tpl | 18 +++++----- .../advsub_request_superior_reminder.tpl | 34 ++++++++++--------- .../advsub_request_superior_reminder_max.tpl | 34 ++++++++----------- 18 files changed, 171 insertions(+), 173 deletions(-) diff --git a/plugin/advancedsubscription/views/admin_view.tpl b/plugin/advancedsubscription/views/admin_view.tpl index 4abd8c01ce..ac145c1422 100644 --- a/plugin/advancedsubscription/views/admin_view.tpl +++ b/plugin/advancedsubscription/views/admin_view.tpl @@ -43,10 +43,10 @@ - - diff --git a/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl index adfd3e03a5..478840590d 100644 --- a/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl +++ b/plugin/advancedsubscription/views/advsub_approval_admin_accepted_notice_admin.tpl @@ -2,7 +2,7 @@ - Solicitud recibida para el curso {{ session.title }} + Solicitud recibida para el curso {{ session.name }} + - -
- {{ "Name" | get_lang }}: {{ session.name }} +
+
+

Elige una sesión de formación

+ + + +

{{ "SessionName" | get_lang }}:

+

{{ session.name }}

+

{{ "Target" | get_lang }}:

+

{{ session.target }}

+
-
- {{ "Target" | get_lang }}: {{ session.target }} +
+

+ {{ session.vacancies }} + {{ "Vacancies" | get_lang }}

+

+ {{ session.recommended_number_of_participants }} + {{ "RecommendedNumberOfParticipants" | get_lang }}

+

{{ "PublicationEndDate" | get_lang }}:

{{ session.publication_end_date }}

+

{{ "Mode" | get_lang }}:

{{ session.mode }}

-
- {{ "PublicationEndDate" | get_lang }}: {{ session.publication_end_date }} +
+
+
+
+
{{ student.lastname }} {{ student.firstname }} {{ student.created_at }} {{ student.validation }}Aceptar + Aceptar Rechazar + Rechazar
+ + + + + + + + + {% set row_class = "row_odd" %} + {% for student in students %} + + + + + + + + {% if row_class == "row_even" %} + {% set row_class = "row_odd" %} + {% else %} + {% set row_class = "row_even" %} + {% endif %} + {% endfor %} + +
{{ "Postulant" | get_lang }}{{ "InscriptionDate" | get_lang }}{{ "BossValidation" | get_lang }}{{ "Decision" | get_lang }}
{{ student.complete_name }}{{ student.created_at }}{{ student.validation }} + + Aceptar + + + Rechazar + +
+ -
- {{ "Mode" | get_lang }}: {{ session.mode }} -
-
- {{ "RecommendedNumberOfParticipants" | get_lang }} : {{ session.recommended_number_of_participants }} -
-
- {{ "Vacancies" | get_lang }}: {{ session.vacancies }} -
- - - - - - - - - - {% set row_class = "row_odd" %} - {% for student in students %} - - - - - - - - {% if row_class == "row_even" %} - {% set row_class = "row_odd" %} - {% else %} - {% set row_class = "row_even" %} - {% endif %} - {% endfor %} - -
Alumno - - Fecha de Inscripción - - Validación del Jefe AceptarRechazar
{{ student.complete_name }}{{ student.created_at }}{{ student.validation }}Aceptar - - Rechazar - -
- + + + \ No newline at end of file From 60ae60b22c4c4d9873714d402c0bf17d8ff19004 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Thu, 12 Feb 2015 19:46:00 -0500 Subject: [PATCH 67/72] Add file documentation - refs BT#9092 --- .../advancedsubscription/src/HookAdvancedSubscription.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugin/advancedsubscription/src/HookAdvancedSubscription.php b/plugin/advancedsubscription/src/HookAdvancedSubscription.php index 3693b333de..2a3c8f53c8 100644 --- a/plugin/advancedsubscription/src/HookAdvancedSubscription.php +++ b/plugin/advancedsubscription/src/HookAdvancedSubscription.php @@ -1,9 +1,9 @@ + * @package chamilo.plugin.advancedsubscription */ require_once __DIR__ . '/../config.php'; From 9e4ba8105347f7e80d0cdfc2e425e4201d9c06e9 Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Fri, 13 Feb 2015 13:18:07 -0500 Subject: [PATCH 68/72] Add condition to avoid non object error - refs BT#9092 --- main/inc/lib/extra_field.lib.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/main/inc/lib/extra_field.lib.php b/main/inc/lib/extra_field.lib.php index 09b62e580d..59fbc6f131 100755 --- a/main/inc/lib/extra_field.lib.php +++ b/main/inc/lib/extra_field.lib.php @@ -735,11 +735,14 @@ class ExtraField extends Model $addOptions = array(); - global $app; $optionsExists = false; - /* - $optionsExists = $app['orm.em']->getRepository('ChamiloLMS\Entity\ExtraFieldOptionRelFieldOption')-> - findOneBy(array('fieldId' => $field_details['id'])); + global $app; + // Check if exist $app['orm.em'] object + if (isset($app['orm.em']) && is_object($app['orm.em'])) { + $optionsExists = $app['orm.em'] + ->getRepository('ChamiloLMS\Entity\ExtraFieldOptionRelFieldOption') + ->findOneBy(array('fieldId' => $field_details['id'])); + } if ($optionsExists) { if (isset($userInfo['status']) && !empty($userInfo['status'])) { @@ -758,7 +761,6 @@ class ExtraField extends Model } } - */ $options = array(); if (empty($defaultValueId)) { $options[''] = get_lang('SelectAnOption'); From 995b26dcec991db20006c2708f2c1f9854aac70a Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Fri, 13 Feb 2015 14:23:34 -0500 Subject: [PATCH 69/72] Improve documentation in session manager - refs BT#9092 --- main/inc/lib/sessionmanager.lib.php | 62 +++++++++++++++++++---------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/main/inc/lib/sessionmanager.lib.php b/main/inc/lib/sessionmanager.lib.php index 26abc66ce8..fa2f2ca83f 100755 --- a/main/inc/lib/sessionmanager.lib.php +++ b/main/inc/lib/sessionmanager.lib.php @@ -5431,22 +5431,26 @@ class SessionManager /** * Returns the list of session (name, short description, start date, end date) from category. * The short description is an extra field value - * @param $categoryId - * @param $publicoObjetivo + * @param int $categoryId + * @param string $target * @return mixed */ - public static function getSessionBriefListByCategory($categoryId, $publicoObjetivo) { + public static function getSessionBriefListByCategory($categoryId, $target) { + // Init variables $categoryId = (int) $categoryId; $sessionList = array(); + // Check if categoryId is valid if ($categoryId > 0) { + $target = Database::escape_string($target); $sTable = Database::get_main_table(TABLE_MAIN_SESSION); $sfTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD); $sfvTable = Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES); - $joinSSfvTable = $sTable . ' o INNER JOIN ' . $sfvTable . ' q ON s.id = sfv.session_id'; + // Join session field and session field values tables $joinTable = $sfTable . ' sf INNER JOIN ' . $sfvTable . ' sfv ON sf.id = sfv.field_id'; $fieldsArray = array( 'short_description', 'mode', 'duration', 'vacancies', 'brochure', 'target', 'schedule' ); + // Get the session list from session category and target $sessionList = Database::select( 'id, name, date_start, date_end', $sTable, @@ -5457,29 +5461,35 @@ class SessionManager sfv.session_id = session.id AND sf.field_variable = 'target' AND sfv.field_value = ? - );" => array($categoryId, $publicoObjetivo) + );" => array($categoryId, $target) ) ) ); + // Get session fields $extraField = new ExtraField('session'); $fieldList = $extraField->get_all(array( 'field_variable IN ( ?, ?, ?, ?, ?, ?, ? )' => $fieldsArray )); + // Index session fields foreach ($fieldList as $field) { $fields[$field['id']] = $field['field_variable']; } + // Get session field values $extra = new ExtraFieldValue('session'); $sessionFieldValueList = $extra->get_all(array('field_id IN ( ?, ?, ?, ?, ?, ?, ? )' => array_keys($fields))); - } - - foreach ($sessionList as $id => &$session) { - foreach ($sessionFieldValueList as $sessionFieldValue) { - if ($sessionFieldValue['session_id'] == $id) { - if (isset($fields[$sessionFieldValue['field_id']])) { - $var = $fields[$sessionFieldValue['field_id']]; - $val = $sessionFieldValue['field_value']; - $session[$var] = $val; + // Add session fields values to session list + foreach ($sessionList as $id => &$session) { + foreach ($sessionFieldValueList as $sessionFieldValue) { + // Match session field values to session + if ($sessionFieldValue['session_id'] == $id) { + // Check if session field value is set in session field list + if (isset($fields[$sessionFieldValue['field_id']])) { + $var = $fields[$sessionFieldValue['field_id']]; + $val = $sessionFieldValue['field_value']; + // Assign session field value to session + $session[$var] = $val; + } } } } @@ -5499,7 +5509,7 @@ class SessionManager public static function getSessionCategoryIdByName($categoryName, $force = false) { // Start error result - $errorResult = array('error' => true, 'errorMessage' => 'There was an error'); + $errorResult = array('error' => true, 'errorMessage' => get_lang('ThereWasAnError')); $categoryName = Database::escape_string($categoryName); // Check if is not empty category name if (!empty($categoryName)) { @@ -5537,12 +5547,14 @@ class SessionManager /** * Return all data from sessions (plus extra field, course and coach data) by category id * @param int $sessionCategoryId session category id used to search sessions - * @return array + * @return array If success, return session list and more session related data, else it will return an array + * with the next structure: + * array('error' => true, 'errorMessage' => ERROR_MESSAGE) */ public static function getSessionListAndExtraByCategoryId($sessionCategoryId) { // Start error result - $errorResult = array('error' => true, 'errorMessage' => 'There was an error'); + $errorResult = array('error' => true, 'errorMessage' => get_lang('ThereWasAnError')); $sessionCategoryId = intval($sessionCategoryId); // Check if sesssion category id is valid if ($sessionCategoryId > 0) { @@ -5597,7 +5609,6 @@ class SessionManager $sessionCourseList = Database::store_result($res, 'ASSOC'); // Check if course list had result if (!empty($sessionCourseList)) { - $sessionCourseListBySession = array(); foreach ($sessionCourseList as $key => $sessionCourse) { // Create an array to index ids to session_id $sessionCourseListBySession[$sessionCourse['session_id']][] = $key; @@ -5606,7 +5617,10 @@ class SessionManager // Join lists if (is_array($sessionList)) { foreach ($sessionList as $id => &$row) { - if (is_array($sessionFieldValueListBySession[$id])) { + if ( + !empty($sessionFieldValueListBySession) && + is_array($sessionFieldValueListBySession[$id]) + ) { // If have an index array for session extra fields, use it to join arrays foreach ($sessionFieldValueListBySession[$id] as $key) { $row['extra'][$key] = array( @@ -5615,7 +5629,10 @@ class SessionManager ); } } - if (is_array($sessionCourseListBySession[$id])) { + if ( + !empty($sessionCourseListBySession) && + is_array($sessionCourseListBySession[$id]) + ) { // If have an index array for session course coach, use it to join arrays foreach ($sessionCourseListBySession[$id] as $key) { $row['course'][$key] = array( @@ -5648,9 +5665,12 @@ class SessionManager */ public static function getDescriptionFromSessionId($sessionId) { + // Init variables $sessionId = intval($sessionId); $description = ''; + // Check if session id is valid if ($sessionId !== 0) { + // Select query from session id $rows = Database::select( 'description', Database::get_main_table(TABLE_MAIN_SESSION), @@ -5661,7 +5681,9 @@ class SessionManager ) ); + // Check if select query result is not empty if (!empty($rows)) { + // Get session description $description = $rows[0]['description']; } } From 5576ccd2d1d0cf0a29bb9887b931fc3b9d3163eb Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Fri, 13 Feb 2015 14:49:00 -0500 Subject: [PATCH 70/72] Improve documentation in advsub ajax script - refs BT#9092 --- .../advancedsubscription/ajax/advsub.ajax.php | 49 ++++++++++++++++--- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/plugin/advancedsubscription/ajax/advsub.ajax.php b/plugin/advancedsubscription/ajax/advsub.ajax.php index c788da6f99..5d31325934 100644 --- a/plugin/advancedsubscription/ajax/advsub.ajax.php +++ b/plugin/advancedsubscription/ajax/advsub.ajax.php @@ -12,7 +12,9 @@ require_once __DIR__ . '/../config.php'; $plugin = AdvancedSubscriptionPlugin::create(); +// Get validation hash $hash = Security::remove_XSS($_REQUEST['v']); +// Get data from request (GET or POST) $data['a'] = Security::remove_XSS($_REQUEST['a']); $data['s'] = intval($_REQUEST['s']); $data['current_user_id'] = intval($_REQUEST['current_user_id']); @@ -21,9 +23,10 @@ $data['q'] = intval($_REQUEST['q']); $data['e'] = intval($_REQUEST['e']); $data['is_connected'] = isset($_REQUEST['is_connected']) ? boolval($_REQUEST['is_connected']) : false; $data['profile_completed'] = isset($_REQUEST['profile_completed']) ? floatval($_REQUEST['profile_completed']) : 0; -$verified = $plugin->checkHash($data, $hash) || $data['a'] == 'subscribe'; // Init result array -$result = array('error' => true, 'errorMessage' => 'There was an error'); +$result = array('error' => true, 'errorMessage' => get_lang('ThereWasAnError')); +// Check if data is valid or is for start subscription +$verified = $plugin->checkHash($data, $hash) || $data['a'] == 'subscribe'; if ($verified) { switch($data['a']) { case 'check': // Check minimum requirements @@ -42,10 +45,12 @@ if ($verified) { } break; case 'subscribe': // Subscription - $bossId = UserManager::getStudentBoss($data['u']); + // Start subscription to queue $res = AdvancedSubscriptionPlugin::create()->startSubscription($data['u'], $data['s'], $data); + // Check if queue subscription was successful if ($res === true) { - // send mail to superior + // Prepare data + // Get session data $sessionArray = api_get_session_info($data['s']); $extraSession = new ExtraFieldValue('session'); $var = $extraSession->get_values_by_handler_and_field_variable($data['s'], 'description'); @@ -58,20 +63,24 @@ if ($verified) { $sessionArray['publication_end_date'] = $var['field_value']; $var = $extraSession->get_values_by_handler_and_field_variable($data['s'], 'recommended_number_of_participants'); $sessionArray['recommended_number_of_participants'] = $var['field_valiue']; + // Get student data $studentArray = api_get_user_info($data['u']); $studentArray['picture'] = UserManager::get_user_picture_path_by_id($studentArray['user_id'], 'web', false, true); $studentArray['picture'] = UserManager::get_picture_user($studentArray['user_id'], $studentArray['picture']['file'], 22, USER_IMAGE_SIZE_MEDIUM); + // Get superior data if exist $superiorId = UserManager::getStudentBoss($data['u']); if (!empty($superiorId)) { $superiorArray = api_get_user_info($superiorId); } else { $superiorArray = null; } + // Get admin data $adminsArray = UserManager::get_all_administrators(); foreach ($adminsArray as &$admin) { $admin['complete_name'] = $admin['lastname'] . ', ' . $admin['firstname']; } unset($admin); + // Set data $data['a'] = 'confirm'; $data['student'] = $studentArray; $data['superior'] = $superiorArray; @@ -79,15 +88,23 @@ if ($verified) { $data['session'] = $sessionArray; $data['signature'] = api_get_setting('Institution'); - if (empty($superiorId)) { // Does not have boss + // Check if student boss exists + if (empty($superiorId)) { + // Student boss does not exist + // Update status to accepted by boss $res = $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_APPROVED); if (!empty($res)) { - $data['admin_view_url'] = api_get_path(WEB_PLUGIN_PATH) . 'advancedsubscription/src/admin_view.php?s=' . $data['s']; + // Prepare admin url + $data['admin_view_url'] = api_get_path(WEB_PLUGIN_PATH) . + 'advancedsubscription/src/admin_view.php?s=' . $data['s']; + // Send mails $result['mailIds'] = $plugin->sendMail($data, ADV_SUB_ACTION_STUDENT_REQUEST_NO_BOSS); + // Check if mails were sent if (!empty($result['mailIds'])) { $result['error'] = false; $result['errorMessage'] = 'No error'; $result['pass'] = true; + // Check if exist an email to render if (isset($result['mailIds']['render'])) { // Render mail $message = MessageManager::get_message_by_id($result['mailIds']['render']); @@ -98,15 +115,21 @@ if ($verified) { } } } else { + // Student boss does exist + // Get url to be accepted by boss $data['e'] = ADV_SUB_QUEUE_STATUS_BOSS_APPROVED; $data['student']['acceptUrl'] = $plugin->getQueueUrl($data); + // Get url to be rejected by boss $data['e'] = ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED; $data['student']['rejectUrl'] = $plugin->getQueueUrl($data); + // Send mails $result['mailIds'] = $plugin->sendMail($data, ADV_SUB_ACTION_STUDENT_REQUEST); + // Check if mails were sent if (!empty($result['mailIds'])) { $result['error'] = false; $result['errorMessage'] = 'No error'; $result['pass'] = true; + // Check if exist an email to render if (isset($result['mailIds']['render'])) { // Render mail $message = MessageManager::get_message_by_id($result['mailIds']['render']); @@ -127,9 +150,13 @@ if ($verified) { break; case 'confirm': + // Check if is set new status if (isset($data['e'])) { + // Update queue status $res = $plugin->updateQueueStatus($data, $data['e']); if ($res === true) { + // Prepare data + // Prepare session data $sessionArray = api_get_session_info($data['s']); $extraSession = new ExtraFieldValue('session'); $var = $extraSession->get_values_by_handler_and_field_variable($data['s'], 'description'); @@ -142,27 +169,33 @@ if ($verified) { $sessionArray['publication_end_date'] = $var['field_value']; $var = $extraSession->get_values_by_handler_and_field_variable($data['s'], 'recommended_number_of_participants'); $sessionArray['recommended_number_of_participants'] = $var['field_valiue']; + // Prepare student data $studentArray = api_get_user_info($data['u']); $studentArray['picture'] = UserManager::get_user_picture_path_by_id($studentArray['user_id'], 'web', false, true); $studentArray['picture'] = UserManager::get_picture_user($studentArray['user_id'], $studentArray['picture']['file'], 22, USER_IMAGE_SIZE_MEDIUM); + // Prepare superior data $superiorId = UserManager::getStudentBoss($data['u']); if (!empty($superiorId)) { $superiorArray = api_get_user_info($superiorId); } else { $superiorArray = null; } + // Prepare admin data $adminsArray = UserManager::get_all_administrators(); foreach ($adminsArray as &$admin) { $admin['complete_name'] = $admin['lastname'] . ', ' . $admin['firstname']; } unset($admin); + // Set data $data['student'] = $studentArray; $data['superior'] = $superiorArray; $data['admins'] = $adminsArray; $data['session'] = $sessionArray; $data['signature'] = api_get_setting('Institution'); $data['admin_view_url'] = api_get_path(WEB_PLUGIN_PATH) . 'advancedsubscription/src/admin_view.php?s=' . $data['s']; + // Check if exist and action in data if (empty($data['action'])) { + // set action in data by new status switch ($data['e']) { case ADV_SUB_QUEUE_STATUS_BOSS_APPROVED: $data['action'] = ADV_SUB_ACTION_SUPERIOR_APPROVE; @@ -186,10 +219,13 @@ if ($verified) { SessionManager::suscribe_users_to_session($data['s'], array($data['u']), null, false); } + // Send mails $result['mailIds'] = $plugin->sendMail($data, $data['action']); + // Check if mails were sent if (!empty($result['mailIds'])) { $result['error'] = false; $result['errorMessage'] = 'User has been processed'; + // Check if exist mail to render if (isset($result['mailIds']['render'])) { // Render mail $message = MessageManager::get_message_by_id($result['mailIds']['render']); @@ -208,4 +244,5 @@ if ($verified) { } } +// Echo result as json echo json_encode($result); From 358518d868bd62c6348e929e11e98c133bc4c3bc Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Fri, 13 Feb 2015 15:35:55 -0500 Subject: [PATCH 71/72] Update english and spanish langs, delete french lang - refs BT#9092 --- plugin/advancedsubscription/lang/english.php | 52 ++++++++++---------- plugin/advancedsubscription/lang/french.php | 21 -------- plugin/advancedsubscription/lang/spanish.php | 2 + 3 files changed, 29 insertions(+), 46 deletions(-) delete mode 100644 plugin/advancedsubscription/lang/french.php diff --git a/plugin/advancedsubscription/lang/english.php b/plugin/advancedsubscription/lang/english.php index cdacbe476a..ab4c8bc9a4 100644 --- a/plugin/advancedsubscription/lang/english.php +++ b/plugin/advancedsubscription/lang/english.php @@ -2,32 +2,34 @@ /* Strings for settings */ $strings['plugin_title'] = 'Advanced Subscription'; -$strings['plugin_comment'] = 'Plugin que permite gestionar la inscripción en cola a sesiones con comunicación a a un portal externo'; -$strings['uit_value'] = 'Valor de la Unidad Impositiva Tributaria (UIT)'; -$strings['ws_url'] = 'URL del Webservice'; -$strings['min_profile_percentage'] = 'Porcentaje mínimo de perfil completado'; -$strings['max_expended_uit'] = 'Limite anual de cursos en UIT por año(Medido en UIT)'; -$strings['max_expended_num'] = 'Limite anual de cursos en horas por año(Medido en UIT)'; -$strings['max_course_times'] = 'Limite anual de cantidad de cursos por año'; -$strings['check_induction'] = 'Activar requerimiento de curso inducción'; +$strings['plugin_comment'] = 'Plugin for managing the registration queue and communication to sessions from an external website'; +$strings['ws_url'] = 'Webservice url'; +$strings['ws_url'] = 'Webservice url'; +$strings['yearly_cost_unit_converter'] = 'Taxation unit (TU)'; +$strings['min_profile_percentage'] = 'Minimum required of completed percentage profile'; +$strings['yearly_cost_limit'] = 'Yearly limit TU for courses (measured in Taxation units)'; +$strings['yearly_hours_limit'] = 'Yearly limit hours for courses'; +$strings['courses_count_limit'] = 'Yearly limit times for courses'; +$strings['check_induction'] = 'Activate induction course requirement'; +$strings['course_session_credit_year_start_date'] = 'Year start date'; /* String for error message about requirements */ -$strings['AdvancedSubscriptionNotConnected'] = "Usted no está conectado en la plataforma. Por favor ingrese su usuario / constraseña para poder inscribirse"; -$strings['AdvancedSubscriptionProfileIncomplete'] = "Su perfil no es lo suficientemente completo para poder inscribirse al curso. Por favor complete su perfil"; -$strings['AdvancedSubscriptionIncompleteInduction'] = "Usted aún no ha completado el curso de inducción. Por favor complete el curso inducción"; -$strings['AdvancedSubscriptionCostXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s UIT para los cursos que ha seguido este año"; -$strings['AdvancedSubscriptionTimeXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s horas para los cursos que ha seguido este año"; -$strings['AdvancedSubscriptionCourseXLimitReached'] = "Lo sentimos, usted ya ha alcanzado el límite anual de %s cursos que ha seguido este año"; -$strings['AdvancedSubscriptionNotMoreAble'] = "Lo sentimos, usted ya no cumple con las condiciones iniciales para poder inscribirse al curso"; +$strings['AdvancedSubscriptionNotConnected'] = "You are not connected to platform. Please login first"; +$strings['AdvancedSubscriptionProfileIncomplete'] = "Your percentage completed profile require to exceed minimum percentage. Please complete percentage"; +$strings['AdvancedSubscriptionIncompleteInduction'] = "You have not yet completed induction course. Please complete it first"; +$strings['AdvancedSubscriptionCostXLimitReached'] = "We are sorry, you have already reached yearly limit mount for courses"; +$strings['AdvancedSubscriptionTimeXLimitReached'] = "We are sorry, you have already reached yearly limit hours for courses"; +$strings['AdvancedSubscriptionCourseXLimitReached'] = "We are sorry, you have already reached yearly limit times for courses"; +$strings['AdvancedSubscriptionNotMoreAble'] = "We are sorry, you no longer fulfills the initial conditions to subscribe this course"; -$strings['AdvancedSubscriptionNoQueue'] = "Usted no está inscrito en este curso."; -$strings['AdvancedSubscriptionNoQueueIsAble'] = "Usted no está inscrito, pero está calificado para este curso."; -$strings['AdvancedSubscriptionQueueStart'] = "Su inscripción está en espera de aprobación por parte de su jefe, por favor este atento."; -$strings['AdvancedSubscriptionQueueBossDisapproved'] = "Lo sentimos, su inscripción ha sido desaprobada por su jefe."; -$strings['AdvancedSubscriptionQueueBossApproved'] = "Su inscripción ha sido aprobada por su jefe, y está en espera de aprobación del Administrador."; -$strings['AdvancedSubscriptionQueueAdminDisapproved'] = "Lo sentimos, su inscripción ha sido desaprobada por el administrador."; -$strings['AdvancedSubscriptionQueueAdminApproved'] = "Felicitaciones, Su inscripción ha sido aprobada por el administrador."; -$strings['AdvancedSubscriptionQueueDefaultX'] = "Ha ocurrido un problema, el estado en cola, %d no está definido en el sistema."; +$strings['AdvancedSubscriptionNoQueue'] = "You are not subscribed for this course."; +$strings['AdvancedSubscriptionNoQueueIsAble'] = "You are not subscribed, but you are qualified for this course."; +$strings['AdvancedSubscriptionQueueStart'] = "Your subscription request is pending for approval by your boss, please wait attentive."; +$strings['AdvancedSubscriptionQueueBossDisapproved'] = "We are sorry, your subscription was rejected by your boss."; +$strings['AdvancedSubscriptionQueueBossApproved'] = "Your subscription request has been accepted by your boss, now is pending for vacancies."; +$strings['AdvancedSubscriptionQueueAdminDisapproved'] = "We are sorry, your subscription was rejected by the administrator."; +$strings['AdvancedSubscriptionQueueAdminApproved'] = "Congratulation, your subscription request has been accepted by administrator"; +$strings['AdvancedSubscriptionQueueDefaultX'] = "There was an error, queue status %d is not defined by system."; // Mail translations $strings['MailStudentRequest'] = 'Student registration request'; @@ -40,8 +42,8 @@ $strings['MailStudentRequestNoBoss'] = 'Student registration request without bos // TPL langs // Admin view -$strings['SelectASession'] = 'Elija una sesión'; -$strings['SessionName'] = 'Nombre de la sesión'; +$strings['SelectASession'] = 'Select a session'; +$strings['SessionName'] = 'Session name'; $strings['Target'] = 'Target audience'; $strings['Vacancies'] = 'Vacancies'; $strings['RecommendedNumberOfParticipants'] = 'Recommended number of participants'; diff --git a/plugin/advancedsubscription/lang/french.php b/plugin/advancedsubscription/lang/french.php deleted file mode 100644 index 99dba6639c..0000000000 --- a/plugin/advancedsubscription/lang/french.php +++ /dev/null @@ -1,21 +0,0 @@ -no sean el curso de inducción"; $strings['course_session_credit_year_start_date'] = 'Fecha de inicio'; $strings['course_session_credit_year_start_date_help'] = "Fecha de inicio del año (día/mes)"; +$strings['min_profile_percentage'] = 'Porcentage de perfil completado mínimo requerido'; +$strings['min_profile_percentage_help'] = 'Número porcentage ( > 0.00 y < 100.00)'; /* String for error message about requirements */ From 1bdc1dd7191d1ba8da0b1b3ae10693e3e6f7e6ca Mon Sep 17 00:00:00 2001 From: Daniel Barreto Date: Fri, 13 Feb 2015 15:44:25 -0500 Subject: [PATCH 72/72] Delete no longer used files, add index.html - refs BT#9092 --- .../cron/notify_by_mail.php | 65 ------------------- plugin/advancedsubscription/index.html | 1 + plugin/advancedsubscription/index.php | 7 -- plugin/advancedsubscription/src/index.php | 63 ------------------ plugin/advancedsubscription/test.php | 28 -------- tests/scripts/hook_install.php | 12 ---- 6 files changed, 1 insertion(+), 175 deletions(-) delete mode 100644 plugin/advancedsubscription/cron/notify_by_mail.php create mode 100644 plugin/advancedsubscription/index.html delete mode 100644 plugin/advancedsubscription/index.php delete mode 100644 plugin/advancedsubscription/src/index.php delete mode 100644 plugin/advancedsubscription/test.php delete mode 100644 tests/scripts/hook_install.php diff --git a/plugin/advancedsubscription/cron/notify_by_mail.php b/plugin/advancedsubscription/cron/notify_by_mail.php deleted file mode 100644 index 10e6aeff00..0000000000 --- a/plugin/advancedsubscription/cron/notify_by_mail.php +++ /dev/null @@ -1,65 +0,0 @@ - - */ - -/** - * Init - */ -require_once '../../../main/inc/global.inc.php'; - -/** - * Get database handle - */ - -$nowUtc = api_get_utc_datetime(); -$weekAgoUtc = api_get_utc_datetime(strtotime('-1 week')); -$sTable = Database::get_main_table(TABLE_MAIN_SESSION); -$uUserTable = Database::get_main_table(TABLE_MAIN_SESSION_USER); -$limitArea = 'limit_area'; -//define('USER_RELATION_TYPE_BOSS', 8); -//define('TABLE_ADV_SUB_QUEUE', 'plugin_advsub_queue'); -//define('TABLE_ADV_SUB_MAIL', 'plugin_advsub_mail'); - -$sessionAdvSub = array(); -$sessionQueue = array(); -$userAdmins = array(); - -$advSubQueueTable = TABLE_ADVSUB_QUEUE; -$advSubMailTable = TABLE_ADVSUB_MAIL; -$advSubMails = Database::select('id, created_at, user_id, status', $advSubMailTable); -$advSubQueue = Database::select('id, status_id, user_id, updated_at', $advSubQueueTable, array('where' => array('start_date > ?' => $nowUtc))); -$sessionIds = Database::select('id', $sTable, array('where' => array('start_date > ?' => $nowUtc))); -$users = Database::select('user_id ASS boss_id, friend_user_id AS id', $uUserTable, array('where' => array('relation_type = ?' => USER_RELATION_TYPE_BOSS))); -$sField = new ExtraField('session'); -$sFieldValue = new ExtraFieldValue('session'); -$areaCounts = array(); -foreach ($users as $userId => $bossId) { - $areaCounts[$bossId] ++; -} -foreach ($advSubMails as $id => $advSubMail) { - $userSubMail[$advSubMail['user_id']][] = $id; -} -foreach ($sessionIds as $sessionId) { - $bossId = $advSubQueue[$sessionQueue[$sessionId]]['user_id']; - $sLimitArea = $sFieldValue->get_values_by_handler_and_field_variable($sessionId, $limitArea); - if ($sLimitArea > $sQueueCount[$bossId]) { - // Register data - $chooseUser = true; - } - if ($advSubMail[end($userSubMail[$bossId])]['created_at'] < $weekAgoUtc) { - // Send mail again - // Session x Boss -> user, status, buttons - if ($chooseUser) { - // Use choose user tpl - } - } - foreach ($userAdmins as $adminId => $userAdmin) { - if ($advSubMail[end($userSubMail[$adminId])]['created_at'] < $weekAgoUtc) { - // send queue status 2 - } - } -} diff --git a/plugin/advancedsubscription/index.html b/plugin/advancedsubscription/index.html new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/plugin/advancedsubscription/index.html @@ -0,0 +1 @@ + diff --git a/plugin/advancedsubscription/index.php b/plugin/advancedsubscription/index.php deleted file mode 100644 index 6ae74e5060..0000000000 --- a/plugin/advancedsubscription/index.php +++ /dev/null @@ -1,7 +0,0 @@ - 16 ? - $plugin->decrypt($_REQUEST['data']) : - null : - null; -if (isset($data)) { - if (is_string($data)) { - $data = unserialize($data); - } - if (is_array($data)) { - if (isset($data['template'])) { - $template = '/advancedsubscription/views/' . $data['template']; - $templateName = $plugin->get_lang('plugin_title'); - $tpl = new Template($templateName); - $tplParams = array('user', 'student', 'students','superior', 'admin', 'session', 'signature', '_p', ); - foreach ($tplParams as $tplParam) { - if (isset($data['superior'])) { - $tpl->assign($tplParam, $data[$tplParam]); - } - } - $content = $tpl->fetch($template); - $tpl->assign('content', $content); - $tpl->display_one_col_template(); - } elseif ($data['action']) { - switch($data['action']) { - case ADV_SUB_ACTION_STUDENT_REQUEST: - $res = $plugin->startSubscription($data['user']['id'], $data['session']['id'], $data); - break; - case ADV_SUB_ACTION_SUPERIOR_APPROVE: - $res = $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_APPROVED); - break; - case ADV_SUB_ACTION_SUPERIOR_DISAPPROVE: - $res = $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED); - break; - case ADV_SUB_ACTION_SUPERIOR_SELECT: - $res = $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_APPROVED); - break; - case ADV_SUB_ACTION_ADMIN_APPROVE: - $res = $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_ADMIN_APPROVED); - break; - case ADV_SUB_ACTION_ADMIN_DISAPPROVE: - $res = $plugin->updateQueueStatus($data, ADV_SUB_QUEUE_STATUS_BOSS_DISAPPROVED); - break; - } - - if ($res === true) { - $plugin->sendMail($data, $data['action']); - } - } - } -} diff --git a/plugin/advancedsubscription/test.php b/plugin/advancedsubscription/test.php deleted file mode 100644 index a54f190771..0000000000 --- a/plugin/advancedsubscription/test.php +++ /dev/null @@ -1,28 +0,0 @@ -fetch('/advancedsubscription/views/advsub_request_received.tpl'); -$advSub->sendMailMessage(18, 'TEST', $body); -*/ \ No newline at end of file diff --git a/tests/scripts/hook_install.php b/tests/scripts/hook_install.php deleted file mode 100644 index 81b1608322..0000000000 --- a/tests/scripts/hook_install.php +++ /dev/null @@ -1,12 +0,0 @@ -install(); \ No newline at end of file