undef HALF_FREQUENCY_SENDING_TO_CLIENT
[ryzomcore.git] / web / public_php / ams / func / install_plugin.php
blob61c9573ccc52bbec8d7b523cffa649745e4e1c9e
1 <?php
3 /**
4 * This module contains the function to install plugins
5 * or check if the uploaded file is an update for a plugin.
7 * When user uploads a file with .zip extension(neccessary requirement)
8 * steps that should perform:
9 * --> Check if the file type is .zip.
10 * --> Extract it to a temp folder.
11 * --> Check for the .info file. If not exists throw error
12 * --> Extract the information from the .info file.
13 * --> Check for the plugin name already exists or not.
14 * --> if Plugin Name exists it compare the version of .info and version of plugin stored in db.
15 * --> if same throw error and if different it checks for UpdateInfo field in .info file.
16 * --> if UpdateInfo not found throw error.
17 * --> if UpdateInfo found add the update to the ryzom_ams_lib.updates table.
18 * --> if it's not an update and plugin with same name already exists throw error.
19 * --> if plugin with same name not present provide option to install plugin
21 * @author Shubham Meena, mentored by Matthew Lagoe
26 /**
27 * This function is used in installing plugins or adding updates
28 * for previously installed plugins.
31 function install_plugin() {
33 $result = array();
35 // if logged in
36 if ( WebUsers :: isLoggedIn() ) {
38 // path of temporary folder for storing files
39 $temp_path = "../../ams_lib/temp";
41 // create a temp directory if not exist
42 // temp folder where we first store all uploaded plugins before install
43 if ( !file_exists( "$temp_path" ) )
45 mkdir( $temp_path );
48 // checking the server if file is uploaded or not
49 if ( ( isset( $_FILES["file"] ) ) && ( $_FILES["file"]["size"] > 0 ) )
51 $fileName = $_FILES["file"]["name"]; //the files name takes from the HTML form
52 $fileTmpLoc = $_FILES["file"]["tmp_name"]; //file in the PHP tmp folder
53 $dir = trim( $_FILES["file"]["name"], ".zip" );
54 $target_path = "../../ams_lib/plugins/$dir"; //path in which the zip extraction is to be done
55 $destination = "../../ams_lib/plugins/";
57 // scanning plugin folder if plugin with same name is already exists or not
58 $x = checkForUpdate( $dir, $destination, $fileTmpLoc, $temp_path );
59 if ( $x == '1' )
61 echo "update found";
62 throw new SystemExit();
64 else if ( $x == '2' )
66 echo "Plugin already exists with same name .";
67 throw new SystemExit();
69 else if ( $x == '3' )
71 echo "Update info is not present in the update";
72 throw new SystemExit();
76 // checking for the command to install plugin is given or not
77 if ( !isset( $_POST['install_plugin'] ) )
79 if ( ( $_FILES["file"]["type"] == 'application/zip' ) )
81 if ( move_uploaded_file( $fileTmpLoc, $temp_path . "/" . $fileName ) ) {
82 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>";
83 throw new SystemExit();
85 else
87 echo "Error in uploading file.";
88 throw new SystemExit();
91 else
93 echo "Please select a file with .zip extension to upload.";
94 throw new SystemExit();
97 else
100 // calling function to unzip archives
101 if ( zipExtraction( $temp_path . "/" . $fileName , $destination ) )
103 if ( file_exists( $target_path . "/.info" ) )
105 $result = readPluginFile( ".info", $target_path );
107 // sending all info to the database
108 $install_result = array();
109 $install_result['FileName'] = $target_path;
110 $install_result['Name'] = $result['PluginName'];
111 $install_result['Type'] = $result['Type'];
112 if ( Ticket_User :: isMod( unserialize( $_SESSION['ticket_user'] ) ) )
114 $install_result['Permission'] = 'admin';
116 else
118 $install_result['Permission'] = 'user';
121 $install_result['Info'] = json_encode( $result );
123 // connection with the database
124 $dbr = new DBLayer( "lib" );
125 $dbr -> insert( "plugins", $install_result );
127 // if everything is successfull redirecting to the plugin template
128 header("Cache-Control: max-age=1");
129 header( "Location: index.php?page=plugins&result=1" );
130 throw new SystemExit();
132 else
134 // file .info not exists
135 rmdir( $target_path );
136 header("Cache-Control: max-age=1");
137 header( "Location: index.php?page=install_plugin&result=2" );
138 throw new SystemExit();
141 } else
143 // extraction failed
144 header("Cache-Control: max-age=1");
145 header( "Location: index.php?page=install_plugin&result=0" );
146 throw new SystemExit();
150 else
152 echo "Please Browse for a file before clicking the upload button";
153 throw new SystemExit();
159 * function to unzip the zipped files
161 * @param $target_path path to the target zipped file
162 * @param $destination path to the destination
163 * @return boolean
165 function zipExtraction( $target_path, $destination )
167 $zip = new ZipArchive();
168 $x = $zip -> open( $target_path );
169 if ( $x === true ) {
170 if ( $zip -> extractTo( $destination ) )
172 $zip -> close();
173 return true;
175 else
177 $zip -> close();
178 return false;
184 * function to read text files and extract
185 * the information into an array
187 * -----------------------------------------------------------
188 * format:
189 * -----------------------------------------------------------
190 * PluginName = Name of the plugin
191 * Version = version of the plugin
192 * Type = type of the plugin
193 * TemplatePath = path to the template
194 * Description = Description of the plugin ,it's functionality
195 * -----------------------------------------------------------
197 * reads only files with name .info
199 * @param $fileName file to read
200 * @param $target_path path to the folder containing .info file
201 * @return array containing above information in array(value => key)
203 function readPluginFile( $fileName, $target_path )
205 $file_handle = fopen( $target_path . "/" . $fileName, "r" );
206 $result = array();
207 while ( !feof( $file_handle ) ) {
208 $line_of_text = fgets( $file_handle );
209 $parts = array_map( 'trim', explode( '=', $line_of_text, 2 ) );
210 @$result[$parts[0]] = $parts[1];
212 fclose( $file_handle );
213 return $result;
217 * function to check for updates or
218 * if the same plugin already exists
219 * also, if the update founds ,check for the UpdateInfo in the .info file.
220 * Update is saved in the temp directory with pluginName_version.zip
222 * @param $fileName file which is uploaded in .zip extension
223 * @param $findPath where we have to look for the installed plugins
224 * @param $tempFile path for the temporary file
225 * @param $tempPath path where we have to store the update
226 * @return 2 if plugin already exists and update not found
227 * @return 3 if update info tag not found in .info file
229 function checkForUpdate( $fileName, $findPath, $tempFile, $tempPath )
231 // check for plugin if exists
232 $file = scandir( $findPath );
233 foreach( $file as $key => $value )
235 if ( strcmp( $value, $fileName ) == 0 )
237 if ( !file_exists( $tempPath . "/test" ) )
239 mkdir( $tempPath . "/test" );
242 // extracting the update
243 if ( zipExtraction( $tempFile, $tempPath . "/test/" ) )
245 $result = readPluginFile( ".info", $tempPath . "/test/" . $fileName );
247 // check for the version for the plugin
248 $db = new DBLayer( "lib" );
249 $sth = $db -> select( "plugins", array( 'Name' => $result['PluginName'] ), "Name = :Name" );
250 $info = $sth -> fetch();
251 $info['Info'] = json_decode( $info['Info'] );
253 // the two versions from main plugin and the updated part
254 $new_version = explode( '.', $result['Version'] );
255 $pre_version = explode( '.', $info['Info'] -> Version );
257 // For all plugins we have used semantic versioning
258 // Format: X.Y.Z ,X->Major, Y->Minor, Z->Patch
259 // change in the X Y & Z values refer the type of change in the plugin.
260 // for initial development only Minor an Patch MUST be 0.
261 // if there is bug fix then there MUST be an increment in the Z value.
262 // if there is change in the functionality or addition of new functionality
263 // then there MUST be an increment in the Y value.
264 // When there is increment in the X value , Y and Z MUST be 0.
265 // comparing if there is some change
266 if ( !array_diff( $new_version , $pre_version ) )
268 // removing the uploaded file
269 Plugincache :: rrmdir( $tempPath . "/test/" . $fileName );
270 return '2'; //plugin already exists
272 else
274 // check for update info if exists
275 if ( !array_key_exists( 'UpdateInfo', $result ) )
277 return '3'; //update info tag not found
279 else
281 // check if update already exists
282 if ( pluginUpdateExists( $info['Id'], $tempPath . "/" . trim( $fileName, ".zip" ) . "_" . $result['Version'] . ".zip" ) )
284 echo "Update already exists";
285 throw new SystemExit();
287 else {
288 // removing the preivous update
289 $dbr = new DBLayer( "lib" );
290 $dbr -> delete( "updates", array( 'id' => $info['Id'] ), "PluginId=:id" );
291 // storing update in the temp directory
292 // format of update save
293 if ( move_uploaded_file( $tempFile, $tempPath . "/" . trim( $fileName, ".zip" ) . "_" . $result['Version'] . ".zip" ) ) {
294 // setting update information in the database
295 $update['PluginId'] = $info['Id'];
296 $update['UpdatePath'] = $tempPath . "/" . trim( $fileName, ".zip" ) . "_" . $result['Version'] . ".zip";
297 $update['UpdateInfo'] = json_encode( $result );
298 $dbr -> insert( "updates", $update );
299 header("Cache-Control: max-age=1");
300 header( "Location: index.php?page=plugins&result=7" );
301 throw new SystemExit();
312 * Function to check for the update of a plugin already exists
314 * @param $pluginId id of the plugin for which update is available
315 * @param $updatePath path of the new update
316 * @return boolean True if update already exists else False
319 function PluginUpdateExists( $pluginId, $updatePath )
321 $db = new DBLayer( 'lib' );
322 $sth = $db -> selectWithParameter( "UpdatePath", "updates", array( 'pluginid' => $pluginId ), "PluginId=:pluginid" );
323 $row = $sth -> fetch();
324 if ( $updatePath == $row['UpdatePath'] )
326 return true;
328 else
330 rmdir( $row['UpdatePath'] );
331 return false;