WordPress File Upload - Version 4.2.0

Version Description

  • changed logic of file sanitizer; dots in filename are by default converted to dashes, in order to avoid upload failures caused when the plugin detects double extensions
  • corrected bug where a Javascript error was generated when askforsubfolders was disabled and showtargetfolder was active
  • added css and js minifier in inline code
  • improved file transfers functionality
  • plugin modified so that Media record is deleted when the associated uploaded file is deleted from plugin's database
  • corrected bug where some plugin images were not loaded while Relax CSS option was inactive
Download this release

Release Info

Developer nickboss
Plugin Icon 128x128 WordPress File Upload
Version 4.2.0
Comparing to
See all releases

Code changes from version 4.1.0 to 4.2.0

js/wordpress_file_upload_functions.js CHANGED
@@ -1,4 +1,6 @@
1
  GlobalData={};Code_Initializators=[];GlobalData.WFU={n:[]};GlobalData.WFUB={n:[]};GlobalData.filestatematch={};GlobalData.filestatematch.success=[0,1,2,2];GlobalData.filestatematch.warning=[1,1,2,2];GlobalData.filestatematch.error1=[3,3,2,3];GlobalData.filestatematch.error2=[2,2,2,3];GlobalData.UploadInProgressString="";GlobalData.FreeChangeHandler=false;wfu_Check_Browser_Capabilities();
 
 
2
  function wfu_Initialize_Consts(consts){if(typeof GlobalData.consts!="undefined")return;GlobalData.consts=new Object;var consts_arr=consts.split(";");var const_arr;for(var i=0;i<consts_arr.length;i++){const_txt=consts_arr[i].split(":");GlobalData.consts[wfu_plugin_decode_string(const_txt[0])]=wfu_plugin_decode_string(const_txt[1])}}
3
  function wfu_Load_Code_Connectors(sid){if(typeof wfu_Code_Objects=="undefined")wfu_Code_Objects={};wfu_Code_Objects[sid]=new wfu_Code_Object(sid);for(var i=0;i<Code_Initializators.length;i++)wfu_Code_Objects[sid].additem(Code_Initializators[i](sid))}
