Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Tue, Feb 25, 5:31 AM

in-portal

Index: branches/5.2.x/core/kernel/globals.php
===================================================================
--- branches/5.2.x/core/kernel/globals.php (revision 15723)
+++ branches/5.2.x/core/kernel/globals.php (revision 15724)
@@ -1,902 +1,942 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class kUtil {
// const KG_TO_POUND = 2.20462262;
const POUND_TO_KG = 0.45359237;
/**
* Similar to array_merge_recursive but keyed-valued are always overwritten.
* Priority goes to the 2nd array.
*
* @param $paArray1 array
* @param $paArray2 array
* @return array
* @access public
*/
public static function array_merge_recursive($paArray1, $paArray2)
{
if (!is_array($paArray1) or !is_array($paArray2)) {
return $paArray2;
}
foreach ($paArray2 AS $sKey2 => $sValue2) {
$paArray1[$sKey2] = isset($paArray1[$sKey2]) ? self::array_merge_recursive($paArray1[$sKey2], $sValue2) : $sValue2;
}
return $paArray1;
}
/**
* Prepend a reference to an element to the beginning of an array.
* Renumbers numeric keys, so $value is always inserted to $array[0]
*
* @param $array array
* @param $value mixed
* @return int
* @access public
*/
public static function array_unshift_ref(&$array, &$value)
{
$return = array_unshift($array,'');
$array[0] =& $value;
return $return;
}
/**
* Rename key in associative array, maintaining keys order
*
* @param Array $array Associative Array
* @param mixed $old Old key name
* @param mixed $new New key name
* @access public
*/
public static function array_rename_key(&$array, $old, $new)
{
$new_array = Array ();
foreach ($array as $key => $val) {
$new_array[ $key == $old ? $new : $key] = $val;
}
$array = $new_array;
}
/**
* Same as print_r, but outputs result on screen or in debugger report (when in debug mode)
*
* @param Array $data
* @param string $label
* @param bool $on_screen
* @access public
*/
public static function print_r($data, $label = '', $on_screen = false)
{
$is_debug = false;
if ( class_exists('kApplication') && !$on_screen ) {
$application =& kApplication::Instance();
$is_debug = $application->isDebugMode();
}
if ( $is_debug && isset($application) ) {
if ( $label ) {
$application->Debugger->appendHTML('<strong>' . $label . '</strong>');
}
$application->Debugger->dumpVars($data);
}
else {
if ( $label ) {
echo '<strong>' . $label . '</strong><br/>';
}
echo '<pre>', print_r($data, true), '</pre>';
}
}
/**
* Define constant if it was not already defined before
*
* @param string $const_name
* @param string $const_value
* @access public
*/
public static function safeDefine($const_name, $const_value)
{
if ( !defined($const_name) ) {
define($const_name, $const_value);
}
}
/**
* Parses "/system/config.php" file and returns the result
*
* @param bool $parse_section
* @return Array
* @access public
*/
public static function parseConfig($parse_section = false)
{
$file = FULL_PATH . DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR . 'config.php';
if ( !file_exists($file) ) {
return Array ();
}
if ( file_exists($file) && !is_readable($file) ) {
die('Could Not Open Ini File');
}
$contents = file($file);
if ( $contents && $contents[0] == '<' . '?' . 'php die() ?' . ">\n" ) {
// format of "config.php" file before 5.1.0 version
array_shift($contents);
return parse_ini_string(implode('', $contents), $parse_section);
}
$_CONFIG = Array ();
require($file);
if ( $parse_section ) {
if ( isset($_CONFIG['Database']['LoadBalancing']) && $_CONFIG['Database']['LoadBalancing'] ) {
require FULL_PATH . DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR . 'db_servers.php';
}
return $_CONFIG;
}
$ret = Array ();
foreach ($_CONFIG as $section => $section_variables) {
$ret = array_merge($ret, $section_variables);
}
return $ret;
}
/**
* Returns parsed variables from "config.php" file
*
* @return Array
* @access public
*/
public static function getConfigVars()
{
static $vars = NULL;
if ( !isset($vars) ) {
$vars = self::parseConfig();
}
return $vars;
}
/**
* Same as "include_once", but also profiles file includes in debug mode and DBG_PROFILE_INCLUDES constant is set
*
* @param string $file
* @access public
*/
public static function includeOnce($file)
{
global $debugger;
if ( defined('DEBUG_MODE') && DEBUG_MODE && isset($debugger) && defined('DBG_PROFILE_INCLUDES') && DBG_PROFILE_INCLUDES ) {
if ( in_array($file, get_included_files()) ) {
return ;
}
global $debugger;
/*$debugger->IncludeLevel++;
$before_mem = memory_get_usage();*/
$debugger->ProfileStart('inc_'.crc32($file), $file);
include_once($file);
$debugger->ProfileFinish('inc_'.crc32($file));
$debugger->profilerAddTotal('includes', 'inc_'.crc32($file));
/*$used_mem = memory_get_usage() - $before_mem;
$debugger->IncludeLevel--;
$debugger->IncludesData['file'][] = str_replace(FULL_PATH, '', $file);
$debugger->IncludesData['mem'][] = $used_mem;
$debugger->IncludesData['time'][] = $used_time;
$debugger->IncludesData['level'][] = $debugger->IncludeLevel;*/
}
else {
include_once($file);
}
}
/**
* Checks if given string is a serialized array
*
* @param string $string
* @return bool
* @access public
*/
public static function IsSerialized($string)
{
if ( is_array($string) ) {
return false;
}
return preg_match('/a:([\d]+):{/', $string);
}
/**
* Generates password of given length
*
* @param int $length
* @return string
* @access public
*/
public static function generatePassword($length = 10)
{
$pass_length = $length;
$p1 = Array ('b','c','d','f','g','h','j','k','l','m','n','p','q','r','s','t','v','w','x','y','z');
$p2 = Array ('a','e','i','o','u');
$p3 = Array ('1','2','3','4','5','6','7','8','9');
$p4 = Array ('(','&',')',';','%'); // if you need real strong stuff
// how much elements in the array
// can be done with a array count but counting once here is faster
$s1 = 21;// this is the count of $p1
$s2 = 5; // this is the count of $p2
$s3 = 9; // this is the count of $p3
$s4 = 5; // this is the count of $p4
// possible readable combinations
$c1 = '121'; // will be like 'bab'
$c2 = '212'; // will be like 'aba'
$c3 = '12'; // will be like 'ab'
$c4 = '3'; // will be just a number '1 to 9' if you dont like number delete the 3
//$c5 = '4'; // uncomment to active the strong stuff
$comb = '4'; // the amount of combinations you made above (and did not comment out)
for ($p = 0; $p < $pass_length;) {
mt_srand((double)microtime() * 1000000);
$strpart = mt_rand(1, $comb);
// checking if the stringpart is not the same as the previous one
if ($strpart != $previous) {
$pass_structure .= ${'c' . $strpart};
// shortcutting the loop a bit
$p = $p + mb_strlen(${'c' . $strpart});
}
$previous = $strpart;
}
// generating the password from the structure defined in $pass_structure
for ($g = 0; $g < mb_strlen($pass_structure); $g++) {
mt_srand((double)microtime() * 1000000);
$sel = mb_substr($pass_structure, $g, 1);
$pass .= ${'p' . $sel}[ mt_rand(0,-1+${'s'.$sel}) ];
}
return $pass;
}
/**
* submits $url with $post as POST
*
* @param string $url
* @param mixed $data
* @param Array $headers
* @param string $request_type
* @param Array $curl_options
* @return string
* @access public
* @deprecated
*/
public static function curl_post($url, $data, $headers = NULL, $request_type = 'POST', $curl_options = NULL)
{
$application =& kApplication::Instance();
$curl_helper = $application->recallObject('CurlHelper');
/* @var $curl_helper kCurlHelper */
if ($request_type == 'POST') {
$curl_helper->SetRequestMethod(kCurlHelper::REQUEST_METHOD_POST);
}
$curl_helper->SetRequestData($data);
if (!is_null($headers)) {
// not an associative array, so don't use kCurlHelper::SetHeaders method
$curl_helper->setOptions( Array (CURLOPT_HTTPHEADER => $headers) );
}
if (is_array($curl_options)) {
$curl_helper->setOptions($curl_options);
}
$curl_helper->followLocation = false;
$ret = $curl_helper->Send($url);
$GLOBALS['curl_errorno'] = $curl_helper->lastErrorCode;
$GLOBALS['curl_error'] = $curl_helper->lastErrorMsg;
return $ret;
}
/**
* Checks if constant is defined and has positive value
*
* @param string $const_name
* @return bool
* @access public
*/
public static function constOn($const_name)
{
return defined($const_name) && constant($const_name);
}
/**
* Converts KG to Pounds
*
* @param float $kg
* @param bool $pounds_only
* @return float
* @access public
*/
public static function Kg2Pounds($kg, $pounds_only = false)
{
$major = floor( round($kg / self::POUND_TO_KG, 3) );
$minor = abs(round(($kg - $major * self::POUND_TO_KG) / self::POUND_TO_KG * 16, 2));
if ($pounds_only) {
$major += round($minor * 0.0625, 2);
$minor = 0;
}
return array($major, $minor);
}
/**
* Converts Pounds to KG
*
* @param float $pounds
* @param float $ounces
* @return float
* @access public
*/
public static function Pounds2Kg($pounds, $ounces = 0.00)
{
return round(($pounds + ($ounces / 16)) * self::POUND_TO_KG, 5);
}
/**
* Formats file/memory size in nice way
*
* @param int $bytes
* @return string
* @access public
*/
public static function formatSize($bytes)
{
if ($bytes >= 1099511627776) {
$return = round($bytes / 1024 / 1024 / 1024 / 1024, 2);
$suffix = "TB";
} elseif ($bytes >= 1073741824) {
$return = round($bytes / 1024 / 1024 / 1024, 2);
$suffix = "GB";
} elseif ($bytes >= 1048576) {
$return = round($bytes / 1024 / 1024, 2);
$suffix = "MB";
} elseif ($bytes >= 1024) {
$return = round($bytes / 1024, 2);
$suffix = "KB";
} else {
$return = $bytes;
$suffix = "Byte";
}
$return .= ' '.$suffix;
return $return;
}
/**
* Enter description here...
*
* @param resource $filePointer the file resource to write to
* @param Array $data the data to write out
* @param string $delimiter the field separator
* @param string $enclosure symbol to enclose field data to
* @param string $recordSeparator symbols to separate records with
* @access public
*/
public static function fputcsv($filePointer, $data, $delimiter = ',', $enclosure = '"', $recordSeparator = "\r\n")
{
fwrite($filePointer, self::getcsvline($data, $delimiter, $enclosure, $recordSeparator));
}
/**
* Enter description here...
*
* @param Array $data the data to write out
* @param string $delimiter the field separator
* @param string $enclosure symbol to enclose field data to
* @param string $recordSeparator symbols to separate records with
* @return string
* @access public
*/
public static function getcsvline($data, $delimiter = ',', $enclosure = '"', $recordSeparator = "\r\n")
{
foreach($data as $field_index => $field_value) {
// replaces an enclosure with two enclosures
$data[$field_index] = str_replace($enclosure, $enclosure.$enclosure, $field_value);
}
$line = $enclosure.implode($enclosure.$delimiter.$enclosure, $data).$enclosure.$recordSeparator;
$line = preg_replace('/'.preg_quote($enclosure, '/').'([0-9\.]+)'.preg_quote($enclosure, '/').'/', '$1', $line);
return $line;
}
/**
* Allows to replace #section# within any string with current section
*
* @param string $string
* @return string
* @access public
*/
public static function replaceModuleSection($string)
{
$application =& kApplication::Instance();
$module_section = $application->RecallVar('section');
if ($module_section) {
// substitute section instead of #section# parameter in title preset name
$module_section = explode(':', $module_section);
$section = preg_replace('/(configuration|configure)_(.*)/i', '\\2', $module_section[count($module_section) == 2 ? 1 : 0]);
$string = str_replace('#section#', mb_strtolower($section), $string);
}
return $string;
}
/**
* Checks, that user IP address is within allowed range
*
* @param string $ip_list semi-column (by default) separated ip address list
* @param string $separator ip address separator (default ";")
*
* @return bool
* @access public
*/
public static function ipMatch($ip_list, $separator = ';')
{
if ( php_sapi_name() == 'cli' ) {
return false;
}
$ip_match = false;
$ip_addresses = $ip_list ? explode($separator, $ip_list) : Array ();
$application =& kApplication::Instance();
$client_ip = $application->getClientIp();
foreach ($ip_addresses as $ip_address) {
if ( self::netMatch($ip_address, $client_ip) ) {
$ip_match = true;
break;
}
}
return $ip_match;
}
/**
* Checks, that given ip belongs to given subnet
*
* @param string $network
* @param string $ip
* @return bool
* @access public
*/
public static function netMatch($network, $ip)
{
$network = trim($network);
$ip = trim($ip);
if ( preg_replace('/[\d\.\/-]/', '', $network) != '' ) {
$network = gethostbyname($network);
}
if ($network == $ip) {
// comparing two ip addresses directly
return true;
}
$d = strpos($network, '-');
if ($d !== false) {
// ip address range specified
$from = ip2long(trim(substr($network, 0, $d)));
$to = ip2long(trim(substr($network, $d + 1)));
$ip = ip2long($ip);
return ($ip >= $from && $ip <= $to);
}
elseif (strpos($network, '/') !== false) {
// single subnet specified
$ip_arr = explode('/', $network);
if (!preg_match("@\d*\.\d*\.\d*\.\d*@", $ip_arr[0], $matches)) {
$ip_arr[0] .= '.0'; // Alternate form 194.1.4/24
}
$network_long = ip2long($ip_arr[0]);
$x = ip2long($ip_arr[1]);
$mask = long2ip($x) == $ip_arr[1] ? $x : (0xffffffff << (32 - $ip_arr[1]));
$ip_long = ip2long($ip);
return ($ip_long & $mask) == ($network_long & $mask);
}
return false;
}
/**
* Returns mime type corresponding to given file
* @param string $file
* @return string
* @access public
*/
public static function mimeContentType($file)
{
- $ret = '';
+ $ret = self::vendorMimeContentType($file);
+
+ if ( $ret ) {
+ // vendor-specific mime types override any automatic detection
+ return $ret;
+ }
if ( function_exists('finfo_open') && function_exists('finfo_file') ) {
$mime_magic_resource = finfo_open(FILEINFO_MIME_TYPE);
if ( $mime_magic_resource ) {
$ret = finfo_file($mime_magic_resource, $file);
finfo_close($mime_magic_resource);
}
}
elseif ( function_exists('mime_content_type') ) {
$ret = mime_content_type($file);
}
return $ret ? $ret : self::mimeContentTypeByExtension($file);
}
/**
+ * Determines vendor-specific mime type from a given file
+ *
+ * @param string $file
+ * @return bool
+ * @access public
+ * @static
+ */
+ public static function vendorMimeContentType($file)
+ {
+ $file_extension = mb_strtolower( pathinfo($file, PATHINFO_EXTENSION) );
+
+ $mapping = Array (
+ 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
+ 'docm' => 'application/vnd.ms-word.document.macroEnabled.12',
+ 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12',
+ 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
+ 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
+ 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
+ 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
+ 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
+ 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+ 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
+ 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
+ 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
+ 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
+ 'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
+ 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12'
+ );
+
+ return isset($mapping[$file_extension]) ? $mapping[$file_extension] : false;
+ }
+
+ /**
* Detects mime type of the file purely based on it's extension
*
* @param string $file
* @return string
* @access public
*/
public static function mimeContentTypeByExtension($file)
{
$file_extension = mb_strtolower( pathinfo($file, PATHINFO_EXTENSION) );
$mapping = '(xls:application/excel)(hqx:application/macbinhex40)(doc,dot,wrd:application/msword)(pdf:application/pdf)
(pgp:application/pgp)(ps,eps,ai:application/postscript)(ppt:application/powerpoint)(rtf:application/rtf)
(tgz,gtar:application/x-gtar)(gz:application/x-gzip)(php,php3:application/x-httpd-php)(js:application/x-javascript)
(ppd,psd:application/x-photoshop)(swf,swc,rf:application/x-shockwave-flash)(tar:application/x-tar)(zip:application/zip)
(mid,midi,kar:audio/midi)(mp2,mp3,mpga:audio/mpeg)(ra:audio/x-realaudio)(wav:audio/wav)(bmp:image/bitmap)(bmp:image/bitmap)
(gif:image/gif)(iff:image/iff)(jb2:image/jb2)(jpg,jpe,jpeg:image/jpeg)(jpx:image/jpx)(png:image/png)(tif,tiff:image/tiff)
(wbmp:image/vnd.wap.wbmp)(xbm:image/xbm)(css:text/css)(txt:text/plain)(htm,html:text/html)(xml:text/xml)
(mpg,mpe,mpeg:video/mpeg)(qt,mov:video/quicktime)(avi:video/x-ms-video)(eml:message/rfc822)
(sxw:application/vnd.sun.xml.writer)(sxc:application/vnd.sun.xml.calc)(sxi:application/vnd.sun.xml.impress)
(sxd:application/vnd.sun.xml.draw)(sxm:application/vnd.sun.xml.math)
(odt:application/vnd.oasis.opendocument.text)(oth:application/vnd.oasis.opendocument.text-web)
(odm:application/vnd.oasis.opendocument.text-master)(odg:application/vnd.oasis.opendocument.graphics)
(odp:application/vnd.oasis.opendocument.presentation)(ods:application/vnd.oasis.opendocument.spreadsheet)
(odc:application/vnd.oasis.opendocument.chart)(odf:application/vnd.oasis.opendocument.formula)
(odi:application/vnd.oasis.opendocument.image)';
if ( preg_match('/[\(,]' . $file_extension . '[,]{0,1}.*?:(.*?)\)/s', $mapping, $regs) ) {
return $regs[1];
}
return 'application/octet-stream';
}
/**
* Return param value and removes it from params array
*
* @param string $name
* @param Array $params
* @param bool $default
* @return string
*/
public static function popParam($name, &$params, $default = false)
{
if ( isset($params[$name]) ) {
$value = $params[$name];
unset($params[$name]);
return $value;
}
return $default;
}
/**
* Generate subpath from hashed value
*
* @param string $name
* @param int $levels
* @return string
*/
public static function getHashPathForLevel($name, $levels = 2)
{
if ( $levels == 0 ) {
return '';
}
else {
$path = '';
$hash = md5($name);
for ($i = 0; $i < $levels; $i++) {
$path .= substr($hash, $i, 1) . '/';
}
return $path;
}
}
/**
* Calculates the crc32 polynomial of a string (always positive number)
*
* @param string $str
* @return int
*/
public static function crc32($str)
{
return sprintf('%u', crc32($str));
}
/**
* Returns instance of DateTime class with date set based on timestamp
*
* @static
* @param int $timestamp
* @return DateTime
* @access public
*/
public static function dateFromTimestamp($timestamp)
{
if ( version_compare(PHP_VERSION, '5.3.0', '<') ) {
$date = new DateTime('@' . $timestamp);
$date->setTimezone(new DateTimeZone(getenv('TZ')));
}
else {
$date = new DateTime();
$date->setTimestamp($timestamp);
}
return $date;
}
/**
* Returns timestamp from given DateTime class instance
*
* @static
* @param DateTime $date_time
* @return int|string
* @access public
*/
public static function timestampFromDate(DateTime $date_time)
{
if ( version_compare(PHP_VERSION, '5.3.0', '<') ) {
return $date_time->format('U');
}
return $date_time->getTimestamp();
}
/**
* Generates random numeric id
*
* @static
* @return string
* @access public
*/
public static function generateId()
{
list($usec, $sec) = explode(' ', microtime());
$id_part_1 = substr($usec, 4, 4);
$id_part_2 = mt_rand(1, 9);
$id_part_3 = substr($sec, 6, 4);
$digit_one = substr($id_part_1, 0, 1);
if ( $digit_one == 0 ) {
$digit_one = mt_rand(1, 9);
$id_part_1 = preg_replace('/^0/', '', $id_part_1);
$id_part_1 = $digit_one . $id_part_1;
}
return $id_part_1 . $id_part_2 . $id_part_3;
}
/**
* Changes script resource limits. Omitted argument results in limit removal.
*
* @static
* @param string|int $memory_limit
* @param int $time_limit
* @return void
* @access public
*/
public static function setResourceLimit($memory_limit = null, $time_limit = null)
{
set_time_limit(isset($time_limit) ? $time_limit : 0);
ini_set('memory_limit', isset($memory_limit) ? $memory_limit : -1);
}
}
/**
* Returns array value if key exists
* Accepts infinite number of parameters
*
* @param Array $array searchable array
* @param int $key array key
* @return string
*/
function getArrayValue(&$array, $key)
{
$ret = isset($array[$key]) ? $array[$key] : false;
if ( $ret && func_num_args() > 2 ) {
for ($i = 2; $i < func_num_args(); $i++) {
$cur_key = func_get_arg($i);
$ret = getArrayValue($ret, $cur_key);
if ( $ret === false ) {
break;
}
}
}
return $ret;
}
if ( !function_exists('parse_ini_string') ) {
/**
* Equivalent for "parse_ini_string" function available since PHP 5.3.0
*
* @param string $ini
* @param bool $process_sections
* @param int $scanner_mode
* @return Array
*/
function parse_ini_string($ini, $process_sections = false, $scanner_mode = NULL)
{
# Generate a temporary file.
$tempname = tempnam('/tmp', 'ini');
$fp = fopen($tempname, 'w');
fwrite($fp, $ini);
$ini = parse_ini_file($tempname, !empty($process_sections));
fclose($fp);
@unlink($tempname);
return $ini;
}
}
if ( !function_exists('memory_get_usage') ) {
// PHP 4.x and compiled without --enable-memory-limit option
function memory_get_usage() { return -1; }
}
if ( !function_exists('imagecreatefrombmp') ) {
// just in case if GD will add this function in future
function imagecreatefrombmp($filename)
{
//Ouverture du fichier en mode binaire
if (! $f1 = fopen($filename,"rb")) return FALSE;
//1 : Chargement des ent�tes FICHIER
$FILE = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1,14));
if ($FILE['file_type'] != 19778) return FALSE;
//2 : Chargement des ent�tes BMP
$BMP = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'.
'/Vcompression/Vsize_bitmap/Vhoriz_resolution'.
'/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1,40));
$BMP['colors'] = pow(2,$BMP['bits_per_pixel']);
if ($BMP['size_bitmap'] == 0) $BMP['size_bitmap'] = $FILE['file_size'] - $FILE['bitmap_offset'];
$BMP['bytes_per_pixel'] = $BMP['bits_per_pixel']/8;
$BMP['bytes_per_pixel2'] = ceil($BMP['bytes_per_pixel']);
$BMP['decal'] = ($BMP['width']*$BMP['bytes_per_pixel']/4);
$BMP['decal'] -= floor($BMP['width']*$BMP['bytes_per_pixel']/4);
$BMP['decal'] = 4-(4*$BMP['decal']);
if ($BMP['decal'] == 4) $BMP['decal'] = 0;
//3 : Chargement des couleurs de la palette
$PALETTE = array();
if ($BMP['colors'] < 16777216)
{
$PALETTE = unpack('V'.$BMP['colors'], fread($f1,$BMP['colors']*4));
}
//4 : Cr�ation de l'image
$IMG = fread($f1,$BMP['size_bitmap']);
$VIDE = chr(0);
$res = imagecreatetruecolor($BMP['width'],$BMP['height']);
$P = 0;
$Y = $BMP['height']-1;
while ($Y >= 0)
{
$X=0;
while ($X < $BMP['width'])
{
if ($BMP['bits_per_pixel'] == 24)
$COLOR = unpack("V",substr($IMG,$P,3).$VIDE);
elseif ($BMP['bits_per_pixel'] == 16)
{
$COLOR = unpack("n",substr($IMG,$P,2));
$COLOR[1] = $PALETTE[$COLOR[1]+1];
}
elseif ($BMP['bits_per_pixel'] == 8)
{
$COLOR = unpack("n",$VIDE.substr($IMG,$P,1));
$COLOR[1] = $PALETTE[$COLOR[1]+1];
}
elseif ($BMP['bits_per_pixel'] == 4)
{
$COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
if (($P*2)%2 == 0) $COLOR[1] = ($COLOR[1] >> 4) ; else $COLOR[1] = ($COLOR[1] & 0x0F);
$COLOR[1] = $PALETTE[$COLOR[1]+1];
}
elseif ($BMP['bits_per_pixel'] == 1)
{
$COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
if (($P*8)%8 == 0) $COLOR[1] = $COLOR[1] >>7;
elseif (($P*8)%8 == 1) $COLOR[1] = ($COLOR[1] & 0x40)>>6;
elseif (($P*8)%8 == 2) $COLOR[1] = ($COLOR[1] & 0x20)>>5;
elseif (($P*8)%8 == 3) $COLOR[1] = ($COLOR[1] & 0x10)>>4;
elseif (($P*8)%8 == 4) $COLOR[1] = ($COLOR[1] & 0x8)>>3;
elseif (($P*8)%8 == 5) $COLOR[1] = ($COLOR[1] & 0x4)>>2;
elseif (($P*8)%8 == 6) $COLOR[1] = ($COLOR[1] & 0x2)>>1;
elseif (($P*8)%8 == 7) $COLOR[1] = ($COLOR[1] & 0x1);
$COLOR[1] = $PALETTE[$COLOR[1]+1];
}
else
return FALSE;
imagesetpixel($res,$X,$Y,$COLOR[1]);
$X++;
$P += $BMP['bytes_per_pixel'];
}
$Y--;
$P+=$BMP['decal'];
}
//Fermeture du fichier
fclose($f1);
return $res;
}
}
\ No newline at end of file
Index: branches/5.2.x/core/admin_templates/js/uploader/uploader.js
===================================================================
--- branches/5.2.x/core/admin_templates/js/uploader/uploader.js (revision 15723)
+++ branches/5.2.x/core/admin_templates/js/uploader/uploader.js (revision 15724)
@@ -1,687 +1,705 @@
// this js class name is hardcoded in flash object :(
var SWFUpload = function () {};
SWFUpload.instances = {};
function Uploader(id, params) {
this.id = id;
// normalize params
if (isNaN(parseInt(params.multiple))) {
// ensure that maximal file number is greather then zero
params.multiple = 1;
}
params.allowedFilesize = this._normalizeFilesize(params.allowedFilesize);
// set params to uploader
this._eventQueue = [];
this.uploadCancelled = false;
this.flashReady = false;
this.params = params;
this._ensureDefaultValues();
this.files_count = 0;
this.files = new Array();
this.deleted = new Array();
this.uploadURL = params.uploadURL;
this.deleteURL = params.deleteURL;
this.enableUploadButton();
}
/* ==== Private methods ==== */
Uploader.prototype._ensureDefaultValues = function() {
// Upload backend settings
var $defaults = {
baseUrl: '',
uploadURL : '',
useQueryString : false,
requeueOnError : false,
httpSuccess : '',
filePostName : 'Filedata',
allowedFiletypes : '*.*',
allowedFiletypesDescription : 'All Files',
allowedFilesize : 0, // Default zero means "unlimited"
multiple : 0,
field: '',
thumb_format: '',
json: '',
previewURL: '',
fileQueueLimit : 0,
buttonImageURL : '',
buttonWidth : 1,
buttonHeight : 1,
buttonText : '',
buttonTextTopPadding : 0,
buttonTextLeftPadding : 0,
buttonTextStyle : 'color: #000000; font-size: 16pt;',
buttonAction : parseInt(this.params.multiple) == 1 ? -100 : -110, // SELECT_FILE : -100, SELECT_FILES : -110
buttonDisabled : true, //false,
buttonCursor : -1, // ARROW : -1, HAND : -2
wmode : 'transparent', // "window", "transparent", "opaque"
buttonPlaceholderId: false
}
for (var $param_name in $defaults) {
if (this.params[$param_name] == null) {
// console.log('setting default value [', $defaults[$param_name], '] for missing parameter [', $param_name, '] instead of [', this.params[$param_name], ']');
this.params[$param_name] = $defaults[$param_name];
}
}
}
Uploader.prototype._normalizeFilesize = function($file_size) {
var $normalize_size = parseInt($file_size);
if (isNaN($normalize_size)) {
return $file_size;
}
// in kilobytes (flash doesn't recognize numbers, that are longer, then 9 digits)
return $normalize_size / 1024;
}
Uploader.prototype._prepareFiles = function() {
var $files_json = [], $raw_file_info, $file_info;
// process uploaded files
for (var f = 0; f < this.files.length; f++) {
$raw_file_info = this.files[f];
$file_info = {
id: $raw_file_info.id,
name: $raw_file_info.name,
size: $raw_file_info.size,
deleted: 0,
temp: $raw_file_info.temp,
order: $raw_file_info.order
};
$files_json.push(JSON.stringify($file_info));
}
// process deleted files;
for (var $i = 0; $i < this.deleted.length; $i++) {
$file_info = {
name: this.deleted[$i],
deleted: 1
};
$files_json.push(JSON.stringify($file_info));
}
document.getElementById(this.id+'[json]').value = $files_json.join('|');
}
Uploader.prototype._formatSize = function (bytes) {
var kb = Math.round(bytes / 1024);
if (kb < 1024) {
return kb + ' KB';
}
var mb = Math.round(kb / 1024 * 100) / 100;
return mb + ' MB';
}
Uploader.prototype._executeNextEvent = function () {
var f = this._eventQueue ? this._eventQueue.shift() : null;
if (typeof(f) === 'function') {
f.apply(this);
}
};
/* ==== Public methods ==== */
Uploader.prototype.init = function() {
this.IconPath = this.params.IconPath ? this.params.IconPath : '../admin_templates/img/browser/icons';
// initialize flash object
this.flash_id = UploadsManager._nextFlashId();
// add callbacks for every event, because none of callbacks will work in other case (see swfupload documentation)
SWFUpload.instances[this.flash_id] = this;
SWFUpload.instances[this.flash_id].flashReady = function () { UploadsManager.onFlashReady(this.id); };
SWFUpload.instances[this.flash_id].fileDialogStart = UploadsManager.onHandleEverything;
SWFUpload.instances[this.flash_id].fileQueued = UploadsManager.onFileQueued;
SWFUpload.instances[this.flash_id].fileQueueError = UploadsManager.onFileQueueError;
SWFUpload.instances[this.flash_id].fileDialogComplete = UploadsManager.onHandleEverything;
SWFUpload.instances[this.flash_id].uploadStart = UploadsManager.onUploadStart;
SWFUpload.instances[this.flash_id].uploadProgress = UploadsManager.onUploadProgress;
SWFUpload.instances[this.flash_id].uploadError = UploadsManager.onUploadError;
SWFUpload.instances[this.flash_id].uploadSuccess = UploadsManager.onUploadSuccess;
SWFUpload.instances[this.flash_id].uploadComplete = UploadsManager.onUploadComplete;
SWFUpload.instances[this.flash_id].debug = UploadsManager.onDebug;
this.swf = new SWFObject(this.params.baseUrl + '/swfupload.swf', this.flash_id, this.params.buttonWidth, this.params.buttonHeight, '9', '#FFFFFF');
this.swf.setAttribute('style', '');
this.swf.addParam('wmode', encodeURIComponent(this.params.wmode));
this.swf.addVariable('movieName', encodeURIComponent(this.flash_id));
this.swf.addVariable('fileUploadLimit', 0);
this.swf.addVariable('fileQueueLimit', encodeURIComponent(this.params.fileQueueLimit));
this.swf.addVariable('fileSizeLimit', encodeURIComponent(this.params.allowedFilesize)); // in kilobytes
this.swf.addVariable('fileTypes', encodeURIComponent(this.params.allowedFiletypes));
this.swf.addVariable('fileTypesDescription', encodeURIComponent(this.params.allowedFiletypesDescription));
this.swf.addVariable('uploadURL', encodeURIComponent(this.params.uploadURL));
// upload button appearance
this.swf.addVariable('buttonImageURL', encodeURIComponent(this.params.buttonImageURL));
this.swf.addVariable('buttonWidth', encodeURIComponent(this.params.buttonWidth));
this.swf.addVariable('buttonHeight', encodeURIComponent(this.params.buttonHeight));
this.swf.addVariable('buttonText', encodeURIComponent(this.params.buttonText));
this.swf.addVariable('buttonTextTopPadding', encodeURIComponent(this.params.buttonTextTopPadding));
this.swf.addVariable('buttonTextLeftPadding', encodeURIComponent(this.params.buttonTextLeftPadding));
this.swf.addVariable('buttonTextStyle', encodeURIComponent(this.params.buttonTextStyle));
this.swf.addVariable('buttonAction', encodeURIComponent(this.params.buttonAction));
this.swf.addVariable('buttonDisabled', encodeURIComponent(this.params.buttonDisabled));
this.swf.addVariable('buttonCursor', encodeURIComponent(this.params.buttonCursor));
if (UploadsManager._debugMode) {
this.swf.addVariable('debugEnabled', encodeURIComponent('true')); // flash var
}
var $me = this;
Application.setHook(
'm:OnAfterFormInit',
function () {
$me.renderBrowseButton();
}
)
if (this.params.json != '') {
var $json_decoded = this.params.json.split('|'), $file, $preview_url;
for (var $i = 0; $i < $json_decoded.length; $i++) {
$file = JSON.parse($json_decoded[$i]);
if ( $file.deleted ) {
this.deleted.push($file.name);
continue;
}
$file.url = this.getUrl($file, 'previewURL');
$file.uploaded = 1;
$file.progress = 100;
this.files.push($file);
this.files_count++;
}
this.updateInfo();
}
}
Uploader.prototype.getUrl = function($file, $param_name) {
var $url = this.params[$param_name];
$url = $url.replace('#TMP#', $file.temp);
$url = $url.replace('#ID#', $file.id);
$url = $url.replace('#FILE#', encodeURIComponent($file.name));
$url = $url.replace('#FIELD#', this.params.field);
return $url;
}
Uploader.prototype.enableUploadButton = function() {
var $me = this;
// enable upload button, when flash is fully loaded
this.queueEvent(
function() {
setTimeout(
function () {
$me.callFlash('SetButtonDisabled', [false]);
}, 0
)
}
);
}
Uploader.prototype.renderBrowseButton = function() {
var holder = document.getElementById(this.params.buttonPlaceholderId);
this.swf.write(holder);
this.flash = document.getElementById(this.flash_id);
}
Uploader.prototype.remove = function() {
var id = this.params.buttonPlaceholderId;
var obj = document.getElementById(id);
if (obj/* && obj.nodeName == "OBJECT"*/) {
var u = navigator.userAgent.toLowerCase();
var p = navigator.platform.toLowerCase();
var windows = p ? /win/.test(p) : /win/.test(u);
var $me = this;
if (document.all && windows) {
obj.style.display = "none";
(function(){
if (obj.readyState == 4) {
$me.removeObjectInIE(id);
}
else {
setTimeout(arguments.callee, 10);
}
})();
}
else {
obj.parentNode.removeChild(obj);
}
}
}
Uploader.prototype.removeObjectInIE = function(id) {
var obj = document.getElementById(id);
if (obj) {
for (var i in obj) {
if (typeof obj[i] == 'function') {
obj[i] = null;
}
}
obj.parentNode.removeChild(obj);
}
}
Uploader.prototype.isImage = function($filename) {
$filename.match(/\.([^.]*)$/);
var $ext = RegExp.$1.toLowerCase();
return $ext.match(/^(bmp|gif|jpg|jpeg|png)$/);
}
Uploader.prototype.getFileIcon = function($filename) {
$filename.match(/\.([^.]*)$/);
- var ext = RegExp.$1.toLowerCase();
+ var $ext = RegExp.$1.toLowerCase(),
+ $ext_overrides = {
+ 'doc': '^(docx|dotx|docm|dotm)$',
+ 'xls': '^(xlsx|xltx|xlsm|xltm|xlam|xlsb)$',
+ 'ppt': '^(pptx|potx|ppsx|ppam|pptm|potm|ppsm)$'
+ };
+
+ $.each($ext_overrides, function ($new_ext, $expression) {
+ var $regexp = new RegExp($expression);
+
+ if ( $ext.match($regexp) ) {
+ $ext = $new_ext;
+
+ return false;
+ }
+
+ return true;
+ });
+
+ var $icon = $ext.match(/^(ai|avi|bmp|cs|dll|doc|dot|exe|fla|gif|htm|html|jpg|js|mdb|mp3|pdf|ppt|rdp|swf|swt|txt|vsd|xls|xml|zip)$/) ? $ext : 'default.icon';
- $icon = ext.match(/^(ai|avi|bmp|cs|dll|doc|dot|exe|fla|gif|htm|html|jpg|js|mdb|mp3|pdf|ppt|rdp|swf|swt|txt|vsd|xls|xml|zip)$/) ? ext : 'default.icon';
return this.IconPath + '/' + $icon + '.gif';
}
Uploader.prototype.getQueueElement = function($file) {
var $ret = '';
var $icon_image = this.getFileIcon($file.name);
var $file_label = $file.name + ' (' + this._formatSize($file.size) + ')';
var $need_preview = false;
if (isset($file.uploaded)) {
// add deletion checkbox
$need_preview = (this.params.thumb_format.length > 0) && this.isImage($file.name);
$ret += '<div class="left delete-checkbox"><input type="checkbox" class="delete-file-btn" checked/></div>';
// add icon based on file type
$ret += '<div class="left">';
if ($need_preview) {
$ret += '<a href="' + $file.url + '" target="_new"><img class="thumbnail-image" large_src="' + $file.url + '&thumb=1" src="' + $icon_image + '" alt=""/></a>';
}
else {
$ret += '<img src="' + $icon_image + '"/>';
}
$ret += '</div>'
// add filename + preview link
$ret += '<div class="left file-label"><a href="' + $file.url + '" target="_new">' + $file_label + '</a></div>';
}
else {
// add icon based on file type
$ret += '<div class="left"><img src="' + $icon_image + '"/></div>';
// add filename
$ret += '<div class="left file-label">' + $file_label + '</div>';
// add empty progress bar
$ret += '<div id="' + $file.id + '_progress" class="progress-container left"><div class="progress-empty"><div class="progress-full" style="width: 0%;"></div></div></div>';
// add cancel upload link
$ret += '<div class="left"><a href="#" class="cancel-upload-btn">Cancel</a></div>';
}
$ret += '<div style="clear: both;"/>';
$ret = $('<div id="' + $file.id + '_queue_row" class="file' + ($need_preview ? ' preview' : '') + '">' + $ret + '</div>');
// set click events
var $me = this;
$('.delete-file-btn', $ret).click(
function ($e) {
$(this).attr('checked', UploadsManager.DeleteFile($me.id, $file) ? '' : 'checked');
}
);
$('.cancel-upload-btn', $ret).click(
function ($e) {
UploadsManager.CancelFile(UploadsManager._getUploader($file).id, $file.id);
return false;
}
);
// prepare auto-loading preview
var $image = $('img.thumbnail-image', $ret);
if ($image.length > 0) {
var $tmp_image = new Image();
$tmp_image.src = $image.attr('large_src');
$($tmp_image).load (
function ($e) {
$image.attr('src', $tmp_image.src).addClass('thumbnail');
}
);
}
return $ret;
}
Uploader.prototype.sortFiles = function($ordered_queue) {
var $file_id, $file_index;
for (var $i = 0; $i < $ordered_queue.length; $i++) {
$file_id = $ordered_queue[$i].replace(/_queue_row$/, '');
$file_index = this.getFileIndex({id: $file_id});
this.files[$file_index].order = $i;
}
}
Uploader.prototype.updateQueueFile = function($file_index, $delete_file) {
$queue_container = $( jq('#' + this.id + '_queueinfo') );
if ($delete_file !== undefined && $delete_file) {
$( jq('#' + this.files[$file_index].id + '_queue_row') ).remove();
if (this.files.length == 1) {
$queue_container.css('margin-top', '0px');
}
return ;
}
$ret = this.getQueueElement( this.files[$file_index] );
var $row = $( jq('#' + this.files[$file_index].id + '_queue_row') );
if ($row.length > 0) {
// file round -> replace
$row.replaceWith($ret);
}
else {
// file not found - add
$( jq('#' + this.id + '_queueinfo') ).append($ret);
$queue_container.css('margin-top', '8px');
}
}
Uploader.prototype.updateInfo = function($file_index, $prepare_only) {
if ($prepare_only === undefined || !$prepare_only) {
if ($file_index === undefined) {
for (var f = 0; f < this.files.length; f++) {
this.updateQueueFile(f);
}
}
else {
this.updateQueueFile($file_index);
}
}
this._prepareFiles();
}
Uploader.prototype.updateProgressOnly = function ($file_index) {
var $progress_code = '<div class="progress-empty" title="' + this.files[$file_index].progress + '%"><div class="progress-full" style="width: ' + this.files[$file_index].progress + '%;"></div></div>';
$('#' + this.files[$file_index].id + '_progress').html($progress_code);
}
Uploader.prototype.removeFile = function (file, $mark_deleted) {
var count = 0;
var n_files = new Array();
var $to_delete = [];
for (var f = 0; f < this.files.length; f++) {
if (this.files[f].id != file.id && this.files[f].name != file.id) {
n_files.push(this.files[f]);
count++;
}
else {
$to_delete.push(f);
}
}
for (var $i = 0; $i < $to_delete.length; $i++) {
this.updateQueueFile($to_delete[$i], true);
}
this.files = n_files;
this.files_count = count;
this.updateInfo(undefined, true);
if ( $mark_deleted !== undefined && $mark_deleted === true ) {
this.markDeleted(file.id);
}
}
Uploader.prototype.markDeleted = function ($file_name) {
if ( !in_array($file_name, this.deleted) ) {
this.deleted.push($file_name);
}
}
Uploader.prototype.unMarkDeleted = function ($file_name) {
var $file_index = array_search($file_name, this.deleted);
if ( $file_index !== -1 ) {
this.deleted.splice($file_index, 1);
}
}
Uploader.prototype.hasQueue = function() {
for (var f = 0; f < this.files.length; f++) {
if (isset(this.files[f].uploaded)) {
continue;
}
return true;
}
return false;
}
Uploader.prototype.startUpload = function() {
this.uploadCancelled = false;
if (!this.hasQueue()) {
return;
}
this.callFlash('StartUpload');
}
Uploader.prototype.cancelUpload = function() {
this.callFlash('StopUpload');
var $stats = this.callFlash('GetStats');
while ($stats.files_queued > 0) {
this.callFlash('CancelUpload');
$stats = this.callFlash('GetStats');
}
this.uploadCancelled = true;
}
Uploader.prototype.UploadFileStart = function(file) {
var $file_index = this.getFileIndex(file);
this.files[$file_index].progress = 0;
this.updateProgressOnly($file_index);
this.callFlash('AddFileParam', [file.id, 'field', this.params.field]);
this.callFlash('AddFileParam', [file.id, 'id', file.id]);
this.callFlash('AddFileParam', [file.id, 'flashsid', this.params.flashsid]);
// we can prevent user from adding any files here :)
this.callFlash('ReturnUploadStart', [true]);
}
Uploader.prototype.UploadProgress = function(file, bytesLoaded, bytesTotal) {
var $file_index = this.getFileIndex(file);
this.files[$file_index].progress = Math.round(bytesLoaded / bytesTotal * 100);
this.updateProgressOnly($file_index);
}
Uploader.prototype.UploadSuccess = function(file, serverData, receivedResponse) {
if (!receivedResponse) {
return ;
}
for (var f = 0; f < this.files.length; f++) {
if (this.files[f].id == file.id) {
// new uploaded file name returned by OnUploadFile event
this.files[f].name = serverData;
}
}
}
Uploader.prototype.UploadFileComplete = function(file) {
// file was uploaded OR file upload was cancelled
var $file_index = this.getFileIndex(file);
this.unMarkDeleted(file.name);
if ($file_index !== false) {
// in case if file upload was cancelled, then no info here
this.files[$file_index].uploaded = 1;
this.files[$file_index].progress = 100;
this.files[$file_index].temp = 1;
this.files[$file_index].url = this.getUrl(this.files[$file_index], 'previewURL');
this.files[$file_index].order = $file_index;
this.updateInfo($file_index);
}
// upload next file in queue
var $stats = this.callFlash('GetStats');
if ($stats.files_queued > 0) {
this.callFlash('StartUpload');
}
else {
UploadsManager.UploadQueueComplete(this);
}
}
Uploader.prototype.getFileIndex = function(file) {
for (var f = 0; f < this.files.length; f++) {
if (this.files[f].id == file.id) {
return f;
}
}
return false;
}
Uploader.prototype.queueEvent = function (function_body) {
// Warning: Don't call this.debug inside here or you'll create an infinite loop
var self = this;
// Queue the event
this._eventQueue.push(function_body);
if (!this.flashReady) {
// don't execute any flash-related events, while it's not completely loaded
return ;
}
// Execute the next queued event
setTimeout(
function () {
self._executeNextEvent();
}, 0
);
};
Uploader.prototype._executeQueuedEvents = function() {
var $me = this;
setTimeout(
function () {
$me._executeNextEvent();
if ($me._eventQueue.length > 0) {
$me._executeQueuedEvents();
}
}, 0
);
}
// Private: callFlash handles function calls made to the Flash element.
// Calls are made with a setTimeout for some functions to work around
// bugs in the ExternalInterface library.
Uploader.prototype.callFlash = function (functionName, argumentArray) {
argumentArray = argumentArray || [];
var returnValue;
if (typeof this.flash[functionName] === 'function') {
// We have to go through all this if/else stuff because the Flash functions don't have apply() and only accept the exact number of arguments.
if (argumentArray.length === 0) {
returnValue = this.flash[functionName]();
} else if (argumentArray.length === 1) {
returnValue = this.flash[functionName](argumentArray[0]);
} else if (argumentArray.length === 2) {
returnValue = this.flash[functionName](argumentArray[0], argumentArray[1]);
} else if (argumentArray.length === 3) {
returnValue = this.flash[functionName](argumentArray[0], argumentArray[1], argumentArray[2]);
} else {
throw 'Too many arguments';
}
// Unescape file post param values
if (returnValue != undefined && typeof returnValue.post === 'object') {
returnValue = this.unescapeFilePostParams(returnValue);
}
return returnValue;
} else {
// alert('invalid function name: ' + functionName);
throw "Invalid function name: " + functionName;
}
};
// Private: unescapeFileParams is part of a workaround for a flash bug where objects passed through ExternalInterface cannot have
// properties that contain characters that are not valid for JavaScript identifiers. To work around this
// the Flash Component escapes the parameter names and we must unescape again before passing them along.
Uploader.prototype.unescapeFilePostParams = function (file) {
var reg = /[$]([0-9a-f]{4})/i;
var unescapedPost = {};
var uk;
if (file != undefined) {
for (var k in file.post) {
if (file.post.hasOwnProperty(k)) {
uk = k;
var match;
while ((match = reg.exec(uk)) !== null) {
uk = uk.replace(match[0], String.fromCharCode(parseInt("0x" + match[1], 16)));
}
unescapedPost[uk] = file.post[k];
}
}
file.post = unescapedPost;
}
return file;
};
Uploader.prototype.onFlashReady = function() {
var $me = this;
this.flashReady = true;
// process events, queued before flash load
this._executeQueuedEvents();
}
\ No newline at end of file

Event Timeline