Merged in Gsoc14-ryzomAppImprovements (pull request #1)
Merging Gsoc 14 branch with defaulthg/feature/cdb-packed
commit
2a2c2b1d67
Binary file not shown.
@ -0,0 +1,269 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* API for loading and interacting with plugins
|
||||
* contains getters and setters
|
||||
*
|
||||
* @author shubham meena mentored by Matthew Lagoe
|
||||
*/
|
||||
class Plugincache {
|
||||
private $id;
|
||||
private $plugin_name;
|
||||
private $plugin_type;
|
||||
private $plugin_permission;
|
||||
private $plugin_status;
|
||||
private $plugin_info = array();
|
||||
private $update_info = array();
|
||||
/**
|
||||
* A constructor.
|
||||
* Empty constructor
|
||||
*/
|
||||
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
public function set( $values ) {
|
||||
$this -> setId( $values['Id'] );
|
||||
$this -> setPluginName( $values['Name'] );
|
||||
$this -> setPluginType( $values['Type'] );
|
||||
$this -> setPluginPermission( $values['Permission'] );
|
||||
$this -> setPluginStatus( $values['Status'] );
|
||||
$this -> setPluginInfo( json_decode( $values['Info'] ) );
|
||||
@$this -> setUpdateInfo( json_decode( $values['UpdateInfo'] ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* loads the object's attributes.
|
||||
*/
|
||||
|
||||
public function load_With_SID() {
|
||||
$dbl = new DBLayer( "lib" );
|
||||
$statement = $dbl -> executeWithoutParams( "SELECT * FROM plugins" );
|
||||
$row = $statement -> fetch();
|
||||
$this -> set( $row );
|
||||
}
|
||||
|
||||
/**
|
||||
* get plugin id attribute of the object.
|
||||
*
|
||||
* @return integer id
|
||||
*/
|
||||
public function getId() {
|
||||
return $this -> Id;
|
||||
}
|
||||
|
||||
/**
|
||||
* get plugin permission attribute of the object.
|
||||
*/
|
||||
public function getPluginPermission() {
|
||||
return $this -> plugin_permission;
|
||||
}
|
||||
|
||||
/**
|
||||
* get plugin Type attribute of the object.
|
||||
*/
|
||||
public function getPluginType() {
|
||||
return $this -> plugin_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* get plugin status attribute of the object.
|
||||
*/
|
||||
public function getPluginStatus() {
|
||||
return $this -> plugin_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* get plugin name attribute of the object.
|
||||
*/
|
||||
public function getPluginName() {
|
||||
return $this -> plugin_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* get plugin info array attribute of the object.
|
||||
*/
|
||||
public function getPluginInfo() {
|
||||
return $this -> plugin_info;
|
||||
}
|
||||
|
||||
/**
|
||||
* set plugin id attribute of the object.
|
||||
*
|
||||
* @param $s integer id
|
||||
*/
|
||||
public function setId( $s ) {
|
||||
$this -> Id = $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* set plugin permission attribute of the object.
|
||||
*
|
||||
* @param $t type of the query, set permission
|
||||
*/
|
||||
public function setPluginPermission( $t ) {
|
||||
$this -> plugin_permission = $t;
|
||||
}
|
||||
|
||||
/**
|
||||
* set plugin version attribute of the object.
|
||||
*
|
||||
* @param $q string to set plugin version
|
||||
*/
|
||||
public function setPluginType( $q ) {
|
||||
$this -> plugin_version = $q;
|
||||
}
|
||||
|
||||
/**
|
||||
* set plugin status attribute of the object.
|
||||
*
|
||||
* @param $d status code type int
|
||||
*/
|
||||
public function setPluginStatus( $d ) {
|
||||
$this -> plugin_status = $d;
|
||||
}
|
||||
|
||||
/**
|
||||
* set plugin name attribute of the object.
|
||||
*
|
||||
* @param $p_n string to set plugin name.
|
||||
*/
|
||||
public function setPluginName( $p_n ) {
|
||||
$this -> plugin_name = $p_n;
|
||||
}
|
||||
|
||||
/**
|
||||
* set plugin info attribute array of the object.
|
||||
*
|
||||
* @param $p_n array
|
||||
*/
|
||||
public function setPluginInfo( $p_n ) {
|
||||
$this -> plugin_info = $p_n;
|
||||
}
|
||||
|
||||
/**
|
||||
* functionalities for plugin updates
|
||||
*/
|
||||
|
||||
/**
|
||||
* set update info attribute array of the object.
|
||||
*
|
||||
* @param $p_n array
|
||||
*/
|
||||
public function setUpdateInfo( $p_n ) {
|
||||
$this -> update_info = $p_n;
|
||||
}
|
||||
|
||||
/**
|
||||
* get plugin info array attribute of the object.
|
||||
*/
|
||||
public function getUpdateInfo() {
|
||||
return $this -> update_info;
|
||||
}
|
||||
|
||||
/**
|
||||
* some more plugin function that requires during plugin operations
|
||||
*/
|
||||
|
||||
/**
|
||||
* function to remove a non empty directory
|
||||
*
|
||||
* @param $dir directory address
|
||||
* @return boolean
|
||||
*/
|
||||
public static function rrmdir( $dir ) {
|
||||
$result = array_diff( scandir( $dir ), array( '.', '..' ) );
|
||||
foreach( $result as $item )
|
||||
{
|
||||
if ( !@unlink( $dir . '/' . $item ) )
|
||||
Plugincache :: rrmdir( $dir . '/' . $item );
|
||||
}
|
||||
return rmdir( $dir );
|
||||
}
|
||||
|
||||
/**
|
||||
* function to unzip the zipped files
|
||||
*
|
||||
* @param $target_path path to the target zipped file
|
||||
* @param $destination path to the destination
|
||||
* @return boolean
|
||||
*/
|
||||
public static function zipExtraction( $target_path, $destination )
|
||||
{
|
||||
$zip = new ZipArchive();
|
||||
$x = $zip -> open( $target_path );
|
||||
if ( $x === true ) {
|
||||
if ( $zip -> extractTo( $destination ) )
|
||||
{
|
||||
$zip -> close();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$zip -> close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns plugin information with respect to the id
|
||||
*
|
||||
* @param id $ plugin id
|
||||
* @return field info for the plugin
|
||||
*/
|
||||
public static function pluginInfoUsingId( $id, $fieldName )
|
||||
{
|
||||
$db = new DBLayer( 'lib' );
|
||||
$sth = $db -> selectWithParameter( $fieldName, 'plugins', array( 'id' => $id ), 'Id=:id' );
|
||||
$row = $sth -> fetch();
|
||||
return $row[$fieldName];
|
||||
}
|
||||
|
||||
/**
|
||||
* function provides list of active plugins
|
||||
*
|
||||
* @return $ac_plugins list of active plugins
|
||||
*/
|
||||
public static function activePlugins()
|
||||
{
|
||||
$db = new DBLayer( 'lib' );
|
||||
$sth = $db -> selectWithParameter( 'Id', 'plugins', array( 'status' => 1 ), 'Status=:status' );
|
||||
$row = $sth -> fetchAll();
|
||||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* function to load hooks for the active plugins
|
||||
* and return the contents in the hooks in an array
|
||||
*
|
||||
* @return $content content available in hooks
|
||||
*/
|
||||
public static function loadHooks()
|
||||
{
|
||||
$content = array();
|
||||
$ac_arr = Plugincache :: activePlugins();
|
||||
foreach( $ac_arr as $key => $value )
|
||||
{
|
||||
$plugin_path = Plugincache :: pluginInfoUsingId( $value['Id'], 'FileName' );
|
||||
$template_path = json_decode( Plugincache :: pluginInfoUsingId( $value['Id'], 'Info' ) ) -> TemplatePath;
|
||||
$plugin_name = explode( '/', $plugin_path )[4];
|
||||
|
||||
// calling hooks in the $pluginName.php
|
||||
include $plugin_path . '/' . $plugin_name . '.php';
|
||||
$arr = get_defined_functions();
|
||||
|
||||
foreach( $arr['user'] as $key => $value )
|
||||
{
|
||||
if ( stristr( $value, $plugin_name ) == true )
|
||||
{
|
||||
$content['hook_info'][$plugin_name] = call_user_func( $value );
|
||||
}
|
||||
}
|
||||
// path for the template
|
||||
$content['hook_info'][$plugin_name]['TemplatePath'] = $template_path;
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* REST API class
|
||||
*
|
||||
* Request for the given url using cURL
|
||||
* and send the AccessToken for authentication
|
||||
* to make public access for the user
|
||||
*
|
||||
* @author Shubham Meena, mentored by Matthew Lagoe
|
||||
*/
|
||||
|
||||
class Rest_Api {
|
||||
|
||||
/**
|
||||
* Makes a request using cURL with authentication headers and returns the response.
|
||||
*
|
||||
* @param $url where request is to be sent
|
||||
* @param $applicationKey user generated key
|
||||
* @param $host host for the website
|
||||
* @return URL response.
|
||||
*/
|
||||
public function request( $url , $applicationKey, $host , $data )
|
||||
{
|
||||
// Check the referer is the host website
|
||||
$referer = $_SERVER['HTTP_REFERER'];
|
||||
$referer_parse = parse_url( $referer );
|
||||
if ( $referer_parse['host'] == $host ) {
|
||||
|
||||
// Initialize the cURL session with the request URL
|
||||
$session = curl_init( $url );
|
||||
|
||||
// Tell cURL to return the request data
|
||||
curl_setopt( $session, CURLOPT_RETURNTRANSFER, true );
|
||||
|
||||
// Set the HTTP request authentication headers
|
||||
$headers = array(
|
||||
'AppKey: ' . $applicationKey,
|
||||
'Timestamp: ' . date( 'Ymd H:i:s', time() ),
|
||||
'Accept: application/json',
|
||||
'Content-Type: application/json'
|
||||
);
|
||||
curl_setopt( $session, CURLOPT_HTTPHEADER, $headers );
|
||||
curl_setopt( $session, CURLOPT_CUSTOMREQUEST, "POST" );
|
||||
curl_setopt( $session, CURLOPT_POSTFIELDS, $data );
|
||||
// Execute cURL on the session handle
|
||||
$response = curl_exec( $session );
|
||||
|
||||
if ( curl_errno( $session ) ) {
|
||||
// if request is not sent
|
||||
die( 'Couldn\'t send request: ' . curl_error( $session ) );
|
||||
} else {
|
||||
// check the HTTP status code of the request
|
||||
$resultStatus = curl_getinfo( $session, CURLINFO_HTTP_CODE );
|
||||
if ( $resultStatus == 200 ) {
|
||||
// everything went fine return response
|
||||
return $response;
|
||||
|
||||
} else {
|
||||
// the request did not complete as expected. common errors are 4xx
|
||||
// (not found, bad request, etc.) and 5xx (usually concerning
|
||||
// errors/exceptions in the remote script execution)
|
||||
die( 'Request failed: HTTP status code: ' . $resultStatus );
|
||||
}
|
||||
}
|
||||
curl_close( $session );
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
PluginName = API Key Management
|
||||
Description = Provides public access to the API's by generating access tokens.
|
||||
Version = 1.0.0
|
||||
Type = automatic
|
||||
TemplatePath = ../../../ams_lib/plugins/API_key_management/templates/index.tpl
|
||||
|
||||
|
||||
|
@ -0,0 +1,213 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Global and Local Hooks for the API key Management plugin
|
||||
* Global Hooks are defined with the prefix(name of the plugin)
|
||||
* Local Hooks are defined with normal function name
|
||||
*
|
||||
* All the Global Hooks are called during the page load
|
||||
* and Local Hooks are called according to conditions
|
||||
*
|
||||
* @author shubham meena mentored by Matthew Lagoe
|
||||
*/
|
||||
|
||||
// Global variable to store the data which is
|
||||
// returned to the templates
|
||||
$return_set = array();
|
||||
|
||||
// Local variable to store data during
|
||||
// functionalities of the hooks
|
||||
$var_set = array();
|
||||
|
||||
/**
|
||||
* Display hook for api key management
|
||||
*/
|
||||
function api_key_management_hook_display()
|
||||
{
|
||||
global $return_set;
|
||||
// to display plugin name in menu bar
|
||||
$return_set['menu_display'] = 'API Key Management';
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Hook to validate the posted data
|
||||
*/
|
||||
function hook_validate( $var )
|
||||
{
|
||||
if ( isset( $var ) && !empty( $var ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Hook to set the POST variables and validate them
|
||||
*/
|
||||
function hook_variables()
|
||||
{
|
||||
global $var_set;
|
||||
global $return_set;
|
||||
|
||||
if ( hook_validate( $_POST['expDate'] ) && hook_validate( $_POST['sp_name'] ) && hook_validate( $_POST['api_type'] )
|
||||
&& hook_validate( $_POST['character_name'] ) )
|
||||
{
|
||||
$var_set['ExpiryDate'] = $_POST['expDate'];
|
||||
$var_set['FrName'] = $_POST['sp_name'];
|
||||
$var_set['UserType'] = $_POST['api_type'];
|
||||
$var_set['UserCharacter'] = $_POST['character_name'];
|
||||
$var_set['User'] = $_SESSION['user'];
|
||||
$var_set['AddedOn'] = date( "Y-m-d H:i:s" );
|
||||
$var_set['Items'] = '';
|
||||
$return_set['gen_key_validate'] = 'true';
|
||||
}
|
||||
else
|
||||
{
|
||||
$return_set['gen_key_validate'] = 'false';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Global Hook to create table of the API_key_management
|
||||
* if not created.
|
||||
* Contains the sql code
|
||||
*/
|
||||
function api_key_management_hook_create_tb()
|
||||
{
|
||||
$dbl = new DBLayer( "lib" );
|
||||
$sql = "
|
||||
--
|
||||
-- Database: `ryzom_ams_lib`
|
||||
--
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `ams_api_keys`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `ams_api_keys` (
|
||||
`SNo` int(10) NOT NULL AUTO_INCREMENT,
|
||||
`User` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`FrName` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`UserType` varchar(10) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`UserCharacter` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`ExpiryDate` date DEFAULT NULL,
|
||||
`AccessToken` text COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`AddedOn` datetime DEFAULT NULL,
|
||||
`Items` text COLLATE utf8_unicode_ci,
|
||||
PRIMARY KEY (`SNo`),
|
||||
KEY `User` (`User`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
|
||||
|
||||
--
|
||||
-- Constraints for table `ams_api_keys`
|
||||
--
|
||||
ALTER TABLE `ams_api_keys`
|
||||
ADD CONSTRAINT `ams_api_keys_ibfk_1` FOREIGN KEY (`User`) REFERENCES `ryzom_ams`.`ams_user` (`Login`);";
|
||||
|
||||
$dbl -> executeWithoutParams( $sql );
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to store data to database which is sent as post
|
||||
* method from the forms in this plugin
|
||||
* It also calls the local hook
|
||||
*/
|
||||
function api_key_management_hook_store_db()
|
||||
{
|
||||
global $var_set;
|
||||
global $return_set;
|
||||
|
||||
// if the form been submited move forward
|
||||
if ( @hook_validate( $_POST['gen_key'] ) ) {
|
||||
|
||||
// local hook to validate the POST variables
|
||||
hook_variables();
|
||||
|
||||
// if validation successfull move forward
|
||||
if ( $return_set['gen_key_validate'] == 'true' && $_GET['plugin_action'] == 'generate_key' )
|
||||
{
|
||||
// this part generated the access token
|
||||
include 'generate_key.php';
|
||||
$var_set['AccessToken'] = generate_key :: randomToken( 56, false, true, false );
|
||||
|
||||
// database connection
|
||||
$db = new DBLayer( 'lib' );
|
||||
// insert the form data to the database
|
||||
$db -> insert( 'ams_api_keys', $var_set );
|
||||
|
||||
// redirect to the the main page with success code
|
||||
// 1 refers to the successfull addition of key to the database
|
||||
header( "Location: index.php?page=layout_plugin&&name=API_key_management&&success=1" );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Global Hook to load the data from db and set it
|
||||
* into the global array to return it to the template
|
||||
*/
|
||||
function api_key_management_hook_load_db()
|
||||
{
|
||||
global $var_set;
|
||||
global $return_set;
|
||||
|
||||
$db = new DBLayer( 'lib' );
|
||||
|
||||
if ( isset( $_SESSION['user'] ) )
|
||||
{
|
||||
// returns the registered keys
|
||||
$sth = $db -> select( 'ams_api_keys', array( 'user' => $_SESSION['user'] ), 'User = :user' );
|
||||
$row = $sth -> fetchAll();
|
||||
$return_set['api_keys'] = $row;
|
||||
|
||||
// fetch the character from the array to compare
|
||||
$com = array_column( $return_set['api_keys'], 'UserCharacter' );
|
||||
|
||||
// returns the characters with respect to the user id in the ring_tool->characters
|
||||
$db = new DBLayer( 'ring' );
|
||||
$sth = $db -> selectWithParameter( 'char_name', 'characters' , array(), '1' );
|
||||
$row = $sth -> fetch();
|
||||
|
||||
// loop through the character list and remove the character if already have an api key
|
||||
$return_set['characters'] = array_diff( $row, $com );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Global Hook to update or delete the data from db
|
||||
*/
|
||||
function api_key_management_hook_update_db()
|
||||
{
|
||||
global $var_set;
|
||||
global $return_set;
|
||||
|
||||
$db = new DBLayer( 'lib' );
|
||||
if ( isset( $_GET['delete_id'] ) )
|
||||
{
|
||||
// removes the registered key using get variable which contains the id of the registered key
|
||||
$db -> delete( 'ams_api_keys', array( 'SNo' => $_GET['delete_id'] ), 'SNo = :SNo' );
|
||||
|
||||
// redirecting to the API_key_management plugins template with success code
|
||||
// 2 refers to the succssfull delete condition
|
||||
header( "Location: index.php?page=layout_plugin&&name=API_key_management&&success=2" );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Global Hook to return global variables which contains
|
||||
* the content to use in the smarty templates
|
||||
*
|
||||
* @return $return_set global array returns the template data
|
||||
*/
|
||||
function api_key_management_hook_return_global()
|
||||
{
|
||||
global $return_set;
|
||||
return $return_set;
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class for API_Key_management plugin
|
||||
* Contains the function to generate random Tokken
|
||||
*
|
||||
* @author shubham meena mentored by Matthew Lagoe
|
||||
*/
|
||||
|
||||
class generate_key {
|
||||
|
||||
/**
|
||||
* Static function to generate random token which is registerd with the user
|
||||
* to allow public access using this random token
|
||||
* It return different types of tokkens according to the parameters pass through it
|
||||
* like length , if standard chracter requires, if special character requires etc
|
||||
*/
|
||||
public static function randomToken( $len = 64, $output = 5, $standardChars = true, $specialChars = true, $chars = array() ) {
|
||||
$out = '';
|
||||
$len = intval( $len );
|
||||
$outputMap = array( 1 => 2, 2 => 8, 3 => 10, 4 => 16, 5 => 10 );
|
||||
if ( !is_array( $chars ) ) {
|
||||
$chars = array_unique( str_split( $chars ) );
|
||||
}
|
||||
if ( $standardChars ) {
|
||||
$chars = array_merge( $chars, range( 48, 57 ), range( 65, 90 ), range( 97, 122 ) );
|
||||
}
|
||||
if ( $specialChars ) {
|
||||
$chars = array_merge( $chars, range( 33, 47 ), range( 58, 64 ), range( 91, 96 ), range( 123, 126 ) );
|
||||
}
|
||||
array_walk( $chars, function( &$val ) {
|
||||
if ( !is_int( $val ) ) {
|
||||
$val = ord( $val ); }
|
||||
}
|
||||
);
|
||||
if ( is_int( $len ) ) {
|
||||
while ( $len ) {
|
||||
$tmp = ord( openssl_random_pseudo_bytes( 1 ) );
|
||||
if ( in_array( $tmp, $chars ) ) {
|
||||
if ( !$output || !in_array( $output, range( 1, 5 ) ) || $output == 3 || $output == 5 ) {
|
||||
$out .= ( $output == 3 ) ? $tmp : chr( $tmp );
|
||||
}
|
||||
else {
|
||||
$based = base_convert( $tmp, 10, $outputMap[$output] );
|
||||
$out .= ( ( ( $output == 1 ) ? '00' : ( ( $output == 4 ) ? '0x' : '' ) ) . ( ( $output == 2 ) ? sprintf( '%03d', $based ) : $based ) );
|
||||
}
|
||||
$len--;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ( empty( $out ) ) ? false : $out;
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
<div class="row-fluid">
|
||||
<div class="box span12">
|
||||
<div class="box-header well" data-original-title>
|
||||
<h2><i class="icon-user"></i> API KEY management</h2>
|
||||
<div class="box-icon">
|
||||
<a href="#" class="btn btn-setting btn-round"><i class="icon-cog"></i></a>
|
||||
<a href="#" class="btn btn-minimize btn-round"><i class="icon-chevron-up"></i></a>
|
||||
<a href="#" class="btn btn-close btn-round"><i class="icon-remove"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box span4">
|
||||
<div class="box-header well" data-original-title="">
|
||||
<h2><i class="icon-th"></i> Generate Access Key</h2>
|
||||
<div class="box-icon">
|
||||
<a href="#" class="btn btn-minimize btn-round"><i class="icon-chevron-up"></i></a>
|
||||
<a href="#" class="btn btn-close btn-round"><i class="icon-remove"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content">
|
||||
<div class="row-fluid">
|
||||
<form id="generateKey" class="form-vertical" method="post" action="index.php?page=layout_plugin&&name={$arrkey}">
|
||||
<legend>Generate Key</legend>
|
||||
|
||||
<div class="control-group ">
|
||||
<label class="control-label">Expirey:</label>
|
||||
<div class="controls">
|
||||
<div class="input-prepend">
|
||||
<span style="margin-left:5px;" class="add-on"><i class="icon-time"></i></span>
|
||||
<input type="text" value="Expiry Date" placeholder="Expiry Date" name="expDate" id="expDate" class="input-xlarge">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label"></label>
|
||||
<div class="controls">
|
||||
<button type="submit" name="gen_key" value="true" class="btn btn-primary" style="margin-left:5px; margin-top:10px;">Generate Key</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/span-->
|
||||
</div><!--/span-->
|
||||
</div><!--/row-->
|
||||
|
||||
|
@ -0,0 +1,133 @@
|
||||
{block name=content}
|
||||
|
||||
{if isset($smarty.get.plugin_action) and $smarty.get.plugin_action eq 'generate_key'}
|
||||
<div class="row-fluid">
|
||||
<div class="box span12">
|
||||
<div class="box-header well" data-original-title>
|
||||
<h2><i class="icon-user"></i> API KEY management</h2>
|
||||
<div class="box-icon">
|
||||
<a href="#" class="btn btn-setting btn-round"><i class="icon-cog"></i></a>
|
||||
<a href="#" class="btn btn-minimize btn-round"><i class="icon-chevron-up"></i></a>
|
||||
<a href="#" class="btn btn-close btn-round"><i class="icon-remove"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box span4">
|
||||
<div class="box-header well" data-original-title="">
|
||||
<h2><i class="icon-th"></i> Generate Access Key</h2>
|
||||
<div class="box-icon">
|
||||
<a href="#" class="btn btn-minimize btn-round"><i class="icon-chevron-up"></i></a>
|
||||
<a href="#" class="btn btn-close btn-round"><i class="icon-remove"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content">
|
||||
<div class="row-fluid">
|
||||
<form id="generateKey" class="form-vertical" method="post" action="index.php?page=layout_plugin&&name={$arrkey}&&plugin_action=generate_key">
|
||||
<legend>Generate Key</legend>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Name:</label>
|
||||
<div class="controls">
|
||||
<div class="input-prepend">
|
||||
<span class="add-on" style="margin-left:5px;"><i class="icon-user"></i></span>
|
||||
<input type="text" class="input-xlarge" id="sp_name" name="sp_name" placeholder="Your friendly name">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Type:</label>
|
||||
<div class="controls">
|
||||
<select name="api_type">
|
||||
<option value="Character">Character</option>
|
||||
<option value="Corporation">Corporation</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">Character:</label>
|
||||
<div class="controls">
|
||||
<select name="character_name">
|
||||
{foreach from=$hook_info.API_key_management.characters item=element}
|
||||
<option value="{$element}">{$element}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group ">
|
||||
<label class="control-label">Expirey:</label>
|
||||
<div class="controls">
|
||||
<div class="input-prepend">
|
||||
<span style="margin-left:5px;" class="add-on"><i class="icon-time"></i></span>
|
||||
<input type="text" placeholder="Expiry Date" name="expDate" id="expDate" class="input-xlarge">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label"></label>
|
||||
<div class="controls">
|
||||
<button type="submit" name="gen_key" value="true" class="btn btn-primary" style="margin-left:5px; margin-top:10px;">Generate Key</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/span-->
|
||||
</div><!--/span-->
|
||||
</div><!--/row-->
|
||||
{else}
|
||||
<div class="row-fluid">
|
||||
<div class="box span12">
|
||||
<div class="box-header well" data-original-title>
|
||||
<h2><i class="icon-user"></i> API KEY management</h2>
|
||||
<div class="box-icon">
|
||||
<a href="#" class="btn btn-setting btn-round"><i class="icon-cog"></i></a>
|
||||
<a href="#" class="btn btn-minimize btn-round"><i class="icon-chevron-up"></i></a>
|
||||
<a href="#" class="btn btn-close btn-round"><i class="icon-remove"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{if isset($hook_info.API_key_management['gen_key_validate']) and $hook_info.API_key_management['gen_key_validate'] eq 'false' }<div class="alert alert-error"><p>Please enter all the fields</p></div>{/if}
|
||||
{if isset($smarty.get.success) and $smarty.get.success eq '1'}<div class="alert alert-error"><p>Key added successfully</p></div>{/if}
|
||||
{if isset($smarty.get.success) and $smarty.get.success eq '2'}<div class="alert alert-error"><p>Key deleted successfully</p></div>{/if}
|
||||
<center>
|
||||
<a href="index.php?page=layout_plugin&&name=API_key_management&&plugin_action=generate_key"><button class="btn btn-primary btn-large dropdown-toggle">Generate key</button></a>
|
||||
</center>
|
||||
<div class="box-content">
|
||||
<div class="row-fluid">
|
||||
<center><p>All the keys you have generated will be shown and you can customize from here.</p></center>
|
||||
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Character</th>
|
||||
<th>Access Key</th>
|
||||
<th>Expires</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{foreach from=$hook_info.API_key_management.api_keys item=element}
|
||||
<tr>
|
||||
<td class="center">{$element.FrName}</td>
|
||||
<td class="center">{$element.UserType}</td>
|
||||
<td class="center">{$element.UserCharacter}</td>
|
||||
<td class="center">{$element.AccessToken}</td>
|
||||
<td class="center">{$element.ExpiryDate}</td>
|
||||
<td><a href="index.php?page=layout_plugin&&name={$arrkey}&&delete_id={$element.SNo}"><button class="btn btn-primary btn-large">Delete</button></a>
|
||||
</tr>
|
||||
{/foreach}
|
||||
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
</div><!--/span-->
|
||||
</div><!--/span-->
|
||||
</div><!--/row-->
|
||||
{/if}
|
||||
{/block}
|
@ -0,0 +1,8 @@
|
||||
PluginName = Achievements
|
||||
Description = Returns the achivements of a user with respect to the character =.
|
||||
Version = 1.0.0
|
||||
TemplatePath = ../../../ams_lib/plugins/Achievements/templates/index.tpl
|
||||
Type = Manual
|
||||
|
||||
|
||||
|
@ -0,0 +1,200 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Global and Local Hooks for the Achievements plugin
|
||||
* Global Hooks are defined with the prefix(name of the plugin)
|
||||
* Local Hooks are defined with normal function name
|
||||
*
|
||||
* All the Global Hooks are called during the page load
|
||||
* and Local Hooks are called according to conditions
|
||||
*
|
||||
* Here, we request to the Achievements url using REST
|
||||
* to get the contents and will display with this plugin.
|
||||
*
|
||||
* @author shubham meena mentored by Matthew Lagoe
|
||||
*/
|
||||
|
||||
|
||||
// Global variable to store the data which is
|
||||
// returned to the templates
|
||||
$return_set = array();
|
||||
|
||||
// Local variable to store data during
|
||||
// functionalities of the hooks
|
||||
$var_set = array();
|
||||
|
||||
/**
|
||||
* Display hook for Achievements plugin
|
||||
*/
|
||||
function achievements_hook_display()
|
||||
{
|
||||
global $return_set;
|
||||
// to display plugin name in menu bar
|
||||
$return_set['menu_display'] = 'Achievements';
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Hook to get database content
|
||||
* which is called by the global hook
|
||||
* by passing a parameter
|
||||
*
|
||||
* This hook returns the api keys registerd with
|
||||
* the logged in user
|
||||
*
|
||||
* @param $data array with respective information
|
||||
* @return $row extracted db content wrt $data
|
||||
*/
|
||||
function hook_get_db_content( $data )
|
||||
{
|
||||
$db = new DBLayer( 'lib' );
|
||||
$sth = $db -> select( 'ams_api_keys', $data , 'User = :User AND UserCharacter = :UserCharacter' );
|
||||
$row = $sth -> fetchAll();
|
||||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Hook to get database content
|
||||
* which is called by the global hook
|
||||
* by passing a parameter
|
||||
*
|
||||
* This hook returns the id of the character
|
||||
* whose achivements we have to get
|
||||
*
|
||||
* @param $data array with respective information
|
||||
* @return $row extracted db content wrt $data
|
||||
*/
|
||||
function hook_get_char_id( $data )
|
||||
{
|
||||
// returns the character id with respect to the character name in the ring_tool->characters
|
||||
$db = new DBLayer( 'ring' );
|
||||
$sth = $db -> selectWithParameter( 'char_id', 'characters' , array( 'char_name' => $data ), 'char_name=:char_name' );
|
||||
$row = $sth -> fetch();
|
||||
return $row['char_id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Hook to get database content
|
||||
* which is called by the global hook
|
||||
* by passing a parameter
|
||||
*
|
||||
* Hook to get the player stats of the character
|
||||
*
|
||||
* @param $data array with respective information
|
||||
* @return $row extracted db content wrt $data
|
||||
*/
|
||||
function hook_get_player_stat( $data )
|
||||
{
|
||||
// returns the character id with respect to the character name in the ring_tool->characters
|
||||
$db = new DBLayer( 'webig' );
|
||||
$sth = $db -> select( 'players' , array( 'name' => $data ), 'name=:name' );
|
||||
$row = $sth -> fetch();
|
||||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Hook to set variables which contains
|
||||
* the content to use during the plugin functionality.
|
||||
*/
|
||||
function hook_variable_set()
|
||||
{
|
||||
global $return_set;
|
||||
global $var_set;
|
||||
if ( isset( $_POST['Character'] ) && !empty( $_POST['Character'] ) )
|
||||
{
|
||||
$var_set['character'] = $_POST['Character'];
|
||||
|
||||
// get char id from ring_open table
|
||||
if ( $var_set['character'] != 'All Characters' )
|
||||
{
|
||||
$var_set['char_id'] = hook_get_char_id( $var_set['character'] );
|
||||
|
||||
}
|
||||
|
||||
// get db content for variable set
|
||||
$row = hook_get_db_content( array( 'User' => $_SESSION['user'], 'UserCharacter' => $var_set['character'] ) );
|
||||
|
||||
// access key automatically taken from the database wrt user and character
|
||||
@$var_set['app_key'] = $row['AccessToken'];
|
||||
|
||||
// here you can set the host where this plugin is set
|
||||
$var_set['host'] = 'localhost';
|
||||
|
||||
// here we get the stats of the character
|
||||
$ref_set = hook_get_player_stat( $var_set['character'] );
|
||||
|
||||
// here we have set items that are required to get the achivements
|
||||
// these are player stats from webig->players table
|
||||
@$var_set['items'] = json_encode( array( 'dev_shard' => $ref_set['dev_shard'] , 'name' => $ref_set['name'] , 'cid' => $ref_set['cid'] , 'lang' => 'en' , 'translater_mode' => '', 'last_played_date' => $ref_set['last_login'] ) );
|
||||
|
||||
// url where we have to make request for achievements
|
||||
// it sends get parameter search(what to search) and format(in which format data exchange takes place)
|
||||
$var_set['url'] = 'http://localhost6/?search=achievements&&format=json';
|
||||
}
|
||||
else
|
||||
{
|
||||
$return_set['no_char'] = "Please Generate key for a character before requesting for achievements";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Global Hook to interact with the REST api
|
||||
* Pass the variables in the REST object to
|
||||
* make request
|
||||
*
|
||||
* variables REST object expects
|
||||
* url --> on which request is to be made
|
||||
* appkey --> app key for authentication
|
||||
* host --> host from which request have been sent
|
||||
*
|
||||
* @return $return_set global array returns the template data
|
||||
*/
|
||||
function achievements_hook_call_rest()
|
||||
{
|
||||
// defined the variables
|
||||
global $var_set;
|
||||
global $return_set;
|
||||
|
||||
if ( isset( $_POST['get_data'] ) )
|
||||
{
|
||||
hook_variable_set();
|
||||
// here we make the REST connection
|
||||
$rest_api = new Rest_Api();
|
||||
$ach_data = $rest_api -> request( $var_set['url'], $var_set['app_key'], $var_set['host'], $var_set['items'] );
|
||||
// here we store the response we get from the server
|
||||
$return_set['char_achievements'] = $ach_data ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Global Hook to return global variables which contains
|
||||
* the content to use in the smarty templates extracted from
|
||||
* the database
|
||||
*
|
||||
* @return $return_set global array returns the template data
|
||||
*/
|
||||
function achievements_hook_get_db()
|
||||
{
|
||||
global $return_set;
|
||||
|
||||
if ( isset( $_SESSION['user'] ) )
|
||||
{
|
||||
$db = new DBLayer( 'lib' );
|
||||
|
||||
// getting content for selecting characters
|
||||
$sth = $db -> selectWithParameter( 'UserCharacter', 'ams_api_keys', array( 'User' => $_SESSION['user'] ) , 'User = :User' );
|
||||
$row = $sth -> fetch();
|
||||
$return_set['Character'] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Global Hook to return global variables which contains
|
||||
* the content to use in the smarty templates
|
||||
*
|
||||
* @return $return_set global array returns the template data
|
||||
*/
|
||||
function achievements_hook_return_global()
|
||||
{
|
||||
global $return_set;
|
||||
return $return_set;
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
{block name=content}
|
||||
|
||||
{if isset($smarty.get.plugin_action) and $smarty.get.plugin_action eq 'get_achievements'}
|
||||
<div class="row-fluid">
|
||||
<div class="box span12">
|
||||
<div class="box-header well" data-original-title>
|
||||
<h2><i class="icon-user"></i> Achievements</h2>
|
||||
<div class="box-icon">
|
||||
<a href="#" class="btn btn-setting btn-round"><i class="icon-cog"></i></a>
|
||||
<a href="#" class="btn btn-minimize btn-round"><i class="icon-chevron-up"></i></a>
|
||||
<a href="#" class="btn btn-close btn-round"><i class="icon-remove"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content">
|
||||
{if isset($hook_info.Achievements.no_char)}<div class="alert alert-error"><p>{$hook_info.Achievements.no_char}</p></div>{/if}
|
||||
<div class="row-fluid">
|
||||
{$hook_info.Achievements.char_achievements}
|
||||
</div>
|
||||
</div><!--/span-->
|
||||
</div><!--/span-->
|
||||
</div><!--/row-->
|
||||
{else}
|
||||
<div class="row-fluid">
|
||||
<div class="box span12">
|
||||
<div class="box-header well" data-original-title>
|
||||
<h2><i class="icon-user"></i> Achievements</h2>
|
||||
<div class="box-icon">
|
||||
<a href="#" class="btn btn-setting btn-round"><i class="icon-cog"></i></a>
|
||||
<a href="#" class="btn btn-minimize btn-round"><i class="icon-chevron-up"></i></a>
|
||||
<a href="#" class="btn btn-close btn-round"><i class="icon-remove"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box span4">
|
||||
<div class="box-header well" data-original-title="">
|
||||
<h2><i class="icon-th"></i> Select your Character</h2>
|
||||
<div class="box-icon">
|
||||
<a href="#" class="btn btn-minimize btn-round"><i class="icon-chevron-up"></i></a>
|
||||
<a href="#" class="btn btn-close btn-round"><i class="icon-remove"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content">
|
||||
<div class="row-fluid">
|
||||
<form id="generateKey" class="form-vertical" method="post" action="index.php?page=layout_plugin&&name={$arrkey}&&plugin_action=get_achievements">
|
||||
|
||||
<div class="control-group">
|
||||
<div class="control-group">
|
||||
<label class="control-label">Character:</label>
|
||||
<div class="controls">
|
||||
<select name="Character">
|
||||
{foreach from=$hook_info.Achievements.Character item=element}
|
||||
<option value="{$element}">{$element}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label"></label>
|
||||
<div class="controls">
|
||||
<button type="submit" name="get_data" value="true" class="btn btn-primary" style="margin-left:5px; margin-top:10px;">Get Achievements</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/span-->
|
||||
</div><!--/span-->
|
||||
</div><!--/row-->
|
||||
|
||||
{/if}
|
||||
{/block}
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* This function is used in activating plugins.
|
||||
*
|
||||
* @author Shubham Meena, mentored by Matthew Lagoe
|
||||
*/
|
||||
function activate_plugin() {
|
||||
|
||||
// if logged in
|
||||
if ( WebUsers :: isLoggedIn() ) {
|
||||
|
||||
if ( isset( $_GET['id'] ) )
|
||||
{
|
||||
// id of plugin to delete
|
||||
$id = filter_var( $_GET['id'], FILTER_SANITIZE_FULL_SPECIAL_CHARS );
|
||||
$db = new DBLayer( 'lib' );
|
||||
$result = $db -> update( "plugins", array( 'Status' => '1' ), "Id = $id" );
|
||||
if ( $result )
|
||||
{
|
||||
header( "Location: index.php?page=plugins&result=3" );
|
||||
exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
header( "Location: index.php?page=plugins&result=4" );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
header( "Location: index.php?page=plugins&result=4" );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* This function is used in deactivating plugins.
|
||||
*
|
||||
* @author Shubham Meena, mentored by Matthew Lagoe
|
||||
*/
|
||||
function deactivate_plugin() {
|
||||
|
||||
// if logged in
|
||||
if ( WebUsers :: isLoggedIn() ) {
|
||||
|
||||
|
||||
if ( isset( $_GET['id'] ) )
|
||||
{
|
||||
// id of plugin to delete
|
||||
$id = filter_var( $_GET['id'], FILTER_SANITIZE_FULL_SPECIAL_CHARS );
|
||||
$db = new DBLayer( 'lib' );
|
||||
$result = $db -> update( "plugins", array( 'Status' => '0' ), "Id = $id" );
|
||||
if ( $result )
|
||||
{
|
||||
header( "Location: index.php?page=plugins&result=5" );
|
||||
exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
header( "Location: index.php?page=plugins&result=6" );
|
||||
exit;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
header( "Location: index.php?page=plugins&result=6" );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* This function is used in deleting plugins.
|
||||
*
|
||||
* It removes the plugin from the codebase.
|
||||
*
|
||||
* @author Shubham Meena, mentored by Matthew Lagoe
|
||||
*/
|
||||
function delete_plugin() {
|
||||
|
||||
// if logged in
|
||||
if ( WebUsers :: isLoggedIn() ) {
|
||||
|
||||
if ( isset( $_GET['id'] ) )
|
||||
{
|
||||
// id of plugin to delete after filtering
|
||||
$id = filter_var( $_GET['id'], FILTER_SANITIZE_FULL_SPECIAL_CHARS );
|
||||
|
||||
$db = new DBLayer( 'lib' );
|
||||
$sth = $db -> selectWithParameter( "FileName", "plugins", array( 'id' => $id ), "Id=:id" );
|
||||
$name = $sth -> fetch();
|
||||
|
||||
if ( is_dir( "$name[FileName]" ) )
|
||||
{
|
||||
// removing plugin directory from the code base
|
||||
if ( Plugincache::rrmdir( "$name[FileName]" ) )
|
||||
{
|
||||
$db -> delete( 'plugins', array( 'id' => $id ), "Id=:id" );
|
||||
|
||||
header( "Location: index.php?page=plugins&result=2" );
|
||||
exit;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
header( "Location: index.php?page=plugins&result=0" );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
header( "Location: index.php?page=plugins&result=0" );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,306 @@
|
||||
<?php
|
||||
/**
|
||||
* This function is used in installing plugins
|
||||
* It performs validation check for the compressed plugin
|
||||
* then extract in plugin folder to get the info
|
||||
*
|
||||
* @author Shubham Meena, mentored by Matthew Lagoe
|
||||
*/
|
||||
function install_plugin() {
|
||||
|
||||
$result = array();
|
||||
|
||||
// if logged in
|
||||
if ( WebUsers :: isLoggedIn() ) {
|
||||
|
||||
// path of temporary folder for storing files
|
||||
$temp_path = "../../ams_lib/temp";
|
||||
|
||||
// create a temp directory if not exist
|
||||
// temp folder where we first store all uploaded plugins before install
|
||||
if ( !file_exists( "$temp_path" ) )
|
||||
{
|
||||
mkdir( $temp_path );
|
||||
}
|
||||
|
||||
// checking the server if file is uploaded or not
|
||||
if ( ( isset( $_FILES["file"] ) ) && ( $_FILES["file"]["size"] > 0 ) )
|
||||
{
|
||||
$fileName = $_FILES["file"]["name"]; //the files name takes from the HTML form
|
||||
$fileTmpLoc = $_FILES["file"]["tmp_name"]; //file in the PHP tmp folder
|
||||
$dir = trim( $_FILES["file"]["name"], ".zip" );
|
||||
$target_path = "../../ams_lib/plugins/$dir"; //path in which the zip extraction is to be done
|
||||
$destination = "../../ams_lib/plugins/";
|
||||
|
||||
// scanning plugin folder if plugin with same name is already exists or not
|
||||
$x = checkForUpdate( $dir, $destination, $fileTmpLoc, $temp_path );
|
||||
if ( $x == '1' )
|
||||
{
|
||||
echo "update found";
|
||||
exit();
|
||||
}
|
||||
else if ( $x == '2' )
|
||||
{
|
||||
echo "Plugin already exists with same name .";
|
||||
exit();
|
||||
}
|
||||
else if ( $x == '3' )
|
||||
{
|
||||
echo "Update info is not present in the update";
|
||||
exit();
|
||||
}
|
||||
|
||||
|
||||
// checking for the command to install plugin is given or not
|
||||
if ( !isset( $_POST['install_plugin'] ) )
|
||||
{
|
||||
if ( ( $_FILES["file"]["type"] == 'application/zip' ) )
|
||||
{
|
||||
if ( move_uploaded_file( $fileTmpLoc, $temp_path . "/" . $fileName ) ) {
|
||||
echo "$fileName upload is complete.</br>" . "<button type='submit' class='btn btn-primary' style='margin-left:5px; margin-top:10px;' name='install_plugin'>Install Plugin</button></br>";
|
||||
exit();
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "Error in uploading file.";
|
||||
exit();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "Please select a file with .zip extension to upload.";
|
||||
exit();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// calling function to unzip archives
|
||||
if ( zipExtraction( $temp_path . "/" . $fileName , $destination ) )
|
||||
{
|
||||
if ( file_exists( $target_path . "/.info" ) )
|
||||
{
|
||||
$result = readPluginFile( ".info", $target_path );
|
||||
|
||||
// sending all info to the database
|
||||
$install_result = array();
|
||||
$install_result['FileName'] = $target_path;
|
||||
$install_result['Name'] = $result['PluginName'];
|
||||
$install_result['Type'] = $result['Type'];
|
||||
if ( Ticket_User :: isMod( unserialize( $_SESSION['ticket_user'] ) ) )
|
||||
{
|
||||
$install_result['Permission'] = 'admin';
|
||||
}
|
||||
else
|
||||
{
|
||||
$install_result['Permission'] = 'user';
|
||||
}
|
||||
|
||||
$install_result['Info'] = json_encode( $result );
|
||||
|
||||
// connection with the database
|
||||
$dbr = new DBLayer( "lib" );
|
||||
$dbr -> insert( "plugins", $install_result );
|
||||
|
||||
// if everything is successfull redirecting to the plugin template
|
||||
header( "Location: index.php?page=plugins&result=1" );
|
||||
exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
// file .info not exists
|
||||
rmdir( $target_path );
|
||||
header( "Location: index.php?page=install_plugin&result=2" );
|
||||
exit;
|
||||
}
|
||||
|
||||
} else
|
||||
{
|
||||
// extraction failed
|
||||
header( "Location: index.php?page=install_plugin&result=0" );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "Please Browse for a file before clicking the upload button";
|
||||
exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* function to unzip the zipped files
|
||||
*
|
||||
* @param $target_path path to the target zipped file
|
||||
* @param $destination path to the destination
|
||||
* @return boolean
|
||||
*/
|
||||
function zipExtraction( $target_path, $destination )
|
||||
{
|
||||
$zip = new ZipArchive();
|
||||
$x = $zip -> open( $target_path );
|
||||
if ( $x === true ) {
|
||||
if ( $zip -> extractTo( $destination ) )
|
||||
{
|
||||
$zip -> close();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$zip -> close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* function to read text files and extract
|
||||
* the information into an array
|
||||
*
|
||||
* -----------------------------------------------------------
|
||||
* format:
|
||||
* -----------------------------------------------------------
|
||||
* PluginName = Name of the plugin
|
||||
* Version = version of the plugin
|
||||
* Type = type of the plugin
|
||||
* Description = Description of the plugin ,it's functionality
|
||||
* -----------------------------------------------------------
|
||||
*
|
||||
* reads only files with name .info
|
||||
*
|
||||
* @param $fileName file to read
|
||||
* @param $targetPath path to the folder containing .info file
|
||||
* @return array containing above information in array(value => key)
|
||||
*/
|
||||
function readPluginFile( $fileName, $target_path )
|
||||
{
|
||||
$file_handle = fopen( $target_path . "/" . $fileName, "r" );
|
||||
$result = array();
|
||||
while ( !feof( $file_handle ) ) {
|
||||
$line_of_text = fgets( $file_handle );
|
||||
$parts = array_map( 'trim', explode( '=', $line_of_text, 2 ) );
|
||||
@$result[$parts[0]] = $parts[1];
|
||||
}
|
||||
fclose( $file_handle );
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* function to check for updates or
|
||||
* if the same plugin already exists
|
||||
* also, if the update founds ,check for the update info in the .info file.
|
||||
* Update is saved in the temp direcotry with pluginName_version.zip
|
||||
*
|
||||
* @param $fileName file which is uploaded in .zip extension
|
||||
* @param $findPath where we have to look for the installed plugins
|
||||
* @param $tempFile path for the temporary file
|
||||
* @param $tempPath path where we have to store the update
|
||||
* @return 2 if plugin already exists and update not found
|
||||
* @return 3 if update info tag not found in .info file
|
||||
*/
|
||||
function checkForUpdate( $fileName, $findPath, $tempFile, $tempPath )
|
||||
{
|
||||
// check for plugin if exists
|
||||
$file = scandir( $findPath );
|
||||
foreach( $file as $key => $value )
|
||||
{
|
||||
if ( strcmp( $value, $fileName ) == 0 )
|
||||
{
|
||||
if ( !file_exists( $tempPath . "/test" ) )
|
||||
{
|
||||
mkdir( $tempPath . "/test" );
|
||||
}
|
||||
|
||||
// extracting the update
|
||||
if ( zipExtraction( $tempFile, $tempPath . "/test/" ) )
|
||||
{
|
||||
$result = readPluginFile( ".info", $tempPath . "/test/" . $fileName );
|
||||
|
||||
// check for the version for the plugin
|
||||
$db = new DBLayer( "lib" );
|
||||
$sth = $db -> select( "plugins", array( 'Name' => $result['PluginName'] ), "Name = :Name" );
|
||||
$info = $sth -> fetch();
|
||||
$info['Info'] = json_decode( $info['Info'] );
|
||||
|
||||
// the two versions from main plugin and the updated part
|
||||
$new_version = explode( '.', $result['Version'] );
|
||||
$pre_version = explode( '.', $info['Info'] -> Version );
|
||||
|
||||
// For all plugins we have used semantic versioning
|
||||
// Format: X.Y.Z ,X->Major, Y->Minor, Z->Patch
|
||||
// change in the X Y & Z values refer the type of change in the plugin.
|
||||
// for initial development only Minor an Patch MUST be 0.
|
||||
// if there is bug fix then there MUST be an increment in the Z value.
|
||||
// if there is change in the functionality or addition of new functionality
|
||||
// then there MUST be an increment in the Y value.
|
||||
// When there is increment in the X value , Y and Z MUST be 0.
|
||||
// comparing if there is some change
|
||||
if ( !array_diff( $new_version , $pre_version ) )
|
||||
{
|
||||
// removing the uploaded file
|
||||
Plugincache :: rrmdir( $tempPath . "/test/" . $fileName );
|
||||
return '2'; //plugin already exists
|
||||
}
|
||||
else
|
||||
{
|
||||
// check for update info if exists
|
||||
if ( !array_key_exists( 'UpdateInfo', $result ) )
|
||||
{
|
||||
return '3'; //update info tag not found
|
||||
}
|
||||
else
|
||||
{
|
||||
// check if update already exists
|
||||
if ( pluginUpdateExists( $info['Id'], $tempPath . "/" . trim( $fileName, ".zip" ) . "_" . $result['Version'] . ".zip" ) )
|
||||
{
|
||||
echo "Update already exists";
|
||||
exit;
|
||||
}
|
||||
else {
|
||||
// removing the preivous update
|
||||
$dbr = new DBLayer( "lib" );
|
||||
$dbr -> delete( "updates", array( 'id' => $info['Id'] ), "PluginId=:id" );
|
||||
// storing update in the temp directory
|
||||
// format of update save
|
||||
if ( move_uploaded_file( $tempFile, $tempPath . "/" . trim( $fileName, ".zip" ) . "_" . $result['Version'] . ".zip" ) ) {
|
||||
// setting update information in the database
|
||||
$update['PluginId'] = $info['Id'];
|
||||
$update['UpdatePath'] = $tempPath . "/" . trim( $fileName, ".zip" ) . "_" . $result['Version'] . ".zip";
|
||||
$update['UpdateInfo'] = json_encode( $result );
|
||||
$dbr -> insert( "updates", $update );
|
||||
header( "Location: index.php?page=plugins&result=7" );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to check for the update of a plugin already exists
|
||||
*
|
||||
* @param $pluginId id of the plugin for which update is available
|
||||
* @param $updatePath path of the new update
|
||||
* @return boolean if update for a plugin already exists or
|
||||
* if update of same version is uploading
|
||||
*/
|
||||
function PluginUpdateExists( $pluginId, $updatePath )
|
||||
{
|
||||
$db = new DBLayer( 'lib' );
|
||||
$sth = $db -> selectWithParameter( "UpdatePath", "updates", array( 'pluginid' => $pluginId ), "PluginId=:pluginid" );
|
||||
$row = $sth -> fetch();
|
||||
if ( $updatePath == $row['UpdatePath'] )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
rmdir( $row['UpdatePath'] );
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* This function is used in installing updates for plugins.
|
||||
*
|
||||
* @author Shubham Meena, mentored by Matthew Lagoe
|
||||
*/
|
||||
function update_plugin() {
|
||||
|
||||
// if logged in
|
||||
if ( WebUsers :: isLoggedIn() ) {
|
||||
|
||||
if ( isset( $_GET['id'] ) )
|
||||
{
|
||||
// id of plugin to delete
|
||||
$id = filter_var( $_GET['id'], FILTER_SANITIZE_FULL_SPECIAL_CHARS );
|
||||
$db = new DBLayer( 'lib' );
|
||||
$sth = $db -> executeWithoutParams( "SELECT * FROM plugins INNER JOIN updates ON plugins.Id=updates.PluginId Where plugins.Id=$id" );
|
||||
$row = $sth -> fetch();
|
||||
|
||||
// replacing update in the database
|
||||
Plugincache :: rrmdir( $row['FileName'] );
|
||||
Plugincache :: zipExtraction( $row['UpdatePath'], rtrim( $row['FileName'], strtolower( $row['Name'] ) ) );
|
||||
|
||||
$db -> update( "plugins", array( 'Info' => $row['UpdateInfo'] ), "Id=$row[Id]" );
|
||||
|
||||
// deleting the previous update
|
||||
$db -> delete( "updates", array( 'id' => $row['s.no'] ), "s.no=:id" );
|
||||
|
||||
header( "Location: index.php?page=plugins&result=8" );
|
||||
exit;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* function plugins to get
|
||||
* plugins from the Database using pagination object
|
||||
*
|
||||
* @author shubham meena mentored by Matthew Lagoe
|
||||
*/
|
||||
|
||||
function plugins()
|
||||
{
|
||||
if ( Ticket_User :: isMod( unserialize( $_SESSION['ticket_user'] ) ) ) {
|
||||
|
||||
$pagination = new Pagination( "SELECT * FROM plugins", "lib", 5, "Plugincache" );
|
||||
$pageResult['plug'] = Gui_Elements :: make_table( $pagination -> getElements(), Array( "getId", "getPluginName", "getPluginType", "getPluginPermission", "getPluginStatus", "getPluginInfo" ), Array( "id", "plugin_name", "plugin_type", "plugin_permission", "plugin_status", "plugin_info" ) );
|
||||
$pageResult['links'] = $pagination -> getLinks( 5 );
|
||||
$pageResult['lastPage'] = $pagination -> getLast();
|
||||
$pageResult['currentPage'] = $pagination -> getCurrent();
|
||||
|
||||
global $INGAME_WEBPATH;
|
||||
$pageResult['ingame_webpath'] = $INGAME_WEBPATH;
|
||||
|
||||
// check if shard is online
|
||||
try {
|
||||
$dbs = new DBLayer( "shard" );
|
||||
$pageResult['shard'] = "online";
|
||||
}
|
||||
catch( PDOException $e ) {
|
||||
$pageResult['shard'] = "offline";
|
||||
}
|
||||
return( $pageResult );
|
||||
} else {
|
||||
// ERROR: No access!
|
||||
$_SESSION['error_code'] = "403";
|
||||
header( "Location: index.php?page=error" );
|
||||
exit;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* function plugins_update to get
|
||||
* plugins updates from the Database using pagination object
|
||||
*
|
||||
* @author shubham meena mentored by Matthew Lagoe
|
||||
*/
|
||||
|
||||
function plugins_update()
|
||||
{
|
||||
if ( Ticket_User :: isMod( unserialize( $_SESSION['ticket_user'] ) ) ) {
|
||||
$pagination = new Pagination( "SELECT * FROM plugins INNER JOIN updates ON plugins.Id=updates.PluginId", "lib", 5, "Plugincache" );
|
||||
$pageResult['plug'] = Gui_Elements :: make_table( $pagination -> getElements(), Array( "getId", "getPluginName", "getPluginInfo", "getUpdateInfo" ), Array( "id", "plugin_name", "plugin_info", "update_info" ) );
|
||||
$pageResult['links'] = $pagination -> getLinks( 5 );
|
||||
$pageResult['lastPage'] = $pagination -> getLast();
|
||||
$pageResult['currentPage'] = $pagination -> getCurrent();
|
||||
|
||||
global $INGAME_WEBPATH;
|
||||
$pageResult['ingame_webpath'] = $INGAME_WEBPATH;
|
||||
|
||||
// check if shard is online
|
||||
try {
|
||||
$dbs = new DBLayer( "shard" );
|
||||
$pageResult['shard'] = "online";
|
||||
}
|
||||
catch( PDOException $e ) {
|
||||
$pageResult['shard'] = "offline";
|
||||
}
|
||||
return( $pageResult );
|
||||
} else {
|
||||
// ERROR: No access!
|
||||
$_SESSION['error_code'] = "403";
|
||||
header( "Location: index.php?page=error" );
|
||||
exit;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
{block name=content}
|
||||
|
||||
<div class="row-fluid">
|
||||
<div class="box span12">
|
||||
<div class="box-header well">
|
||||
<h2><i class="icon-info-sign"></i>{$ip_title}</h2>
|
||||
<div class="box-icon">
|
||||
<a href="#" class="btn btn-round" onclick="javascript:show_help('intro');return false;"><i class="icon-info-sign"></i></a>
|
||||
<a href="#" class="btn btn-setting btn-round"><i class="icon-cog"></i></a>
|
||||
<a href="#" class="btn btn-minimize btn-round"><i class="icon-chevron-up"></i></a>
|
||||
<a href="#" class="btn btn-close btn-round"><i class="icon-remove"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content">
|
||||
<center>
|
||||
<p>{$ip_support}</p>
|
||||
<div class="alert alert-error">
|
||||
<form enctype="multipart/form-data" method="post" action="index.php?page=plugin&action=install_plugin" id="upload_plugin" >
|
||||
<label for="file">Filename:</label>
|
||||
<input type="file" name="file" id="file"></br>
|
||||
<progress id="progressBar" value="0" max="100" style="width:300px;"></progress></br>
|
||||
<input type="button" value="Upload" onclick="uploadPlugin()"></br>
|
||||
<h3 id="status"></h3>
|
||||
{if isset($smarty.get.result) and $smarty.get.result eq "0"}<p>{$ip_file_nfnd}</p>{/if}
|
||||
{if isset($smarty.get.result) and $smarty.get.result eq "2"}<p>{$ip_info_nfound}</p>{/if}
|
||||
</div>
|
||||
{$ip_message}
|
||||
</center>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/span-->
|
||||
|
||||
</div><!--/row-->
|
||||
{/block}
|
@ -0,0 +1,12 @@
|
||||
{block name=content}
|
||||
<div class="row-fluid">
|
||||
{if isset($hook_info)}
|
||||
{foreach from=$hook_info key=arrkey item=element}
|
||||
{if $arrkey eq $smarty.get.name}
|
||||
{include file=$element.TemplatePath}
|
||||
{/if}
|
||||
{/foreach}
|
||||
{/if}
|
||||
</div>
|
||||
{/block}
|
||||
|
@ -0,0 +1,71 @@
|
||||
{block name=content}
|
||||
<div class="row-fluid">
|
||||
<div class="box span12">
|
||||
<div class="box-header well" data-original-title>
|
||||
<h2><i class="icon-user"></i> {$plugin_title}</h2>
|
||||
<div class="box-icon">
|
||||
<a href="#" class="btn btn-setting btn-round"><i class="icon-cog"></i></a>
|
||||
<a href="#" class="btn btn-minimize btn-round"><i class="icon-chevron-up"></i></a>
|
||||
<a href="#" class="btn btn-close btn-round"><i class="icon-remove"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
{if isset($smarty.get.result) and $smarty.get.result eq "1"}<div class="alert alert-error"><p>{$ip_success}</p></div>{/if}
|
||||
{if isset($smarty.get.result) and $smarty.get.result eq "0"}<div class="alert alert-error"><p>{$dp_error}</p></div>{/if}
|
||||
{if isset($smarty.get.result) and $smarty.get.result eq "2"}<div class="alert alert-error"><p>{$dp_success}</p></div>{/if}
|
||||
{if isset($smarty.get.result) and $smarty.get.result eq "3"}<div class="alert alert-error"><p>{$ac_success}</p></div>{/if}
|
||||
{if isset($smarty.get.result) and $smarty.get.result eq "4"}<div class="alert alert-error"><p>{$ac_error}</p></div>{/if}
|
||||
{if isset($smarty.get.result) and $smarty.get.result eq "5"}<div class="alert alert-error"><p>{$dc_success}</p></div>{/if}
|
||||
{if isset($smarty.get.result) and $smarty.get.result eq "6"}<div class="alert alert-error"><p>{$dc_error}</p></div>{/if}
|
||||
{if isset($smarty.get.result) and $smarty.get.result eq "7"}<div class="alert alert-error"><p>{$up_success}</p></div>{/if}
|
||||
{if isset($smarty.get.result) and $smarty.get.result eq "8"}<div class="alert alert-error"><p>{$up_install_success}</p></div>{/if}
|
||||
<div class="box-content">
|
||||
<center><p>{$plugin_info}</p></center>
|
||||
<center>
|
||||
<a href="index.php?page=install_plugin"><button class="btn btn-primary btn-large dropdown-toggle">Install New Plugin</button></a>
|
||||
<a href="index.php?page=plugins_update"><button class="btn btn-primary btn-large dropdown-toggle">Check for updates</button></a>
|
||||
</center>
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{$plugin_status}</th>
|
||||
<th width="100">{$plugin_name}</th>
|
||||
<th>{$plugin_version}</th>
|
||||
<th width="350">{$plugin_description}</th>
|
||||
<th width="80">{$plugin_type}</th>
|
||||
<th>{$plugin_permission}</th>
|
||||
<th>{$plugin_actions}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{foreach from=$plug item=element}
|
||||
<tr>
|
||||
<td><input type="checkbox" name ="{$element.id}"{if ($element.plugin_status) eq "1"}checked{/if}/></td>
|
||||
<td class="center">{$element.plugin_name}</td>
|
||||
<td class="center">{$element.plugin_info->Version}</td>
|
||||
<td class="center">{$element.plugin_info->Description}</td>
|
||||
<td class="center">{$element.plugin_type}</td>
|
||||
<td class="center">{$element.plugin_permission}</td>
|
||||
<td>
|
||||
{if ($element.plugin_status) eq "0"}
|
||||
<a href="index.php?page=plugins&action=delete_plugin&id={$element.id}"><button class="btn btn-primary btn-large">Delete</button></a>
|
||||
<a href="index.php?page=plugins&action=activate_plugin&id={$element.id}"><button class="btn btn-primary btn-large dropdown-toggle">Activate</button></a>{/if}
|
||||
{if ($element.plugin_status) eq "1"}<a href="index.php?page=plugins&action=deactivate_plugin&id={$element.id}"><button class="btn btn-primary btn-large dropdown-toggle">Deactivate</button></a>{/if}</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="width: 300px; margin:0px auto;">
|
||||
<ul class="pagination">
|
||||
<li><a href="index.php?page=plugins&pagenum=1">«</a></li>
|
||||
{foreach from=$links item=link}
|
||||
<li {if $link == $currentPage}class="active"{/if}><a href="index.php?page=plugins&pagenum={$link}">{$link}</a></li>
|
||||
{/foreach}
|
||||
<li><a href="index.php?page=plugins&pagenum={$lastPage}">»</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div><!--/span-->
|
||||
</div><!--/row-->
|
||||
{/block}
|
@ -0,0 +1,50 @@
|
||||
{block name=content}
|
||||
<div class="row-fluid">
|
||||
<div class="box span12">
|
||||
<div class="box-header well" data-original-title>
|
||||
<h2><i class="icon-user"></i> {$up_title}</h2>
|
||||
<div class="box-icon">
|
||||
<a href="#" class="btn btn-setting btn-round"><i class="icon-cog"></i></a>
|
||||
<a href="#" class="btn btn-minimize btn-round"><i class="icon-chevron-up"></i></a>
|
||||
<a href="#" class="btn btn-close btn-round"><i class="icon-remove"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content">
|
||||
<center><p>{$up_info}</p></center>
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="100">{$plugin_name}</th>
|
||||
<th>{$plugin_version}</th>
|
||||
<th>{$up_updated_version}</th>
|
||||
<th width="500">{$up_description}</th>
|
||||
<th>{$up_actions}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{foreach from=$plug item=element}
|
||||
<tr>
|
||||
<td class="center">{$element.plugin_name}</td>
|
||||
<td class="center">{$element.plugin_info->Version}</td>
|
||||
<td class="center">{$element.update_info->Version}</td>
|
||||
<td class="center">{$element.update_info->UpdateInfo}</td>
|
||||
<td><a href="index.php?page=plugins&action=update_plugins&id={$element.id}"><button class="btn btn-primary btn-large">Update</button></a>
|
||||
</tr>
|
||||
{/foreach}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="width: 300px; margin:0px auto;">
|
||||
<ul class="pagination">
|
||||
<li><a href="index.php?page=plugins&pagenum=1">«</a></li>
|
||||
{foreach from=$links item=link}
|
||||
<li {if $link == $currentPage}class="active"{/if}><a href="index.php?page=plugins&pagenum={$link}">{$link}</a></li>
|
||||
{/foreach}
|
||||
<li><a href="index.php?page=plugins&pagenum={$lastPage}">»</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div><!--/span-->
|
||||
</div><!--/row-->
|
||||
{/block}
|
Loading…
Reference in New Issue