4
  function wfu_Code_Object(sid){this.sid=sid;this.items=[];this._calc_prioritized_list=function(section){var item,list=[],idlist=[],nolist=[],priority;for(var i=0;i<this.items.length;i++){item=this.items[i];if(item[section]){priority=-1;if(item.priority)priority=item.priority;if(item[section].priority)priority=item[section].priority;if(priority>=0){list.push(priority);idlist.push(i)}else nolist.push(i)}}for(var i=1;i<list.length;i++)for(var j=i;j<list.length;j++)if(list[j]<list[i-1]){var temp=list[j];
@@ -8,7 +10,7 @@ item[section].func;if(func!=null){val=func.apply(this,Array.prototype.slice.call
8
  function wfu_plugin_load_action(sid){var WFU=GlobalData.WFU[sid];wfu_install_unload_hook();if(!!WFU.visualeditorbutton_exist){WFU.visualeditorbutton.init();var invoke_function=function(){wfu_invoke_shortcode_editor(WFU)};WFU.visualeditorbutton.attachInvokeHandler(invoke_function)}if(WFU.is_formupload)WFU.uploadaction=function(){wfu_redirect_to_classic(sid,0,0)};else WFU.uploadaction=function(){wfu_HTML5UploadFile(sid)};var clickaction=function(){wfu_selectbutton_clicked(sid)};var changeaction=function(fileselected){var WFU=
9
  GlobalData.WFU[sid];var usefilearray=0;wfu_selectbutton_changed(sid,usefilearray);wfu_update_uploadbutton_status(sid);if(WFU.singlebutton&&fileselected)WFU.uploadaction()};if(!!WFU.uploadform_exist)WFU.uploadform.attachActions(clickaction,changeaction);if(!!WFU.submit_exist){if(WFU.testmode)clickaction=function(){alert(GlobalData.consts.notify_testmode)};else clickaction=function(){WFU.uploadaction()};WFU.submit.attachClickAction(clickaction)}}
10
  function wfu_install_unload_hook(){window.onbeforeunload=wfu_unload_hook}function wfu_unload_hook(){if(GlobalData.UploadInProgressString!="")if(GlobalData.UploadInProgressString.trim()!="")return GlobalData.consts.wfu_pageexit_prompt}
11
- function wfu_Check_Browser_Capabilities(){if(typeof wfu_BrowserCaps!="undefined")return;wfu_BrowserCaps=new Object;var xmlhttp=wfu_GetHttpRequestObject();wfu_BrowserCaps.supportsAJAX=xmlhttp!=null;wfu_BrowserCaps.supportsUploadProgress=!!(xmlhttp&&"upload"in xmlhttp&&"onprogress"in xmlhttp.upload);var fd=null;try{var fd=new FormData}catch(e$0){}wfu_BrowserCaps.supportsHTML5=fd!=null;var e=document.createElement("iframe");wfu_BrowserCaps.supportsIFRAME=e!=null;wfu_BrowserCaps.supportsDRAGDROP=window.FileReader?
12
  true:false;wfu_BrowserCaps.supportsAnimation=wfu_check_animation();wfu_BrowserCaps.isSafari=Object.prototype.toString.call(window.HTMLElement).indexOf("Constructor")>0}
13
  function wfu_check_animation(){var animation=false,animationstring="animation",keyframeprefix="",domPrefixes="Webkit Moz O ms Khtml".split(" "),pfx="";var elm=document.createElement("DIV");if(elm.style.animationName)animation=true;if(animation===false)for(var i=0;i<domPrefixes.length;i++)if(elm.style[domPrefixes[i]+"AnimationName"]!==undefined){pfx=domPrefixes[i];animationstring=pfx+"Animation";keyframeprefix="-"+pfx.toLowerCase()+"-";animation=true;break}return animation}
14
  function wfu_join_strings(delimeter){var args=[].slice.call(arguments);var str="";var delim="";for(var i=1;i<args.length;i++){if(str==""||args[i]=="")delim="";else delim=delimeter;str+=delim+args[i]}return str}
@@ -16,7 +18,7 @@ function wfu_plugin_decode_string(str){var i=0;var newstr="";var num,val;while(i
16
  function wfu_plugin_encode_string(str){var i=0;var newstr="";var hex="";for(i=0;i<str.length;i++){num=str.charCodeAt(i);if(num>=2048)num=((num&16773120|917504)<<4)+((num&4032|8192)<<2)+(num&63|128);else if(num>=128)num=((num&65472|12288)<<2)+(num&63|128);hex=num.toString(16);if(hex.length==1||hex.length==3||hex.length==5)hex="0"+hex;newstr+=hex}return newstr}
17
  function wfu_randomString(len){var chars="0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";var string_length=len;var randomstring="";for(var i=0;i<string_length;i++){var rnum=Math.floor(Math.random()*chars.length);randomstring+=chars.substring(rnum,rnum+1)}return randomstring}function wfu_addEventHandler(obj,evt,handler){if(obj.addEventListener)obj.addEventListener(evt,handler,false);else if(obj.attachEvent)obj.attachEvent("on"+evt,handler);else obj["on"+evt]=handler}
18
  function wfu_attach_element_handlers(item,handler){var elem_events=["DOMAttrModified","textInput","input","change","keypress","paste","focus","propertychange"];for(var i=0;i<elem_events.length;i++)wfu_addEventHandler(item,elem_events[i],handler)}
19
- function wfu_GetHttpRequestObject(){var xhr=null;try{xhr=new XMLHttpRequest}catch(e$1){try{xhr=new ActiveXObject("Msxml2.XMLHTTP")}catch(e2){try{xhr=new ActiveXObject("Microsoft.XMLHTTP")}catch(e){}}}if(xhr==null&&window.createRequest)try{xmlhttp=window.createRequest()}catch(e$2){}return xhr}
20
  function wfu_get_filelist(sid,include_filearray){var WFU=GlobalData.WFU[sid];include_filearray=typeof include_filearray!=="undefined"?include_filearray:true;var farr=[];if(!!WFU.uploadform_exist)farr=WFU.uploadform.files();if(include_filearray&&typeof WFU.filearray!=="undefined")farr=WFU.filearray;return farr}
21
  function wfu_add_files(sid,files){var WFU=GlobalData.WFU[sid];if(typeof WFU.filearray=="undefined"){WFU.filearray=Array();WFU.filearrayprops=Array()}if(!!WFU.uploadform_exist)WFU.uploadform.reset();WFU.filearray.length=WFU.filearrayprops.length=0;for(var i=0;i<files.length;i++){WFU.filearray.push(files[i].file);WFU.filearrayprops.push(files[i].props)}}
22
  function wfu_attach_cancel_event(sid,unique_upload_id){function wfu_cancel_classic_upload_final(){var Params=wfu_Initialize_Params();Params.general.shortcode_id=sid;Params.general.unique_id="";Params.general.files_count=0;Params.general.state=16;wfu_ProcessUploadComplete(sid,0,Params,"no-ajax","",[false,null,false]);if(!!WFU.uploadform_exist){WFU.uploadform.reset();WFU.uploadform.submit();WFU.uploadform.lock()}}function wfu_cancel_classic_upload(){var url=GlobalData.consts.ajax_url+"?action=wfu_ajax_action_cancel_upload&wfu_uploader_nonce="+
@@ -143,4 +145,4 @@ wfu_webcam_onstop=function(e,sid){var webcam_obj=GlobalData.WFU[sid].webcam;var
143
  wfu_webcam_play=function(sid){var webcam_obj=GlobalData.WFU[sid].webcam;var webcam_props=GlobalData.WFU[sid].webcamProps;if(webcam_props.playing)return;webcam_obj.updateButtonStatus("playing");webcam_props.playing=true;webcam_obj.play()};wfu_webcam_ended=function(sid){var webcam_obj=GlobalData.WFU[sid].webcam;var webcam_props=GlobalData.WFU[sid].webcamProps;webcam_obj.ended();webcam_obj.updateButtonStatus("ready_playback");webcam_props.playing=false};
144
  wfu_webcam_pause=function(sid){var webcam_obj=GlobalData.WFU[sid].webcam;var webcam_props=GlobalData.WFU[sid].webcamProps;webcam_obj.pause();webcam_obj.updateButtonStatus("ready_playback");webcam_props.playing=false};wfu_webcam_back=function(sid){GlobalData.WFU[sid].webcam.back()};wfu_webcam_fwd=function(sid){var webcam_obj=GlobalData.WFU[sid].webcam;var webcam_props=GlobalData.WFU[sid].webcamProps;webcam_obj.fwd(webcam_props.duration)};
145
  wfu_webcam_take_picture=function(sid){var webcam_obj=GlobalData.WFU[sid].webcam;var webcam_props=GlobalData.WFU[sid].webcamProps;if(webcam_props.stream){webcam_obj.screenshot(function(image_file){image_file.name="image.png";wfu_add_files(sid,[{file:image_file,props:{}}],false);wfu_update_uploadbutton_status(sid)},"image/png");webcam_obj.updateButtonStatus("after_screenshot")}};
146
- wfu_webcam_update_pos=function(sid){var webcam_obj=GlobalData.WFU[sid].webcam;var webcam_props=GlobalData.WFU[sid].webcamProps;webcam_obj.updatePlayProgress(webcam_props.duration);webcam_obj.updateTimer(video.currentTime)};
1
  GlobalData={};Code_Initializators=[];GlobalData.WFU={n:[]};GlobalData.WFUB={n:[]};GlobalData.filestatematch={};GlobalData.filestatematch.success=[0,1,2,2];GlobalData.filestatematch.warning=[1,1,2,2];GlobalData.filestatematch.error1=[3,3,2,3];GlobalData.filestatematch.error2=[2,2,2,3];GlobalData.UploadInProgressString="";GlobalData.FreeChangeHandler=false;wfu_Check_Browser_Capabilities();
2
+ if(typeof wfu_js_decode_obj=="undefined")var wfu_js_decode_obj$0=function(obj_str){var obj=null;if(obj_str=="window")obj=window;else{var match=obj_str.match(/GlobalData(\.(WFU|WFUB)\[(.*?)\](\.(.*))?)?$/);if(match){obj=GlobalData;if(match[3])obj=obj[match[2]][match[3]];if(match[5])obj=obj[match[5]]}}return obj};
3
+ function wfu_run_js_from_bank(){if(typeof WFU_JS_BANK!="undefined")while(WFU_JS_BANK.length>0){var obj=wfu_js_decode_obj(WFU_JS_BANK[0].obj_str);if(obj)obj[WFU_JS_BANK[0].func].call(obj);WFU_JS_BANK.splice(0,1)}}
4
  function wfu_Initialize_Consts(consts){if(typeof GlobalData.consts!="undefined")return;GlobalData.consts=new Object;var consts_arr=consts.split(";");var const_arr;for(var i=0;i<consts_arr.length;i++){const_txt=consts_arr[i].split(":");GlobalData.consts[wfu_plugin_decode_string(const_txt[0])]=wfu_plugin_decode_string(const_txt[1])}}
5
  function wfu_Load_Code_Connectors(sid){if(typeof wfu_Code_Objects=="undefined")wfu_Code_Objects={};wfu_Code_Objects[sid]=new wfu_Code_Object(sid);for(var i=0;i<Code_Initializators.length;i++)wfu_Code_Objects[sid].additem(Code_Initializators[i](sid))}
6
  function wfu_Code_Object(sid){this.sid=sid;this.items=[];this._calc_prioritized_list=function(section){var item,list=[],idlist=[],nolist=[],priority;for(var i=0;i<this.items.length;i++){item=this.items[i];if(item[section]){priority=-1;if(item.priority)priority=item.priority;if(item[section].priority)priority=item[section].priority;if(priority>=0){list.push(priority);idlist.push(i)}else nolist.push(i)}}for(var i=1;i<list.length;i++)for(var j=i;j<list.length;j++)if(list[j]<list[i-1]){var temp=list[j];
10
  function wfu_plugin_load_action(sid){var WFU=GlobalData.WFU[sid];wfu_install_unload_hook();if(!!WFU.visualeditorbutton_exist){WFU.visualeditorbutton.init();var invoke_function=function(){wfu_invoke_shortcode_editor(WFU)};WFU.visualeditorbutton.attachInvokeHandler(invoke_function)}if(WFU.is_formupload)WFU.uploadaction=function(){wfu_redirect_to_classic(sid,0,0)};else WFU.uploadaction=function(){wfu_HTML5UploadFile(sid)};var clickaction=function(){wfu_selectbutton_clicked(sid)};var changeaction=function(fileselected){var WFU=
11
  GlobalData.WFU[sid];var usefilearray=0;wfu_selectbutton_changed(sid,usefilearray);wfu_update_uploadbutton_status(sid);if(WFU.singlebutton&&fileselected)WFU.uploadaction()};if(!!WFU.uploadform_exist)WFU.uploadform.attachActions(clickaction,changeaction);if(!!WFU.submit_exist){if(WFU.testmode)clickaction=function(){alert(GlobalData.consts.notify_testmode)};else clickaction=function(){WFU.uploadaction()};WFU.submit.attachClickAction(clickaction)}}
12
  function wfu_install_unload_hook(){window.onbeforeunload=wfu_unload_hook}function wfu_unload_hook(){if(GlobalData.UploadInProgressString!="")if(GlobalData.UploadInProgressString.trim()!="")return GlobalData.consts.wfu_pageexit_prompt}
13
+ function wfu_Check_Browser_Capabilities(){if(typeof wfu_BrowserCaps!="undefined")return;wfu_BrowserCaps=new Object;var xmlhttp=wfu_GetHttpRequestObject();wfu_BrowserCaps.supportsAJAX=xmlhttp!=null;wfu_BrowserCaps.supportsUploadProgress=!!(xmlhttp&&"upload"in xmlhttp&&"onprogress"in xmlhttp.upload);var fd=null;try{var fd=new FormData}catch(e$1){}wfu_BrowserCaps.supportsHTML5=fd!=null;var e=document.createElement("iframe");wfu_BrowserCaps.supportsIFRAME=e!=null;wfu_BrowserCaps.supportsDRAGDROP=window.FileReader?
14
  true:false;wfu_BrowserCaps.supportsAnimation=wfu_check_animation();wfu_BrowserCaps.isSafari=Object.prototype.toString.call(window.HTMLElement).indexOf("Constructor")>0}
15
  function wfu_check_animation(){var animation=false,animationstring="animation",keyframeprefix="",domPrefixes="Webkit Moz O ms Khtml".split(" "),pfx="";var elm=document.createElement("DIV");if(elm.style.animationName)animation=true;if(animation===false)for(var i=0;i<domPrefixes.length;i++)if(elm.style[domPrefixes[i]+"AnimationName"]!==undefined){pfx=domPrefixes[i];animationstring=pfx+"Animation";keyframeprefix="-"+pfx.toLowerCase()+"-";animation=true;break}return animation}
16
  function wfu_join_strings(delimeter){var args=[].slice.call(arguments);var str="";var delim="";for(var i=1;i<args.length;i++){if(str==""||args[i]=="")delim="";else delim=delimeter;str+=delim+args[i]}return str}
18
  function wfu_plugin_encode_string(str){var i=0;var newstr="";var hex="";for(i=0;i<str.length;i++){num=str.charCodeAt(i);if(num>=2048)num=((num&16773120|917504)<<4)+((num&4032|8192)<<2)+(num&63|128);else if(num>=128)num=((num&65472|12288)<<2)+(num&63|128);hex=num.toString(16);if(hex.length==1||hex.length==3||hex.length==5)hex="0"+hex;newstr+=hex}return newstr}
19
  function wfu_randomString(len){var chars="0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";var string_length=len;var randomstring="";for(var i=0;i<string_length;i++){var rnum=Math.floor(Math.random()*chars.length);randomstring+=chars.substring(rnum,rnum+1)}return randomstring}function wfu_addEventHandler(obj,evt,handler){if(obj.addEventListener)obj.addEventListener(evt,handler,false);else if(obj.attachEvent)obj.attachEvent("on"+evt,handler);else obj["on"+evt]=handler}
20
  function wfu_attach_element_handlers(item,handler){var elem_events=["DOMAttrModified","textInput","input","change","keypress","paste","focus","propertychange"];for(var i=0;i<elem_events.length;i++)wfu_addEventHandler(item,elem_events[i],handler)}
21
+ function wfu_GetHttpRequestObject(){var xhr=null;try{xhr=new XMLHttpRequest}catch(e$2){try{xhr=new ActiveXObject("Msxml2.XMLHTTP")}catch(e2){try{xhr=new ActiveXObject("Microsoft.XMLHTTP")}catch(e){}}}if(xhr==null&&window.createRequest)try{xmlhttp=window.createRequest()}catch(e$3){}return xhr}
22
  function wfu_get_filelist(sid,include_filearray){var WFU=GlobalData.WFU[sid];include_filearray=typeof include_filearray!=="undefined"?include_filearray:true;var farr=[];if(!!WFU.uploadform_exist)farr=WFU.uploadform.files();if(include_filearray&&typeof WFU.filearray!=="undefined")farr=WFU.filearray;return farr}
23
  function wfu_add_files(sid,files){var WFU=GlobalData.WFU[sid];if(typeof WFU.filearray=="undefined"){WFU.filearray=Array();WFU.filearrayprops=Array()}if(!!WFU.uploadform_exist)WFU.uploadform.reset();WFU.filearray.length=WFU.filearrayprops.length=0;for(var i=0;i<files.length;i++){WFU.filearray.push(files[i].file);WFU.filearrayprops.push(files[i].props)}}
24
  function wfu_attach_cancel_event(sid,unique_upload_id){function wfu_cancel_classic_upload_final(){var Params=wfu_Initialize_Params();Params.general.shortcode_id=sid;Params.general.unique_id="";Params.general.files_count=0;Params.general.state=16;wfu_ProcessUploadComplete(sid,0,Params,"no-ajax","",[false,null,false]);if(!!WFU.uploadform_exist){WFU.uploadform.reset();WFU.uploadform.submit();WFU.uploadform.lock()}}function wfu_cancel_classic_upload(){var url=GlobalData.consts.ajax_url+"?action=wfu_ajax_action_cancel_upload&wfu_uploader_nonce="+
145
  wfu_webcam_play=function(sid){var webcam_obj=GlobalData.WFU[sid].webcam;var webcam_props=GlobalData.WFU[sid].webcamProps;if(webcam_props.playing)return;webcam_obj.updateButtonStatus("playing");webcam_props.playing=true;webcam_obj.play()};wfu_webcam_ended=function(sid){var webcam_obj=GlobalData.WFU[sid].webcam;var webcam_props=GlobalData.WFU[sid].webcamProps;webcam_obj.ended();webcam_obj.updateButtonStatus("ready_playback");webcam_props.playing=false};
146
  wfu_webcam_pause=function(sid){var webcam_obj=GlobalData.WFU[sid].webcam;var webcam_props=GlobalData.WFU[sid].webcamProps;webcam_obj.pause();webcam_obj.updateButtonStatus("ready_playback");webcam_props.playing=false};wfu_webcam_back=function(sid){GlobalData.WFU[sid].webcam.back()};wfu_webcam_fwd=function(sid){var webcam_obj=GlobalData.WFU[sid].webcam;var webcam_props=GlobalData.WFU[sid].webcamProps;webcam_obj.fwd(webcam_props.duration)};
147
  wfu_webcam_take_picture=function(sid){var webcam_obj=GlobalData.WFU[sid].webcam;var webcam_props=GlobalData.WFU[sid].webcamProps;if(webcam_props.stream){webcam_obj.screenshot(function(image_file){image_file.name="image.png";wfu_add_files(sid,[{file:image_file,props:{}}],false);wfu_update_uploadbutton_status(sid)},"image/png");webcam_obj.updateButtonStatus("after_screenshot")}};
148
+ wfu_webcam_update_pos=function(sid){var webcam_obj=GlobalData.WFU[sid].webcam;var webcam_props=GlobalData.WFU[sid].webcamProps;webcam_obj.updatePlayProgress(webcam_props.duration);webcam_obj.updateTimer(video.currentTime)};wfu_run_js_from_bank();
lib/wfu_admin_browser.php CHANGED
@@ -550,11 +550,8 @@ function wfu_delete_file($file_code, $type) {
550
  if ( $_POST['submit'] == "Delete" ) {
551
  foreach ( $dec_files as $dec_file ) {
552
  //pre-log delete action
553
- if ( $type == 'file' ) $retid = wfu_log_action('delete', $dec_file, $user->ID, '', 0, 0, '', null);
554
- if ( $type == 'dir' && $dec_file != "" ) wfu_delTree($dec_file);
555
- else unlink($dec_file);
556
- //revert log action if file has not been deleted
557
- if ( $type == 'file' && file_exists($dec_file) ) wfu_revert_log_action($retid);
558
  }
559
  }
560
  }
550
  if ( $_POST['submit'] == "Delete" ) {
551
  foreach ( $dec_files as $dec_file ) {
552
  //pre-log delete action
553
+ if ( $type == 'file' ) wfu_delete_file_execute($dec_file, $user->ID);
554
+ elseif ( $type == 'dir' && $dec_file != "" ) wfu_delTree($dec_file);
 
 
 
555
  }
556
  }
557
  }
lib/wfu_blocks.php CHANGED
@@ -512,7 +512,7 @@ function wfu_prepare_userdata_block($params, $additional_params, $occurrence_ind
512
  $userdata_init = "";
513
  $userdata_init .= "\n".'GlobalData.WFU['.$data["ID"].'].userdata._init'.$init_index.' = GlobalData.WFU['.$data["ID"].'].userdata.init;';
514
  $userdata_init .= "\n".'GlobalData.WFU['.$data["ID"].'].userdata.init = function() {';
515
- $userdata_init .= "\n\t".'this._init'.$init_index.'();';
516
  $userdata_init .= "\n\t".'var WFU = GlobalData.WFU['.$data["ID"].'];';
517
  if ( $init_index == 0 ) {
518
  $userdata_init .= "\n\t".'if (typeof WFU.userdata.init_count == "undefined") {';
512
  $userdata_init = "";
513
  $userdata_init .= "\n".'GlobalData.WFU['.$data["ID"].'].userdata._init'.$init_index.' = GlobalData.WFU['.$data["ID"].'].userdata.init;';
514
  $userdata_init .= "\n".'GlobalData.WFU['.$data["ID"].'].userdata.init = function() {';
515
+ $userdata_init .= "\n\t".'GlobalData.WFU['.$data["ID"].'].userdata._init'.$init_index.'();';
516
  $userdata_init .= "\n\t".'var WFU = GlobalData.WFU['.$data["ID"].'];';
517
  if ( $init_index == 0 ) {
518
  $userdata_init .= "\n\t".'if (typeof WFU.userdata.init_count == "undefined") {';
lib/wfu_constants.php CHANGED
@@ -298,6 +298,7 @@ $GLOBALS["WFU_GLOBALS"] += array(
298
  "WFU_HISTORYLOG_TABLE_MAXROWS" => array( "History Log Table Rows Per Page", "integer", 25, "The number of rows per page of the History Log table." ),
299
  "WFU_ALTERNATIVE_RANDOMIZER" => array( "Use Alternative Randomizer", "string", "false", "On fast web servers the plugin's generator of random strings may not work properly causing various problems. If it is set to true, an alternative randomizer method is employed that works for fast web servers. It can be 'true' or 'false'." ),
300
  "WFU_FORCE_NOTIFICATIONS" => array( "Force Email Notifications", "string", "false", "Send email notifications (if they are activated) even if no file has been uploaded. It can be 'true' or 'false'." ),
 
301
  "WFU_DASHBOARD_PROTECTED" => array( "Dashboard Is Protected", "string", "false", "If /wp-admin folder is password protected then this variable should be set to 'true' so that internal operations of the plugin can work. The username and password should also be set." ),
302
  "WFU_DASHBOARD_USERNAME" => array( "Protected Dashboard Username", "string", "", "Username entry for accessing protected /wp-admin folder." ),
303
  "WFU_DASHBOARD_PASSWORD" => array( "Protected Dashboard Password", "string", "", "Password entry for accessing protected /wp-admin folder." ),
@@ -307,7 +308,9 @@ $GLOBALS["WFU_GLOBALS"] += array(
307
  "WFU_RELAX_CURL_VERIFY_HOST" => array( "Relax cURL Host Verification", "string", "false", "If it is set to 'true' then CURLOPT_SSL_VERIFYHOST will be disabled when executing a cURL POST request. This is required in some cases so that the plugin can reach https://services2.iptanus.com, because on some servers it fails with a file_get_contents warning. It can be 'true' or 'false'." ),
308
  "WFU_USE_ALT_IPTANUS_SERVER" => array( "Use Alternative Iptanus Server", "string", "false", "If it is set to 'true' then the alternative Iptanus server will be used. This is a work-around in some cases where the website cannot reach https://services2.iptanus.com. It can be 'true' or 'false'." ),
309
  "WFU_ALT_IPTANUS_SERVER" => array( "Alternative Iptanus Server", "string", "https://iptanusservices.appspot.com", "If it is set then this is the URL of the alternative Iptanus server." ),
310
- "WFU_ALT_VERSION_SERVER" => array( "Alternative Version Server", "string", "https://iptanusservices.appspot.com/g79xo30q8s", "If the alternative Iptanus server is used and this variable is not empty, then it will be used as the alternative Version Server URL." )
 
 
311
  );
312
  //color definitions
313
  $GLOBALS["WFU_GLOBALS"] += array(
298
  "WFU_HISTORYLOG_TABLE_MAXROWS" => array( "History Log Table Rows Per Page", "integer", 25, "The number of rows per page of the History Log table." ),
299
  "WFU_ALTERNATIVE_RANDOMIZER" => array( "Use Alternative Randomizer", "string", "false", "On fast web servers the plugin's generator of random strings may not work properly causing various problems. If it is set to true, an alternative randomizer method is employed that works for fast web servers. It can be 'true' or 'false'." ),
300
  "WFU_FORCE_NOTIFICATIONS" => array( "Force Email Notifications", "string", "false", "Send email notifications (if they are activated) even if no file has been uploaded. It can be 'true' or 'false'." ),
301
+ "WFU_UPDATE_MEDIA_ON_DELETE" => array( "Update Media on Delete", "string", "true", "When an uploaded file is deleted then delete also the corresponding Media Library item if exists. It can be 'true' or 'false'." ),
302
  "WFU_DASHBOARD_PROTECTED" => array( "Dashboard Is Protected", "string", "false", "If /wp-admin folder is password protected then this variable should be set to 'true' so that internal operations of the plugin can work. The username and password should also be set." ),
303
  "WFU_DASHBOARD_USERNAME" => array( "Protected Dashboard Username", "string", "", "Username entry for accessing protected /wp-admin folder." ),
304
  "WFU_DASHBOARD_PASSWORD" => array( "Protected Dashboard Password", "string", "", "Password entry for accessing protected /wp-admin folder." ),
308
  "WFU_RELAX_CURL_VERIFY_HOST" => array( "Relax cURL Host Verification", "string", "false", "If it is set to 'true' then CURLOPT_SSL_VERIFYHOST will be disabled when executing a cURL POST request. This is required in some cases so that the plugin can reach https://services2.iptanus.com, because on some servers it fails with a file_get_contents warning. It can be 'true' or 'false'." ),
309
  "WFU_USE_ALT_IPTANUS_SERVER" => array( "Use Alternative Iptanus Server", "string", "false", "If it is set to 'true' then the alternative Iptanus server will be used. This is a work-around in some cases where the website cannot reach https://services2.iptanus.com. It can be 'true' or 'false'." ),
310
  "WFU_ALT_IPTANUS_SERVER" => array( "Alternative Iptanus Server", "string", "https://iptanusservices.appspot.com", "If it is set then this is the URL of the alternative Iptanus server." ),
311
+ "WFU_ALT_VERSION_SERVER" => array( "Alternative Version Server", "string", "https://iptanusservices.appspot.com/g79xo30q8s", "If the alternative Iptanus server is used and this variable is not empty, then it will be used as the alternative Version Server URL." ),
312
+ "WFU_MINIFY_INLINE_CSS" => array( "Minify Inline CSS Code", "string", "true", "Defines whether the inline CSS code will be minified. It can be 'true' or 'false'." ),
313
+ "WFU_MINIFY_INLINE_JS" => array( "Minify Inline JS Code", "string", "true", "Defines whether the inline Javascript code will be minified. It can be 'true' or 'false'." )
314
  );
315
  //color definitions
316
  $GLOBALS["WFU_GLOBALS"] += array(
lib/wfu_functions.php CHANGED
@@ -410,7 +410,39 @@ function wfu_echo_array($arr) {
410
  echo '<pre>'.print_r($arr, true).'</pre>';
411
  }
412
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
413
  function wfu_css_to_HTML($css) {
 
 
 
 
414
  $echo_str = "\n\t".'<style>';
415
  $echo_str .= "\n".$css;
416
  $echo_str .= "\n\t".'</style>';
@@ -419,13 +451,23 @@ function wfu_css_to_HTML($css) {
419
  }
420
 
421
  function wfu_js_to_HTML($js) {
422
- $echo_str = "\n\t".'<script type="text/javascript">';
 
 
 
 
423
  $echo_str .= "\n".$js;
424
- $echo_str .= "\n\t".'</script>';
425
 
426
  return $echo_str;
427
  }
428
 
 
 
 
 
 
 
429
  function wfu_PHP_array_to_JS_object($arr) {
430
  $ret = "";
431
  foreach ( $arr as $prop => $value ) {
@@ -597,6 +639,19 @@ function wfu_path_rel2abs($path) {
597
  return ( substr($path, 0, 6) == 'ftp://' || substr($path, 0, 7) == 'ftps://' || substr($path, 0, 7) == 'sftp://' ? $path : wfu_abspath().$path );
598
  }
599
 
 
 
 
 
 
 
 
 
 
 
 
 
 
600
  function wfu_upload_plugin_full_path( $params ) {
601
  $path = $params["uploadpath"];
602
  if ( $params["accessmethod"] == 'ftp' && $params["ftpinfo"] != '' && $params["useftpdomain"] == "true" ) {
@@ -1014,22 +1069,7 @@ function wfu_log_action($action, $filepath, $userid, $uploadid, $pageid, $blogid
1014
  'date_to' => 0,
1015
  'action' => $action
1016
  ),
1017
- array(
1018
- '%d',
1019
- '%d',
1020
- '%d',
1021
- '%s',
1022
- '%s',
1023
- '%s',
1024
- '%d',
1025
- '%s',
1026
- '%d',
1027
- '%d',
1028
- '%s',
1029
- '%s',
1030
- '%s',
1031
- '%s'
1032
- )) !== false ) {
1033
  $retid = $wpdb->insert_id;
1034
  // if new log record has been created, also create user data records
1035
  if ( $userdata != null && $uploadid != '' ) {
@@ -1045,15 +1085,7 @@ function wfu_log_action($action, $filepath, $userid, $uploadid, $pageid, $blogid
1045
  'date_from' => $now_date,
1046
  'date_to' => 0
1047
  ),
1048
- array(
1049
- '%s',
1050
- '%s',
1051
- '%d',
1052
- '%s',
1053
- '%s',
1054
- '%s'
1055
- )
1056
- );
1057
  }
1058
  }
1059
  }
@@ -1093,9 +1125,10 @@ function wfu_log_action($action, $filepath, $userid, $uploadid, $pageid, $blogid
1093
  'date_from' => $now_date,
1094
  'date_to' => 0,
1095
  'action' => 'rename',
1096
- 'linkedto' => $filerec->idlog
 
1097
  ),
1098
- array( '%d', '%d', '%d', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%s', '%s', '%s', '%s', '%d' ) ) !== false )
1099
  $retid = $wpdb->insert_id;
1100
  }
1101
  }
@@ -1129,9 +1162,10 @@ function wfu_log_action($action, $filepath, $userid, $uploadid, $pageid, $blogid
1129
  'date_from' => $now_date,
1130
  'date_to' => $now_date,
1131
  'action' => 'delete',
1132
- 'linkedto' => $filerec->idlog
 
1133
  ),
1134
- array( '%d', '%d', '%d', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%s', '%s', '%s', '%s', '%d' )) != false )
1135
  $retid = $wpdb->insert_id;
1136
  }
1137
  }
@@ -1165,9 +1199,10 @@ function wfu_log_action($action, $filepath, $userid, $uploadid, $pageid, $blogid
1165
  'date_from' => $now_date,
1166
  'date_to' => 0,
1167
  'action' => 'download',
1168
- 'linkedto' => $filerec->idlog
 
1169
  ),
1170
- array( '%d', '%d', '%d', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%s', '%s', '%s', '%s', '%d' )) != false )
1171
  $retid = $wpdb->insert_id;
1172
  }
1173
  }
@@ -1202,9 +1237,10 @@ function wfu_log_action($action, $filepath, $userid, $uploadid, $pageid, $blogid
1202
  'date_from' => $now_date,
1203
  'date_to' => 0,
1204
  'action' => 'modify',
1205
- 'linkedto' => $filerec->idlog
 
1206
  ),
1207
- array( '%d', '%d', '%d', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%s', '%s', '%s', '%s', '%d' )) != false )
1208
  $retid = $wpdb->insert_id;
1209
  }
1210
  }
@@ -1239,9 +1275,10 @@ function wfu_log_action($action, $filepath, $userid, $uploadid, $pageid, $blogid
1239
  'date_from' => $now_date,
1240
  'date_to' => 0,
1241
  'action' => 'changeuser',
1242
- 'linkedto' => $filerec->idlog
 
1243
  ),
1244
- array( '%d', '%d', '%d', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%s', '%s', '%s', '%s', '%d' )) != false )
1245
  $retid = $wpdb->insert_id;
1246
  }
1247
  }
@@ -1347,6 +1384,79 @@ function wfu_get_file_rec_from_id($idlog) {
1347
  return $filerec;
1348
  }
1349
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1350
  //get userdata from uploadid
1351
  function wfu_get_userdata_from_uploadid($uploadid) {
1352
  global $wpdb;
@@ -1922,12 +2032,25 @@ function wfu_read_template_output($blockname, $data) {
1922
  function wfu_template_to_HTML($blockname, $params, $additional_params, $occurrence_index) {
1923
  $plugin_options = wfu_decode_plugin_options(get_option( "wordpress_file_upload_options" ));
1924
  $block = call_user_func("wfu_prepare_".$blockname."_block", $params, $additional_params, $occurrence_index);
 
 
 
 
 
 
 
 
1925
  $css = $block["css"];
1926
- $js = $block["js"];
 
 
 
 
 
1927
  //relax css rules if this option is enabled
1928
  if ( $plugin_options['relaxcss'] == '1' ) $css = preg_replace('#.*?/\*relax\*/\s*#', '', $css);
1929
  $echo_str = wfu_css_to_HTML($css);
1930
- $echo_str .= wfu_js_to_HTML($js);
1931
  $k = 1;
1932
  while ( isset($block["line".$k]) ) {
1933
  if ( $block["line".$k] != "" ) $echo_str .= "\n".$block["line".$k];
@@ -2111,6 +2234,15 @@ function wfu_process_media_insert($file_path, $userdata_fields, $page_id){
2111
  foreach ( $userdata_fields as $userdata_field )
2112
  $attach_data["WFU User Data"][$userdata_field["label"]] = $userdata_field["value"];
2113
  $update_attach = wp_update_attachment_metadata( $attach_id, $attach_data );
 
 
 
 
 
 
 
 
 
2114
 
2115
  return $attach_id;
2116
  }
410
  echo '<pre>'.print_r($arr, true).'</pre>';
411
  }
412
 
413
+ function wfu_minify_code($lang, $code) {
414
+ $ret = array( "result" => false, "minified_code" => "" );
415
+ $php_version = preg_replace("/-.*/", "", phpversion());
416
+ $unsupported = false;
417
+ $ret = wfu_compare_versions($php_version, '5.3.0');
418
+ $unsupported = ( $ret['status'] && $ret['result'] == 'lower' );
419
+ if ( !$unsupported ) {
420
+ $path = ABSWPFILEUPLOAD_DIR;
421
+ include_once $path.'vendor/minifier/minify/src/Minify.php';
422
+ include_once $path.'vendor/minifier/minify/src/CSS.php';
423
+ include_once $path.'vendor/minifier/minify/src/JS.php';
424
+ include_once $path.'vendor/minifier/minify/src/Exception.php';
425
+ include_once $path.'vendor/minifier/minify/src/Exceptions/BasicException.php';
426
+ include_once $path.'vendor/minifier/minify/src/Exceptions/FileImportException.php';
427
+ include_once $path.'vendor/minifier/minify/src/Exceptions/IOException.php';
428
+ include_once $path.'vendor/minifier/path-converter/src/ConverterInterface.php';
429
+ include_once $path.'vendor/minifier/path-converter/src/Converter.php';
430
+ $minifier = null;
431
+ eval('$minifier = new MatthiasMullie\Minify\\'.strtoupper($lang).'($code);');
432
+ if ( $minifier !== null ) {
433
+ $ret["result"] = true;
434
+ $ret["minified_code"] = $minifier->minify();
435
+ }
436
+ }
437
+
438
+ return $ret;
439
+ }
440
+
441
  function wfu_css_to_HTML($css) {
442
+ if ( WFU_VAR("WFU_MINIFY_INLINE_CSS") == "true" ) {
443
+ $ret = wfu_minify_code("CSS", $css);
444
+ if ( $ret["result"] ) $css = $ret["minified_code"];
445
+ }
446
  $echo_str = "\n\t".'<style>';
447
  $echo_str .= "\n".$css;
448
  $echo_str .= "\n\t".'</style>';
451
  }
452
 
453
  function wfu_js_to_HTML($js) {
454
+ if ( WFU_VAR("WFU_MINIFY_INLINE_JS") == "true" ) {
455
+ $ret = wfu_minify_code("JS", $js);
456
+ if ( $ret["result"] ) $js = $ret["minified_code"];
457
+ }
458
+ $echo_str = '<script type="text/javascript">';
459
  $echo_str .= "\n".$js;
460
+ $echo_str .= "\n".'</script>';
461
 
462
  return $echo_str;
463
  }
464
 
465
+ function wfu_init_run_js_script() {
466
+ $script = 'if (typeof wfu_js_decode_obj == "undefined") function wfu_js_decode_obj(obj_str) { var obj = null; if (obj_str == "window") obj = window; else { var match = obj_str.match(/GlobalData(\.(WFU|WFUB)\[(.*?)\](\.(.*))?)?$/); if (match) { obj = GlobalData; if (match[3]) obj = obj[match[2]][match[3]]; if (match[5]) obj = obj[match[5]]; } } return obj; }';
467
+ $script .= "\n".'if (typeof wfu_run_js == "undefined") function wfu_run_js(obj_str, func) { if (typeof GlobalData == "undefined") { if (typeof window.WFU_JS_BANK == "undefined") WFU_JS_BANK = []; WFU_JS_BANK.push({obj_str: obj_str, func: func}) } else { var obj = wfu_js_decode_obj(obj_str); if (obj) obj[func].call(obj); } }';
468
+ return wfu_js_to_HTML($script);
469
+ }
470
+
471
  function wfu_PHP_array_to_JS_object($arr) {
472
  $ret = "";
473
  foreach ( $arr as $prop => $value ) {
639
  return ( substr($path, 0, 6) == 'ftp://' || substr($path, 0, 7) == 'ftps://' || substr($path, 0, 7) == 'sftp://' ? $path : wfu_abspath().$path );
640
  }
641
 
642
+ function wfu_delete_file_execute($filepath, $userid) {
643
+ $filedata = wfu_get_filedata($filepath);
644
+ $retid = wfu_log_action('delete', $filepath, $userid, '', 0, 0, '', null);
645
+ $result = unlink($filepath);
646
+ if ( !$result ) wfu_revert_log_action($retid);
647
+ //delete linked attachment if exists and it is allowed to be deleted
648
+ elseif ($filedata != null && isset($filedata["media"]) && WFU_VAR("WFU_UPDATE_MEDIA_ON_DELETE") == "true" ) {
649
+ wp_delete_attachment( $filedata["media"]["attach_id"] );
650
+ }
651
+
652
+ return $result;
653
+ }
654
+
655
  function wfu_upload_plugin_full_path( $params ) {
656
  $path = $params["uploadpath"];
657
  if ( $params["accessmethod"] == 'ftp' && $params["ftpinfo"] != '' && $params["useftpdomain"] == "true" ) {
1069
  'date_to' => 0,
1070
  'action' => $action
1071
  ),
1072
+ array( '%d', '%d', '%d', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%s', '%s', '%s', '%s' )) !== false ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1073
  $retid = $wpdb->insert_id;
1074
  // if new log record has been created, also create user data records
1075
  if ( $userdata != null && $uploadid != '' ) {
1085
  'date_from' => $now_date,
1086
  'date_to' => 0
1087
  ),
1088
+ array( '%s', '%s', '%d', '%s', '%s', '%s' ));
 
 
 
 
 
 
 
 
1089
  }
1090
  }
1091
  }
1125
  'date_from' => $now_date,
1126
  'date_to' => 0,
1127
  'action' => 'rename',
1128
+ 'linkedto' => $filerec->idlog,
1129
+ 'filedata' => $filerec->filedata
1130
  ),
1131
+ array( '%d', '%d', '%d', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%s', '%s', '%s', '%s', '%d', '%s' ) ) !== false )
1132
  $retid = $wpdb->insert_id;
1133
  }
1134
  }
1162
  'date_from' => $now_date,
1163
  'date_to' => $now_date,
1164
  'action' => 'delete',
1165
+ 'linkedto' => $filerec->idlog,
1166
+ 'filedata' => $filerec->filedata
1167
  ),
1168
+ array( '%d', '%d', '%d', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%s', '%s', '%s', '%s', '%d', '%s' )) != false )
1169
  $retid = $wpdb->insert_id;
1170
  }
1171
  }
1199
  'date_from' => $now_date,
1200
  'date_to' => 0,
1201
  'action' => 'download',
1202
+ 'linkedto' => $filerec->idlog,
1203
+ 'filedata' => $filerec->filedata
1204
  ),
1205
+ array( '%d', '%d', '%d', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%s', '%s', '%s', '%s', '%d', '%s' )) != false )
1206
  $retid = $wpdb->insert_id;
1207
  }
1208
  }
1237
  'date_from' => $now_date,
1238
  'date_to' => 0,
1239
  'action' => 'modify',
1240
+ 'linkedto' => $filerec->idlog,
1241
+ 'filedata' => $filerec->filedata
1242
  ),
1243
+ array( '%d', '%d', '%d', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%s', '%s', '%s', '%s', '%d', '%s' )) != false )
1244
  $retid = $wpdb->insert_id;
1245
  }
1246
  }
1275
  'date_from' => $now_date,
1276
  'date_to' => 0,
1277
  'action' => 'changeuser',
1278
+ 'linkedto' => $filerec->idlog,
1279
+ 'filedata' => $filerec->filedata
1280
  ),
1281
+ array( '%d', '%d', '%d', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%s', '%s', '%s', '%s', '%d', '%s' )) != false )
1282
  $retid = $wpdb->insert_id;
1283
  }
1284
  }
1384
  return $filerec;
1385
  }
1386
 
1387
+ function wfu_get_latest_rec_from_id($idlog) {
1388
+ global $wpdb;
1389
+ $table_name1 = $wpdb->prefix . "wfu_log";
1390
+ $filerec = $wpdb->get_row('SELECT * FROM '.$table_name1.' WHERE idlog = '.$idlog);
1391
+ while ( $filerec != null && $filerec->date_to != "0000-00-00 00:00:00" )
1392
+ $filerec = $wpdb->get_row('SELECT * FROM '.$table_name1.' WHERE linkedto = '.$filerec->idlog);
1393
+
1394
+ return $filerec;
1395
+ }
1396
+
1397
+ /**
1398
+ * gets the filedata property from file record in database
1399
+ *
1400
+ * This function returns the filedata property of the corresponding record of
1401
+ * the file in the database holding data about its transfer to a service
1402
+ * account like Dropbox, provided that this record is still valid. If the
1403
+ * record does not exist or exists but it is absolete, then the function
1404
+ * returns null, otherwise it returns an array.
1405
+ *
1406
+ * The [$service]["filepath"] item of the array is set to the final $filepath
1407
+ * of the file, in case that the original filename was renamed.
1408
+ *
1409
+ * @param int $idlog file id of the file
1410
+ * @param bool $is_new it is true if the function is called during addition of
1411
+ * a new file
1412
+ * @return mixed
1413
+ */
1414
+ function wfu_get_latest_filedata_from_id($idlog, $is_new = false) {
1415
+ global $wpdb;
1416
+ $table_name1 = $wpdb->prefix . "wfu_log";
1417
+
1418
+ //get latest database record of file, if it is still valid
1419
+ $filerec = wfu_get_latest_rec_from_id($idlog);
1420
+ //return null if the record does not exist or it is obsolete
1421
+ if ( $filerec == null ) return null;
1422
+ //return filedata, if it does not exist return null
1423
+ if ( !isset($filerec->filedata) || $filerec->filedata == null ) return ( $is_new ? array() : null );
1424
+ $filedata = wfu_decode_array_from_string($filerec->filedata);
1425
+ if ( !is_array($filedata) ) return ( $is_new ? array() : null );
1426
+ //update filepath property in filedata of "transfer" type, if service
1427
+ //records exist
1428
+ foreach ( $filedata as $key => $data )
1429
+ if ( !isset($data["type"]) || $data["type"] == "transfer" )
1430
+ $filedata[$key]["filepath"] = $filerec->filepath;
1431
+
1432
+ return $filedata;
1433
+ }
1434
+
1435
+ function wfu_get_filedata($filepath, $include_id = false) {
1436
+ $filerec = wfu_get_file_rec($filepath, false);
1437
+ if ( $filerec == null ) return null;
1438
+ //get filedata, if it does not exist create an empty array
1439
+ if ( !isset($filerec->filedata) || $filerec->filedata == null ) $filedata = array();
1440
+ else {
1441
+ $filedata = wfu_decode_array_from_string($filerec->filedata);
1442
+ if ( !is_array($filedata) ) $filedata = array();
1443
+ }
1444
+ //add idlog in filedata if $include_id is true
1445
+ if ( $include_id )
1446
+ $filedata["general"] = array(
1447
+ "type" => "data",
1448
+ "idlog" => $filerec->idlog
1449
+ );
1450
+
1451
+ return $filedata;
1452
+ }
1453
+
1454
+ function wfu_save_filedata_from_id($idlog, $filedata) {
1455
+ global $wpdb;
1456
+ $table_name1 = $wpdb->prefix . "wfu_log";
1457
+ return $wpdb->update($table_name1, array( 'filedata' => wfu_encode_array_to_string($filedata) ), array( 'idlog' => $idlog ), array( '%s' ), array( '%d' ));
1458
+ }
1459
+
1460
  //get userdata from uploadid
1461
  function wfu_get_userdata_from_uploadid($uploadid) {
1462
  global $wpdb;
2032
  function wfu_template_to_HTML($blockname, $params, $additional_params, $occurrence_index) {
2033
  $plugin_options = wfu_decode_plugin_options(get_option( "wordpress_file_upload_options" ));
2034
  $block = call_user_func("wfu_prepare_".$blockname."_block", $params, $additional_params, $occurrence_index);
2035
+ if ( isset($params["uploadid"]) ) {
2036
+ $ID = $params["uploadid"];
2037
+ $WF = "WFU";
2038
+ }
2039
+ else {
2040
+ $ID = $params["browserid"];
2041
+ $WF = "WFUB";
2042
+ }
2043
  $css = $block["css"];
2044
+ if ( $block["js"] != "" ) {
2045
+ $js = 'var '.$WF.'_JS_'.$ID.'_'.$blockname.' = function() {';
2046
+ $js .= "\n".$block["js"];
2047
+ $js .= "\n".'}';
2048
+ $js .= "\n".'wfu_run_js("window", "'.$WF.'_JS_'.$ID.'_'.$blockname.'");';
2049
+ }
2050
  //relax css rules if this option is enabled
2051
  if ( $plugin_options['relaxcss'] == '1' ) $css = preg_replace('#.*?/\*relax\*/\s*#', '', $css);
2052
  $echo_str = wfu_css_to_HTML($css);
2053
+ $echo_str .= "\n".wfu_js_to_HTML($js);
2054
  $k = 1;
2055
  while ( isset($block["line".$k]) ) {
2056
  if ( $block["line".$k] != "" ) $echo_str .= "\n".$block["line".$k];
2234
  foreach ( $userdata_fields as $userdata_field )
2235
  $attach_data["WFU User Data"][$userdata_field["label"]] = $userdata_field["value"];
2236
  $update_attach = wp_update_attachment_metadata( $attach_id, $attach_data );
2237
+ // link attachment with file in plugin's database
2238
+ $filedata = wfu_get_filedata($file_path, true);
2239
+ if ( $filedata != null ) {
2240
+ $filedata["media"] = array(
2241
+ "type" => "data",
2242
+ "attach_id" => $attach_id
2243
+ );
2244
+ wfu_save_filedata_from_id($filedata["general"]["idlog"], $filedata);
2245
+ }
2246
 
2247
  return $attach_id;
2248
  }
lib/wfu_io.php CHANGED
@@ -61,32 +61,6 @@ function wfu_create_directory($path, $method, $ftpdata) {
61
  $ftpdata_flat = str_replace(array('\:', '\@'), array('\_', '\_'), $ftpdata);
62
  $pos1 = strpos($ftpdata_flat, ":");
63
  $pos2 = strpos($ftpdata_flat, "@");
64
- if ( $pos1 && $pos2 && $pos2 > $pos1 ) {
65
- $ftp_username = substr($ftpdata, 0, $pos1);
66
- $ftp_password = substr($ftpdata, $pos1 + 1, $pos2 - $pos1 - 1);
67
- $ftp_host = substr($ftpdata, $pos2 + 1);
68
- $ftp_port = preg_replace("/^[^:]*:?/", "", $ftp_host);
69
- $ftp_host_clean = preg_replace("/:.*/", "", $ftp_host);
70
- if ( $ftp_port != "" ) $conn_id = ftp_connect($ftp_host_clean, $ftp_port);
71
- else $conn_id = ftp_connect($ftp_host_clean);
72
- $login_result = ftp_login($conn_id, $ftp_username, $ftp_password);
73
- if ( $conn_id && $login_result ) {
74
- $flat_host = preg_replace("/^(.*\.)?([^.]*\..*)$/", "$2", $ftp_host);
75
- $pos1 = strpos($path, $flat_host);
76
- if ( $pos1 ) {
77
- $path = substr($path, $pos1 + strlen($flat_host));
78
- wfu_mk_dir_deep($conn_id, '/', $path);
79
- }
80
- else {
81
- $ret_message = WFU_ERROR_ADMIN_FTPDIR_RESOLVE;
82
- }
83
- }
84
- else {
85
- $ret_message = WFU_ERROR_ADMIN_FTPINFO_INVALID;
86
- }
87
- ftp_quit($conn_id);
88
- }
89
-
90
  if ( $pos1 && $pos2 && $pos2 > $pos1 ) {
91
  $ftp_username = substr($ftpdata, 0, $pos1);
92
  $ftp_password = substr($ftpdata, $pos1 + 1, $pos2 - $pos1 - 1);
61
  $ftpdata_flat = str_replace(array('\:', '\@'), array('\_', '\_'), $ftpdata);
62
  $pos1 = strpos($ftpdata_flat, ":");
63
  $pos2 = strpos($ftpdata_flat, "@");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  if ( $pos1 && $pos2 && $pos2 > $pos1 ) {
65
  $ftp_username = substr($ftpdata, 0, $pos1);
66
  $ftp_password = substr($ftpdata, $pos1 + 1, $pos2 - $pos1 - 1);
lib/wfu_template.php CHANGED
@@ -99,7 +99,7 @@ function wfu_row_container_template($data) {?>
99
  <?php endforeach ?>
100
  <div class="file_space_clean"></div>
101
  <?php if ( isset($p["object"]) ): ?>
102
- <script type="text/javascript"><?php echo $p["object"]; ?>.init();</script>
103
  <?php endif ?>
104
  </div>
105
  <?php endforeach ?>
@@ -117,7 +117,7 @@ function wfu_row_container_template($data) {?>
117
  <?php endforeach ?>
118
  <div class="file_space_clean"></div>
119
  <?php if ( isset($p["object"]) ): ?>
120
- <script type="text/javascript"><?php echo $p["object"]; ?>.init();</script>
121
  <?php endif ?>
122
  </div>
123
  </td>
@@ -1256,9 +1256,11 @@ this._set_editbox_status = function(status) {
1256
 
1257
  this._sel = document.getElementById("selectsubdir_$ID");
1258
  this._editbox = document.getElementById("selectsubdiredit_$ID");
1259
- this._editable = (this._get_editbox_status() != "disabled");
1260
- //attach subfolder edit box handlers if it is editable
1261
- if (this._editable) wfu_attach_element_handlers(this._editbox, new Function("GlobalData.WFU[$ID].subfolders._editbox_changed();"));
 
 
1262
 
1263
  /* do not change this line */}
1264
  </script><?php /****************************************************************
@@ -1353,7 +1355,7 @@ input[type="button"].file_input_button
1353
  padding: 0px; /*relax*/
1354
  background-color: #EEEEEE; /*relax*/
1355
  color: #555555; /*relax*/
1356
- background-image: url("../images/white-grad-active.png"); /*relax*/
1357
  background-position: left top; /*relax*/
1358
  background-repeat: repeat-x; /*relax*/
1359
  border-style: solid; /*relax*/
@@ -1375,7 +1377,7 @@ input[type="button"].file_input_button_hover
1375
  padding: 0px; /*relax*/
1376
  background-color: #EEEEEE; /*relax*/
1377
  color: #111111; /*relax*/
1378
- background-image: url("../images/white-grad-active.png"); /*relax*/
1379
  background-position: left top; /*relax*/
1380
  background-repeat: repeat-x; /*relax*/
1381
  border-style: solid; /*relax*/
@@ -1397,7 +1399,7 @@ input[type="button"].file_input_button:disabled, input[type="button"].file_input
1397
  padding: 0px; /*relax*/
1398
  background-color: #EEEEEE; /*relax*/
1399
  color: silver; /*relax*/
1400
- background-image: url("../images/white-grad-active.png"); /*relax*/
1401
  background-position: left top; /*relax*/
1402
  background-repeat: repeat-x; /*relax*/
1403
  border-style: solid; /*relax*/
@@ -1603,7 +1605,7 @@ input[type="button"].file_input_submit
1603
  padding: 0px; /*relax*/
1604
  background-color: #EEEEEE; /*relax*/
1605
  color: #555555; /*relax*/
1606
- background-image: url("../images/white-grad-active.png"); /*relax*/
1607
  background-position: left top; /*relax*/
1608
  background-repeat: repeat-x; /*relax*/
1609
  border-style: solid; /*relax*/
@@ -1624,7 +1626,7 @@ input[type="button"].file_input_submit:hover, input[type="button"].file_input_su
1624
  padding: 0px; /*relax*/
1625
  background-color: #EEEEEE; /*relax*/
1626
  color: #111111; /*relax*/
1627
- background-image: url("../images/white-grad-active.png"); /*relax*/
1628
  background-position: left top; /*relax*/
1629
  background-repeat: repeat-x; /*relax*/
1630
  border-style: solid; /*relax*/
@@ -1645,7 +1647,7 @@ input[type="button"].file_input_submit:disabled
1645
  padding: 0px; /*relax*/
1646
  background-color: #EEEEEE; /*relax*/
1647
  color: silver; /*relax*/
1648
- background-image: url("../images/white-grad-active.png"); /*relax*/
1649
  background-position: left top; /*relax*/
1650
  background-repeat: repeat-x; /*relax*/
1651
  border-style: solid; /*relax*/
99
  <?php endforeach ?>
100
  <div class="file_space_clean"></div>
101
  <?php if ( isset($p["object"]) ): ?>
102
+ <script type="text/javascript">wfu_run_js("<?php echo $p["object"]; ?>", "init");</script>
103
  <?php endif ?>
104
  </div>
105
  <?php endforeach ?>
117
  <?php endforeach ?>
118
  <div class="file_space_clean"></div>
119
  <?php if ( isset($p["object"]) ): ?>
120
+ <script type="text/javascript">wfu_run_js("<?php echo $p["object"]; ?>", "init");</script>
121
  <?php endif ?>
122
  </div>
123
  </td>
1256
 
1257
  this._sel = document.getElementById("selectsubdir_$ID");
1258
  this._editbox = document.getElementById("selectsubdiredit_$ID");
1259
+ if (this._editbox) {
1260
+ this._editable = (this._get_editbox_status() != "disabled");
1261
+ //attach subfolder edit box handlers if it is editable
1262
+ if (this._editable) wfu_attach_element_handlers(this._editbox, new Function("GlobalData.WFU[$ID].subfolders._editbox_changed();"));
1263
+ }
1264
 
1265
  /* do not change this line */}
1266
  </script><?php /****************************************************************
1355
  padding: 0px; /*relax*/
1356
  background-color: #EEEEEE; /*relax*/
1357
  color: #555555; /*relax*/
1358
+ background-image: url("<?php echo WPFILEUPLOAD_DIR; ?>images/white-grad-active.png"); /*relax*/
1359
  background-position: left top; /*relax*/
1360
  background-repeat: repeat-x; /*relax*/
1361
  border-style: solid; /*relax*/
1377
  padding: 0px; /*relax*/
1378
  background-color: #EEEEEE; /*relax*/
1379
  color: #111111; /*relax*/
1380
+ background-image: url("<?php echo WPFILEUPLOAD_DIR; ?>images/white-grad-active.png"); /*relax*/
1381
  background-position: left top; /*relax*/
1382
  background-repeat: repeat-x; /*relax*/
1383
  border-style: solid; /*relax*/
1399
  padding: 0px; /*relax*/
1400
  background-color: #EEEEEE; /*relax*/
1401
  color: silver; /*relax*/
1402
+ background-image: url("<?php echo WPFILEUPLOAD_DIR; ?>images/white-grad-active.png"); /*relax*/
1403
  background-position: left top; /*relax*/
1404
  background-repeat: repeat-x; /*relax*/
1405
  border-style: solid; /*relax*/
1605
  padding: 0px; /*relax*/
1606
  background-color: #EEEEEE; /*relax*/
1607
  color: #555555; /*relax*/
1608
+ background-image: url("<?php echo WPFILEUPLOAD_DIR; ?>images/white-grad-active.png"); /*relax*/
1609
  background-position: left top; /*relax*/
1610
  background-repeat: repeat-x; /*relax*/
1611
  border-style: solid; /*relax*/
1626
  padding: 0px; /*relax*/
1627
  background-color: #EEEEEE; /*relax*/
1628
  color: #111111; /*relax*/
1629
+ background-image: url("<?php echo WPFILEUPLOAD_DIR; ?>images/white-grad-active.png"); /*relax*/
1630
  background-position: left top; /*relax*/
1631
  background-repeat: repeat-x; /*relax*/
1632
  border-style: solid; /*relax*/
1647
  padding: 0px; /*relax*/
1648
  background-color: #EEEEEE; /*relax*/
1649
  color: silver; /*relax*/
1650
+ background-image: url("<?php echo WPFILEUPLOAD_DIR; ?>images/white-grad-active.png"); /*relax*/
1651
  background-position: left top; /*relax*/
1652
  background-repeat: repeat-x; /*relax*/
1653
  border-style: solid; /*relax*/
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: nickboss
3
  Donate link: http://www.iptanus.com/support/wordpress-file-upload
4
  Tags: file, upload, ajax, form, page, post, sidebar, responsive, widget, webcam, ftp
5
  Requires at least: 2.9.2
6
- Tested up to: 4.9.0
7
  Stable tag: "trunk"
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -146,6 +146,14 @@ There is an option in plugin's settings in Dashboard to relax the CSS rules, so
146
 
147
  == Changelog ==
148
 
 
 
 
 
 
 
 
 
149
  = 4.1.0 =
150
  * changed logic of file sanitizer; dots in filename are by default converted to dashes, in order to avoid upload failures caused when the plugin detects double extensions
151
  * added advanced option WFU_SANITIZE_FILENAME_DOTS that determines whether file sanitizer will sanitize dots or not
@@ -712,6 +720,9 @@ Initial version.
712
 
713
  == Upgrade Notice ==
714
 
 
 
 
715
  = 4.1.0 =
716
  Significant update to fix several bugs and introduce some new features.
717
 
3
  Donate link: http://www.iptanus.com/support/wordpress-file-upload
4
  Tags: file, upload, ajax, form, page, post, sidebar, responsive, widget, webcam, ftp
5
  Requires at least: 2.9.2
6
+ Tested up to: 4.9.1
7
  Stable tag: "trunk"
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
146
 
147
  == Changelog ==
148
 
149
+ = 4.2.0 =
150
+ * changed logic of file sanitizer; dots in filename are by default converted to dashes, in order to avoid upload failures caused when the plugin detects double extensions
151
+ * corrected bug where a Javascript error was generated when askforsubfolders was disabled and showtargetfolder was active
152
+ * added css and js minifier in inline code
153
+ * improved file transfers functionality
154
+ * plugin modified so that Media record is deleted when the associated uploaded file is deleted from plugin's database
155
+ * corrected bug where some plugin images were not loaded while Relax CSS option was inactive
156
+
157
  = 4.1.0 =
158
  * changed logic of file sanitizer; dots in filename are by default converted to dashes, in order to avoid upload failures caused when the plugin detects double extensions
159
  * added advanced option WFU_SANITIZE_FILENAME_DOTS that determines whether file sanitizer will sanitize dots or not
720
 
721
  == Upgrade Notice ==
722
 
723
+ = 4.2.0 =
724
+ Significant update to introduce some new features and fix some bugs.
725
+
726
  = 4.1.0 =
727
  Significant update to fix several bugs and introduce some new features.
728
 
release_notes.txt CHANGED
@@ -1,2 +1,2 @@
1
- <!-- --><span>Version 4.1.0 is a significant update incorporating several bug fixes, removal of unnecessary / obsolete plugin files, code improvements and some new features. The most important new feature has to do with <strong>filename sanitization</strong>. By default the plugin converts invalid characters in the filename (like accent and symbols) to dashes (-). Now it will also convert dot symbols (.) to dashes. This way the user will not get an <em>"Upload failed! File not allowed."</em> message when trying to upload a file containing dots in the filename. Of course this is the default behaviour. The website administrator can change it by changing the plugin's appropriate attributes and options.<br/><br/>For more details about this version's changes please visit the Release Notes of the plugin's </span><a href="http://www.iptanus.com/wordpress-plugins/wordpress-file-upload/">support page</a><span>.</span><!-- -->
2
  <!-- -->
1
+ <!-- --><span>Version 4.2.0 is a significant update bringing two modifications, which are not visible to the users, however they improve its performance.<br/><br/>The first one makes the plugin work better when <strong>caching</strong> is enabled, either from another plugin (e.g. Autoptimize or W3 Total Cache) or from the web server. Speaking more technically, the plugin will render correctly and without errors either its Javascript files load early (in page header) or late (in footer).<br/><br/>The second improvement relates to compression and simplification of the plugin's <strong>inline CSS and Javascript code</strong>. The result is that a page containing the upload form will load a bit faster.<br/><br/>Other less significant changes of this version relate to bug fixes and code improvements.<br/><br/>For more details about this version's changes please visit the Release Notes of the plugin's </span><a href="http://www.iptanus.com/wordpress-plugins/wordpress-file-upload/">support page</a><span>.</span><!-- -->
2
  <!-- -->
vendor/minifier/minify/data/js/keywords_after.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ in
2
+ public
3
+ extends
4
+ private
5
+ protected
6
+ implements
7
+ instanceof
vendor/minifier/minify/data/js/keywords_before.txt ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ do
2
+ in
3
+ let
4
+ new
5
+ var
6
+ case
7
+ else
8
+ enum
9
+ void
10
+ with
11
+ class
12
+ const
13
+ yield
14
+ delete
15
+ export
16
+ import
17
+ public
18
+ static
19
+ typeof
20
+ extends
21
+ package
22
+ private
23
+ function
24
+ protected
25
+ implements
26
+ instanceof
vendor/minifier/minify/data/js/keywords_reserved.txt ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ do
2
+ if
3
+ in
4
+ for
5
+ let
6
+ new
7
+ try
8
+ var
9
+ case
10
+ else
11
+ enum
12
+ eval
13
+ null
14
+ this
15
+ true
16
+ void
17
+ with
18
+ break
19
+ catch
20
+ class
21
+ const
22
+ false
23
+ super
24
+ throw
25
+ while
26
+ yield
27
+ delete
28
+ export
29
+ import
30
+ public
31
+ return
32
+ static
33
+ switch
34
+ typeof
35
+ default
36
+ extends
37
+ finally
38
+ package
39
+ private
40
+ continue
41
+ debugger
42
+ function
43
+ arguments
44
+ interface
45
+ protected
46
+ implements
47
+ instanceof
48
+ abstract
49
+ boolean
50
+ byte
51
+ char
52
+ double
53
+ final
54
+ float
55
+ goto
56
+ int
57
+ long
58
+ native
59
+ short
60
+ synchronized
61
+ throws
62
+ transient
63
+ volatile
vendor/minifier/minify/data/js/operators.txt ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ +
2
+ -
3
+ *
4
+ /
5
+ %
6
+ =
7
+ +=
8
+ -=
9
+ *=
10
+ /=
11
+ %=
12
+ <<=
13
+ >>=
14
+ >>>=
15
+ &=
16
+ ^=
17
+ |=
18
+ &
19
+ |
20
+ ^
21
+ ~
22
+ <<
23
+ >>
24
+ >>>
25
+ ==
26
+ ===
27
+ !=
28
+ !==
29
+ >
30
+ <
31
+ >=
32
+ <=
33
+ &&
34
+ ||
35
+ !
36
+ .
37
+ [
38
+ ]
39
+ ?
40
+ :
41
+ ,
42
+ ;
43
+ (
44
+ )
45
+ {
46
+ }
vendor/minifier/minify/data/js/operators_after.txt ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ +
2
+ -
3
+ *
4
+ /
5
+ %
6
+ =
7
+ +=
8
+ -=
9
+ *=
10
+ /=
11
+ %=
12
+ <<=
13
+ >>=
14
+ >>>=
15
+ &=
16
+ ^=
17
+ |=
18
+ &
19
+ |
20
+ ^
21
+ <<
22
+ >>
23
+ >>>
24
+ ==
25
+ ===
26
+ !=
27
+ !==
28
+ >
29
+ <
30
+ >=
31
+ <=
32
+ &&
33
+ ||
34
+ .
35
+ [
36
+ ]
37
+ ?
38
+ :
39
+ ,
40
+ ;
41
+ (
42
+ )
43
+ }
vendor/minifier/minify/data/js/operators_before.txt ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ +
2
+ -
3
+ *
4
+ /
5
+ %
6
+ =
7
+ +=
8
+ -=
9
+ *=
10
+ /=
11
+ %=
12
+ <<=
13
+ >>=
14
+ >>>=
15
+ &=
16
+ ^=
17
+ |=
18
+ &
19
+ |
20
+ ^
21
+ ~
22
+ <<
23
+ >>
24
+ >>>
25
+ ==
26
+ ===
27
+ !=
28
+ !==
29
+ >
30
+ <
31
+ >=
32
+ <=
33
+ &&
34
+ ||
35
+ !
36
+ .
37
+ [
38
+ ?
39
+ :
40
+ ,
41
+ ;
42
+ (
43
+ {
vendor/minifier/minify/src/CSS.php ADDED
@@ -0,0 +1,707 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * CSS Minifier
4
+ *
5
+ * Please report bugs on https://github.com/matthiasmullie/minify/issues
6
+ *
7
+ * @author Matthias Mullie <minify@mullie.eu>
8
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
9
+ * @license MIT License
10
+ */
11
+
12
+ namespace MatthiasMullie\Minify;
13
+
14
+ use MatthiasMullie\Minify\Exceptions\FileImportException;
15
+ use MatthiasMullie\PathConverter\ConverterInterface;
16
+ use MatthiasMullie\PathConverter\Converter;
17
+
18
+ /**
19
+ * CSS minifier
20
+ *
21
+ * Please report bugs on https://github.com/matthiasmullie/minify/issues
22
+ *
23
+ * @package Minify
24
+ * @author Matthias Mullie <minify@mullie.eu>
25
+ * @author Tijs Verkoyen <minify@verkoyen.eu>
26
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
27
+ * @license MIT License
28
+ */
29
+ class CSS extends Minify
30
+ {
31
+ /**
32
+ * @var int maximum inport size in kB
33
+ */
34
+ protected $maxImportSize = 5;
35
+
36
+ /**
37
+ * @var string[] valid import extensions
38
+ */
39
+ protected $importExtensions = array(
40
+ 'gif' => 'data:image/gif',
41
+ 'png' => 'data:image/png',
42
+ 'jpe' => 'data:image/jpeg',
43
+ 'jpg' => 'data:image/jpeg',
44
+ 'jpeg' => 'data:image/jpeg',
45
+ 'svg' => 'data:image/svg+xml',
46
+ 'woff' => 'data:application/x-font-woff',
47
+ 'tif' => 'image/tiff',
48
+ 'tiff' => 'image/tiff',
49
+ 'xbm' => 'image/x-xbitmap',
50
+ );
51
+
52
+ /**
53
+ * Set the maximum size if files to be imported.
54
+ *
55
+ * Files larger than this size (in kB) will not be imported into the CSS.
56
+ * Importing files into the CSS as data-uri will save you some connections,
57
+ * but we should only import relatively small decorative images so that our
58
+ * CSS file doesn't get too bulky.
59
+ *
60
+ * @param int $size Size in kB
61
+ */
62
+ public function setMaxImportSize($size)
63
+ {
64
+ $this->maxImportSize = $size;
65
+ }
66
+
67
+ /**
68
+ * Set the type of extensions to be imported into the CSS (to save network
69
+ * connections).
70
+ * Keys of the array should be the file extensions & respective values
71
+ * should be the data type.
72
+ *
73
+ * @param string[] $extensions Array of file extensions
74
+ */
75
+ public function setImportExtensions(array $extensions)
76
+ {
77
+ $this->importExtensions = $extensions;
78
+ }
79
+
80
+ /**
81
+ * Move any import statements to the top.
82
+ *
83
+ * @param string $content Nearly finished CSS content
84
+ *
85
+ * @return string
86
+ */
87
+ protected function moveImportsToTop($content)
88
+ {
89
+ if (preg_match_all('/(;?)(@import (?<url>url\()?(?P<quotes>["\']?).+?(?P=quotes)(?(url)\)))/', $content, $matches)) {
90
+ // remove from content
91
+ foreach ($matches[0] as $import) {
92
+ $content = str_replace($import, '', $content);
93
+ }
94
+
95
+ // add to top
96
+ $content = implode(';', $matches[2]).';'.trim($content, ';');
97
+ }
98
+
99
+ return $content;
100
+ }
101
+
102
+ /**
103
+ * Combine CSS from import statements.
104
+ *
105
+ * @import's will be loaded and their content merged into the original file,
106
+ * to save HTTP requests.
107
+ *
108
+ * @param string $source The file to combine imports for
109
+ * @param string $content The CSS content to combine imports for
110
+ * @param string[] $parents Parent paths, for circular reference checks
111
+ *
112
+ * @return string
113
+ *
114
+ * @throws FileImportException
115
+ */
116
+ protected function combineImports($source, $content, $parents)
117
+ {
118
+ $importRegexes = array(
119
+ // @import url(xxx)
120
+ '/
121
+ # import statement
122
+ @import
123
+
124
+ # whitespace
125
+ \s+
126
+
127
+ # open url()
128
+ url\(
129
+
130
+ # (optional) open path enclosure
131
+ (?P<quotes>["\']?)
132
+
133
+ # fetch path
134
+ (?P<path>.+?)
135
+
136
+ # (optional) close path enclosure
137
+ (?P=quotes)
138
+
139
+ # close url()
140
+ \)
141
+
142
+ # (optional) trailing whitespace
143
+ \s*
144
+
145
+ # (optional) media statement(s)
146
+ (?P<media>[^;]*)
147
+
148
+ # (optional) trailing whitespace
149
+ \s*
150
+
151
+ # (optional) closing semi-colon
152
+ ;?
153
+
154
+ /ix',
155
+
156
+ // @import 'xxx'
157
+ '/
158
+
159
+ # import statement
160
+ @import
161
+
162
+ # whitespace
163
+ \s+
164
+
165
+ # open path enclosure
166
+ (?P<quotes>["\'])
167
+
168
+ # fetch path
169
+ (?P<path>.+?)
170
+
171
+ # close path enclosure
172
+ (?P=quotes)
173
+
174
+ # (optional) trailing whitespace
175
+ \s*
176
+
177
+ # (optional) media statement(s)
178
+ (?P<media>[^;]*)
179
+
180
+ # (optional) trailing whitespace
181
+ \s*
182
+
183
+ # (optional) closing semi-colon
184
+ ;?
185
+
186
+ /ix',
187
+ );
188
+
189
+ // find all relative imports in css
190
+ $matches = array();
191
+ foreach ($importRegexes as $importRegex) {
192
+ if (preg_match_all($importRegex, $content, $regexMatches, PREG_SET_ORDER)) {
193
+ $matches = array_merge($matches, $regexMatches);
194
+ }
195
+ }
196
+
197
+ $search = array();
198
+ $replace = array();
199
+
200
+ // loop the matches
201
+ foreach ($matches as $match) {
202
+ // get the path for the file that will be imported
203
+ $importPath = dirname($source).'/'.$match['path'];
204
+
205
+ // only replace the import with the content if we can grab the
206
+ // content of the file
207
+ if (!$this->canImportByPath($match['path']) || !$this->canImportFile($importPath)) {
208
+ continue;
209
+ }
210
+
211
+ // check if current file was not imported previously in the same
212
+ // import chain.
213
+ if (in_array($importPath, $parents)) {
214
+ throw new FileImportException('Failed to import file "'.$importPath.'": circular reference detected.');
215
+ }
216
+
217
+ // grab referenced file & minify it (which may include importing
218
+ // yet other @import statements recursively)
219
+ $minifier = new static($importPath);
220
+ $importContent = $minifier->execute($source, $parents);
221
+
222
+ // check if this is only valid for certain media
223
+ if (!empty($match['media'])) {
224
+ $importContent = '@media '.$match['media'].'{'.$importContent.'}';
225
+ }
226
+
227
+ // add to replacement array
228
+ $search[] = $match[0];
229
+ $replace[] = $importContent;
230
+ }
231
+
232
+ // replace the import statements
233
+ return str_replace($search, $replace, $content);
234
+ }
235
+
236
+ /**
237
+ * Import files into the CSS, base64-ized.
238
+ *
239
+ * @url(image.jpg) images will be loaded and their content merged into the
240
+ * original file, to save HTTP requests.
241
+ *
242
+ * @param string $source The file to import files for
243
+ * @param string $content The CSS content to import files for
244
+ *
245
+ * @return string
246
+ */
247
+ protected function importFiles($source, $content)
248
+ {
249
+ $regex = '/url\((["\']?)(.+?)\\1\)/i';
250
+ if ($this->importExtensions && preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) {
251
+ $search = array();
252
+ $replace = array();
253
+
254
+ // loop the matches
255
+ foreach ($matches as $match) {
256
+ $extension = substr(strrchr($match[2], '.'), 1);
257
+ if ($extension && !array_key_exists($extension, $this->importExtensions)) {
258
+ continue;
259
+ }
260
+
261
+ // get the path for the file that will be imported
262
+ $path = $match[2];
263
+ $path = dirname($source).'/'.$path;
264
+
265
+ // only replace the import with the content if we're able to get
266
+ // the content of the file, and it's relatively small
267
+ if ($this->canImportFile($path) && $this->canImportBySize($path)) {
268
+ // grab content && base64-ize
269
+ $importContent = $this->load($path);
270
+ $importContent = base64_encode($importContent);
271
+
272
+ // build replacement
273
+ $search[] = $match[0];
274
+ $replace[] = 'url('.$this->importExtensions[$extension].';base64,'.$importContent.')';
275
+ }
276
+ }
277
+
278
+ // replace the import statements
279
+ $content = str_replace($search, $replace, $content);
280
+ }
281
+
282
+ return $content;
283
+ }
284
+
285
+ /**
286
+ * Minify the data.
287
+ * Perform CSS optimizations.
288
+ *
289
+ * @param string[optional] $path Path to write the data to
290
+ * @param string[] $parents Parent paths, for circular reference checks
291
+ *
292
+ * @return string The minified data
293
+ */
294
+ public function execute($path = null, $parents = array())
295
+ {
296
+ $content = '';
297
+
298
+ // loop CSS data (raw data and files)
299
+ foreach ($this->data as $source => $css) {
300
+ /*
301
+ * Let's first take out strings & comments, since we can't just
302
+ * remove whitespace anywhere. If whitespace occurs inside a string,
303
+ * we should leave it alone. E.g.:
304
+ * p { content: "a test" }
305
+ */
306
+ $this->extractStrings();
307
+ $this->stripComments();
308
+ $css = $this->replace($css);
309
+
310
+ $css = $this->stripWhitespace($css);
311
+ $css = $this->shortenHex($css);
312
+ $css = $this->shortenZeroes($css);
313
+ $css = $this->shortenFontWeights($css);
314
+ $css = $this->stripEmptyTags($css);
315
+
316
+ // restore the string we've extracted earlier
317
+ $css = $this->restoreExtractedData($css);
318
+
319
+ $source = is_int($source) ? '' : $source;
320
+ $parents = $source ? array_merge($parents, array($source)) : $parents;
321
+ $css = $this->combineImports($source, $css, $parents);
322
+ $css = $this->importFiles($source, $css);
323
+
324
+ /*
325
+ * If we'll save to a new path, we'll have to fix the relative paths
326
+ * to be relative no longer to the source file, but to the new path.
327
+ * If we don't write to a file, fall back to same path so no
328
+ * conversion happens (because we still want it to go through most
329
+ * of the move code, which also addresses url() & @import syntax...)
330
+ */
331
+ $converter = $this->getPathConverter($source, $path ?: $source);
332
+ $css = $this->move($converter, $css);
333
+
334
+ // combine css
335
+ $content .= $css;
336
+ }
337
+
338
+ $content = $this->moveImportsToTop($content);
339
+
340
+ return $content;
341
+ }
342
+
343
+ /**
344
+ * Moving a css file should update all relative urls.
345
+ * Relative references (e.g. ../images/image.gif) in a certain css file,
346
+ * will have to be updated when a file is being saved at another location
347
+ * (e.g. ../../images/image.gif, if the new CSS file is 1 folder deeper).
348
+ *
349
+ * @param ConverterInterface $converter Relative path converter
350
+ * @param string $content The CSS content to update relative urls for
351
+ *
352
+ * @return string
353
+ */
354
+ protected function move(ConverterInterface $converter, $content)
355
+ {
356
+ /*
357
+ * Relative path references will usually be enclosed by url(). @import
358
+ * is an exception, where url() is not necessary around the path (but is
359
+ * allowed).
360
+ * This *could* be 1 regular expression, where both regular expressions
361
+ * in this array are on different sides of a |. But we're using named
362
+ * patterns in both regexes, the same name on both regexes. This is only
363
+ * possible with a (?J) modifier, but that only works after a fairly
364
+ * recent PCRE version. That's why I'm doing 2 separate regular
365
+ * expressions & combining the matches after executing of both.
366
+ */
367
+ $relativeRegexes = array(
368
+ // url(xxx)
369
+ '/
370
+ # open url()
371
+ url\(
372
+
373
+ \s*
374
+
375
+ # open path enclosure
376
+ (?P<quotes>["\'])?
377
+
378
+ # fetch path
379
+ (?P<path>.+?)
380
+
381
+ # close path enclosure
382
+ (?(quotes)(?P=quotes))
383
+
384
+ \s*
385
+
386
+ # close url()
387
+ \)
388
+
389
+ /ix',
390
+
391
+ // @import "xxx"
392
+ '/
393
+ # import statement
394
+ @import
395
+
396
+ # whitespace
397
+ \s+
398
+
399
+ # we don\'t have to check for @import url(), because the
400
+ # condition above will already catch these
401
+
402
+ # open path enclosure
403
+ (?P<quotes>["\'])
404
+
405
+ # fetch path
406
+ (?P<path>.+?)
407
+
408
+ # close path enclosure
409
+ (?P=quotes)
410
+
411
+ /ix',
412
+ );
413
+
414
+ // find all relative urls in css
415
+ $matches = array();
416
+ foreach ($relativeRegexes as $relativeRegex) {
417
+ if (preg_match_all($relativeRegex, $content, $regexMatches, PREG_SET_ORDER)) {
418
+ $matches = array_merge($matches, $regexMatches);
419
+ }
420
+ }
421
+
422
+ $search = array();
423
+ $replace = array();
424
+
425
+ // loop all urls
426
+ foreach ($matches as $match) {
427
+ // determine if it's a url() or an @import match
428
+ $type = (strpos($match[0], '@import') === 0 ? 'import' : 'url');
429
+
430
+ $url = $match['path'];
431
+ if ($this->canImportByPath($url)) {
432
+ // attempting to interpret GET-params makes no sense, so let's discard them for awhile
433
+ $params = strrchr($url, '?');
434
+ $url = $params ? substr($url, 0, -strlen($params)) : $url;
435
+
436
+ // fix relative url
437
+ $url = $converter->convert($url);
438
+
439
+ // now that the path has been converted, re-apply GET-params
440
+ $url .= $params;
441
+ }
442
+
443
+ /*
444
+ * Urls with control characters above 0x7e should be quoted.
445
+ * According to Mozilla's parser, whitespace is only allowed at the
446
+ * end of unquoted urls.
447
+ * Urls with `)` (as could happen with data: uris) should also be
448
+ * quoted to avoid being confused for the url() closing parentheses.
449
+ * And urls with a # have also been reported to cause issues.
450
+ * Urls with quotes inside should also remain escaped.
451
+ *
452
+ * @see https://developer.mozilla.org/nl/docs/Web/CSS/url#The_url()_functional_notation
453
+ * @see https://hg.mozilla.org/mozilla-central/rev/14abca4e7378
454
+ * @see https://github.com/matthiasmullie/minify/issues/193
455
+ */
456
+ $url = trim($url);
457
+ if (preg_match('/[\s\)\'"#\x{7f}-\x{9f}]/u', $url)) {
458
+ $url = $match['quotes'] . $url . $match['quotes'];
459
+ }
460
+
461
+ // build replacement
462
+ $search[] = $match[0];
463
+ if ($type === 'url') {
464
+ $replace[] = 'url('.$url.')';
465
+ } elseif ($type === 'import') {
466
+ $replace[] = '@import "'.$url.'"';
467
+ }
468
+ }
469
+
470
+ // replace urls
471
+ return str_replace($search, $replace, $content);
472
+ }
473
+
474
+ /**
475
+ * Shorthand hex color codes.
476
+ * #FF0000 -> #F00.
477
+ *
478
+ * @param string $content The CSS content to shorten the hex color codes for
479
+ *
480
+ * @return string
481
+ */
482
+ protected function shortenHex($content)
483
+ {
484
+ $content = preg_replace('/(?<=[: ])#([0-9a-z])\\1([0-9a-z])\\2([0-9a-z])\\3(?=[; }])/i', '#$1$2$3', $content);
485
+
486
+ // we can shorten some even more by replacing them with their color name
487
+ $colors = array(
488
+ '#F0FFFF' => 'azure',
489
+ '#F5F5DC' => 'beige',
490
+ '#A52A2A' => 'brown',
491
+ '#FF7F50' => 'coral',
492
+ '#FFD700' => 'gold',
493
+ '#808080' => 'gray',
494
+ '#008000' => 'green',
495
+ '#4B0082' => 'indigo',
496
+ '#FFFFF0' => 'ivory',
497
+ '#F0E68C' => 'khaki',
498
+ '#FAF0E6' => 'linen',
499
+ '#800000' => 'maroon',
500
+ '#000080' => 'navy',
501
+ '#808000' => 'olive',
502
+ '#CD853F' => 'peru',
503
+ '#FFC0CB' => 'pink',
504
+ '#DDA0DD' => 'plum',
505
+ '#800080' => 'purple',
506
+ '#F00' => 'red',
507
+ '#FA8072' => 'salmon',
508
+ '#A0522D' => 'sienna',
509
+ '#C0C0C0' => 'silver',
510
+ '#FFFAFA' => 'snow',
511
+ '#D2B48C' => 'tan',
512
+ '#FF6347' => 'tomato',
513
+ '#EE82EE' => 'violet',
514
+ '#F5DEB3' => 'wheat',
515
+ );
516
+
517
+ return preg_replace_callback(
518
+ '/(?<=[: ])('.implode(array_keys($colors), '|').')(?=[; }])/i',
519
+ function ($match) use ($colors) {
520
+ return $colors[strtoupper($match[0])];
521
+ },
522
+ $content
523
+ );
524
+ }
525
+
526
+ /**
527
+ * Shorten CSS font weights.
528
+ *
529
+ * @param string $content The CSS content to shorten the font weights for
530
+ *
531
+ * @return string
532
+ */
533
+ protected function shortenFontWeights($content)
534
+ {
535
+ $weights = array(
536
+ 'normal' => 400,
537
+ 'bold' => 700,
538
+ );
539
+
540
+ $callback = function ($match) use ($weights) {
541
+ return $match[1].$weights[$match[2]];
542
+ };
543
+
544
+ return preg_replace_callback('/(font-weight\s*:\s*)('.implode('|', array_keys($weights)).')(?=[;}])/', $callback, $content);
545
+ }
546
+
547
+ /**
548
+ * Shorthand 0 values to plain 0, instead of e.g. -0em.
549
+ *
550
+ * @param string $content The CSS content to shorten the zero values for
551
+ *
552
+ * @return string
553
+ */
554
+ protected function shortenZeroes($content)
555
+ {
556
+ // reusable bits of code throughout these regexes:
557
+ // before & after are used to make sure we don't match lose unintended
558
+ // 0-like values (e.g. in #000, or in http://url/1.0)
559
+ // units can be stripped from 0 values, or used to recognize non 0
560
+ // values (where wa may be able to strip a .0 suffix)
561
+ $before = '(?<=[:(, ])';
562
+ $after = '(?=[ ,);}])';
563
+ $units = '(em|ex|%|px|cm|mm|in|pt|pc|ch|rem|vh|vw|vmin|vmax|vm)';
564
+
565
+ // strip units after zeroes (0px -> 0)
566
+ // NOTE: it should be safe to remove all units for a 0 value, but in
567
+ // practice, Webkit (especially Safari) seems to stumble over at least
568
+ // 0%, potentially other units as well. Only stripping 'px' for now.
569
+ // @see https://github.com/matthiasmullie/minify/issues/60
570
+ $content = preg_replace('/'.$before.'(-?0*(\.0+)?)(?<=0)px'.$after.'/', '\\1', $content);
571
+
572
+ // strip 0-digits (.0 -> 0)
573
+ $content = preg_replace('/'.$before.'\.0+'.$units.'?'.$after.'/', '0\\1', $content);
574
+ // strip trailing 0: 50.10 -> 50.1, 50.10px -> 50.1px
575
+ $content = preg_replace('/'.$before.'(-?[0-9]+\.[0-9]+)0+'.$units.'?'.$after.'/', '\\1\\2', $content);
576
+ // strip trailing 0: 50.00 -> 50, 50.00px -> 50px
577
+ $content = preg_replace('/'.$before.'(-?[0-9]+)\.0+'.$units.'?'.$after.'/', '\\1\\2', $content);
578
+ // strip leading 0: 0.1 -> .1, 01.1 -> 1.1
579
+ $content = preg_replace('/'.$before.'(-?)0+([0-9]*\.[0-9]+)'.$units.'?'.$after.'/', '\\1\\2\\3', $content);
580
+
581
+ // strip negative zeroes (-0 -> 0) & truncate zeroes (00 -> 0)
582
+ $content = preg_replace('/'.$before.'-?0+'.$units.'?'.$after.'/', '0\\1', $content);
583
+
584
+ // remove zeroes where they make no sense in calc: e.g. calc(100px - 0)
585
+ // the 0 doesn't have any effect, and this isn't even valid without unit
586
+ // strip all `+ 0` or `- 0` occurrences: calc(10% + 0) -> calc(10%)
587
+ // looped because there may be multiple 0s inside 1 group of parentheses
588
+ do {
589
+ $previous = $content;
590
+ $content = preg_replace('/\(([^\(\)]+) [\+\-] 0( [^\(\)]+)?\)/', '(\\1\\2)', $content);
591
+ } while ($content !== $previous);
592
+ // strip all `0 +` occurrences: calc(0 + 10%) -> calc(10%)
593
+ $content = preg_replace('/\(0 \+ ([^\(\)]+)\)/', '(\\1)', $content);
594
+ // strip all `0 -` occurrences: calc(0 - 10%) -> calc(-10%)
595
+ $content = preg_replace('/\(0 \- ([^\(\)]+)\)/', '(-\\1)', $content);
596
+ // I'm not going to attempt to optimize away `x * 0` instances:
597
+ // it's dumb enough code already that it likely won't occur, and it's
598
+ // too complex to do right (order of operations would have to be
599
+ // respected etc)
600
+ // what I cared about most here was fixing incorrectly truncated units
601
+
602
+ // IE doesn't seem to understand a unitless flex-basis value, so let's
603
+ // add it in again (make it `%`, which is only 1 char: 0%, 0px, 0
604
+ // anything, it's all just the same)
605
+ $content = preg_replace('/flex:([^ ]+ [^ ]+ )0([;\}])/', 'flex:${1}0%${2}', $content);
606
+ $content = preg_replace('/flex-basis:0([;\}])/', 'flex-basis:0%${1}', $content);
607
+
608
+ return $content;
609
+ }
610
+
611
+ /**
612
+ * Strip empty tags from source code.
613
+ *
614
+ * @param string $content
615
+ *
616
+ * @return string
617
+ */
618
+ protected function stripEmptyTags($content)
619
+ {
620
+ $content = preg_replace('/(?<=^)[^\{\};]+\{\s*\}/', '', $content);
621
+ $content = preg_replace('/(?<=(\}|;))[^\{\};]+\{\s*\}/', '', $content);
622
+
623
+ return $content;
624
+ }
625
+
626
+ /**
627
+ * Strip comments from source code.
628
+ */
629
+ protected function stripComments()
630
+ {
631
+ $this->registerPattern('/\/\*.*?\*\//s', '');
632
+ }
633
+
634
+ /**
635
+ * Strip whitespace.
636
+ *
637
+ * @param string $content The CSS content to strip the whitespace for
638
+ *
639
+ * @return string
640
+ */
641
+ protected function stripWhitespace($content)
642
+ {
643
+ // remove leading & trailing whitespace
644
+ $content = preg_replace('/^\s*/m', '', $content);
645
+ $content = preg_replace('/\s*$/m', '', $content);
646
+
647
+ // replace newlines with a single space
648
+ $content = preg_replace('/\s+/', ' ', $content);
649
+
650
+ // remove whitespace around meta characters
651
+ // inspired by stackoverflow.com/questions/15195750/minify-compress-css-with-regex
652
+ $content = preg_replace('/\s*([\*$~^|]?+=|[{};,>~]|!important\b)\s*/', '$1', $content);
653
+ $content = preg_replace('/([\[(:])\s+/', '$1', $content);
654
+ $content = preg_replace('/\s+([\]\)])/', '$1', $content);
655
+ $content = preg_replace('/\s+(:)(?![^\}]*\{)/', '$1', $content);
656
+
657
+ // whitespace around + and - can only be stripped inside some pseudo-
658
+ // classes, like `:nth-child(3+2n)`
659
+ // not in things like `calc(3px + 2px)`, shorthands like `3px -2px`, or
660
+ // selectors like `div.weird- p`
661
+ $pseudos = array('nth-child', 'nth-last-child', 'nth-last-of-type', 'nth-of-type');
662
+ $content = preg_replace('/:('.implode('|', $pseudos).')\(\s*([+-]?)\s*(.+?)\s*([+-]?)\s*(.*?)\s*\)/', ':$1($2$3$4$5)', $content);
663
+
664
+ // remove semicolon/whitespace followed by closing bracket
665
+ $content = str_replace(';}', '}', $content);
666
+
667
+ return trim($content);
668
+ }
669
+
670
+ /**
671
+ * Check if file is small enough to be imported.
672
+ *
673
+ * @param string $path The path to the file
674
+ *
675
+ * @return bool
676
+ */
677
+ protected function canImportBySize($path)
678
+ {
679
+ return ($size = @filesize($path)) && $size <= $this->maxImportSize * 1024;
680
+ }
681
+
682
+ /**
683
+ * Check if file a file can be imported, going by the path.
684
+ *
685
+ * @param string $path
686
+ *
687
+ * @return bool
688
+ */
689
+ protected function canImportByPath($path)
690
+ {
691
+ return preg_match('/^(data:|https?:|\\/)/', $path) === 0;
692
+ }
693
+
694
+ /**
695
+ * Return a converter to update relative paths to be relative to the new
696
+ * destination.
697
+ *
698
+ * @param string $source
699
+ * @param string $target
700
+ *
701
+ * @return ConverterInterface
702
+ */
703
+ protected function getPathConverter($source, $target)
704
+ {
705
+ return new Converter($source, $target);
706
+ }
707
+ }
vendor/minifier/minify/src/Exception.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Base Exception
4
+ *
5
+ * @deprecated Use Exceptions\BasicException instead
6
+ *
7
+ * @author Matthias Mullie <minify@mullie.eu>
8
+ */
9
+ namespace MatthiasMullie\Minify;
10
+
11
+ /**
12
+ * Base Exception Class
13
+ * @deprecated Use Exceptions\BasicException instead
14
+ *
15
+ * @package Minify
16
+ * @author Matthias Mullie <minify@mullie.eu>
17
+ */
18
+ abstract class Exception extends \Exception
19
+ {
20
+ }
vendor/minifier/minify/src/Exceptions/BasicException.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Basic exception
4
+ *
5
+ * Please report bugs on https://github.com/matthiasmullie/minify/issues
6
+ *
7
+ * @author Matthias Mullie <minify@mullie.eu>
8
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
9
+ * @license MIT License
10
+ */
11
+ namespace MatthiasMullie\Minify\Exceptions;
12
+
13
+ use MatthiasMullie\Minify\Exception;
14
+
15
+ /**
16
+ * Basic Exception Class
17
+ *
18
+ * @package Minify\Exception
19
+ * @author Matthias Mullie <minify@mullie.eu>
20
+ */
21
+ abstract class BasicException extends Exception
22
+ {
23
+ }
vendor/minifier/minify/src/Exceptions/FileImportException.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * File Import Exception
4
+ *
5
+ * Please report bugs on https://github.com/matthiasmullie/minify/issues
6
+ *
7
+ * @author Matthias Mullie <minify@mullie.eu>
8
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
9
+ * @license MIT License
10
+ */
11
+ namespace MatthiasMullie\Minify\Exceptions;
12
+
13
+ /**
14
+ * File Import Exception Class
15
+ *
16
+ * @package Minify\Exception
17
+ * @author Matthias Mullie <minify@mullie.eu>
18
+ */
19
+ class FileImportException extends BasicException
20
+ {
21
+ }
vendor/minifier/minify/src/Exceptions/IOException.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IO Exception
4
+ *
5
+ * Please report bugs on https://github.com/matthiasmullie/minify/issues
6
+ *
7
+ * @author Matthias Mullie <minify@mullie.eu>
8
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
9
+ * @license MIT License
10
+ */
11
+ namespace MatthiasMullie\Minify\Exceptions;
12
+
13
+ /**
14
+ * IO Exception Class
15
+ *
16
+ * @package Minify\Exception
17
+ * @author Matthias Mullie <minify@mullie.eu>
18
+ */
19
+ class IOException extends BasicException
20
+ {
21
+ }
vendor/minifier/minify/src/JS.php ADDED
@@ -0,0 +1,639 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * JavaScript minifier
4
+ *
5
+ * Please report bugs on https://github.com/matthiasmullie/minify/issues
6
+ *
7
+ * @author Matthias Mullie <minify@mullie.eu>
8
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
9
+ * @license MIT License
10
+ */
11
+ namespace MatthiasMullie\Minify;
12
+
13
+ /**
14
+ * JavaScript Minifier Class
15
+ *
16
+ * Please report bugs on https://github.com/matthiasmullie/minify/issues
17
+ *
18
+ * @package Minify
19
+ * @author Matthias Mullie <minify@mullie.eu>
20
+ * @author Tijs Verkoyen <minify@verkoyen.eu>
21
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
22
+ * @license MIT License
23
+ */
24
+ class JS extends Minify
25
+ {
26
+ /**
27
+ * Var-matching regex based on http://stackoverflow.com/a/9337047/802993.
28
+ *
29
+ * Note that regular expressions using that bit must have the PCRE_UTF8
30
+ * pattern modifier (/u) set.
31
+ *
32
+ * @var string
33
+ */
34
+ const REGEX_VARIABLE = '\b[$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}][$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}0-9\x{0300}-\x{036f}\x{0483}-\x{0487}\x{0591}-\x{05bd}\x{05bf}\x{05c1}\x{05c2}\x{05c4}\x{05c5}\x{05c7}\x{0610}-\x{061a}\x{064b}-\x{0669}\x{0670}\x{06d6}-\x{06dc}\x{06df}-\x{06e4}\x{06e7}\x{06e8}\x{06ea}-\x{06ed}\x{06f0}-\x{06f9}\x{0711}\x{0730}-\x{074a}\x{07a6}-\x{07b0}\x{07c0}-\x{07c9}\x{07eb}-\x{07f3}\x{0816}-\x{0819}\x{081b}-\x{0823}\x{0825}-\x{0827}\x{0829}-\x{082d}\x{0859}-\x{085b}\x{08e4}-\x{08fe}\x{0900}-\x{0903}\x{093a}-\x{093c}\x{093e}-\x{094f}\x{0951}-\x{0957}\x{0962}\x{0963}\x{0966}-\x{096f}\x{0981}-\x{0983}\x{09bc}\x{09be}-\x{09c4}\x{09c7}\x{09c8}\x{09cb}-\x{09cd}\x{09d7}\x{09e2}\x{09e3}\x{09e6}-\x{09ef}\x{0a01}-\x{0a03}\x{0a3c}\x{0a3e}-\x{0a42}\x{0a47}\x{0a48}\x{0a4b}-\x{0a4d}\x{0a51}\x{0a66}-\x{0a71}\x{0a75}\x{0a81}-\x{0a83}\x{0abc}\x{0abe}-\x{0ac5}\x{0ac7}-\x{0ac9}\x{0acb}-\x{0acd}\x{0ae2}\x{0ae3}\x{0ae6}-\x{0aef}\x{0b01}-\x{0b03}\x{0b3c}\x{0b3e}-\x{0b44}\x{0b47}\x{0b48}\x{0b4b}-\x{0b4d}\x{0b56}\x{0b57}\x{0b62}\x{0b63}\x{0b66}-\x{0b6f}\x{0b82}\x{0bbe}-\x{0bc2}\x{0bc6}-\x{0bc8}\x{0bca}-\x{0bcd}\x{0bd7}\x{0be6}-\x{0bef}\x{0c01}-\x{0c03}\x{0c3e}-\x{0c44}\x{0c46}-\x{0c48}\x{0c4a}-\x{0c4d}\x{0c55}\x{0c56}\x{0c62}\x{0c63}\x{0c66}-\x{0c6f}\x{0c82}\x{0c83}\x{0cbc}\x{0cbe}-\x{0cc4}\x{0cc6}-\x{0cc8}\x{0cca}-\x{0ccd}\x{0cd5}\x{0cd6}\x{0ce2}\x{0ce3}\x{0ce6}-\x{0cef}\x{0d02}\x{0d03}\x{0d3e}-\x{0d44}\x{0d46}-\x{0d48}\x{0d4a}-\x{0d4d}\x{0d57}\x{0d62}\x{0d63}\x{0d66}-\x{0d6f}\x{0d82}\x{0d83}\x{0dca}\x{0dcf}-\x{0dd4}\x{0dd6}\x{0dd8}-\x{0ddf}\x{0df2}\x{0df3}\x{0e31}\x{0e34}-\x{0e3a}\x{0e47}-\x{0e4e}\x{0e50}-\x{0e59}\x{0eb1}\x{0eb4}-\x{0eb9}\x{0ebb}\x{0ebc}\x{0ec8}-\x{0ecd}\x{0ed0}-\x{0ed9}\x{0f18}\x{0f19}\x{0f20}-\x{0f29}\x{0f35}\x{0f37}\x{0f39}\x{0f3e}\x{0f3f}\x{0f71}-\x{0f84}\x{0f86}\x{0f87}\x{0f8d}-\x{0f97}\x{0f99}-\x{0fbc}\x{0fc6}\x{102b}-\x{103e}\x{1040}-\x{1049}\x{1056}-\x{1059}\x{105e}-\x{1060}\x{1062}-\x{1064}\x{1067}-\x{106d}\x{1071}-\x{1074}\x{1082}-\x{108d}\x{108f}-\x{109d}\x{135d}-\x{135f}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}\x{1753}\x{1772}\x{1773}\x{17b4}-\x{17d3}\x{17dd}\x{17e0}-\x{17e9}\x{180b}-\x{180d}\x{1810}-\x{1819}\x{18a9}\x{1920}-\x{192b}\x{1930}-\x{193b}\x{1946}-\x{194f}\x{19b0}-\x{19c0}\x{19c8}\x{19c9}\x{19d0}-\x{19d9}\x{1a17}-\x{1a1b}\x{1a55}-\x{1a5e}\x{1a60}-\x{1a7c}\x{1a7f}-\x{1a89}\x{1a90}-\x{1a99}\x{1b00}-\x{1b04}\x{1b34}-\x{1b44}\x{1b50}-\x{1b59}\x{1b6b}-\x{1b73}\x{1b80}-\x{1b82}\x{1ba1}-\x{1bad}\x{1bb0}-\x{1bb9}\x{1be6}-\x{1bf3}\x{1c24}-\x{1c37}\x{1c40}-\x{1c49}\x{1c50}-\x{1c59}\x{1cd0}-\x{1cd2}\x{1cd4}-\x{1ce8}\x{1ced}\x{1cf2}-\x{1cf4}\x{1dc0}-\x{1de6}\x{1dfc}-\x{1dff}\x{200c}\x{200d}\x{203f}\x{2040}\x{2054}\x{20d0}-\x{20dc}\x{20e1}\x{20e5}-\x{20f0}\x{2cef}-\x{2cf1}\x{2d7f}\x{2de0}-\x{2dff}\x{302a}-\x{302f}\x{3099}\x{309a}\x{a620}-\x{a629}\x{a66f}\x{a674}-\x{a67d}\x{a69f}\x{a6f0}\x{a6f1}\x{a802}\x{a806}\x{a80b}\x{a823}-\x{a827}\x{a880}\x{a881}\x{a8b4}-\x{a8c4}\x{a8d0}-\x{a8d9}\x{a8e0}-\x{a8f1}\x{a900}-\x{a909}\x{a926}-\x{a92d}\x{a947}-\x{a953}\x{a980}-\x{a983}\x{a9b3}-\x{a9c0}\x{a9d0}-\x{a9d9}\x{aa29}-\x{aa36}\x{aa43}\x{aa4c}\x{aa4d}\x{aa50}-\x{aa59}\x{aa7b}\x{aab0}\x{aab2}-\x{aab4}\x{aab7}\x{aab8}\x{aabe}\x{aabf}\x{aac1}\x{aaeb}-\x{aaef}\x{aaf5}\x{aaf6}\x{abe3}-\x{abea}\x{abec}\x{abed}\x{abf0}-\x{abf9}\x{fb1e}\x{fe00}-\x{fe0f}\x{fe20}-\x{fe26}\x{fe33}\x{fe34}\x{fe4d}-\x{fe4f}\x{ff10}-\x{ff19}\x{ff3f}]*\b';
35
+
36
+ /**
37
+ * Full list of JavaScript reserved words.
38
+ * Will be loaded from /data/js/keywords_reserved.txt.
39
+ *
40
+ * @see https://mathiasbynens.be/notes/reserved-keywords
41
+ *
42
+ * @var string[]
43
+ */
44
+ protected $keywordsReserved = array();
45
+
46
+ /**
47
+ * List of JavaScript reserved words that accept a <variable, value, ...>
48
+ * after them. Some end of lines are not the end of a statement, like with
49
+ * these keywords.
50
+ *
51
+ * E.g.: we shouldn't insert a ; after this else
52
+ * else
53
+ * console.log('this is quite fine')
54
+ *
55
+ * Will be loaded from /data/js/keywords_before.txt
56
+ *
57
+ * @var string[]
58
+ */
59
+ protected $keywordsBefore = array();
60
+
61
+ /**
62
+ * List of JavaScript reserved words that accept a <variable, value, ...>
63
+ * before them. Some end of lines are not the end of a statement, like when
64
+ * continued by one of these keywords on the newline.
65
+ *
66
+ * E.g.: we shouldn't insert a ; before this instanceof
67
+ * variable
68
+ * instanceof String
69
+ *
70
+ * Will be loaded from /data/js/keywords_after.txt
71
+ *
72
+ * @var string[]
73
+ */
74
+ protected $keywordsAfter = array();
75
+
76
+ /**
77
+ * List of all JavaScript operators.
78
+ *
79
+ * Will be loaded from /data/js/operators.txt
80
+ *
81
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
82
+ *
83
+ * @var string[]
84
+ */
85
+ protected $operators = array();
86
+
87
+ /**
88
+ * List of JavaScript operators that accept a <variable, value, ...> after
89
+ * them. Some end of lines are not the end of a statement, like with these
90
+ * operators.
91
+ *
92
+ * Note: Most operators are fine, we've only removed ++ and --.
93
+ * ++ & -- have to be joined with the value they're in-/decrementing.
94
+ *
95
+ * Will be loaded from /data/js/operators_before.txt
96
+ *
97
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
98
+ *
99
+ * @var string[]
100
+ */
101
+ protected $operatorsBefore = array();
102
+
103
+ /**
104
+ * List of JavaScript operators that accept a <variable, value, ...> before
105
+ * them. Some end of lines are not the end of a statement, like when
106
+ * continued by one of these operators on the newline.
107
+ *
108
+ * Note: Most operators are fine, we've only removed ), ], ++, --, ! and ~.
109
+ * There can't be a newline separating ! or ~ and whatever it is negating.
110
+ * ++ & -- have to be joined with the value they're in-/decrementing.
111
+ * ) & ] are "special" in that they have lots or usecases. () for example
112
+ * is used for function calls, for grouping, in if () and for (), ...
113
+ *
114
+ * Will be loaded from /data/js/operators_after.txt
115
+ *
116
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
117
+ *
118
+ * @var string[]
119
+ */
120
+ protected $operatorsAfter = array();
121
+
122
+ /**
123
+ * Public property so it can be accessed from inside the closure in
124
+ * extractRegex. Once PHP5.3 compatibility is dropped, we can make this
125
+ * property protected again.
126
+ *
127
+ * @var array
128
+ */
129
+ public $nestedExtracted = array();
130
+
131
+ /**
132
+ * {@inheritdoc}
133
+ */
134
+ public function __construct()
135
+ {
136
+ call_user_func_array(array('parent', '__construct'), func_get_args());
137
+
138
+ $dataDir = __DIR__.'/../data/js/';
139
+ $options = FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES;
140
+ $this->keywordsReserved = file($dataDir.'keywords_reserved.txt', $options);
141
+ $this->keywordsBefore = file($dataDir.'keywords_before.txt', $options);
142
+ $this->keywordsAfter = file($dataDir.'keywords_after.txt', $options);
143
+ $this->operators = file($dataDir.'operators.txt', $options);
144
+ $this->operatorsBefore = file($dataDir.'operators_before.txt', $options);
145
+ $this->operatorsAfter = file($dataDir.'operators_after.txt', $options);
146
+ }
147
+
148
+ /**
149
+ * Minify the data.
150
+ * Perform JS optimizations.
151
+ *
152
+ * @param string[optional] $path Path to write the data to
153
+ *
154
+ * @return string The minified data
155
+ */
156
+ public function execute($path = null)
157
+ {
158
+ $content = '';
159
+
160
+ /*
161
+ * Let's first take out strings, comments and regular expressions.
162
+ * All of these can contain JS code-like characters, and we should make
163
+ * sure any further magic ignores anything inside of these.
164
+ *
165
+ * Consider this example, where we should not strip any whitespace:
166
+ * var str = "a test";
167
+ *
168
+ * Comments will be removed altogether, strings and regular expressions
169
+ * will be replaced by placeholder text, which we'll restore later.
170
+ */
171
+ $this->extractStrings('\'"`');
172
+ $this->stripComments();
173
+ $this->extractRegex();
174
+
175
+ // loop files
176
+ foreach ($this->data as $source => $js) {
177
+ // take out strings, comments & regex (for which we've registered
178
+ // the regexes just a few lines earlier)
179
+ $js = $this->replace($js);
180
+
181
+ $js = $this->propertyNotation($js);
182
+ $js = $this->shortenBools($js);
183
+ $js = $this->stripWhitespace($js);
184
+
185
+ // combine js: separating the scripts by a ;
186
+ $content .= $js.";";
187
+ }
188
+
189
+ // clean up leftover `;`s from the combination of multiple scripts
190
+ $content = ltrim($content, ';');
191
+ $content = substr($content, 0, -1);
192
+
193
+ /*
194
+ * Earlier, we extracted strings & regular expressions and replaced them
195
+ * with placeholder text. This will restore them.
196
+ */
197
+ $content = $this->restoreExtractedData($content);
198
+
199
+ return $content;
200
+ }
201
+
202
+ /**
203
+ * Strip comments from source code.
204
+ *
205
+ * Public method so it can be accessed from inside the closure in
206
+ * extractRegex. Once PHP5.3 compatibility is dropped, we can make this
207
+ * method protected again.
208
+ */
209
+ public function stripComments()
210
+ {
211
+ // single-line comments
212
+ $this->registerPattern('/\/\/.*$/m', '');
213
+
214
+ // multi-line comments
215
+ $this->registerPattern('/\/\*.*?\*\//s', '');
216
+ }
217
+
218
+ /**
219
+ * JS can have /-delimited regular expressions, like: /ab+c/.match(string).
220
+ *
221
+ * The content inside the regex can contain characters that may be confused
222
+ * for JS code: e.g. it could contain whitespace it needs to match & we
223
+ * don't want to strip whitespace in there.
224
+ *
225
+ * The regex can be pretty simple: we don't have to care about comments,
226
+ * (which also use slashes) because stripComments() will have stripped those
227
+ * already.
228
+ *
229
+ * This method will replace all string content with simple REGEX#
230
+ * placeholder text, so we've rid all regular expressions from characters
231
+ * that may be misinterpreted. Original regex content will be saved in
232
+ * $this->extracted and after doing all other minifying, we can restore the
233
+ * original content via restoreRegex()
234
+ */
235
+ protected function extractRegex()
236
+ {
237
+ // PHP only supports $this inside anonymous functions since 5.4
238
+ $minifier = $this;
239
+ $callback = function ($match) use ($minifier) {
240
+ $count = count($minifier->extracted);
241
+ $placeholder = '"'.$count.'"';
242
+ $minifier->extracted[$placeholder] = $match['regex'];
243
+
244
+ // because we're also trying to find regular expressions that follow
245
+ // if/when/for statements, we should also make sure that the content
246
+ // within these statements is also minified...
247
+ // e.g. `if("some string"/* or comment */)` should become
248
+ // `if("some string")`
249
+ if (isset($match['before'])) {
250
+ $other = new $minifier();
251
+ $other->extractStrings('\'"`', "$count-");
252
+ $other->stripComments();
253
+ $match['before'] = $other->replace($match['before']);
254
+ $minifier->nestedExtracted += $other->extracted;
255
+ }
256
+
257
+ return (isset($match['before']) ? $match['before'] : '').
258
+ $placeholder.
259
+ (isset($match['after']) ? $match['after'] : '');
260
+ };
261
+
262
+ $pattern = '(?P<regex>\/(?!\/).*?(?<!\\\\)(\\\\\\\\)*\/[gimy]*)(?![0-9a-zA-Z\/])';
263
+
264
+ // a regular expression can only be followed by a few operators or some
265
+ // of the RegExp methods (a `\` followed by a variable or value is
266
+ // likely part of a division, not a regex)
267
+ $keywords = array('do', 'in', 'new', 'else', 'throw', 'yield', 'delete', 'return', 'typeof');
268
+ $before = '(?P<before>[=:,;\}\(\{\[&\|!]|^|'.implode('|', $keywords).')';
269
+ $propertiesAndMethods = array(
270
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#Properties_2
271
+ 'constructor',
272
+ 'flags',
273
+ 'global',
274
+ 'ignoreCase',
275
+ 'multiline',
276
+ 'source',
277
+ 'sticky',
278
+ 'unicode',
279
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#Methods_2
280
+ 'compile(',
281
+ 'exec(',
282
+ 'test(',
283
+ 'toSource(',
284
+ 'toString(',
285
+ );
286
+ $delimiters = array_fill(0, count($propertiesAndMethods), '/');
287
+ $propertiesAndMethods = array_map('preg_quote', $propertiesAndMethods, $delimiters);
288
+ $after = '(?P<after>[\.,;\)\}&\|+]|$|\.('.implode('|', $propertiesAndMethods).'))';
289
+ $this->registerPattern('/'.$before.'\s*'.$pattern.'\s*'.$after.'/', $callback);
290
+
291
+ // we didn't check for regular expressions after `)`, because that is
292
+ // more often than not not a character where a regex can follow (e.g.
293
+ // (1+2)/3/4 -> /3/ could be considered a regex, but it's not)
294
+ // however, after single-line if/while/for, there could very well be a
295
+ // regex after `)` (e.g. if(true)/regex/)
296
+ // there is one problem, though: it's (near) impossible to check for
297
+ // when the if/while/for statement is closed (same amount of closing
298
+ // brackets as there were opened), so I'll ignore single-line statements
299
+ // with nested brackets followed by a regex for now...
300
+ $before = '(?P<before>\b(if|while|for)\s*\((?P<code>[^\(]+?)\))';
301
+ $this->registerPattern('/'.$before.'\s*'.$pattern.'\s*'.$after.'/', $callback);
302
+
303
+ // 1 more edge case: a regex can be followed by a lot more operators or
304
+ // keywords if there's a newline (ASI) in between, where the operator
305
+ // actually starts a new statement
306
+ // (https://github.com/matthiasmullie/minify/issues/56)
307
+ $operators = $this->getOperatorsForRegex($this->operatorsBefore, '/');
308
+ $operators += $this->getOperatorsForRegex($this->keywordsReserved, '/');
309
+ $after = '(?P<after>\n\s*('.implode('|', $operators).'))';
310
+ $this->registerPattern('/'.$pattern.'\s*'.$after.'/', $callback);
311
+ }
312
+
313
+ /**
314
+ * In addition to the regular restore routine, we also need to restore a few
315
+ * more things that have been extracted as part of the regex extraction...
316
+ *
317
+ * {@inheritdoc}
318
+ */
319
+ protected function restoreExtractedData($content)
320
+ {
321
+ // restore regular extracted stuff
322
+ $content = parent::restoreExtractedData($content);
323
+
324
+ // restore nested stuff from within regex extraction
325
+ $content = strtr($content, $this->nestedExtracted);
326
+
327
+ return $content;
328
+ }
329
+
330
+ /**
331
+ * Strip whitespace.
332
+ *
333
+ * We won't strip *all* whitespace, but as much as possible. The thing that
334
+ * we'll preserve are newlines we're unsure about.
335
+ * JavaScript doesn't require statements to be terminated with a semicolon.
336
+ * It will automatically fix missing semicolons with ASI (automatic semi-
337
+ * colon insertion) at the end of line causing errors (without semicolon.)
338
+ *
339
+ * Because it's sometimes hard to tell if a newline is part of a statement
340
+ * that should be terminated or not, we'll just leave some of them alone.
341
+ *
342
+ * @param string $content The content to strip the whitespace for
343
+ *
344
+ * @return string
345
+ */
346
+ protected function stripWhitespace($content)
347
+ {
348
+ // uniform line endings, make them all line feed
349
+ $content = str_replace(array("\r\n", "\r"), "\n", $content);
350
+
351
+ // collapse all non-line feed whitespace into a single space
352
+ $content = preg_replace('/[^\S\n]+/', ' ', $content);
353
+
354
+ // strip leading & trailing whitespace
355
+ $content = str_replace(array(" \n", "\n "), "\n", $content);
356
+
357
+ // collapse consecutive line feeds into just 1
358
+ $content = preg_replace('/\n+/', "\n", $content);
359
+
360
+ $operatorsBefore = $this->getOperatorsForRegex($this->operatorsBefore, '/');
361
+ $operatorsAfter = $this->getOperatorsForRegex($this->operatorsAfter, '/');
362
+ $operators = $this->getOperatorsForRegex($this->operators, '/');
363
+ $keywordsBefore = $this->getKeywordsForRegex($this->keywordsBefore, '/');
364
+ $keywordsAfter = $this->getKeywordsForRegex($this->keywordsAfter, '/');
365
+
366
+ // strip whitespace that ends in (or next line begin with) an operator
367
+ // that allows statements to be broken up over multiple lines
368
+ unset($operatorsBefore['+'], $operatorsBefore['-'], $operatorsAfter['+'], $operatorsAfter['-']);
369
+ $content = preg_replace(
370
+ array(
371
+ '/('.implode('|', $operatorsBefore).')\s+/',
372
+ '/\s+('.implode('|', $operatorsAfter).')/',
373
+ ), '\\1', $content
374
+ );
375
+
376
+ // make sure + and - can't be mistaken for, or joined into ++ and --
377
+ $content = preg_replace(
378
+ array(
379
+ '/(?<![\+\-])\s*([\+\-])(?![\+\-])/',
380
+ '/(?<![\+\-])([\+\-])\s*(?![\+\-])/',
381
+ ), '\\1', $content
382
+ );
383
+
384
+ // collapse whitespace around reserved words into single space
385
+ $content = preg_replace('/(^|[;\}\s])\K('.implode('|', $keywordsBefore).')\s+/', '\\2 ', $content);
386
+ $content = preg_replace('/\s+('.implode('|', $keywordsAfter).')(?=([;\{\s]|$))/', ' \\1', $content);
387
+
388
+ /*
389
+ * We didn't strip whitespace after a couple of operators because they
390
+ * could be used in different contexts and we can't be sure it's ok to
391
+ * strip the newlines. However, we can safely strip any non-line feed
392
+ * whitespace that follows them.
393
+ */
394
+ $operatorsDiffBefore = array_diff($operators, $operatorsBefore);
395
+ $operatorsDiffAfter = array_diff($operators, $operatorsAfter);
396
+ $content = preg_replace('/('.implode('|', $operatorsDiffBefore).')[^\S\n]+/', '\\1', $content);
397
+ $content = preg_replace('/[^\S\n]+('.implode('|', $operatorsDiffAfter).')/', '\\1', $content);
398
+
399
+ /*
400
+ * Get rid of double semicolons, except where they can be used like:
401
+ * "for(v=1,_=b;;)", "for(v=1;;v++)" or "for(;;ja||(ja=true))".
402
+ * I'll safeguard these double semicolons inside for-loops by
403
+ * temporarily replacing them with an invalid condition: they won't have
404
+ * a double semicolon and will be easy to spot to restore afterwards.
405
+ */
406
+ $content = preg_replace('/\bfor\(([^;]*);;([^;]*)\)/', 'for(\\1;-;\\2)', $content);
407
+ $content = preg_replace('/;+/', ';', $content);
408
+ $content = preg_replace('/\bfor\(([^;]*);-;([^;]*)\)/', 'for(\\1;;\\2)', $content);
409
+
410
+ /*
411
+ * Next, we'll be removing all semicolons where ASI kicks in.
412
+ * for-loops however, can have an empty body (ending in only a
413
+ * semicolon), like: `for(i=1;i<3;i++);`, of `for(i in list);`
414
+ * Here, nothing happens during the loop; it's just used to keep
415
+ * increasing `i`. With that ; omitted, the next line would be expected
416
+ * to be the for-loop's body... Same goes for while loops.
417
+ * I'm going to double that semicolon (if any) so after the next line,
418
+ * which strips semicolons here & there, we're still left with this one.
419
+ */
420
+ $content = preg_replace('/(for\([^;\{]*;[^;\{]*;[^;\{]*\));(\}|$)/s', '\\1;;\\2', $content);
421
+ $content = preg_replace('/(for\([^;\{]+\s+in\s+[^;\{]+\));(\}|$)/s', '\\1;;\\2', $content);
422
+ $content = preg_replace('/(while\([^;\{]+\));(\}|$)/s', '\\1;;\\2', $content); // @todo: no if part of a do{}while()
423
+
424
+ /*
425
+ * We also can't strip empty else-statements. Even though they're
426
+ * useless and probably shouldn't be in the code in the first place, we
427
+ * shouldn't be stripping the `;` that follows it as it breaks the code.
428
+ * We can just remove those useless else-statements completely.
429
+ *
430
+ * @see https://github.com/matthiasmullie/minify/issues/91
431
+ */
432
+ $content = preg_replace('/else;/s', '', $content);
433
+
434
+ /*
435
+ * We also don't really want to terminate statements followed by closing
436
+ * curly braces (which we've ignored completely up until now) or end-of-
437
+ * script: ASI will kick in here & we're all about minifying.
438
+ * Semicolons at beginning of the file don't make any sense either.
439
+ */
440
+ $content = preg_replace('/;(\}|$)/s', '\\1', $content);
441
+ $content = ltrim($content, ';');
442
+
443
+ // get rid of remaining whitespace af beginning/end
444
+ return trim($content);
445
+ }
446
+
447
+ /**
448
+ * We'll strip whitespace around certain operators with regular expressions.
449
+ * This will prepare the given array by escaping all characters.
450
+ *
451
+ * @param string[] $operators
452
+ * @param string $delimiter
453
+ *
454
+ * @return string[]
455
+ */
456
+ protected function getOperatorsForRegex(array $operators, $delimiter = '/')
457
+ {
458
+ // escape operators for use in regex
459
+ $delimiters = array_fill(0, count($operators), $delimiter);
460
+ $escaped = array_map('preg_quote', $operators, $delimiters);
461
+
462
+ $operators = array_combine($operators, $escaped);
463
+
464
+ // ignore + & - for now, they'll get special treatment
465
+ unset($operators['+'], $operators['-']);
466
+
467
+ // dot can not just immediately follow a number; it can be confused for
468
+ // decimal point, or calling a method on it, e.g. 42 .toString()
469
+ $operators['.'] = '(?<![0-9]\s)\.';
470
+
471
+ // don't confuse = with other assignment shortcuts (e.g. +=)
472
+ $chars = preg_quote('+-*\=<>%&|', $delimiter);
473
+ $operators['='] = '(?<!['.$chars.'])\=';
474
+
475
+ return $operators;
476
+ }
477
+
478
+ /**
479
+ * We'll strip whitespace around certain keywords with regular expressions.
480
+ * This will prepare the given array by escaping all characters.
481
+ *
482
+ * @param string[] $keywords
483
+ * @param string $delimiter
484
+ *
485
+ * @return string[]
486
+ */
487
+ protected function getKeywordsForRegex(array $keywords, $delimiter = '/')
488
+ {
489
+ // escape keywords for use in regex
490
+ $delimiter = array_fill(0, count($keywords), $delimiter);
491
+ $escaped = array_map('preg_quote', $keywords, $delimiter);
492
+
493
+ // add word boundaries
494
+ array_walk($keywords, function ($value) {
495
+ return '\b'.$value.'\b';
496
+ });
497
+
498
+ $keywords = array_combine($keywords, $escaped);
499
+
500
+ return $keywords;
501
+ }
502
+
503
+ /**
504
+ * Replaces all occurrences of array['key'] by array.key.
505
+ *
506
+ * @param string $content
507
+ *
508
+ * @return string
509
+ */
510
+ protected function propertyNotation($content)
511
+ {
512
+ // PHP only supports $this inside anonymous functions since 5.4
513
+ $minifier = $this;
514
+ $keywords = $this->keywordsReserved;
515
+ $callback = function ($match) use ($minifier, $keywords) {
516
+ $property = trim($minifier->extracted[$match[1]], '\'"');
517
+
518
+ /*
519
+ * Check if the property is a reserved keyword. In this context (as
520
+ * property of an object literal/array) it shouldn't matter, but IE8
521
+ * freaks out with "Expected identifier".
522
+ */
523
+ if (in_array($property, $keywords)) {
524
+ return $match[0];
525
+ }
526
+
527
+ /*
528
+ * See if the property is in a variable-like format (e.g.
529
+ * array['key-here'] can't be replaced by array.key-here since '-'
530
+ * is not a valid character there.
531
+ */
532
+ if (!preg_match('/^'.$minifier::REGEX_VARIABLE.'$/u', $property)) {
533
+ return $match[0];
534
+ }
535
+
536
+ return '.'.$property;
537
+ };
538
+
539
+ /*
540
+ * Figure out if previous character is a variable name (of the array
541
+ * we want to use property notation on) - this is to make sure
542
+ * standalone ['value'] arrays aren't confused for keys-of-an-array.
543
+ * We can (and only have to) check the last character, because PHP's
544
+ * regex implementation doesn't allow unfixed-length look-behind
545
+ * assertions.
546
+ */
547
+ preg_match('/(\[[^\]]+\])[^\]]*$/', static::REGEX_VARIABLE, $previousChar);
548
+ $previousChar = $previousChar[1];
549
+
550
+ /*
551
+ * Make sure word preceding the ['value'] is not a keyword, e.g.
552
+ * return['x']. Because -again- PHP's regex implementation doesn't allow
553
+ * unfixed-length look-behind assertions, I'm just going to do a lot of
554
+ * separate look-behind assertions, one for each keyword.
555
+ */
556
+ $keywords = $this->getKeywordsForRegex($keywords);
557
+ $keywords = '(?<!'.implode(')(?<!', $keywords).')';
558
+
559
+ return preg_replace_callback('/(?<='.$previousChar.'|\])'.$keywords.'\[\s*(([\'"])[0-9]+\\2)\s*\]/u', $callback, $content);
560
+ }
561
+
562
+ /**
563
+ * Replaces true & false by !0 and !1.
564
+ *
565
+ * @param string $content
566
+ *
567
+ * @return string
568
+ */
569
+ protected function shortenBools($content)
570
+ {
571
+ /*
572
+ * 'true' or 'false' could be used as property names (which may be
573
+ * followed by whitespace) - we must not replace those!
574
+ * Since PHP doesn't allow variable-length (to account for the
575
+ * whitespace) lookbehind assertions, I need to capture the leading
576
+ * character and check if it's a `.`
577
+ */
578
+ $callback = function ($match) {
579
+ if (trim($match[1]) === '.') {
580
+ return $match[0];
581
+ }
582
+
583
+ return $match[1].($match[2] === 'true' ? '!0' : '!1');
584
+ };
585
+ $content = preg_replace_callback('/(^|.\s*)\b(true|false)\b(?!:)/', $callback, $content);
586
+
587
+ // for(;;) is exactly the same as while(true), but shorter :)
588
+ $content = preg_replace('/\bwhile\(!0\){/', 'for(;;){', $content);
589
+
590
+ // now make sure we didn't turn any do ... while(true) into do ... for(;;)
591
+ preg_match_all('/\bdo\b/', $content, $dos, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
592
+
593
+ // go backward to make sure positional offsets aren't altered when $content changes
594
+ $dos = array_reverse($dos);
595
+ foreach ($dos as $do) {
596
+ $offsetDo = $do[0][1];
597
+
598
+ // find all `while` (now `for`) following `do`: one of those must be
599
+ // associated with the `do` and be turned back into `while`
600
+ preg_match_all('/\bfor\(;;\)/', $content, $whiles, PREG_OFFSET_CAPTURE | PREG_SET_ORDER, $offsetDo);
601
+ foreach ($whiles as $while) {
602
+ $offsetWhile = $while[0][1];
603
+
604
+ $open = substr_count($content, '{', $offsetDo, $offsetWhile - $offsetDo);
605
+ $close = substr_count($content, '}', $offsetDo, $offsetWhile - $offsetDo);
606
+ if ($open === $close) {
607
+ // only restore `while` if amount of `{` and `}` are the same;
608
+ // otherwise, that `for` isn't associated with this `do`
609
+ $content = substr_replace($content, 'while(!0)', $offsetWhile, strlen('for(;;)'));
610
+ break;
611
+ }
612
+ }
613
+ }
614
+
615
+ return $content;
616
+ }
617
+
618
+ /**
619
+ * Protected method in parent made public, so it can be accessed from inside
620
+ * the closure in extractRegex. Once PHP5.3 compatibility is dropped, we can
621
+ * remove this.
622
+ *
623
+ * {@inheritdoc}
624
+ */
625
+ public function extractStrings($chars = '\'"', $placeholderPrefix = '') {
626
+ parent::extractStrings($chars, $placeholderPrefix);
627
+ }
628
+
629
+ /**
630
+ * Protected method in parent made public, so it can be accessed from inside
631
+ * the closure in extractRegex. Once PHP5.3 compatibility is dropped, we can
632
+ * remove this.
633
+ *
634
+ * {@inheritdoc}
635
+ */
636
+ public function replace($content) {
637
+ return parent::replace($content);
638
+ }
639
+ }
vendor/minifier/minify/src/Minify.php ADDED
@@ -0,0 +1,444 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Abstract minifier class
4
+ *
5
+ * Please report bugs on https://github.com/matthiasmullie/minify/issues
6
+ *
7
+ * @author Matthias Mullie <minify@mullie.eu>
8
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
9
+ * @license MIT License
10
+ */
11
+ namespace MatthiasMullie\Minify;
12
+
13
+ use MatthiasMullie\Minify\Exceptions\IOException;
14
+ use Psr\Cache\CacheItemInterface;
15
+
16
+ /**
17
+ * Abstract minifier class.
18
+ *
19
+ * Please report bugs on https://github.com/matthiasmullie/minify/issues
20
+ *
21
+ * @package Minify
22
+ * @author Matthias Mullie <minify@mullie.eu>
23
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
24
+ * @license MIT License
25
+ */
26
+ abstract class Minify
27
+ {
28
+ /**
29
+ * The data to be minified.
30
+ *
31
+ * @var string[]
32
+ */
33
+ protected $data = array();
34
+
35
+ /**
36
+ * Array of patterns to match.
37
+ *
38
+ * @var string[]
39
+ */
40
+ protected $patterns = array();
41
+
42
+ /**
43
+ * This array will hold content of strings and regular expressions that have
44
+ * been extracted from the JS source code, so we can reliably match "code",
45
+ * without having to worry about potential "code-like" characters inside.
46
+ *
47
+ * @var string[]
48
+ */
49
+ public $extracted = array();
50
+
51
+ /**
52
+ * Init the minify class - optionally, code may be passed along already.
53
+ */
54
+ public function __construct(/* $data = null, ... */)
55
+ {
56
+ // it's possible to add the source through the constructor as well ;)
57
+ if (func_num_args()) {
58
+ call_user_func_array(array($this, 'add'), func_get_args());
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Add a file or straight-up code to be minified.
64
+ *
65
+ * @param string|string[] $data
66
+ *
67
+ * @return static
68
+ */
69
+ public function add($data /* $data = null, ... */)
70
+ {
71
+ // bogus "usage" of parameter $data: scrutinizer warns this variable is
72
+ // not used (we're using func_get_args instead to support overloading),
73
+ // but it still needs to be defined because it makes no sense to have
74
+ // this function without argument :)
75
+ $args = array($data) + func_get_args();
76
+
77
+ // this method can be overloaded
78
+ foreach ($args as $data) {
79
+ if (is_array($data)) {
80
+ call_user_func_array(array($this, 'add'), $data);
81
+ continue;
82
+ }
83
+
84
+ // redefine var
85
+ $data = (string) $data;
86
+
87
+ // load data
88
+ $value = $this->load($data);
89
+ $key = ($data != $value) ? $data : count($this->data);
90
+
91
+ // replace CR linefeeds etc.
92
+ // @see https://github.com/matthiasmullie/minify/pull/139
93
+ $value = str_replace(array("\r\n", "\r"), "\n", $value);
94
+
95
+ // store data
96
+ $this->data[$key] = $value;
97
+ }
98
+
99
+ return $this;
100
+ }
101
+
102
+ /**
103
+ * Minify the data & (optionally) saves it to a file.
104
+ *
105
+ * @param string[optional] $path Path to write the data to
106
+ *
107
+ * @return string The minified data
108
+ */
109
+ public function minify($path = null)
110
+ {
111
+ $content = $this->execute($path);
112
+
113
+ // save to path
114
+ if ($path !== null) {
115
+ $this->save($content, $path);
116
+ }
117
+
118
+ return $content;
119
+ }
120
+
121
+ /**
122
+ * Minify & gzip the data & (optionally) saves it to a file.
123
+ *
124
+ * @param string[optional] $path Path to write the data to
125
+ * @param int[optional] $level Compression level, from 0 to 9
126
+ *
127
+ * @return string The minified & gzipped data
128
+ */
129
+ public function gzip($path = null, $level = 9)
130
+ {
131
+ $content = $this->execute($path);
132
+ $content = gzencode($content, $level, FORCE_GZIP);
133
+
134
+ // save to path
135
+ if ($path !== null) {
136
+ $this->save($content, $path);
137
+ }
138
+
139
+ return $content;
140
+ }
141
+
142
+ /**
143
+ * Minify the data & write it to a CacheItemInterface object.
144
+ *
145
+ * @param CacheItemInterface $item Cache item to write the data to
146
+ *
147
+ * @return CacheItemInterface Cache item with the minifier data
148
+ */
149
+ public function cache(CacheItemInterface $item)
150
+ {
151
+ $content = $this->execute();
152
+ $item->set($content);
153
+
154
+ return $item;
155
+ }
156
+
157
+ /**
158
+ * Minify the data.
159
+ *
160
+ * @param string[optional] $path Path to write the data to
161
+ *
162
+ * @return string The minified data
163
+ */
164
+ abstract public function execute($path = null);
165
+
166
+ /**
167
+ * Load data.
168
+ *
169
+ * @param string $data Either a path to a file or the content itself
170
+ *
171
+ * @return string
172
+ */
173
+ protected function load($data)
174
+ {
175
+ // check if the data is a file
176
+ if ($this->canImportFile($data)) {
177
+ $data = file_get_contents($data);
178
+
179
+ // strip BOM, if any
180
+ if (substr($data, 0, 3) == "\xef\xbb\xbf") {
181
+ $data = substr($data, 3);
182
+ }
183
+ }
184
+
185
+ return $data;
186
+ }
187
+
188
+ /**
189
+ * Save to file.
190
+ *
191
+ * @param string $content The minified data
192
+ * @param string $path The path to save the minified data to
193
+ *
194
+ * @throws IOException
195
+ */
196
+ protected function save($content, $path)
197
+ {
198
+ $handler = $this->openFileForWriting($path);
199
+
200
+ $this->writeToFile($handler, $content);
201
+
202
+ @fclose($handler);
203
+ }
204
+
205
+ /**
206
+ * Register a pattern to execute against the source content.
207
+ *
208
+ * @param string $pattern PCRE pattern
209
+ * @param string|callable $replacement Replacement value for matched pattern
210
+ */
211
+ protected function registerPattern($pattern, $replacement = '')
212
+ {
213
+ // study the pattern, we'll execute it more than once
214
+ $pattern .= 'S';
215
+
216
+ $this->patterns[] = array($pattern, $replacement);
217
+ }
218
+
219
+ /**
220
+ * We can't "just" run some regular expressions against JavaScript: it's a
221
+ * complex language. E.g. having an occurrence of // xyz would be a comment,
222
+ * unless it's used within a string. Of you could have something that looks
223
+ * like a 'string', but inside a comment.
224
+ * The only way to accurately replace these pieces is to traverse the JS one
225
+ * character at a time and try to find whatever starts first.
226
+ *
227
+ * @param string $content The content to replace patterns in
228
+ *
229
+ * @return string The (manipulated) content
230
+ */
231
+ protected function replace($content)
232
+ {
233
+ $processed = '';
234
+ $positions = array_fill(0, count($this->patterns), -1);
235
+ $matches = array();
236
+
237
+ while ($content) {
238
+ // find first match for all patterns
239
+ foreach ($this->patterns as $i => $pattern) {
240
+ list($pattern, $replacement) = $pattern;
241
+
242
+ // no need to re-run matches that are still in the part of the
243
+ // content that hasn't been processed
244
+ if ($positions[$i] >= 0) {
245
+ continue;
246
+ }
247
+
248
+ $match = null;
249
+ if (preg_match($pattern, $content, $match)) {
250
+ $matches[$i] = $match;
251
+
252
+ // we'll store the match position as well; that way, we
253
+ // don't have to redo all preg_matches after changing only
254
+ // the first (we'll still know where those others are)
255
+ $positions[$i] = strpos($content, $match[0]);
256
+ } else {
257
+ // if the pattern couldn't be matched, there's no point in
258
+ // executing it again in later runs on this same content;
259
+ // ignore this one until we reach end of content
260
+ unset($matches[$i]);
261
+ $positions[$i] = strlen($content);
262
+ }
263
+ }
264
+
265
+ // no more matches to find: everything's been processed, break out
266
+ if (!$matches) {
267
+ $processed .= $content;
268
+ break;
269
+ }
270
+
271
+ // see which of the patterns actually found the first thing (we'll
272
+ // only want to execute that one, since we're unsure if what the
273
+ // other found was not inside what the first found)
274
+ $discardLength = min($positions);
275
+ $firstPattern = array_search($discardLength, $positions);
276
+ $match = $matches[$firstPattern][0];
277
+
278
+ // execute the pattern that matches earliest in the content string
279
+ list($pattern, $replacement) = $this->patterns[$firstPattern];
280
+ $replacement = $this->replacePattern($pattern, $replacement, $content);
281
+
282
+ // figure out which part of the string was unmatched; that's the
283
+ // part we'll execute the patterns on again next
284
+ $content = substr($content, $discardLength);
285
+ $unmatched = (string) substr($content, strpos($content, $match) + strlen($match));
286
+
287
+ // move the replaced part to $processed and prepare $content to
288
+ // again match batch of patterns against
289
+ $processed .= substr($replacement, 0, strlen($replacement) - strlen($unmatched));
290
+ $content = $unmatched;
291
+
292
+ // first match has been replaced & that content is to be left alone,
293
+ // the next matches will start after this replacement, so we should
294
+ // fix their offsets
295
+ foreach ($positions as $i => $position) {
296
+ $positions[$i] -= $discardLength + strlen($match);
297
+ }
298
+ }
299
+
300
+ return $processed;
301
+ }
302
+
303
+ /**
304
+ * This is where a pattern is matched against $content and the matches
305
+ * are replaced by their respective value.
306
+ * This function will be called plenty of times, where $content will always
307
+ * move up 1 character.
308
+ *
309
+ * @param string $pattern Pattern to match
310
+ * @param string|callable $replacement Replacement value
311
+ * @param string $content Content to match pattern against
312
+ *
313
+ * @return string
314
+ */
315
+ protected function replacePattern($pattern, $replacement, $content)
316
+ {
317
+ if (is_callable($replacement)) {
318
+ return preg_replace_callback($pattern, $replacement, $content, 1, $count);
319
+ } else {
320
+ return preg_replace($pattern, $replacement, $content, 1, $count);
321
+ }
322
+ }
323
+
324
+ /**
325
+ * Strings are a pattern we need to match, in order to ignore potential
326
+ * code-like content inside them, but we just want all of the string
327
+ * content to remain untouched.
328
+ *
329
+ * This method will replace all string content with simple STRING#
330
+ * placeholder text, so we've rid all strings from characters that may be
331
+ * misinterpreted. Original string content will be saved in $this->extracted
332
+ * and after doing all other minifying, we can restore the original content
333
+ * via restoreStrings().
334
+ *
335
+ * @param string[optional] $chars
336
+ * @param string[optional] $placeholderPrefix
337
+ */
338
+ protected function extractStrings($chars = '\'"', $placeholderPrefix = '')
339
+ {
340
+ // PHP only supports $this inside anonymous functions since 5.4
341
+ $minifier = $this;
342
+ $callback = function ($match) use ($minifier, $placeholderPrefix) {
343
+ // check the second index here, because the first always contains a quote
344
+ if ($match[2] === '') {
345
+ /*
346
+ * Empty strings need no placeholder; they can't be confused for
347
+ * anything else anyway.
348
+ * But we still needed to match them, for the extraction routine
349
+ * to skip over this particular string.
350
+ */
351
+ return $match[0];
352
+ }
353
+
354
+ $count = count($minifier->extracted);
355
+ $placeholder = $match[1].$placeholderPrefix.$count.$match[1];
356
+ $minifier->extracted[$placeholder] = $match[1].$match[2].$match[1];
357
+
358
+ return $placeholder;
359
+ };
360
+
361
+ /*
362
+ * The \\ messiness explained:
363
+ * * Don't count ' or " as end-of-string if it's escaped (has backslash
364
+ * in front of it)
365
+ * * Unless... that backslash itself is escaped (another leading slash),
366
+ * in which case it's no longer escaping the ' or "
367
+ * * So there can be either no backslash, or an even number
368
+ * * multiply all of that times 4, to account for the escaping that has
369
+ * to be done to pass the backslash into the PHP string without it being
370
+ * considered as escape-char (times 2) and to get it in the regex,
371
+ * escaped (times 2)
372
+ */
373
+ $this->registerPattern('/(['.$chars.'])(.*?(?<!\\\\)(\\\\\\\\)*+)\\1/s', $callback);
374
+ }
375
+
376
+ /**
377
+ * This method will restore all extracted data (strings, regexes) that were
378
+ * replaced with placeholder text in extract*(). The original content was
379
+ * saved in $this->extracted.
380
+ *
381
+ * @param string $content
382
+ *
383
+ * @return string
384
+ */
385
+ protected function restoreExtractedData($content)
386
+ {
387
+ if (!$this->extracted) {
388
+ // nothing was extracted, nothing to restore
389
+ return $content;
390
+ }
391
+
392
+ $content = strtr($content, $this->extracted);
393
+
394
+ $this->extracted = array();
395
+
396
+ return $content;
397
+ }
398
+
399
+ /**
400
+ * Check if the path is a regular file and can be read.
401
+ *
402
+ * @param string $path
403
+ *
404
+ * @return bool
405
+ */
406
+ protected function canImportFile($path)
407
+ {
408
+ return strlen($path) < PHP_MAXPATHLEN && @is_file($path) && is_readable($path);
409
+ }
410
+
411
+ /**
412
+ * Attempts to open file specified by $path for writing.
413
+ *
414
+ * @param string $path The path to the file
415
+ *
416
+ * @return resource Specifier for the target file
417
+ *
418
+ * @throws IOException
419
+ */
420
+ protected function openFileForWriting($path)
421
+ {
422
+ if (($handler = @fopen($path, 'w')) === false) {
423
+ throw new IOException('The file "'.$path.'" could not be opened for writing. Check if PHP has enough permissions.');
424
+ }
425
+
426
+ return $handler;
427
+ }
428
+
429
+ /**
430
+ * Attempts to write $content to the file specified by $handler. $path is used for printing exceptions.
431
+ *
432
+ * @param resource $handler The resource to write to
433
+ * @param string $content The content to write
434
+ * @param string $path The path to the file (for exception printing only)
435
+ *
436
+ * @throws IOException
437
+ */
438
+ protected function writeToFile($handler, $content, $path = '')
439
+ {
440
+ if (($result = @fwrite($handler, $content)) === false || ($result < strlen($content))) {
441
+ throw new IOException('The file "'.$path.'" could not be written to. Check your disk space and file permissions.');
442
+ }
443
+ }
444
+ }
vendor/minifier/path-converter/src/Converter.php ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace MatthiasMullie\PathConverter;
4
+
5
+ /**
6
+ * Convert paths relative from 1 file to another.
7
+ *
8
+ * E.g.
9
+ * ../../images/icon.jpg relative to /css/imports/icons.css
10
+ * becomes
11
+ * ../images/icon.jpg relative to /css/minified.css
12
+ *
13
+ * Please report bugs on https://github.com/matthiasmullie/path-converter/issues
14
+ *
15
+ * @author Matthias Mullie <pathconverter@mullie.eu>
16
+ * @copyright Copyright (c) 2015, Matthias Mullie. All rights reserved
17
+ * @license MIT License
18
+ */
19
+ class Converter implements ConverterInterface
20
+ {
21
+ /**
22
+ * @var string
23
+ */
24
+ protected $from;
25
+
26
+ /**
27
+ * @var string
28
+ */
29
+ protected $to;
30
+
31
+ /**
32
+ * @param string $from The original base path (directory, not file!)
33
+ * @param string $to The new base path (directory, not file!)
34
+ */
35
+ public function __construct($from, $to)
36
+ {
37
+ $shared = $this->shared($from, $to);
38
+ if ($shared === '') {
39
+ // when both paths have nothing in common, one of them is probably
40
+ // absolute while the other is relative
41
+ $cwd = getcwd();
42
+ $from = strpos($from, $cwd) === 0 ? $from : $cwd.'/'.$from;
43
+ $to = strpos($to, $cwd) === 0 ? $to : $cwd.'/'.$to;
44
+
45
+ // or traveling the tree via `..`
46
+ // attempt to resolve path, or assume it's fine if it doesn't exist
47
+ $from = realpath($from) ?: $from;
48
+ $to = realpath($to) ?: $to;
49
+ }
50
+
51
+ $from = $this->dirname($from);
52
+ $to = $this->dirname($to);
53
+
54
+ $from = $this->normalize($from);
55
+ $to = $this->normalize($to);
56
+
57
+ $this->from = $from;
58
+ $this->to = $to;
59
+ }
60
+
61
+ /**
62
+ * Normalize path.
63
+ *
64
+ * @param string $path
65
+ *
66
+ * @return string
67
+ */
68
+ protected function normalize($path)
69
+ {
70
+ // deal with different operating systems' directory structure
71
+ $path = rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $path), '/');
72
+
73
+ /*
74
+ * Example:
75
+ * /home/forkcms/frontend/cache/compiled_templates/../../core/layout/css/../images/img.gif
76
+ * to
77
+ * /home/forkcms/frontend/core/layout/images/img.gif
78
+ */
79
+ do {
80
+ $path = preg_replace('/[^\/]+(?<!\.\.)\/\.\.\//', '', $path, -1, $count);
81
+ } while ($count);
82
+
83
+ return $path;
84
+ }
85
+
86
+ /**
87
+ * Figure out the shared path of 2 locations.
88
+ *
89
+ * Example:
90
+ * /home/forkcms/frontend/core/layout/images/img.gif
91
+ * and
92
+ * /home/forkcms/frontend/cache/minified_css
93
+ * share
94
+ * /home/forkcms/frontend
95
+ *
96
+ * @param string $path1
97
+ * @param string $path2
98
+ *
99
+ * @return string
100
+ */
101
+ protected function shared($path1, $path2)
102
+ {
103
+ // $path could theoretically be empty (e.g. no path is given), in which
104
+ // case it shouldn't expand to array(''), which would compare to one's
105
+ // root /
106
+ $path1 = $path1 ? explode('/', $path1) : array();
107
+ $path2 = $path2 ? explode('/', $path2) : array();
108
+
109
+ $shared = array();
110
+
111
+ // compare paths & strip identical ancestors
112
+ foreach ($path1 as $i => $chunk) {
113
+ if (isset($path2[$i]) && $path1[$i] == $path2[$i]) {
114
+ $shared[] = $chunk;
115
+ } else {
116
+ break;
117
+ }
118
+ }
119
+
120
+ return implode('/', $shared);
121
+ }
122
+
123
+ /**
124
+ * Convert paths relative from 1 file to another.
125
+ *
126
+ * E.g.
127
+ * ../images/img.gif relative to /home/forkcms/frontend/core/layout/css
128
+ * should become:
129
+ * ../../core/layout/images/img.gif relative to
130
+ * /home/forkcms/frontend/cache/minified_css
131
+ *
132
+ * @param string $path The relative path that needs to be converted
133
+ *
134
+ * @return string The new relative path
135
+ */
136
+ public function convert($path)
137
+ {
138
+ // quit early if conversion makes no sense
139
+ if ($this->from === $this->to) {
140
+ return $path;
141
+ }
142
+
143
+ $path = $this->normalize($path);
144
+ // if we're not dealing with a relative path, just return absolute
145
+ if (strpos($path, '/') === 0) {
146
+ return $path;
147
+ }
148
+
149
+ // normalize paths
150
+ $path = $this->normalize($this->from.'/'.$path);
151
+
152
+ // strip shared ancestor paths
153
+ $shared = $this->shared($path, $this->to);
154
+ $path = mb_substr($path, mb_strlen($shared));
155
+ $to = mb_substr($this->to, mb_strlen($shared));
156
+
157
+ // add .. for every directory that needs to be traversed to new path
158
+ $to = str_repeat('../', mb_substr_count($to, '/'));
159
+
160
+ return $to.ltrim($path, '/');
161
+ }
162
+
163
+ /**
164
+ * Attempt to get the directory name from a path.
165
+ *
166
+ * @param string $path
167
+ *
168
+ * @return string
169
+ */
170
+ protected function dirname($path)
171
+ {
172
+ if (is_file($path)) {
173
+ return dirname($path);
174
+ }
175
+
176
+ if (is_dir($path)) {
177
+ return rtrim($path, '/');
178
+ }
179
+
180
+ // no known file/dir, start making assumptions
181
+
182
+ // ends in / = dir
183
+ if (mb_substr($path, -1) === '/') {
184
+ return rtrim($path, '/');
185
+ }
186
+
187
+ // has a dot in the name, likely a file
188
+ if (preg_match('/.*\..*$/', basename($path)) !== 0) {
189
+ return dirname($path);
190
+ }
191
+
192
+ // you're on your own here!
193
+ return $path;
194
+ }
195
+ }
vendor/minifier/path-converter/src/ConverterInterface.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace MatthiasMullie\PathConverter;
4
+
5
+ /**
6
+ * Convert file paths.
7
+ *
8
+ * Please report bugs on https://github.com/matthiasmullie/path-converter/issues
9
+ *
10
+ * @author Matthias Mullie <pathconverter@mullie.eu>
11
+ * @copyright Copyright (c) 2015, Matthias Mullie. All rights reserved
12
+ * @license MIT License
13
+ */
14
+ interface ConverterInterface
15
+ {
16
+ /**
17
+ * Convert file paths.
18
+ *
19
+ * @param string $path The path to be converted
20
+ *
21
+ * @return string The new path
22
+ */
23
+ public function convert($path);
24
+ }
vendor/minifier/path-converter/src/NoConverter.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace MatthiasMullie\PathConverter;
4
+
5
+ /**
6
+ * Don't convert paths.
7
+ *
8
+ * Please report bugs on https://github.com/matthiasmullie/path-converter/issues
9
+ *
10
+ * @author Matthias Mullie <pathconverter@mullie.eu>
11
+ * @copyright Copyright (c) 2015, Matthias Mullie. All rights reserved
12
+ * @license MIT License
13
+ */
14
+ class NoConverter implements ConverterInterface
15
+ {
16
+ /**
17
+ * {@inheritdoc}
18
+ */
19
+ public function convert($path)
20
+ {
21
+ return $path;
22
+ }
23
+ }
wordpress_file_upload.php CHANGED
@@ -4,7 +4,7 @@ if( !session_id() ) { session_start(); }
4
  /*
5
  Plugin URI: http://www.iptanus.com/support/wordpress-file-upload
6
  Description: Simple interface to upload files from a page.
7
- Version: 4.1.0
8
  Author: Nickolas Bossinas
9
  Author URI: http://www.iptanus.com
10
  */
@@ -107,12 +107,12 @@ function wfu_enqueue_frontpage_scripts() {
107
  if ( isset($ret_data['return_value']) ) return $ret_data['return_value'];
108
 
109
  if ( $relaxcss ) {
110
- wp_enqueue_style('wordpress-file-upload-style', WPFILEUPLOAD_DIR.'css/wordpress_file_upload_style_relaxed.css',false,'1.0','all');
111
- wp_enqueue_style('wordpress-file-upload-style-safe', WPFILEUPLOAD_DIR.'css/wordpress_file_upload_style_safe_relaxed.css',false,'1.0','all');
112
  }
113
  else {
114
- wp_enqueue_style('wordpress-file-upload-style', WPFILEUPLOAD_DIR.'css/wordpress_file_upload_style.css',false,'1.0','all');
115
- wp_enqueue_style('wordpress-file-upload-style-safe', WPFILEUPLOAD_DIR.'css/wordpress_file_upload_style_safe.css',false,'1.0','all');
116
  }
117
  //do not load JQuery UI css if $ret_data denotes incompatibility issues
118
  if ( ( !isset($ret_data["correct_NextGenGallery_incompatibility"]) || $ret_data["correct_NextGenGallery_incompatibility"] != "true" ) &&
@@ -121,9 +121,8 @@ function wfu_enqueue_frontpage_scripts() {
121
  wp_enqueue_style('jquery-ui-timepicker-addon-css', '//cdnjs.cloudflare.com/ajax/libs/jquery-ui-timepicker-addon/1.6.3/jquery-ui-timepicker-addon.min.css');
122
  wp_enqueue_script('json2');
123
  wp_enqueue_script('wordpress_file_upload_script', WPFILEUPLOAD_DIR.'js/wordpress_file_upload_functions.js');
124
- wp_enqueue_script('jquery-ui-slider', false, array('jquery'), false, true);
125
- wp_enqueue_script('jquery-ui-datepicker', false, array('jquery'), false, true);
126
- wp_enqueue_script('jquery-ui-timepicker-addon-js', '//cdnjs.cloudflare.com/ajax/libs/jquery-ui-timepicker-addon/1.6.3/jquery-ui-timepicker-addon.min.js', array(), false, true);
127
  }
128
 
129
  function wfu_include_lib() {
@@ -306,11 +305,12 @@ function wordpress_file_upload_function($incomingfromhandler) {
306
  $uploadertemplate = wfu_get_uploader_template($params["uploadertemplate"]);
307
  /* Compose the html code for the plugin */
308
  $wordpress_file_upload_output = "";
 
309
  $plugin_style = "";
310
  if ( $widths["plugin"] != "" ) $plugin_style .= 'width: '.$widths["plugin"].'; ';
311
  if ( $heights["plugin"] != "" ) $plugin_style .= 'height: '.$heights["plugin"].'; ';
312
  if ( $plugin_style != "" ) $plugin_style = ' style="'.$plugin_style.'"';
313
- $wordpress_file_upload_output .= '<div id="'.$init_params["container_id"].'" class="file_div_clean'.( $params["fitmode"] == "responsive" ? '_responsive_container' : '' ).' wfu_container"'.$plugin_style.'>';
314
  $wordpress_file_upload_output .= "\n".'<!-- Using template '.call_user_func(array($uploadertemplate, 'get_name')).' -->';
315
  //read indexed component definitions
316
  $component_output = "";
@@ -376,8 +376,12 @@ function wordpress_file_upload_function($incomingfromhandler) {
376
  //output javascript code
377
  if ( $js != "" ) {
378
  //add initialization of the object of the upload form
379
- $js = 'GlobalData.WFU['.$sid.'] = '.wfu_PHP_array_to_JS_object($init_params).'; GlobalData.WFU.n.push('.$sid.');'."\n".$js;
380
- $wordpress_file_upload_output .= wfu_js_to_HTML($js);
 
 
 
 
381
  }
382
  //add visual editor overlay if the current user is administrator
383
  if ( current_user_can( 'manage_options' ) ) {
@@ -389,7 +393,9 @@ function wordpress_file_upload_function($incomingfromhandler) {
389
  /* Pass constants to javascript and run plugin post-load actions */
390
  $consts = wfu_set_javascript_constants();
391
  $handler = 'function() { wfu_Initialize_Consts("'.$consts.'"); wfu_Load_Code_Connectors('.$sid.'); wfu_plugin_load_action('.$sid.'); }';
392
- $wordpress_file_upload_output .= "\n\t".'<script type="text/javascript">if(window.addEventListener) { window.addEventListener("load", '.$handler.', false); } else if(window.attachEvent) { window.attachEvent("onload", '.$handler.'); } else { window["onload"] = '.$handler.'; }</script>';
 
 
393
  $wordpress_file_upload_output .= '</div>';
394
  // $wordpress_file_upload_output .= '<div>';
395
  // $wordpress_file_upload_output .= wfu_test_admin();
@@ -468,7 +474,8 @@ function wordpress_file_upload_function($incomingfromhandler) {
468
  }
469
 
470
  $ProcessUploadComplete_functiondef = 'function(){wfu_ProcessUploadComplete('.$sid.', 1, "'.$wfu_process_file_array_str.'", "no-ajax", "'.$safe_output.'", [false, null, false], "fileupload", "'.$js_script_enc.'");}';
471
- $wordpress_file_upload_output .= '<script type="text/javascript">window.onload='.$ProcessUploadComplete_functiondef.'</script>';
 
472
  }
473
 
474
  $wordpress_file_upload_output .= wfu_post_plugin_actions($params);
4
  /*
5
  Plugin URI: http://www.iptanus.com/support/wordpress-file-upload
6
  Description: Simple interface to upload files from a page.
7
+ Version: 4.2.0
8
  Author: Nickolas Bossinas
9
  Author URI: http://www.iptanus.com
10
  */
107
  if ( isset($ret_data['return_value']) ) return $ret_data['return_value'];
108
 
109
  if ( $relaxcss ) {
110
+ wp_enqueue_style('wordpress-file-upload-style', WPFILEUPLOAD_DIR.'css/wordpress_file_upload_style_relaxed.css');
111
+ wp_enqueue_style('wordpress-file-upload-style-safe', WPFILEUPLOAD_DIR.'css/wordpress_file_upload_style_safe_relaxed.css');
112
  }
113
  else {
114
+ wp_enqueue_style('wordpress-file-upload-style', WPFILEUPLOAD_DIR.'css/wordpress_file_upload_style.css');
115
+ wp_enqueue_style('wordpress-file-upload-style-safe', WPFILEUPLOAD_DIR.'css/wordpress_file_upload_style_safe.css');
116
  }
117
  //do not load JQuery UI css if $ret_data denotes incompatibility issues
118
  if ( ( !isset($ret_data["correct_NextGenGallery_incompatibility"]) || $ret_data["correct_NextGenGallery_incompatibility"] != "true" ) &&
121
  wp_enqueue_style('jquery-ui-timepicker-addon-css', '//cdnjs.cloudflare.com/ajax/libs/jquery-ui-timepicker-addon/1.6.3/jquery-ui-timepicker-addon.min.css');
122
  wp_enqueue_script('json2');
123
  wp_enqueue_script('wordpress_file_upload_script', WPFILEUPLOAD_DIR.'js/wordpress_file_upload_functions.js');
124
+ wp_enqueue_script('jquery-ui-slider');
125
+ wp_enqueue_script('jquery-ui-timepicker-addon-jss', '//cdnjs.cloudflare.com/ajax/libs/jquery-ui-timepicker-addon/1.6.3/jquery-ui-timepicker-addon.min.js', array("jquery-ui-datepicker"));
 
126
  }
127
 
128
  function wfu_include_lib() {
305
  $uploadertemplate = wfu_get_uploader_template($params["uploadertemplate"]);
306
  /* Compose the html code for the plugin */
307
  $wordpress_file_upload_output = "";
308
+ $wordpress_file_upload_output .= wfu_init_run_js_script();
309
  $plugin_style = "";
310
  if ( $widths["plugin"] != "" ) $plugin_style .= 'width: '.$widths["plugin"].'; ';
311
  if ( $heights["plugin"] != "" ) $plugin_style .= 'height: '.$heights["plugin"].'; ';
312
  if ( $plugin_style != "" ) $plugin_style = ' style="'.$plugin_style.'"';
313
+ $wordpress_file_upload_output .= "\n".'<div id="'.$init_params["container_id"].'" class="file_div_clean'.( $params["fitmode"] == "responsive" ? '_responsive_container' : '' ).' wfu_container"'.$plugin_style.'>';
314
  $wordpress_file_upload_output .= "\n".'<!-- Using template '.call_user_func(array($uploadertemplate, 'get_name')).' -->';
315
  //read indexed component definitions
316
  $component_output = "";
376
  //output javascript code
377
  if ( $js != "" ) {
378
  //add initialization of the object of the upload form
379
+ $wfu_js = 'var WFU_JS_'.$sid.' = function() {';
380
+ $wfu_js .= "\n".'GlobalData.WFU['.$sid.'] = '.wfu_PHP_array_to_JS_object($init_params).'; GlobalData.WFU.n.push('.$sid.');';
381
+ $wfu_js .= "\n".$js;
382
+ $wfu_js .= "\n".'}';
383
+ $wfu_js .= "\n".'wfu_run_js("window", "WFU_JS_'.$sid.'");';
384
+ $wordpress_file_upload_output .= "\n".wfu_js_to_HTML($wfu_js);
385
  }
386
  //add visual editor overlay if the current user is administrator
387
  if ( current_user_can( 'manage_options' ) ) {
393
  /* Pass constants to javascript and run plugin post-load actions */
394
  $consts = wfu_set_javascript_constants();
395
  $handler = 'function() { wfu_Initialize_Consts("'.$consts.'"); wfu_Load_Code_Connectors('.$sid.'); wfu_plugin_load_action('.$sid.'); }';
396
+ $wfu_js = 'if (typeof wfu_addLoadHandler == "undefined") function wfu_addLoadHandler(handler) { if(window.addEventListener) { window.addEventListener("load", handler, false); } else if(window.attachEvent) { window.attachEvent("onload", handler); } else { window["onload"] = handler; } }';
397
+ $wfu_js .= "\n".'wfu_addLoadHandler('.$handler.');';
398
+ $wordpress_file_upload_output .= "\n".wfu_js_to_HTML($wfu_js);
399
  $wordpress_file_upload_output .= '</div>';
400
  // $wordpress_file_upload_output .= '<div>';
401
  // $wordpress_file_upload_output .= wfu_test_admin();
474
  }
475
 
476
  $ProcessUploadComplete_functiondef = 'function(){wfu_ProcessUploadComplete('.$sid.', 1, "'.$wfu_process_file_array_str.'", "no-ajax", "'.$safe_output.'", [false, null, false], "fileupload", "'.$js_script_enc.'");}';
477
+ $wfu_js = 'wfu_addLoadHandler('.$ProcessUploadComplete_functiondef.');';
478
+ $wordpress_file_upload_output .= "\n".wfu_js_to_HTML($wfu_js);
479
  }
480
 
481
  $wordpress_file_upload_output .= wfu_post_plugin_actions($params);