Version Description
Download this release
Release Info
Developer | cory@lamle.org |
Plugin | Duplicator – WordPress Migration Plugin |
Version | 1.3.0 |
Comparing to | |
See all releases |
Code changes from version 1.2.52 to 1.3.0
- assets/css/global_admin_style.css +34 -0
- assets/css/style.css +3 -5
- assets/img/hdivider.png +0 -0
- assets/img/logo-dpro-300x50-nosnap.png +0 -0
- assets/js/javascript.php +59 -3
- assets/js/jquery.qtip/jquery.qtip.min.js.map +1 -0
- assets/js/parsley.min.js.map +1 -0
- classes/class.archive.config.php +42 -0
- classes/class.db.php +30 -35
- classes/class.io.php +93 -0
- classes/class.logging.php +255 -48
- classes/class.password.php +4 -0
- classes/class.server.php +117 -81
- classes/class.settings.php +28 -31
- classes/package/class.pack.archive.filters.php +86 -84
- classes/package/class.pack.archive.php +661 -605
- classes/package/class.pack.archive.zip.php +56 -15
- classes/package/class.pack.database.php +226 -57
- classes/package/class.pack.installer.php +418 -167
- classes/package/class.pack.php +885 -115
- classes/package/duparchive/class.pack.archive.duparchive.php +368 -0
- classes/package/duparchive/class.pack.archive.duparchive.state.create.php +82 -0
- classes/package/duparchive/class.pack.archive.duparchive.state.expand.php +135 -0
- classes/package/duparchive/index.php +2 -0
- classes/ui/class.ui.dialog.php +197 -201
- classes/ui/class.ui.notice.php +10 -14
- classes/ui/class.ui.screen.base.php +77 -76
- classes/ui/class.ui.viewstate.php +70 -73
- classes/utilities/class.u.json.php +192 -152
- classes/utilities/class.u.multisite.php +53 -0
- classes/utilities/class.u.php +87 -74
- classes/utilities/class.u.scancheck.php +5 -8
- classes/utilities/class.u.shell.php +39 -0
- classes/utilities/class.u.string.php +98 -0
- classes/utilities/class.u.validator.php +228 -0
- classes/utilities/class.u.zip.php +155 -0
- ctrls/ctrl.base.php +10 -0
- ctrls/ctrl.package.php +423 -155
- ctrls/ctrl.tools.php +77 -6
- ctrls/ctrl.ui.php +4 -9
- debug/main.php +0 -191
- debug/tst.packages.php +0 -31
- debug/tst.tools.php +0 -38
- debug/tst.ui.php +0 -45
- define.php +33 -10
- duplicator.php +37 -25
- installer/build/assets/inc.css.php +0 -246
- installer/build/assets/inc.js.php +0 -78
- installer/build/assets/inc.libs.css.php +0 -48
- installer/build/assets/inc.libs.js.php +0 -191
- installer/build/classes/class.csrf.php +0 -75
- installer/build/classes/class.db.php +0 -215
- installer/build/classes/class.engine.php +0 -450
- installer/build/classes/class.logging.php +0 -67
- installer/build/classes/class.server.php +0 -183
- installer/build/classes/config/class.conf.srv.php +0 -113
- installer/build/classes/config/class.conf.wp.php +0 -246
- installer/build/ctrls/ctrl.step1.php +0 -148
- installer/build/ctrls/ctrl.step2.php +0 -499
- installer/build/ctrls/ctrl.step3.php +0 -390
- installer/build/main.installer.php +0 -418
- installer/build/view.step1.php +0 -798
- installer/build/view.step2.php +0 -441
- installer/build/view.step3.php +0 -340
- installer/dup-installer/assets/font-awesome/css/font-awesome.min.css +4 -0
assets/css/global_admin_style.css
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* ================================================
|
2 |
+
* DUPLICATOR STYLE
|
3 |
+
* Included in all admin pages
|
4 |
+
* ================================================ */
|
5 |
+
|
6 |
+
.dup-updated {
|
7 |
+
margin-left: 0;
|
8 |
+
background: #fff;
|
9 |
+
border-left: 4px solid #fff;
|
10 |
+
box-shadow: 0 1px 1px 0 rgba( 0, 0, 0, 0.1 );
|
11 |
+
margin: 5px 15px 2px;
|
12 |
+
padding: 1px 12px;
|
13 |
+
}
|
14 |
+
|
15 |
+
.dup-updated p {
|
16 |
+
margin: 0.5em 0;
|
17 |
+
padding: 2px;
|
18 |
+
}
|
19 |
+
|
20 |
+
.dup-updated a {
|
21 |
+
padding-bottom: 2px;
|
22 |
+
}
|
23 |
+
|
24 |
+
.dup-updated {
|
25 |
+
border-left-color: #46b450;
|
26 |
+
}
|
27 |
+
|
28 |
+
.wrap .dup-updated {
|
29 |
+
margin: 5px 0 15px;
|
30 |
+
margin: 20px 0 10px 0;
|
31 |
+
padding: 5px 10px;
|
32 |
+
font-size: 14px;
|
33 |
+
line-height: 175%;
|
34 |
+
}
|
assets/css/style.css
CHANGED
@@ -42,12 +42,12 @@ div#dup-progress-bar-area {width:500px; margin:40px auto 0px auto; padding:25px
|
|
42 |
div#dup-progress-bar-area h2 {margin-bottom:15px}
|
43 |
|
44 |
/*HEADER MESSAGES*/
|
45 |
-
div.dup-hdr-success {color
|
46 |
div.dup-hdr-error {color:#A62426; font-size:22px; font-weight:bold}
|
47 |
|
48 |
/*DIALOGS: THICKBOX */
|
49 |
#TB_title { padding-bottom: 3px!important; margin-bottom:5px!important; font-size:16px!important;}
|
50 |
-
div.dup-dlg-alert-txt {padding:10px 0; font-size:16px}
|
51 |
div.dup-dlg-alert-btns {position:absolute; bottom:20px; right:20px;}
|
52 |
div.dup-dlg-confirm-txt {padding:10px 0; font-size:16px}
|
53 |
div.dup-dlg-confirm-btns {position:absolute; bottom:20px; right:20px;}
|
@@ -68,12 +68,10 @@ input.parsley-error, textarea.parsley-error {
|
|
68 |
border:1px solid #EED3D7 !important;
|
69 |
}
|
70 |
div.qtip-content {line-height:16px}
|
71 |
-
ul.parsley-
|
72 |
-
|
73 |
div.notice-safemode {color: maroon;}
|
74 |
div.cleanup-notice b.title {color: green;font-size: 20px;}
|
75 |
|
76 |
/*SCREEN TABS*/
|
77 |
div.dup-screen-hlp-info {line-height:26px; padding:10px 0 10px 0}
|
78 |
#screen-meta-links .button { font-size:13px !important; height:auto !important;font-weight: normal; padding: 3px 6px 3px 16px !important;min-width:72px !important}
|
79 |
-
|
42 |
div#dup-progress-bar-area h2 {margin-bottom:15px}
|
43 |
|
44 |
/*HEADER MESSAGES*/
|
45 |
+
div.dup-hdr-success {color:#23282d; font-size:22px; font-weight:bold}
|
46 |
div.dup-hdr-error {color:#A62426; font-size:22px; font-weight:bold}
|
47 |
|
48 |
/*DIALOGS: THICKBOX */
|
49 |
#TB_title { padding-bottom: 3px!important; margin-bottom:5px!important; font-size:16px!important;}
|
50 |
+
div.dup-dlg-alert-txt {padding:10px 0; font-size:16px; line-height:22px}
|
51 |
div.dup-dlg-alert-btns {position:absolute; bottom:20px; right:20px;}
|
52 |
div.dup-dlg-confirm-txt {padding:10px 0; font-size:16px}
|
53 |
div.dup-dlg-confirm-btns {position:absolute; bottom:20px; right:20px;}
|
68 |
border:1px solid #EED3D7 !important;
|
69 |
}
|
70 |
div.qtip-content {line-height:16px}
|
71 |
+
ul.parsley-error-list {margin:1px 0px -7px 0px}
|
|
|
72 |
div.notice-safemode {color: maroon;}
|
73 |
div.cleanup-notice b.title {color: green;font-size: 20px;}
|
74 |
|
75 |
/*SCREEN TABS*/
|
76 |
div.dup-screen-hlp-info {line-height:26px; padding:10px 0 10px 0}
|
77 |
#screen-meta-links .button { font-size:13px !important; height:auto !important;font-weight: normal; padding: 3px 6px 3px 16px !important;min-width:72px !important}
|
|
assets/img/hdivider.png
DELETED
Binary file
|
assets/img/logo-dpro-300x50-nosnap.png
DELETED
Binary file
|
assets/js/javascript.php
CHANGED
@@ -14,6 +14,49 @@ Duplicator.Debug = new Object();
|
|
14 |
Duplicator.DEBUG_AJAX_RESPONSE = false;
|
15 |
Duplicator.AJAX_TIMER = null;
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
|
18 |
/* ============================================================================
|
19 |
* BASE NAMESPACE: All methods at the top of the Duplicator Namespace
|
@@ -66,9 +109,22 @@ Duplicator.UI.SaveViewState = function (key, value)
|
|
66 |
jQuery.ajax({
|
67 |
type: "POST",
|
68 |
url: ajaxurl,
|
69 |
-
dataType: "
|
70 |
-
data: {
|
71 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
error: function(data) {}
|
73 |
});
|
74 |
}
|
14 |
Duplicator.DEBUG_AJAX_RESPONSE = false;
|
15 |
Duplicator.AJAX_TIMER = null;
|
16 |
|
17 |
+
Duplicator.parseJSON = function(mixData) {
|
18 |
+
try {
|
19 |
+
var parsed = JSON.parse(mixData);
|
20 |
+
return parsed;
|
21 |
+
} catch (e) {
|
22 |
+
console.log("JSON parse failed - 1");
|
23 |
+
console.log(mixData);
|
24 |
+
}
|
25 |
+
|
26 |
+
if (mixData.indexOf('[') > -1 && mixData.indexOf('{') > -1) {
|
27 |
+
if (mixData.indexOf('{') < mixData.indexOf('[')) {
|
28 |
+
var startBracket = '{';
|
29 |
+
var endBracket = '}';
|
30 |
+
} else {
|
31 |
+
var startBracket = '[';
|
32 |
+
var endBracket = ']';
|
33 |
+
}
|
34 |
+
} else if (mixData.indexOf('[') > -1 && mixData.indexOf('{') === -1) {
|
35 |
+
var startBracket = '[';
|
36 |
+
var endBracket = ']';
|
37 |
+
} else {
|
38 |
+
var startBracket = '{';
|
39 |
+
var endBracket = '}';
|
40 |
+
}
|
41 |
+
|
42 |
+
var jsonStartPos = mixData.indexOf(startBracket);
|
43 |
+
var jsonLastPos = mixData.lastIndexOf(endBracket);
|
44 |
+
if (jsonStartPos > -1 && jsonLastPos > -1) {
|
45 |
+
var expectedJsonStr = mixData.slice(jsonStartPos, jsonLastPos + 1);
|
46 |
+
try {
|
47 |
+
var parsed = JSON.parse(expectedJsonStr);
|
48 |
+
return parsed;
|
49 |
+
} catch (e) {
|
50 |
+
console.log("JSON parse failed - 2");
|
51 |
+
console.log(mixData);
|
52 |
+
throw e;
|
53 |
+
return false;
|
54 |
+
}
|
55 |
+
}
|
56 |
+
throw "could not parse the JSON";
|
57 |
+
return false;
|
58 |
+
}
|
59 |
+
|
60 |
|
61 |
/* ============================================================================
|
62 |
* BASE NAMESPACE: All methods at the top of the Duplicator Namespace
|
109 |
jQuery.ajax({
|
110 |
type: "POST",
|
111 |
url: ajaxurl,
|
112 |
+
dataType: "text",
|
113 |
+
data: {
|
114 |
+
action : 'DUP_CTRL_UI_SaveViewState',
|
115 |
+
key: key,
|
116 |
+
value: value,
|
117 |
+
nonce: '<?php echo wp_create_nonce('DUP_CTRL_UI_SaveViewState'); ?>'
|
118 |
+
},
|
119 |
+
success: function(respData) {
|
120 |
+
try {
|
121 |
+
var data = Duplicator.parseJSON(respData);
|
122 |
+
} catch(err) {
|
123 |
+
console.error(err);
|
124 |
+
console.error('JSON parse failed for response data: ' + respData);
|
125 |
+
return false;
|
126 |
+
}
|
127 |
+
},
|
128 |
error: function(data) {}
|
129 |
});
|
130 |
}
|
assets/js/jquery.qtip/jquery.qtip.min.js.map
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
{"version":3,"file":"jquery.qtip.min.js","sources":["jquery.qtip.js"],"names":["window","document","undefined","factory","define","amd","jQuery","fn","qtip","$","QTip","target","options","id","attr","this","tooltip","NULL","elements","_id","NAMESPACE","timers","img","plugins","cache","event","disabled","FALSE","onTooltip","lastClass","rendered","destroyed","waiting","hiddenDuringWait","positioning","triggering","invalidOpt","a","type","invalidContent","c","isFunction","length","jquery","then","sanitizeOptions","opts","content","text","ajax","once","metadata","done","api","loading","deferred","extend","context","success","error","set","xhr","status","isPlainObject","title","button","position","my","at","show","TRUE","ready","hide","style","classes","each","PLUGINS","sanitize","convertNotation","notation","obj","i","option","levels","split","pop","setCallback","args","category","rule","match","checks","RegExp","exec","push","apply","createWidgetClass","cls","WIDGET","concat","join","delay","callback","duration","setTimeout","proxy","call","showMethod","hasClass","CLASS_DISABLED","clearTimeout","toggle","hideMethod","relatedTarget","ontoTooltip","closest","SELECTOR","ontoTarget","fixed","test","preventDefault","stopImmediatePropagation","e","inactiveMethod","inactive","repositionMethod","offsetWidth","reposition","delegate","selector","events","method","body","QTIP","ATTR_ID","arguments","init","elem","posOptions","config","docBody","newTarget","metadata5","name","html5","data","parseJSON","defaults","container","solo","viewport","eq","CORNER","overwrite","ATTR_HAS","suppress","removeAttr","oldtitle","camel","s","charAt","toUpperCase","slice","vendorCss","prop","cur","val","ucProp","props","cssPrefixes","cssProps","css","intCss","Math","ceil","parseFloat","Tip","_ns","offset","size","width","height","Modal","Ie6","PROTOTYPE","CHECKS","trackingBound","X","Y","WIDTH","HEIGHT","TOP","LEFT","BOTTOM","RIGHT","CENTER","FLIPINVERT","SHIFT","INACTIVE_EVENTS","CLASS_FIXED","CLASS_DEFAULT","CLASS_FOCUS","CLASS_HOVER","replaceSuffix","BROWSER","ie","v","createElement","innerHTML","getElementsByTagName","NaN","iOS","navigator","userAgent","replace","prototype","_when","deferreds","when","render","self","posClass","_createPosClass","class","tracking","adjust","mouse","role","aria-live","aria-atomic","aria-describedby","aria-hidden","toggleClass","appendTo","append","_createTitle","_updateTitle","_createButton","_updateContent","_setWidget","instance","initialize","_unassignEvents","_assignEvents","_trigger","destroy","immediate","process","timer","stop","find","remove","end","removeData","one","builtin","^id$","o","prev","nextid","new_id","^prerender","^content.text$","^content.attr$","^content.title$","_removeTitle","^content.button$","_updateButton","^content.title.(text|button)$","^position.(my|at)$","^position.container$","^show.ready$","^style.classes$","p","removeClass","addClass","^style.(width|height)","^style.widget|content.title","^style.def","^events.(render|show|move|hide|focus|blur)$","^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)","get","toLowerCase","result","precedance","string","rmove","rrender","value","previous","nodeType","_update","element","empty","display","visibility","html","_waitForContent","images","imagesLoaded","Deferred","resolve","promise","titlebar","widget","insertBefore","substr","abbrev","effect","pluginCalculations","adjusted","newClass","tooltipWidth","outerWidth","tooltipHeight","outerHeight","targetWidth","targetHeight","left","top","visible","isScroll","win","doc","ownerDocument","isArray","x","y","distance","origin","pageX","innerWidth","documentElement","clientWidth","pageY","scrollX","scrollLeft","scrollY","scrollTop","innerHeight","imagemap","is","svg","ownerSVGElement","adjustable","isNaN","queue","next","opacity","removeAttribute","pos","scroll","scrolled","parentOffset","overflow","quirks","compatMode","parent","getBoundingClientRect","offsetParent","C","Corner","corner","forceY","f","invert","z","center","clone","state","add","has","fix","identicalState","allow","after","contentOptions","animate","sameTarget","search","focus","bind","_storeMouse","not","Event","unbind","blur","autofocus","trigger","n","fadeTo","qtips","curIndex","parseInt","zIndex","newIndex","zindex","filter","disable","enable","isString","close","aria-label","prepend","click","on","def","_bind","targets","suffix","ns","_unbind","originalEvent","isDefaultPrevented","_bindEvents","showEvents","hideEvents","showTargets","hideTargets","similarTargets","toggleEvents","showIndex","inArray","splice","_assignInitialEvents","hoverIntent","prerender","showTarget","hideTarget","trim","onTarget","containerTarget","viewportTarget","documentTarget","windowTarget","leave","nodeName","indexOf","enabled","isAncestor","parents","inactiveEvents","limit","abs","resize","special","grep","toArray","currentTarget","newValue","command","returned","makeArray","timeStamp","keepData","elems","func","old","ui","cleanData","triggerHandler","version","move","hidden","TIP","MARGIN","BORDER","COLOR","BG_COLOR","TRANSPARENT","IMPORTANT","HASCANVAS","getContext","INVALID","PIXEL_RATIO","devicePixelRatio","BACKING_STORE_RATIO","backingStorePixelRatio","webkitBackingStorePixelRatio","mozBackingStorePixelRatio","msBackingStorePixelRatio","oBackingStorePixelRatio","SCALE","createVML","tag","tip","prependTo","lineJoin","miterLimit","save","stopPropagation","create","_swapDimensions","_resetDimensions","_useTitle","_parseCorner","_parseWidth","side","use","_parseRadius","_invalidColour","compare","_parseColours","borderSide","colorElem","color","_calculateSize","bigHyp","ratio","isCenter","base","pow","round","smallHyp","sqrt","hyp","border","reverse","_calculateTip","scale","width2","height2","tips","br","bl","tr","tl","tc","bc","rc","lc","lt","rt","lb","rb","_drawCoords","coords","beginPath","moveTo","lineTo","closePath","update","bigCoords","translate","newSize","inner","children","curSize","mimic","lineHeight","restore","clearRect","fillStyle","fill","coordsize","antialias","Number","$this","path","fillcolor","filled","stroked","opera","calculate","corners","userOffset","b","max","margin","bottom","right","shiftflip","direction","popposite","opposite","newCorner","shiftonly","xy","shift","horizontal","vertical","cornerTop","cornerLeft","user","^position.my|style.tip.(corner|mimic|border)$","^style.tip.(height|width)$","^content.title|style.(classes|widget)$","MODAL","OVERLAY","MODALCLASS","MODALSELECTOR","focusable","expr","map","mapName","isTabIndexNotNaN","parentNode","href","focusInputs","blurElems","focusableElems","first","stealFocus","targetOnTop","current","onLast","prevState","mousedown","modal","escape","keyCode","stealfocus","visibleModals","detach","overlay","modal_zindex","oEvent","last","^show.modal.(on|blur)$","elemWidth","elemHeight","otherSide","side1","side2","lengthName","targetLength","elemLength","initialPos","mySide","atSide","isShift","myLength","atLength","sideOffset","viewportScroll","viewportOffset","containerStatic","containerOffset","overflow1","overflow2","viewportWidth","viewportHeight","min","newMy","methodX","methodY","polys","polygon","baseCoords","newWidth","newHeight","compareX","compareY","realX","realY","floor","rect","ax","ay","bx","by","_angles","ellipse","cx","cy","rx","ry","rxc","cos","PI","rys","sin","circle","r","frameOffset","mtx","transformed","len","points","root","strokeWidth2","getBBox","baseVal","x1","y1","x2","y2","numberOfItems","getItem","createSVGPoint","getScreenCTM","matrixTransform","defaultView","parentWindow","frameElement","area","imageOffset","shape","image","coordsString","coordsArray","IE6","BGIFRAME","_scroll","bgiframe","adjustBGIFrame","redrawContainer","redraw","tipAdjust","dimensions","plugin","drawing","perc","ie6","^content|style$"],"mappings":"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"}
|
assets/js/parsley.min.js.map
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
{"version":3,"sources":["parsley.min.js","/source/parsley.js","/source/src/parsley/pubsub.js","/source/src/parsley/utils.js","/source/src/parsley/defaults.js","/source/src/parsley/abstract.js","/source/src/parsley/validator.js","/source/src/parsley/validator_registry.js","/source/src/parsley/ui.js","/source/src/parsley/form.js","/source/src/parsley/factory/constraint.js","/source/src/parsley/field.js","/source/src/parsley/multiple.js","/source/src/parsley/factory.js","/source/src/parsley/main.js","/source/src/parsley/remote.js","/source/src/i18n/en.js","/source/src/parsley.js"],"names":["_toConsumableArray","arr","Array","isArray","i","arr2","length","from","_slice","prototype","slice","global","factory","exports","module","require","define","amd","parsley","jQuery","this","$","adapt","fn","context","parsleyAdaptedCallback","args","call","arguments","unshift","apply","o","eventName","name","lastIndexOf","eventPrefix","substr","globalID","pastWarnings","ParsleyUtils__ParsleyUtils","attr","$element","namespace","obj","attribute","attributes","regex","RegExp","hasOwnProperty","specified","test","camelize","deserializeValue","value","checkAttr","_checkAttr","is","setAttr","setAttribute","dasherize","String","generateID","num","isNaN","Number","parseJSON","e","str","replace","match","chr","toUpperCase","toLowerCase","warn","_window$console","window","console","warnOnce","msg","_resetWarnings","trimString","string","namespaceEvents","events","split","map","evt","join","objectCreate","Object","create","Error","TypeError","result","ParsleyUtils__default","ParsleyDefaults","inputs","excluded","priorityEnabled","multiple","group","uiEnabled","validationThreshold","focus","trigger","triggerAfterFailure","errorClass","successClass","classHandler","ParsleyField","errorsContainer","errorsWrapper","errorTemplate","ParsleyAbstract","asyncSupport","actualizeOptions","options","domOptions","parent","_resetOptions","initOptions","_listeners","on","queue","push","subscribe","listenTo","off","splice","unsubscribe","unsubscribeTo","target","extraArg","reset","__class__","_resetUI","_trigger","fields","destroy","_destroyUI","removeData","asyncIsValid","force","whenValid","_findRelated","find","requirementConverters","_string","integer","parseInt","number","parseFloat","reference","boolean","object","regexp","_regexp","flags","convertArrayRequirement","m","values","convertRequirement","requirementType","converter","convertExtraOptionRequirement","requirementSpec","extraOptionReader","main","extra","key","ParsleyValidator","spec","extend","validate","requirementFirstArg","validateMultiple","validateNumber","validateString","parseRequirements","requirements","type","isPlainObject","priority","ParsleyValidatorRegistry","validators","catalog","locale","init","typeRegexes","email","digits","alphanum","url","range","decimalPlaces","Math","max","addValidator","Parsley","setLocale","addCatalog","messages","set","addMessage","message","addMessages","nameMessageObject","arg1","arg2","_setValidator","updateValidator","removeValidator","validator","getErrorMessage","constraint","typeMessages","formatMessage","defaultMessage","en","parameters","notblank","required","_ref","undefined","_ref$step","step","_ref$base","base","nb","decimals","toInt","f","round","pow","pattern","minlength","requirement","maxlength","min","mincheck","maxcheck","check","equalto","refOrValue","$reference","val","ParsleyUI","diffResults","newResult","oldResult","deep","added","kept","found","j","assert","removed","Form","_actualizeTriggers","_this","onSubmitValidate","onSubmitButton","_focusedField","validationResult","field","noFocus","Field","_reflowUI","_buildUI","_ui","diff","lastValidationResult","_manageStatusClass","_manageErrorsMessages","_failedOnce","getErrorsMessages","errorMessage","_getErrorMessage","addError","_ref2","_ref2$updateClass","updateClass","_addError","_errorClass","updateError","_ref3","_ref3$updateClass","_updateError","removeError","_ref4","_ref4$updateClass","_removeError","hasConstraints","needsValidation","_successClass","_resetClass","errorsMessagesDisabled","_insertErrorWrapper","$errorsWrapper","append","addClass","html","removeClass","remove","_ref5","_ref6","customConstraintErrorMessage","__id__","$errorClassHandler","_manageClassHandler","errorsWrapperId","validationInformationVisible","$handler","$errorsContainer","$from","after","_this2","$toBind","event","_eventValidate","getValue","children","ParsleyForm","element","ParsleyForm__statusMapping","pending","resolved","rejected","_this3","$submitSource","_$submitSource","first","prop","promise","whenValidate","state","stopImmediatePropagation","preventDefault","done","_submit","$synthetic","appendTo","Event","_arguments","_this4","_ref7","submitEvent","_refreshFields","promises","_withoutReactualizingFormOptions","promiseBasedOnValidationResult","r","Deferred","reject","resolve","when","fail","always","pipe","isValid","_arguments2","_this5","_ref8","_bindFields","_this6","oldFields","fieldsMappedById","not","each","_","fieldInstance","Factory","oldActualizeOptions","ConstraintFactory","parsleyField","isDomConstraint","validatorSpec","_validatorRegistry","_parseRequirements","capitalize","cap","instance","requirementList","_this7","parsleyFormInstance","constraints","constraintsByName","_bindConstraints","parsley_field__statusMapping","_this8","_ref9","refreshConstraints","_isInGroup","_refreshed","_isRequired","validateIfEmpty","inArray","_arguments3","_this9","_ref10","_ref10$force","groupedConstraints","_getGroupedConstraints","_validateConstraint","_this10","_handleWhitespace","addConstraint","removeConstraint","updateConstraint","_bindHtml5Constraints","hasClass","trimValue","whitespace","index","p","sort","a","b","parsley_field","ParsleyMultiple","addElement","$elements","fieldConstraints","has","data","filter","_init","ParsleyFactory","savedparsleyFormInstance","__version__","bind","isMultiple","handleMultiple","parsleyMultipleInstance","_this11","input","$previouslyRelated","get","doNotStore","parsleyInstance","ParsleyExtend","vernums","jquery","forEach","document","version","psly","instances","ParsleyConfig","ParsleyUtils","registry","i18n","method","proxy","_window$Parsley","UI","doNotUpdateClass","navigator","userAgent","autoBind","deprecated","listen","callback","unsubscribeAll","emit","_instance","instanceGiven","asyncValidators","default","xhr","status","reverse","addAsyncValidator","ajaxOptions","csr","indexOf","encodeURIComponent","remoteOptions","param","_remoteCache","ajax","handleXhr","then"],"mappings":"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","file":"parsley.min.js","sourcesContent":[null,"(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) :\n typeof define === 'function' && define.amd ? define(['jquery'], factory) :\n global.parsley = factory(global.$)\n}(this, function ($) { 'use strict';\n\n var globalID = 1;\n var pastWarnings = {};\n\n var ParsleyUtils__ParsleyUtils = {\n // Parsley DOM-API\n // returns object from dom attributes and values\n attr: function ($element, namespace, obj) {\n var i;\n var attribute;\n var attributes;\n var regex = new RegExp('^' + namespace, 'i');\n\n if ('undefined' === typeof obj)\n obj = {};\n else {\n // Clear all own properties. This won't affect prototype's values\n for (i in obj) {\n if (obj.hasOwnProperty(i))\n delete obj[i];\n }\n }\n\n if ('undefined' === typeof $element || 'undefined' === typeof $element[0])\n return obj;\n\n attributes = $element[0].attributes;\n for (i = attributes.length; i--; ) {\n attribute = attributes[i];\n\n if (attribute && attribute.specified && regex.test(attribute.name)) {\n obj[this.camelize(attribute.name.slice(namespace.length))] = this.deserializeValue(attribute.value);\n }\n }\n\n return obj;\n },\n\n checkAttr: function ($element, namespace, checkAttr) {\n return $element.is('[' + namespace + checkAttr + ']');\n },\n\n setAttr: function ($element, namespace, attr, value) {\n $element[0].setAttribute(this.dasherize(namespace + attr), String(value));\n },\n\n generateID: function () {\n return '' + globalID++;\n },\n\n /** Third party functions **/\n // Zepto deserialize function\n deserializeValue: function (value) {\n var num;\n\n try {\n return value ?\n value == \"true\" ||\n (value == \"false\" ? false :\n value == \"null\" ? null :\n !isNaN(num = Number(value)) ? num :\n /^[\\[\\{]/.test(value) ? $.parseJSON(value) :\n value)\n : value;\n } catch (e) { return value; }\n },\n\n // Zepto camelize function\n camelize: function (str) {\n return str.replace(/-+(.)?/g, function (match, chr) {\n return chr ? chr.toUpperCase() : '';\n });\n },\n\n // Zepto dasherize function\n dasherize: function (str) {\n return str.replace(/::/g, '/')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')\n .replace(/([a-z\\d])([A-Z])/g, '$1_$2')\n .replace(/_/g, '-')\n .toLowerCase();\n },\n\n warn: function () {\n if (window.console && 'function' === typeof window.console.warn)\n window.console.warn(...arguments);\n },\n\n warnOnce: function(msg) {\n if (!pastWarnings[msg]) {\n pastWarnings[msg] = true;\n this.warn(...arguments);\n }\n },\n\n _resetWarnings: function () {\n pastWarnings = {};\n },\n\n trimString: function(string) {\n return string.replace(/^\\s+|\\s+$/g, '');\n },\n\n namespaceEvents: function(events, namespace) {\n events = this.trimString(events || '').split(/\\s+/);\n if (!events[0])\n return '';\n return $.map(events, evt => { return `${evt}.${namespace}`; }).join(' ');\n },\n\n // Object.create polyfill, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create#Polyfill\n objectCreate: Object.create || (function () {\n var Object = function () {};\n return function (prototype) {\n if (arguments.length > 1) {\n throw Error('Second argument not supported');\n }\n if (typeof prototype != 'object') {\n throw TypeError('Argument must be an object');\n }\n Object.prototype = prototype;\n var result = new Object();\n Object.prototype = null;\n return result;\n };\n })()\n };\n\n var ParsleyUtils__default = ParsleyUtils__ParsleyUtils;\n\n // All these options could be overriden and specified directly in DOM using\n // `data-parsley-` default DOM-API\n // eg: `inputs` can be set in DOM using `data-parsley-inputs=\"input, textarea\"`\n // eg: `data-parsley-stop-on-first-failing-constraint=\"false\"`\n\n var ParsleyDefaults = {\n // ### General\n\n // Default data-namespace for DOM API\n namespace: 'data-parsley-',\n\n // Supported inputs by default\n inputs: 'input, textarea, select',\n\n // Excluded inputs by default\n excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden]',\n\n // Stop validating field on highest priority failing constraint\n priorityEnabled: true,\n\n // ### Field only\n\n // identifier used to group together inputs (e.g. radio buttons...)\n multiple: null,\n\n // identifier (or array of identifiers) used to validate only a select group of inputs\n group: null,\n\n // ### UI\n // Enable\\Disable error messages\n uiEnabled: true,\n\n // Key events threshold before validation\n validationThreshold: 3,\n\n // Focused field on form validation error. 'first'|'last'|'none'\n focus: 'first',\n\n // event(s) that will trigger validation before first failure. eg: `input`...\n trigger: false,\n\n // event(s) that will trigger validation after first failure.\n triggerAfterFailure: 'input',\n\n // Class that would be added on every failing validation Parsley field\n errorClass: 'parsley-error',\n\n // Same for success validation\n successClass: 'parsley-success',\n\n // Return the `$element` that will receive these above success or error classes\n // Could also be (and given directly from DOM) a valid selector like `'#div'`\n classHandler: function (ParsleyField) {},\n\n // Return the `$element` where errors will be appended\n // Could also be (and given directly from DOM) a valid selector like `'#div'`\n errorsContainer: function (ParsleyField) {},\n\n // ul elem that would receive errors' list\n errorsWrapper: '<ul class=\"parsley-errors-list\"></ul>',\n\n // li elem that would receive error message\n errorTemplate: '<li></li>'\n };\n\n var ParsleyAbstract = function () {};\n\n ParsleyAbstract.prototype = {\n asyncSupport: true, // Deprecated\n\n actualizeOptions: function () {\n ParsleyUtils__default.attr(this.$element, this.options.namespace, this.domOptions);\n if (this.parent && this.parent.actualizeOptions)\n this.parent.actualizeOptions();\n return this;\n },\n\n _resetOptions: function (initOptions) {\n this.domOptions = ParsleyUtils__default.objectCreate(this.parent.options);\n this.options = ParsleyUtils__default.objectCreate(this.domOptions);\n // Shallow copy of ownProperties of initOptions:\n for (var i in initOptions) {\n if (initOptions.hasOwnProperty(i))\n this.options[i] = initOptions[i];\n }\n this.actualizeOptions();\n },\n\n _listeners: null,\n\n // Register a callback for the given event name\n // Callback is called with context as the first argument and the `this`\n // The context is the current parsley instance, or window.Parsley if global\n // A return value of `false` will interrupt the calls\n on: function (name, fn) {\n this._listeners = this._listeners || {};\n var queue = this._listeners[name] = this._listeners[name] || [];\n queue.push(fn);\n\n return this;\n },\n\n // Deprecated. Use `on` instead\n subscribe: function(name, fn) {\n $.listenTo(this, name.toLowerCase(), fn);\n },\n\n // Unregister a callback (or all if none is given) for the given event name\n off: function (name, fn) {\n var queue = this._listeners && this._listeners[name];\n if (queue) {\n if (!fn) {\n delete this._listeners[name];\n } else {\n for (var i = queue.length; i--; )\n if (queue[i] === fn)\n queue.splice(i, 1);\n }\n }\n return this;\n },\n\n // Deprecated. Use `off`\n unsubscribe: function(name, fn) {\n $.unsubscribeTo(this, name.toLowerCase());\n },\n\n // Trigger an event of the given name\n // A return value of `false` interrupts the callback chain\n // Returns false if execution was interrupted\n trigger: function (name, target, extraArg) {\n target = target || this;\n var queue = this._listeners && this._listeners[name];\n var result;\n var parentResult;\n if (queue) {\n for (var i = queue.length; i--; ) {\n result = queue[i].call(target, target, extraArg);\n if (result === false) return result;\n }\n }\n if (this.parent) {\n return this.parent.trigger(name, target, extraArg);\n }\n return true;\n },\n\n // Reset UI\n reset: function () {\n // Field case: just emit a reset event for UI\n if ('ParsleyForm' !== this.__class__) {\n this._resetUI();\n return this._trigger('reset');\n }\n\n // Form case: emit a reset event for each field\n for (var i = 0; i < this.fields.length; i++)\n this.fields[i].reset();\n\n this._trigger('reset');\n },\n\n // Destroy Parsley instance (+ UI)\n destroy: function () {\n // Field case: emit destroy event to clean UI and then destroy stored instance\n this._destroyUI();\n if ('ParsleyForm' !== this.__class__) {\n this.$element.removeData('Parsley');\n this.$element.removeData('ParsleyFieldMultiple');\n this._trigger('destroy');\n\n return;\n }\n\n // Form case: destroy all its fields and then destroy stored instance\n for (var i = 0; i < this.fields.length; i++)\n this.fields[i].destroy();\n\n this.$element.removeData('Parsley');\n this._trigger('destroy');\n },\n\n asyncIsValid: function (group, force) {\n ParsleyUtils__default.warnOnce(\"asyncIsValid is deprecated; please use whenValid instead\");\n return this.whenValid({group, force});\n },\n\n _findRelated: function () {\n return this.options.multiple ?\n this.parent.$element.find(`[${this.options.namespace}multiple=\"${this.options.multiple}\"]`)\n : this.$element;\n }\n };\n\n var requirementConverters = {\n string: function(string) {\n return string;\n },\n integer: function(string) {\n if (isNaN(string))\n throw 'Requirement is not an integer: \"' + string + '\"';\n return parseInt(string, 10);\n },\n number: function(string) {\n if (isNaN(string))\n throw 'Requirement is not a number: \"' + string + '\"';\n return parseFloat(string);\n },\n reference: function(string) { // Unused for now\n var result = $(string);\n if (result.length === 0)\n throw 'No such reference: \"' + string + '\"';\n return result;\n },\n boolean: function(string) {\n return string !== 'false';\n },\n object: function(string) {\n return ParsleyUtils__default.deserializeValue(string);\n },\n regexp: function(regexp) {\n var flags = '';\n\n // Test if RegExp is literal, if not, nothing to be done, otherwise, we need to isolate flags and pattern\n if (/^\\/.*\\/(?:[gimy]*)$/.test(regexp)) {\n // Replace the regexp literal string with the first match group: ([gimy]*)\n // If no flag is present, this will be a blank string\n flags = regexp.replace(/.*\\/([gimy]*)$/, '$1');\n // Again, replace the regexp literal string with the first match group:\n // everything excluding the opening and closing slashes and the flags\n regexp = regexp.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1');\n } else {\n // Anchor regexp:\n regexp = '^' + regexp + '$';\n }\n return new RegExp(regexp, flags);\n }\n };\n\n var convertArrayRequirement = function(string, length) {\n var m = string.match(/^\\s*\\[(.*)\\]\\s*$/);\n if (!m)\n throw 'Requirement is not an array: \"' + string + '\"';\n var values = m[1].split(',').map(ParsleyUtils__default.trimString);\n if (values.length !== length)\n throw 'Requirement has ' + values.length + ' values when ' + length + ' are needed';\n return values;\n };\n\n var convertRequirement = function(requirementType, string) {\n var converter = requirementConverters[requirementType || 'string'];\n if (!converter)\n throw 'Unknown requirement specification: \"' + requirementType + '\"';\n return converter(string);\n };\n\n var convertExtraOptionRequirement = function(requirementSpec, string, extraOptionReader) {\n var main = null;\n var extra = {};\n for (var key in requirementSpec) {\n if (key) {\n var value = extraOptionReader(key);\n if ('string' === typeof value)\n value = convertRequirement(requirementSpec[key], value);\n extra[key] = value;\n } else {\n main = convertRequirement(requirementSpec[key], string);\n }\n }\n return [main, extra];\n };\n\n // A Validator needs to implement the methods `validate` and `parseRequirements`\n\n var ParsleyValidator = function(spec) {\n $.extend(true, this, spec);\n };\n\n ParsleyValidator.prototype = {\n // Returns `true` iff the given `value` is valid according the given requirements.\n validate: function(value, requirementFirstArg) {\n if (this.fn) { // Legacy style validator\n\n if (arguments.length > 3) // If more args then value, requirement, instance...\n requirementFirstArg = [].slice.call(arguments, 1, -1); // Skip first arg (value) and last (instance), combining the rest\n return this.fn.call(this, value, requirementFirstArg);\n }\n\n if ($.isArray(value)) {\n if (!this.validateMultiple)\n throw 'Validator `' + this.name + '` does not handle multiple values';\n return this.validateMultiple(...arguments);\n } else {\n if (this.validateNumber) {\n if (isNaN(value))\n return false;\n arguments[0] = parseFloat(arguments[0]);\n return this.validateNumber(...arguments);\n }\n if (this.validateString) {\n return this.validateString(...arguments);\n }\n throw 'Validator `' + this.name + '` only handles multiple values';\n }\n },\n\n // Parses `requirements` into an array of arguments,\n // according to `this.requirementType`\n parseRequirements: function(requirements, extraOptionReader) {\n if ('string' !== typeof requirements) {\n // Assume requirement already parsed\n // but make sure we return an array\n return $.isArray(requirements) ? requirements : [requirements];\n }\n var type = this.requirementType;\n if ($.isArray(type)) {\n var values = convertArrayRequirement(requirements, type.length);\n for (var i = 0; i < values.length; i++)\n values[i] = convertRequirement(type[i], values[i]);\n return values;\n } else if ($.isPlainObject(type)) {\n return convertExtraOptionRequirement(type, requirements, extraOptionReader);\n } else {\n return [convertRequirement(type, requirements)];\n }\n },\n // Defaults:\n requirementType: 'string',\n\n priority: 2\n\n };\n\n var ParsleyValidatorRegistry = function (validators, catalog) {\n this.__class__ = 'ParsleyValidatorRegistry';\n\n // Default Parsley locale is en\n this.locale = 'en';\n\n this.init(validators || {}, catalog || {});\n };\n\n var typeRegexes = {\n email: /^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))$/i,\n\n // Follow https://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers\n number: /^-?(\\d*\\.)?\\d+(e[-+]?\\d+)?$/i,\n\n integer: /^-?\\d+$/,\n\n digits: /^\\d+$/,\n\n alphanum: /^\\w+$/i,\n\n url: new RegExp(\n \"^\" +\n // protocol identifier\n \"(?:(?:https?|ftp)://)?\" + // ** mod: make scheme optional\n // user:pass authentication\n \"(?:\\\\S+(?::\\\\S*)?@)?\" +\n \"(?:\" +\n // IP address exclusion\n // private & local networks\n // \"(?!(?:10|127)(?:\\\\.\\\\d{1,3}){3})\" + // ** mod: allow local networks\n // \"(?!(?:169\\\\.254|192\\\\.168)(?:\\\\.\\\\d{1,3}){2})\" + // ** mod: allow local networks\n // \"(?!172\\\\.(?:1[6-9]|2\\\\d|3[0-1])(?:\\\\.\\\\d{1,3}){2})\" + // ** mod: allow local networks\n // IP address dotted notation octets\n // excludes loopback network 0.0.0.0\n // excludes reserved space >= 224.0.0.0\n // excludes network & broacast addresses\n // (first & last IP address of each class)\n \"(?:[1-9]\\\\d?|1\\\\d\\\\d|2[01]\\\\d|22[0-3])\" +\n \"(?:\\\\.(?:1?\\\\d{1,2}|2[0-4]\\\\d|25[0-5])){2}\" +\n \"(?:\\\\.(?:[1-9]\\\\d?|1\\\\d\\\\d|2[0-4]\\\\d|25[0-4]))\" +\n \"|\" +\n // host name\n \"(?:(?:[a-z\\\\u00a1-\\\\uffff0-9]-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)\" +\n // domain name\n \"(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff0-9]-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)*\" +\n // TLD identifier\n \"(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff]{2,}))\" +\n \")\" +\n // port number\n \"(?::\\\\d{2,5})?\" +\n // resource path\n \"(?:/\\\\S*)?\" +\n \"$\", 'i'\n )\n };\n typeRegexes.range = typeRegexes.number;\n\n // See http://stackoverflow.com/a/10454560/8279\n var decimalPlaces = num => {\n var match = ('' + num).match(/(?:\\.(\\d+))?(?:[eE]([+-]?\\d+))?$/);\n if (!match) { return 0; }\n return Math.max(\n 0,\n // Number of digits right of decimal point.\n (match[1] ? match[1].length : 0) -\n // Adjust for scientific notation.\n (match[2] ? +match[2] : 0));\n };\n\n ParsleyValidatorRegistry.prototype = {\n init: function (validators, catalog) {\n this.catalog = catalog;\n // Copy prototype's validators:\n this.validators = $.extend({}, this.validators);\n\n for (var name in validators)\n this.addValidator(name, validators[name].fn, validators[name].priority);\n\n window.Parsley.trigger('parsley:validator:init');\n },\n\n // Set new messages locale if we have dictionary loaded in ParsleyConfig.i18n\n setLocale: function (locale) {\n if ('undefined' === typeof this.catalog[locale])\n throw new Error(locale + ' is not available in the catalog');\n\n this.locale = locale;\n\n return this;\n },\n\n // Add a new messages catalog for a given locale. Set locale for this catalog if set === `true`\n addCatalog: function (locale, messages, set) {\n if ('object' === typeof messages)\n this.catalog[locale] = messages;\n\n if (true === set)\n return this.setLocale(locale);\n\n return this;\n },\n\n // Add a specific message for a given constraint in a given locale\n addMessage: function (locale, name, message) {\n if ('undefined' === typeof this.catalog[locale])\n this.catalog[locale] = {};\n\n this.catalog[locale][name] = message;\n\n return this;\n },\n\n // Add messages for a given locale\n addMessages: function (locale, nameMessageObject) {\n for (var name in nameMessageObject)\n this.addMessage(locale, name, nameMessageObject[name]);\n\n return this;\n },\n\n // Add a new validator\n //\n // addValidator('custom', {\n // requirementType: ['integer', 'integer'],\n // validateString: function(value, from, to) {},\n // priority: 22,\n // messages: {\n // en: \"Hey, that's no good\",\n // fr: \"Aye aye, pas bon du tout\",\n // }\n // })\n //\n // Old API was addValidator(name, function, priority)\n //\n addValidator: function (name, arg1, arg2) {\n if (this.validators[name])\n ParsleyUtils__default.warn('Validator \"' + name + '\" is already defined.');\n else if (ParsleyDefaults.hasOwnProperty(name)) {\n ParsleyUtils__default.warn('\"' + name + '\" is a restricted keyword and is not a valid validator name.');\n return;\n }\n return this._setValidator(...arguments);\n },\n\n updateValidator: function (name, arg1, arg2) {\n if (!this.validators[name]) {\n ParsleyUtils__default.warn('Validator \"' + name + '\" is not already defined.');\n return this.addValidator(...arguments);\n }\n return this._setValidator(this, arguments);\n },\n\n removeValidator: function (name) {\n if (!this.validators[name])\n ParsleyUtils__default.warn('Validator \"' + name + '\" is not defined.');\n\n delete this.validators[name];\n\n return this;\n },\n\n _setValidator: function (name, validator, priority) {\n if ('object' !== typeof validator) {\n // Old style validator, with `fn` and `priority`\n validator = {\n fn: validator,\n priority: priority\n };\n }\n if (!validator.validate) {\n validator = new ParsleyValidator(validator);\n }\n this.validators[name] = validator;\n\n for (var locale in validator.messages || {})\n this.addMessage(locale, name, validator.messages[locale]);\n\n return this;\n },\n\n getErrorMessage: function (constraint) {\n var message;\n\n // Type constraints are a bit different, we have to match their requirements too to find right error message\n if ('type' === constraint.name) {\n var typeMessages = this.catalog[this.locale][constraint.name] || {};\n message = typeMessages[constraint.requirements];\n } else\n message = this.formatMessage(this.catalog[this.locale][constraint.name], constraint.requirements);\n\n return message || this.catalog[this.locale].defaultMessage || this.catalog.en.defaultMessage;\n },\n\n // Kind of light `sprintf()` implementation\n formatMessage: function (string, parameters) {\n if ('object' === typeof parameters) {\n for (var i in parameters)\n string = this.formatMessage(string, parameters[i]);\n\n return string;\n }\n\n return 'string' === typeof string ? string.replace(/%s/i, parameters) : '';\n },\n\n // Here is the Parsley default validators list.\n // A validator is an object with the following key values:\n // - priority: an integer\n // - requirement: 'string' (default), 'integer', 'number', 'regexp' or an Array of these\n // - validateString, validateMultiple, validateNumber: functions returning `true`, `false` or a promise\n // Alternatively, a validator can be a function that returns such an object\n //\n validators: {\n notblank: {\n validateString: function(value) {\n return /\\S/.test(value);\n },\n priority: 2\n },\n required: {\n validateMultiple: function(values) {\n return values.length > 0;\n },\n validateString: function(value) {\n return /\\S/.test(value);\n },\n priority: 512\n },\n type: {\n validateString: function(value, type, {step = '1', base = 0} = {}) {\n var regex = typeRegexes[type];\n if (!regex) {\n throw new Error('validator type `' + type + '` is not supported');\n }\n if (!regex.test(value))\n return false;\n if ('number' === type) {\n if (!/^any$/i.test(step || '')) {\n var nb = Number(value);\n var decimals = Math.max(decimalPlaces(step), decimalPlaces(base));\n if (decimalPlaces(nb) > decimals) // Value can't have too many decimals\n return false;\n // Be careful of rounding errors by using integers.\n var toInt = f => { return Math.round(f * Math.pow(10, decimals)); };\n if ((toInt(nb) - toInt(base)) % toInt(step) != 0)\n return false;\n }\n }\n return true;\n },\n requirementType: {\n '': 'string',\n step: 'string',\n base: 'number'\n },\n priority: 256\n },\n pattern: {\n validateString: function(value, regexp) {\n return regexp.test(value);\n },\n requirementType: 'regexp',\n priority: 64\n },\n minlength: {\n validateString: function (value, requirement) {\n return value.length >= requirement;\n },\n requirementType: 'integer',\n priority: 30\n },\n maxlength: {\n validateString: function (value, requirement) {\n return value.length <= requirement;\n },\n requirementType: 'integer',\n priority: 30\n },\n length: {\n validateString: function (value, min, max) {\n return value.length >= min && value.length <= max;\n },\n requirementType: ['integer', 'integer'],\n priority: 30\n },\n mincheck: {\n validateMultiple: function (values, requirement) {\n return values.length >= requirement;\n },\n requirementType: 'integer',\n priority: 30\n },\n maxcheck: {\n validateMultiple: function (values, requirement) {\n return values.length <= requirement;\n },\n requirementType: 'integer',\n priority: 30\n },\n check: {\n validateMultiple: function (values, min, max) {\n return values.length >= min && values.length <= max;\n },\n requirementType: ['integer', 'integer'],\n priority: 30\n },\n min: {\n validateNumber: function (value, requirement) {\n return value >= requirement;\n },\n requirementType: 'number',\n priority: 30\n },\n max: {\n validateNumber: function (value, requirement) {\n return value <= requirement;\n },\n requirementType: 'number',\n priority: 30\n },\n range: {\n validateNumber: function (value, min, max) {\n return value >= min && value <= max;\n },\n requirementType: ['number', 'number'],\n priority: 30\n },\n equalto: {\n validateString: function (value, refOrValue) {\n var $reference = $(refOrValue);\n if ($reference.length)\n return value === $reference.val();\n else\n return value === refOrValue;\n },\n priority: 256\n }\n }\n };\n\n var ParsleyUI = {};\n\n var diffResults = function (newResult, oldResult, deep) {\n var added = [];\n var kept = [];\n\n for (var i = 0; i < newResult.length; i++) {\n var found = false;\n\n for (var j = 0; j < oldResult.length; j++)\n if (newResult[i].assert.name === oldResult[j].assert.name) {\n found = true;\n break;\n }\n\n if (found)\n kept.push(newResult[i]);\n else\n added.push(newResult[i]);\n }\n\n return {\n kept: kept,\n added: added,\n removed: !deep ? diffResults(oldResult, newResult, true).added : []\n };\n };\n\n ParsleyUI.Form = {\n\n _actualizeTriggers: function () {\n this.$element.on('submit.Parsley', evt => { this.onSubmitValidate(evt); });\n this.$element.on('click.Parsley', 'input[type=\"submit\"], button[type=\"submit\"]', evt => { this.onSubmitButton(evt); });\n\n // UI could be disabled\n if (false === this.options.uiEnabled)\n return;\n\n this.$element.attr('novalidate', '');\n },\n\n focus: function () {\n this._focusedField = null;\n\n if (true === this.validationResult || 'none' === this.options.focus)\n return null;\n\n for (var i = 0; i < this.fields.length; i++) {\n var field = this.fields[i];\n if (true !== field.validationResult && field.validationResult.length > 0 && 'undefined' === typeof field.options.noFocus) {\n this._focusedField = field.$element;\n if ('first' === this.options.focus)\n break;\n }\n }\n\n if (null === this._focusedField)\n return null;\n\n return this._focusedField.focus();\n },\n\n _destroyUI: function () {\n // Reset all event listeners\n this.$element.off('.Parsley');\n }\n\n };\n\n ParsleyUI.Field = {\n\n _reflowUI: function () {\n this._buildUI();\n\n // If this field doesn't have an active UI don't bother doing something\n if (!this._ui)\n return;\n\n // Diff between two validation results\n var diff = diffResults(this.validationResult, this._ui.lastValidationResult);\n\n // Then store current validation result for next reflow\n this._ui.lastValidationResult = this.validationResult;\n\n // Handle valid / invalid / none field class\n this._manageStatusClass();\n\n // Add, remove, updated errors messages\n this._manageErrorsMessages(diff);\n\n // Triggers impl\n this._actualizeTriggers();\n\n // If field is not valid for the first time, bind keyup trigger to ease UX and quickly inform user\n if ((diff.kept.length || diff.added.length) && !this._failedOnce) {\n this._failedOnce = true;\n this._actualizeTriggers();\n }\n },\n\n // Returns an array of field's error message(s)\n getErrorsMessages: function () {\n // No error message, field is valid\n if (true === this.validationResult)\n return [];\n\n var messages = [];\n\n for (var i = 0; i < this.validationResult.length; i++)\n messages.push(this.validationResult[i].errorMessage ||\n this._getErrorMessage(this.validationResult[i].assert));\n\n return messages;\n },\n\n // It's a goal of Parsley that this method is no longer required [#1073]\n addError: function (name, {message, assert, updateClass = true} = {}) {\n this._buildUI();\n this._addError(name, {message, assert});\n\n if (updateClass)\n this._errorClass();\n },\n\n // It's a goal of Parsley that this method is no longer required [#1073]\n updateError: function (name, {message, assert, updateClass = true} = {}) {\n this._buildUI();\n this._updateError(name, {message, assert});\n\n if (updateClass)\n this._errorClass();\n },\n\n // It's a goal of Parsley that this method is no longer required [#1073]\n removeError: function (name, {updateClass = true} = {}) {\n this._buildUI();\n this._removeError(name);\n\n // edge case possible here: remove a standard Parsley error that is still failing in this.validationResult\n // but highly improbable cuz' manually removing a well Parsley handled error makes no sense.\n if (updateClass)\n this._manageStatusClass();\n },\n\n _manageStatusClass: function () {\n if (this.hasConstraints() && this.needsValidation() && true === this.validationResult)\n this._successClass();\n else if (this.validationResult.length > 0)\n this._errorClass();\n else\n this._resetClass();\n },\n\n _manageErrorsMessages: function (diff) {\n if ('undefined' !== typeof this.options.errorsMessagesDisabled)\n return;\n\n // Case where we have errorMessage option that configure an unique field error message, regardless failing validators\n if ('undefined' !== typeof this.options.errorMessage) {\n if ((diff.added.length || diff.kept.length)) {\n this._insertErrorWrapper();\n\n if (0 === this._ui.$errorsWrapper.find('.parsley-custom-error-message').length)\n this._ui.$errorsWrapper\n .append(\n $(this.options.errorTemplate)\n .addClass('parsley-custom-error-message')\n );\n\n return this._ui.$errorsWrapper\n .addClass('filled')\n .find('.parsley-custom-error-message')\n .html(this.options.errorMessage);\n }\n\n return this._ui.$errorsWrapper\n .removeClass('filled')\n .find('.parsley-custom-error-message')\n .remove();\n }\n\n // Show, hide, update failing constraints messages\n for (var i = 0; i < diff.removed.length; i++)\n this._removeError(diff.removed[i].assert.name);\n\n for (i = 0; i < diff.added.length; i++)\n this._addError(diff.added[i].assert.name, {message: diff.added[i].errorMessage, assert: diff.added[i].assert});\n\n for (i = 0; i < diff.kept.length; i++)\n this._updateError(diff.kept[i].assert.name, {message: diff.kept[i].errorMessage, assert: diff.kept[i].assert});\n },\n\n\n _addError: function (name, {message, assert}) {\n this._insertErrorWrapper();\n this._ui.$errorsWrapper\n .addClass('filled')\n .append(\n $(this.options.errorTemplate)\n .addClass('parsley-' + name)\n .html(message || this._getErrorMessage(assert))\n );\n },\n\n _updateError: function (name, {message, assert}) {\n this._ui.$errorsWrapper\n .addClass('filled')\n .find('.parsley-' + name)\n .html(message || this._getErrorMessage(assert));\n },\n\n _removeError: function (name) {\n this._ui.$errorsWrapper\n .removeClass('filled')\n .find('.parsley-' + name)\n .remove();\n },\n\n _getErrorMessage: function (constraint) {\n var customConstraintErrorMessage = constraint.name + 'Message';\n\n if ('undefined' !== typeof this.options[customConstraintErrorMessage])\n return window.Parsley.formatMessage(this.options[customConstraintErrorMessage], constraint.requirements);\n\n return window.Parsley.getErrorMessage(constraint);\n },\n\n _buildUI: function () {\n // UI could be already built or disabled\n if (this._ui || false === this.options.uiEnabled)\n return;\n\n var _ui = {};\n\n // Give field its Parsley id in DOM\n this.$element.attr(this.options.namespace + 'id', this.__id__);\n\n /** Generate important UI elements and store them in this **/\n // $errorClassHandler is the $element that woul have parsley-error and parsley-success classes\n _ui.$errorClassHandler = this._manageClassHandler();\n\n // $errorsWrapper is a div that would contain the various field errors, it will be appended into $errorsContainer\n _ui.errorsWrapperId = 'parsley-id-' + (this.options.multiple ? 'multiple-' + this.options.multiple : this.__id__);\n _ui.$errorsWrapper = $(this.options.errorsWrapper).attr('id', _ui.errorsWrapperId);\n\n // ValidationResult UI storage to detect what have changed bwt two validations, and update DOM accordingly\n _ui.lastValidationResult = [];\n _ui.validationInformationVisible = false;\n\n // Store it in this for later\n this._ui = _ui;\n },\n\n // Determine which element will have `parsley-error` and `parsley-success` classes\n _manageClassHandler: function () {\n // An element selector could be passed through DOM with `data-parsley-class-handler=#foo`\n if ('string' === typeof this.options.classHandler && $(this.options.classHandler).length)\n return $(this.options.classHandler);\n\n // Class handled could also be determined by function given in Parsley options\n var $handler = this.options.classHandler.call(this, this);\n\n // If this function returned a valid existing DOM element, go for it\n if ('undefined' !== typeof $handler && $handler.length)\n return $handler;\n\n // Otherwise, if simple element (input, texatrea, select...) it will perfectly host the classes\n if (!this.options.multiple || this.$element.is('select'))\n return this.$element;\n\n // But if multiple element (radio, checkbox), that would be their parent\n return this.$element.parent();\n },\n\n _insertErrorWrapper: function () {\n var $errorsContainer;\n\n // Nothing to do if already inserted\n if (0 !== this._ui.$errorsWrapper.parent().length)\n return this._ui.$errorsWrapper.parent();\n\n if ('string' === typeof this.options.errorsContainer) {\n if ($(this.options.errorsContainer).length)\n return $(this.options.errorsContainer).append(this._ui.$errorsWrapper);\n else\n ParsleyUtils__default.warn('The errors container `' + this.options.errorsContainer + '` does not exist in DOM');\n } else if ('function' === typeof this.options.errorsContainer)\n $errorsContainer = this.options.errorsContainer.call(this, this);\n\n if ('undefined' !== typeof $errorsContainer && $errorsContainer.length)\n return $errorsContainer.append(this._ui.$errorsWrapper);\n\n var $from = this.$element;\n if (this.options.multiple)\n $from = $from.parent();\n return $from.after(this._ui.$errorsWrapper);\n },\n\n _actualizeTriggers: function () {\n var $toBind = this._findRelated();\n\n // Remove Parsley events already bound on this field\n $toBind.off('.Parsley');\n if (this._failedOnce)\n $toBind.on(ParsleyUtils__default.namespaceEvents(this.options.triggerAfterFailure, 'Parsley'), () => {\n this.validate();\n });\n else {\n $toBind.on(ParsleyUtils__default.namespaceEvents(this.options.trigger, 'Parsley'), event => {\n this._eventValidate(event);\n });\n }\n },\n\n _eventValidate: function (event) {\n // For keyup, keypress, keydown, input... events that could be a little bit obstrusive\n // do not validate if val length < min threshold on first validation. Once field have been validated once and info\n // about success or failure have been displayed, always validate with this trigger to reflect every yalidation change.\n if (/key|input/.test(event.type))\n if (!(this._ui && this._ui.validationInformationVisible) && this.getValue().length <= this.options.validationThreshold)\n return;\n\n this.validate();\n },\n\n _resetUI: function () {\n // Reset all event listeners\n this._failedOnce = false;\n this._actualizeTriggers();\n\n // Nothing to do if UI never initialized for this field\n if ('undefined' === typeof this._ui)\n return;\n\n // Reset all errors' li\n this._ui.$errorsWrapper\n .removeClass('filled')\n .children()\n .remove();\n\n // Reset validation class\n this._resetClass();\n\n // Reset validation flags and last validation result\n this._ui.lastValidationResult = [];\n this._ui.validationInformationVisible = false;\n },\n\n _destroyUI: function () {\n this._resetUI();\n\n if ('undefined' !== typeof this._ui)\n this._ui.$errorsWrapper.remove();\n\n delete this._ui;\n },\n\n _successClass: function () {\n this._ui.validationInformationVisible = true;\n this._ui.$errorClassHandler.removeClass(this.options.errorClass).addClass(this.options.successClass);\n },\n _errorClass: function () {\n this._ui.validationInformationVisible = true;\n this._ui.$errorClassHandler.removeClass(this.options.successClass).addClass(this.options.errorClass);\n },\n _resetClass: function () {\n this._ui.$errorClassHandler.removeClass(this.options.successClass).removeClass(this.options.errorClass);\n }\n };\n\n var ParsleyForm = function (element, domOptions, options) {\n this.__class__ = 'ParsleyForm';\n this.__id__ = ParsleyUtils__default.generateID();\n\n this.$element = $(element);\n this.domOptions = domOptions;\n this.options = options;\n this.parent = window.Parsley;\n\n this.fields = [];\n this.validationResult = null;\n };\n\n var ParsleyForm__statusMapping = {pending: null, resolved: true, rejected: false};\n\n ParsleyForm.prototype = {\n onSubmitValidate: function (event) {\n // This is a Parsley generated submit event, do not validate, do not prevent, simply exit and keep normal behavior\n if (true === event.parsley)\n return;\n\n // If we didn't come here through a submit button, use the first one in the form\n var $submitSource = this._$submitSource || this.$element.find('input[type=\"submit\"], button[type=\"submit\"]').first();\n this._$submitSource = null;\n this.$element.find('.parsley-synthetic-submit-button').prop('disabled', true);\n if ($submitSource.is('[formnovalidate]'))\n return;\n\n var promise = this.whenValidate({event});\n\n if ('resolved' === promise.state() && false !== this._trigger('submit')) {\n // All good, let event go through. We make this distinction because browsers\n // differ in their handling of `submit` being called from inside a submit event [#1047]\n } else {\n // Rejected or pending: cancel this submit\n event.stopImmediatePropagation();\n event.preventDefault();\n if ('pending' === promise.state())\n promise.done(() => { this._submit($submitSource); });\n }\n },\n\n onSubmitButton: function(event) {\n this._$submitSource = $(event.target);\n },\n // internal\n // _submit submits the form, this time without going through the validations.\n // Care must be taken to \"fake\" the actual submit button being clicked.\n _submit: function ($submitSource) {\n if (false === this._trigger('submit'))\n return;\n // Add submit button's data\n if ($submitSource) {\n var $synthetic = this.$element.find('.parsley-synthetic-submit-button').prop('disabled', false);\n if (0 === $synthetic.length)\n $synthetic = $('<input class=\"parsley-synthetic-submit-button\" type=\"hidden\">').appendTo(this.$element);\n $synthetic.attr({\n name: $submitSource.attr('name'),\n value: $submitSource.attr('value')\n });\n }\n\n this.$element.trigger($.extend($.Event('submit'), {parsley: true}));\n },\n\n // Performs validation on fields while triggering events.\n // @returns `true` if all validations succeeds, `false`\n // if a failure is immediately detected, or `null`\n // if dependant on a promise.\n // Consider using `whenValidate` instead.\n validate: function (options) {\n if (arguments.length >= 1 && !$.isPlainObject(options)) {\n ParsleyUtils__default.warnOnce('Calling validate on a parsley form without passing arguments as an object is deprecated.');\n var [group, force, event] = arguments;\n options = {group, force, event};\n }\n return ParsleyForm__statusMapping[ this.whenValidate(options).state() ];\n },\n\n whenValidate: function ({group, force, event} = {}) {\n this.submitEvent = event;\n if (event) {\n this.submitEvent = $.extend({}, event, {preventDefault: () => {\n ParsleyUtils__default.warnOnce(\"Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`\");\n this.validationResult = false;\n }});\n }\n this.validationResult = true;\n\n // fire validate event to eventually modify things before very validation\n this._trigger('validate');\n\n // Refresh form DOM options and form's fields that could have changed\n this._refreshFields();\n\n var promises = this._withoutReactualizingFormOptions(() => {\n return $.map(this.fields, field => {\n return field.whenValidate({force, group});\n });\n });\n\n var promiseBasedOnValidationResult = () => {\n var r = $.Deferred();\n if (false === this.validationResult)\n r.reject();\n return r.resolve().promise();\n };\n\n return $.when(...promises)\n .done( () => { this._trigger('success'); })\n .fail( () => {\n this.validationResult = false;\n this.focus();\n this._trigger('error');\n })\n .always(() => { this._trigger('validated'); })\n .pipe( promiseBasedOnValidationResult, promiseBasedOnValidationResult);\n },\n\n // Iterate over refreshed fields, and stop on first failure.\n // Returns `true` if all fields are valid, `false` if a failure is detected\n // or `null` if the result depends on an unresolved promise.\n // Prefer using `whenValid` instead.\n isValid: function (options) {\n if (arguments.length >= 1 && !$.isPlainObject(options)) {\n ParsleyUtils__default.warnOnce('Calling isValid on a parsley form without passing arguments as an object is deprecated.');\n var [group, force] = arguments;\n options = {group, force};\n }\n return ParsleyForm__statusMapping[ this.whenValid(options).state() ];\n },\n\n // Iterate over refreshed fields and validate them.\n // Returns a promise.\n // A validation that immediately fails will interrupt the validations.\n whenValid: function ({group, force} = {}) {\n this._refreshFields();\n\n var promises = this._withoutReactualizingFormOptions(() => {\n return $.map(this.fields, field => {\n return field.whenValid({group, force});\n });\n });\n return $.when(...promises);\n },\n\n _refreshFields: function () {\n return this.actualizeOptions()._bindFields();\n },\n\n _bindFields: function () {\n var oldFields = this.fields;\n\n this.fields = [];\n this.fieldsMappedById = {};\n\n this._withoutReactualizingFormOptions(() => {\n this.$element\n .find(this.options.inputs)\n .not(this.options.excluded)\n .each((_, element) => {\n var fieldInstance = new window.Parsley.Factory(element, {}, this);\n\n // Only add valid and not excluded `ParsleyField` and `ParsleyFieldMultiple` children\n if (('ParsleyField' === fieldInstance.__class__ || 'ParsleyFieldMultiple' === fieldInstance.__class__) && (true !== fieldInstance.options.excluded))\n if ('undefined' === typeof this.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__]) {\n this.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__] = fieldInstance;\n this.fields.push(fieldInstance);\n }\n });\n\n $(oldFields).not(this.fields).each((_, field) => {\n field._trigger('reset');\n });\n });\n return this;\n },\n\n // Internal only.\n // Looping on a form's fields to do validation or similar\n // will trigger reactualizing options on all of them, which\n // in turn will reactualize the form's options.\n // To avoid calling actualizeOptions so many times on the form\n // for nothing, _withoutReactualizingFormOptions temporarily disables\n // the method actualizeOptions on this form while `fn` is called.\n _withoutReactualizingFormOptions: function (fn) {\n var oldActualizeOptions = this.actualizeOptions;\n this.actualizeOptions = function () { return this; };\n var result = fn();\n this.actualizeOptions = oldActualizeOptions;\n return result;\n },\n\n // Internal only.\n // Shortcut to trigger an event\n // Returns true iff event is not interrupted and default not prevented.\n _trigger: function (eventName) {\n return this.trigger('form:' + eventName);\n }\n\n };\n\n var ConstraintFactory = function (parsleyField, name, requirements, priority, isDomConstraint) {\n if (!/ParsleyField/.test(parsleyField.__class__))\n throw new Error('ParsleyField or ParsleyFieldMultiple instance expected');\n\n var validatorSpec = window.Parsley._validatorRegistry.validators[name];\n var validator = new ParsleyValidator(validatorSpec);\n\n $.extend(this, {\n validator: validator,\n name: name,\n requirements: requirements,\n priority: priority || parsleyField.options[name + 'Priority'] || validator.priority,\n isDomConstraint: true === isDomConstraint\n });\n this._parseRequirements(parsleyField.options);\n };\n\n var capitalize = function(str) {\n var cap = str[0].toUpperCase();\n return cap + str.slice(1);\n };\n\n ConstraintFactory.prototype = {\n validate: function(value, instance) {\n var args = this.requirementList.slice(0); // Make copy\n args.unshift(value);\n args.push(instance);\n return this.validator.validate.apply(this.validator, args);\n },\n\n _parseRequirements: function(options) {\n this.requirementList = this.validator.parseRequirements(this.requirements, key => {\n return options[this.name + capitalize(key)];\n });\n }\n };\n\n var ParsleyField = function (field, domOptions, options, parsleyFormInstance) {\n this.__class__ = 'ParsleyField';\n this.__id__ = ParsleyUtils__default.generateID();\n\n this.$element = $(field);\n\n // Set parent if we have one\n if ('undefined' !== typeof parsleyFormInstance) {\n this.parent = parsleyFormInstance;\n }\n\n this.options = options;\n this.domOptions = domOptions;\n\n // Initialize some properties\n this.constraints = [];\n this.constraintsByName = {};\n this.validationResult = [];\n\n // Bind constraints\n this._bindConstraints();\n };\n\n var parsley_field__statusMapping = {pending: null, resolved: true, rejected: false};\n\n ParsleyField.prototype = {\n // # Public API\n // Validate field and trigger some events for mainly `ParsleyUI`\n // @returns `true`, an array of the validators that failed, or\n // `null` if validation is not finished. Prefer using whenValidate\n validate: function (options) {\n if (arguments.length >= 1 && !$.isPlainObject(options)) {\n ParsleyUtils__default.warnOnce('Calling validate on a parsley field without passing arguments as an object is deprecated.');\n options = {options};\n }\n var promise = this.whenValidate(options);\n if (!promise) // If excluded with `group` option\n return true;\n switch (promise.state()) {\n case 'pending': return null;\n case 'resolved': return true;\n case 'rejected': return this.validationResult;\n }\n },\n\n // Validate field and trigger some events for mainly `ParsleyUI`\n // @returns a promise that succeeds only when all validations do\n // or `undefined` if field is not in the given `group`.\n whenValidate: function ({force, group} = {}) {\n // do not validate a field if not the same as given validation group\n this.refreshConstraints();\n if (group && !this._isInGroup(group))\n return;\n\n this.value = this.getValue();\n\n // Field Validate event. `this.value` could be altered for custom needs\n this._trigger('validate');\n\n return this.whenValid({force, value: this.value, _refreshed: true})\n .always(() => { this._reflowUI(); })\n .done(() => { this._trigger('success'); })\n .fail(() => { this._trigger('error'); })\n .always(() => { this._trigger('validated'); });\n },\n\n hasConstraints: function () {\n return 0 !== this.constraints.length;\n },\n\n // An empty optional field does not need validation\n needsValidation: function (value) {\n if ('undefined' === typeof value)\n value = this.getValue();\n\n // If a field is empty and not required, it is valid\n // Except if `data-parsley-validate-if-empty` explicitely added, useful for some custom validators\n if (!value.length && !this._isRequired() && 'undefined' === typeof this.options.validateIfEmpty)\n return false;\n\n return true;\n },\n\n _isInGroup: function (group) {\n if ($.isArray(this.options.group))\n return -1 !== $.inArray(group, this.options.group);\n return this.options.group === group;\n },\n\n // Just validate field. Do not trigger any event.\n // Returns `true` iff all constraints pass, `false` if there are failures,\n // or `null` if the result can not be determined yet (depends on a promise)\n // See also `whenValid`.\n isValid: function (options) {\n if (arguments.length >= 1 && !$.isPlainObject(options)) {\n ParsleyUtils__default.warnOnce('Calling isValid on a parsley field without passing arguments as an object is deprecated.');\n var [force, value] = arguments;\n options = {force, value};\n }\n var promise = this.whenValid(options);\n if (!promise) // Excluded via `group`\n return true;\n return parsley_field__statusMapping[promise.state()];\n },\n\n // Just validate field. Do not trigger any event.\n // @returns a promise that succeeds only when all validations do\n // or `undefined` if the field is not in the given `group`.\n // The argument `force` will force validation of empty fields.\n // If a `value` is given, it will be validated instead of the value of the input.\n whenValid: function ({force = false, value, group, _refreshed} = {}) {\n // Recompute options and rebind constraints to have latest changes\n if (!_refreshed)\n this.refreshConstraints();\n // do not validate a field if not the same as given validation group\n if (group && !this._isInGroup(group))\n return;\n\n this.validationResult = true;\n\n // A field without constraint is valid\n if (!this.hasConstraints())\n return $.when();\n\n // Value could be passed as argument, needed to add more power to 'parsley:field:validate'\n if ('undefined' === typeof value || null === value)\n value = this.getValue();\n\n if (!this.needsValidation(value) && true !== force)\n return $.when();\n\n var groupedConstraints = this._getGroupedConstraints();\n var promises = [];\n $.each(groupedConstraints, (_, constraints) => {\n // Process one group of constraints at a time, we validate the constraints\n // and combine the promises together.\n var promise = $.when(\n ...$.map(constraints, constraint => this._validateConstraint(value, constraint))\n );\n promises.push(promise);\n if (promise.state() === 'rejected')\n return false; // Interrupt processing if a group has already failed\n });\n return $.when.apply($, promises);\n },\n\n // @returns a promise\n _validateConstraint: function(value, constraint) {\n var result = constraint.validate(value, this);\n // Map false to a failed promise\n if (false === result)\n result = $.Deferred().reject();\n // Make sure we return a promise and that we record failures\n return $.when(result).fail(errorMessage => {\n if (true === this.validationResult)\n this.validationResult = [];\n this.validationResult.push({\n assert: constraint,\n errorMessage: 'string' === typeof errorMessage && errorMessage\n });\n });\n },\n\n // @returns Parsley field computed value that could be overrided or configured in DOM\n getValue: function () {\n var value;\n\n // Value could be overriden in DOM or with explicit options\n if ('function' === typeof this.options.value)\n value = this.options.value(this);\n else if ('undefined' !== typeof this.options.value)\n value = this.options.value;\n else\n value = this.$element.val();\n\n // Handle wrong DOM or configurations\n if ('undefined' === typeof value || null === value)\n return '';\n\n return this._handleWhitespace(value);\n },\n\n // Actualize options that could have change since previous validation\n // Re-bind accordingly constraints (could be some new, removed or updated)\n refreshConstraints: function () {\n return this.actualizeOptions()._bindConstraints();\n },\n\n /**\n * Add a new constraint to a field\n *\n * @param {String} name\n * @param {Mixed} requirements optional\n * @param {Number} priority optional\n * @param {Boolean} isDomConstraint optional\n */\n addConstraint: function (name, requirements, priority, isDomConstraint) {\n\n if (window.Parsley._validatorRegistry.validators[name]) {\n var constraint = new ConstraintFactory(this, name, requirements, priority, isDomConstraint);\n\n // if constraint already exist, delete it and push new version\n if ('undefined' !== this.constraintsByName[constraint.name])\n this.removeConstraint(constraint.name);\n\n this.constraints.push(constraint);\n this.constraintsByName[constraint.name] = constraint;\n }\n\n return this;\n },\n\n // Remove a constraint\n removeConstraint: function (name) {\n for (var i = 0; i < this.constraints.length; i++)\n if (name === this.constraints[i].name) {\n this.constraints.splice(i, 1);\n break;\n }\n delete this.constraintsByName[name];\n return this;\n },\n\n // Update a constraint (Remove + re-add)\n updateConstraint: function (name, parameters, priority) {\n return this.removeConstraint(name)\n .addConstraint(name, parameters, priority);\n },\n\n // # Internals\n\n // Internal only.\n // Bind constraints from config + options + DOM\n _bindConstraints: function () {\n var constraints = [];\n var constraintsByName = {};\n\n // clean all existing DOM constraints to only keep javascript user constraints\n for (var i = 0; i < this.constraints.length; i++)\n if (false === this.constraints[i].isDomConstraint) {\n constraints.push(this.constraints[i]);\n constraintsByName[this.constraints[i].name] = this.constraints[i];\n }\n\n this.constraints = constraints;\n this.constraintsByName = constraintsByName;\n\n // then re-add Parsley DOM-API constraints\n for (var name in this.options)\n this.addConstraint(name, this.options[name], undefined, true);\n\n // finally, bind special HTML5 constraints\n return this._bindHtml5Constraints();\n },\n\n // Internal only.\n // Bind specific HTML5 constraints to be HTML5 compliant\n _bindHtml5Constraints: function () {\n // html5 required\n if (this.$element.hasClass('required') || this.$element.attr('required'))\n this.addConstraint('required', true, undefined, true);\n\n // html5 pattern\n if ('string' === typeof this.$element.attr('pattern'))\n this.addConstraint('pattern', this.$element.attr('pattern'), undefined, true);\n\n // range\n if ('undefined' !== typeof this.$element.attr('min') && 'undefined' !== typeof this.$element.attr('max'))\n this.addConstraint('range', [this.$element.attr('min'), this.$element.attr('max')], undefined, true);\n\n // HTML5 min\n else if ('undefined' !== typeof this.$element.attr('min'))\n this.addConstraint('min', this.$element.attr('min'), undefined, true);\n\n // HTML5 max\n else if ('undefined' !== typeof this.$element.attr('max'))\n this.addConstraint('max', this.$element.attr('max'), undefined, true);\n\n\n // length\n if ('undefined' !== typeof this.$element.attr('minlength') && 'undefined' !== typeof this.$element.attr('maxlength'))\n this.addConstraint('length', [this.$element.attr('minlength'), this.$element.attr('maxlength')], undefined, true);\n\n // HTML5 minlength\n else if ('undefined' !== typeof this.$element.attr('minlength'))\n this.addConstraint('minlength', this.$element.attr('minlength'), undefined, true);\n\n // HTML5 maxlength\n else if ('undefined' !== typeof this.$element.attr('maxlength'))\n this.addConstraint('maxlength', this.$element.attr('maxlength'), undefined, true);\n\n\n // html5 types\n var type = this.$element.attr('type');\n\n if ('undefined' === typeof type)\n return this;\n\n // Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise\n if ('number' === type) {\n return this.addConstraint('type', ['number', {\n step: this.$element.attr('step'),\n base: this.$element.attr('min') || this.$element.attr('value')\n }], undefined, true);\n // Regular other HTML5 supported types\n } else if (/^(email|url|range)$/i.test(type)) {\n return this.addConstraint('type', type, undefined, true);\n }\n return this;\n },\n\n // Internal only.\n // Field is required if have required constraint without `false` value\n _isRequired: function () {\n if ('undefined' === typeof this.constraintsByName.required)\n return false;\n\n return false !== this.constraintsByName.required.requirements;\n },\n\n // Internal only.\n // Shortcut to trigger an event\n _trigger: function (eventName) {\n return this.trigger('field:' + eventName);\n },\n\n // Internal only\n // Handles whitespace in a value\n // Use `data-parsley-whitespace=\"squish\"` to auto squish input value\n // Use `data-parsley-whitespace=\"trim\"` to auto trim input value\n _handleWhitespace: function (value) {\n if (true === this.options.trimValue)\n ParsleyUtils__default.warnOnce('data-parsley-trim-value=\"true\" is deprecated, please use data-parsley-whitespace=\"trim\"');\n\n if ('squish' === this.options.whitespace)\n value = value.replace(/\\s{2,}/g, ' ');\n\n if (('trim' === this.options.whitespace) || ('squish' === this.options.whitespace) || (true === this.options.trimValue))\n value = ParsleyUtils__default.trimString(value);\n\n return value;\n },\n\n // Internal only.\n // Returns the constraints, grouped by descending priority.\n // The result is thus an array of arrays of constraints.\n _getGroupedConstraints: function () {\n if (false === this.options.priorityEnabled)\n return [this.constraints];\n\n var groupedConstraints = [];\n var index = {};\n\n // Create array unique of priorities\n for (var i = 0; i < this.constraints.length; i++) {\n var p = this.constraints[i].priority;\n if (!index[p])\n groupedConstraints.push(index[p] = []);\n index[p].push(this.constraints[i]);\n }\n // Sort them by priority DESC\n groupedConstraints.sort(function (a, b) { return b[0].priority - a[0].priority; });\n\n return groupedConstraints;\n }\n\n };\n\n var parsley_field = ParsleyField;\n\n var ParsleyMultiple = function () {\n this.__class__ = 'ParsleyFieldMultiple';\n };\n\n ParsleyMultiple.prototype = {\n // Add new `$element` sibling for multiple field\n addElement: function ($element) {\n this.$elements.push($element);\n\n return this;\n },\n\n // See `ParsleyField.refreshConstraints()`\n refreshConstraints: function () {\n var fieldConstraints;\n\n this.constraints = [];\n\n // Select multiple special treatment\n if (this.$element.is('select')) {\n this.actualizeOptions()._bindConstraints();\n\n return this;\n }\n\n // Gather all constraints for each input in the multiple group\n for (var i = 0; i < this.$elements.length; i++) {\n\n // Check if element have not been dynamically removed since last binding\n if (!$('html').has(this.$elements[i]).length) {\n this.$elements.splice(i, 1);\n continue;\n }\n\n fieldConstraints = this.$elements[i].data('ParsleyFieldMultiple').refreshConstraints().constraints;\n\n for (var j = 0; j < fieldConstraints.length; j++)\n this.addConstraint(fieldConstraints[j].name, fieldConstraints[j].requirements, fieldConstraints[j].priority, fieldConstraints[j].isDomConstraint);\n }\n\n return this;\n },\n\n // See `ParsleyField.getValue()`\n getValue: function () {\n // Value could be overriden in DOM\n if ('function' === typeof this.options.value)\n value = this.options.value(this);\n else if ('undefined' !== typeof this.options.value)\n return this.options.value;\n\n // Radio input case\n if (this.$element.is('input[type=radio]'))\n return this._findRelated().filter(':checked').val() || '';\n\n // checkbox input case\n if (this.$element.is('input[type=checkbox]')) {\n var values = [];\n\n this._findRelated().filter(':checked').each(function () {\n values.push($(this).val());\n });\n\n return values;\n }\n\n // Select multiple case\n if (this.$element.is('select') && null === this.$element.val())\n return [];\n\n // Default case that should never happen\n return this.$element.val();\n },\n\n _init: function () {\n this.$elements = [this.$element];\n\n return this;\n }\n };\n\n var ParsleyFactory = function (element, options, parsleyFormInstance) {\n this.$element = $(element);\n\n // If the element has already been bound, returns its saved Parsley instance\n var savedparsleyFormInstance = this.$element.data('Parsley');\n if (savedparsleyFormInstance) {\n\n // If the saved instance has been bound without a ParsleyForm parent and there is one given in this call, add it\n if ('undefined' !== typeof parsleyFormInstance && savedparsleyFormInstance.parent === window.Parsley) {\n savedparsleyFormInstance.parent = parsleyFormInstance;\n savedparsleyFormInstance._resetOptions(savedparsleyFormInstance.options);\n }\n\n return savedparsleyFormInstance;\n }\n\n // Parsley must be instantiated with a DOM element or jQuery $element\n if (!this.$element.length)\n throw new Error('You must bind Parsley on an existing element.');\n\n if ('undefined' !== typeof parsleyFormInstance && 'ParsleyForm' !== parsleyFormInstance.__class__)\n throw new Error('Parent instance must be a ParsleyForm instance');\n\n this.parent = parsleyFormInstance || window.Parsley;\n return this.init(options);\n };\n\n ParsleyFactory.prototype = {\n init: function (options) {\n this.__class__ = 'Parsley';\n this.__version__ = '2.3.5';\n this.__id__ = ParsleyUtils__default.generateID();\n\n // Pre-compute options\n this._resetOptions(options);\n\n // A ParsleyForm instance is obviously a `<form>` element but also every node that is not an input and has the `data-parsley-validate` attribute\n if (this.$element.is('form') || (ParsleyUtils__default.checkAttr(this.$element, this.options.namespace, 'validate') && !this.$element.is(this.options.inputs)))\n return this.bind('parsleyForm');\n\n // Every other element is bound as a `ParsleyField` or `ParsleyFieldMultiple`\n return this.isMultiple() ? this.handleMultiple() : this.bind('parsleyField');\n },\n\n isMultiple: function () {\n return (this.$element.is('input[type=radio], input[type=checkbox]')) || (this.$element.is('select') && 'undefined' !== typeof this.$element.attr('multiple'));\n },\n\n // Multiples fields are a real nightmare :(\n // Maybe some refactoring would be appreciated here...\n handleMultiple: function () {\n var name;\n var multiple;\n var parsleyMultipleInstance;\n\n // Handle multiple name\n if (this.options.multiple)\n ; // We already have our 'multiple' identifier\n else if ('undefined' !== typeof this.$element.attr('name') && this.$element.attr('name').length)\n this.options.multiple = name = this.$element.attr('name');\n else if ('undefined' !== typeof this.$element.attr('id') && this.$element.attr('id').length)\n this.options.multiple = this.$element.attr('id');\n\n // Special select multiple input\n if (this.$element.is('select') && 'undefined' !== typeof this.$element.attr('multiple')) {\n this.options.multiple = this.options.multiple || this.__id__;\n return this.bind('parsleyFieldMultiple');\n\n // Else for radio / checkboxes, we need a `name` or `data-parsley-multiple` to properly bind it\n } else if (!this.options.multiple) {\n ParsleyUtils__default.warn('To be bound by Parsley, a radio, a checkbox and a multiple select input must have either a name or a multiple option.', this.$element);\n return this;\n }\n\n // Remove special chars\n this.options.multiple = this.options.multiple.replace(/(:|\\.|\\[|\\]|\\{|\\}|\\$)/g, '');\n\n // Add proper `data-parsley-multiple` to siblings if we have a valid multiple name\n if ('undefined' !== typeof name) {\n $('input[name=\"' + name + '\"]').each((i, input) => {\n if ($(input).is('input[type=radio], input[type=checkbox]'))\n $(input).attr(this.options.namespace + 'multiple', this.options.multiple);\n });\n }\n\n // Check here if we don't already have a related multiple instance saved\n var $previouslyRelated = this._findRelated();\n for (var i = 0; i < $previouslyRelated.length; i++) {\n parsleyMultipleInstance = $($previouslyRelated.get(i)).data('Parsley');\n if ('undefined' !== typeof parsleyMultipleInstance) {\n\n if (!this.$element.data('ParsleyFieldMultiple')) {\n parsleyMultipleInstance.addElement(this.$element);\n }\n\n break;\n }\n }\n\n // Create a secret ParsleyField instance for every multiple field. It will be stored in `data('ParsleyFieldMultiple')`\n // And will be useful later to access classic `ParsleyField` stuff while being in a `ParsleyFieldMultiple` instance\n this.bind('parsleyField', true);\n\n return parsleyMultipleInstance || this.bind('parsleyFieldMultiple');\n },\n\n // Return proper `ParsleyForm`, `ParsleyField` or `ParsleyFieldMultiple`\n bind: function (type, doNotStore) {\n var parsleyInstance;\n\n switch (type) {\n case 'parsleyForm':\n parsleyInstance = $.extend(\n new ParsleyForm(this.$element, this.domOptions, this.options),\n window.ParsleyExtend\n )._bindFields();\n break;\n case 'parsleyField':\n parsleyInstance = $.extend(\n new parsley_field(this.$element, this.domOptions, this.options, this.parent),\n window.ParsleyExtend\n );\n break;\n case 'parsleyFieldMultiple':\n parsleyInstance = $.extend(\n new parsley_field(this.$element, this.domOptions, this.options, this.parent),\n new ParsleyMultiple(),\n window.ParsleyExtend\n )._init();\n break;\n default:\n throw new Error(type + 'is not a supported Parsley type');\n }\n\n if (this.options.multiple)\n ParsleyUtils__default.setAttr(this.$element, this.options.namespace, 'multiple', this.options.multiple);\n\n if ('undefined' !== typeof doNotStore) {\n this.$element.data('ParsleyFieldMultiple', parsleyInstance);\n\n return parsleyInstance;\n }\n\n // Store the freshly bound instance in a DOM element for later access using jQuery `data()`\n this.$element.data('Parsley', parsleyInstance);\n\n // Tell the world we have a new ParsleyForm or ParsleyField instance!\n parsleyInstance._actualizeTriggers();\n parsleyInstance._trigger('init');\n\n return parsleyInstance;\n }\n };\n\n var vernums = $.fn.jquery.split('.');\n if (parseInt(vernums[0]) <= 1 && parseInt(vernums[1]) < 8) {\n throw \"The loaded version of jQuery is too old. Please upgrade to 1.8.x or better.\";\n }\n if (!vernums.forEach) {\n ParsleyUtils__default.warn('Parsley requires ES5 to run properly. Please include https://github.com/es-shims/es5-shim');\n }\n // Inherit `on`, `off` & `trigger` to Parsley:\n var Parsley = $.extend(new ParsleyAbstract(), {\n $element: $(document),\n actualizeOptions: null,\n _resetOptions: null,\n Factory: ParsleyFactory,\n version: '2.3.5'\n });\n\n // Supplement ParsleyField and Form with ParsleyAbstract\n // This way, the constructors will have access to those methods\n $.extend(parsley_field.prototype, ParsleyUI.Field, ParsleyAbstract.prototype);\n $.extend(ParsleyForm.prototype, ParsleyUI.Form, ParsleyAbstract.prototype);\n // Inherit actualizeOptions and _resetOptions:\n $.extend(ParsleyFactory.prototype, ParsleyAbstract.prototype);\n\n // ### jQuery API\n // `$('.elem').parsley(options)` or `$('.elem').psly(options)`\n $.fn.parsley = $.fn.psly = function (options) {\n if (this.length > 1) {\n var instances = [];\n\n this.each(function () {\n instances.push($(this).parsley(options));\n });\n\n return instances;\n }\n\n // Return undefined if applied to non existing DOM element\n if (!$(this).length) {\n ParsleyUtils__default.warn('You must bind Parsley on an existing element.');\n\n return;\n }\n\n return new ParsleyFactory(this, options);\n };\n\n // ### ParsleyField and ParsleyForm extension\n // Ensure the extension is now defined if it wasn't previously\n if ('undefined' === typeof window.ParsleyExtend)\n window.ParsleyExtend = {};\n\n // ### Parsley config\n // Inherit from ParsleyDefault, and copy over any existing values\n Parsley.options = $.extend(ParsleyUtils__default.objectCreate(ParsleyDefaults), window.ParsleyConfig);\n window.ParsleyConfig = Parsley.options; // Old way of accessing global options\n\n // ### Globals\n window.Parsley = window.psly = Parsley;\n window.ParsleyUtils = ParsleyUtils__default;\n\n // ### Define methods that forward to the registry, and deprecate all access except through window.Parsley\n var registry = window.Parsley._validatorRegistry = new ParsleyValidatorRegistry(window.ParsleyConfig.validators, window.ParsleyConfig.i18n);\n window.ParsleyValidator = {};\n $.each('setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator'.split(' '), function (i, method) {\n window.Parsley[method] = $.proxy(registry, method);\n window.ParsleyValidator[method] = function () {\n ParsleyUtils__default.warnOnce(`Accessing the method '${method}' through ParsleyValidator is deprecated. Simply call 'window.Parsley.${method}(...)'`);\n return window.Parsley[method](...arguments);\n };\n });\n\n // ### ParsleyUI\n // Deprecated global object\n window.Parsley.UI = ParsleyUI;\n window.ParsleyUI = {\n removeError: function (instance, name, doNotUpdateClass) {\n var updateClass = true !== doNotUpdateClass;\n ParsleyUtils__default.warnOnce(`Accessing ParsleyUI is deprecated. Call 'removeError' on the instance directly. Please comment in issue 1073 as to your need to call this method.`);\n return instance.removeError(name, {updateClass});\n },\n getErrorsMessages: function (instance) {\n ParsleyUtils__default.warnOnce(`Accessing ParsleyUI is deprecated. Call 'getErrorsMessages' on the instance directly.`);\n return instance.getErrorsMessages();\n }\n };\n $.each('addError updateError'.split(' '), function (i, method) {\n window.ParsleyUI[method] = function (instance, name, message, assert, doNotUpdateClass) {\n var updateClass = true !== doNotUpdateClass;\n ParsleyUtils__default.warnOnce(`Accessing ParsleyUI is deprecated. Call '${method}' on the instance directly. Please comment in issue 1073 as to your need to call this method.`);\n return instance[method](name, {message, assert, updateClass});\n };\n });\n\n // Alleviate glaring Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=1250521\n // See also https://github.com/guillaumepotier/Parsley.js/issues/1068\n if (/firefox/i.test(navigator.userAgent)) {\n $(document).on('change', 'select', evt => {\n $(evt.target).trigger('input');\n });\n }\n\n // ### PARSLEY auto-binding\n // Prevent it by setting `ParsleyConfig.autoBind` to `false`\n if (false !== window.ParsleyConfig.autoBind) {\n $(function () {\n // Works only on `data-parsley-validate`.\n if ($('[data-parsley-validate]').length)\n $('[data-parsley-validate]').parsley();\n });\n }\n\n var o = $({});\n var deprecated = function () {\n ParsleyUtils__default.warnOnce(\"Parsley's pubsub module is deprecated; use the 'on' and 'off' methods on parsley instances or window.Parsley\");\n };\n\n // Returns an event handler that calls `fn` with the arguments it expects\n function adapt(fn, context) {\n // Store to allow unbinding\n if (!fn.parsleyAdaptedCallback) {\n fn.parsleyAdaptedCallback = function () {\n var args = Array.prototype.slice.call(arguments, 0);\n args.unshift(this);\n fn.apply(context || o, args);\n };\n }\n return fn.parsleyAdaptedCallback;\n }\n\n var eventPrefix = 'parsley:';\n // Converts 'parsley:form:validate' into 'form:validate'\n function eventName(name) {\n if (name.lastIndexOf(eventPrefix, 0) === 0)\n return name.substr(eventPrefix.length);\n return name;\n }\n\n // $.listen is deprecated. Use Parsley.on instead.\n $.listen = function (name, callback) {\n var context;\n deprecated();\n if ('object' === typeof arguments[1] && 'function' === typeof arguments[2]) {\n context = arguments[1];\n callback = arguments[2];\n }\n\n if ('function' !== typeof callback)\n throw new Error('Wrong parameters');\n\n window.Parsley.on(eventName(name), adapt(callback, context));\n };\n\n $.listenTo = function (instance, name, fn) {\n deprecated();\n if (!(instance instanceof parsley_field) && !(instance instanceof ParsleyForm))\n throw new Error('Must give Parsley instance');\n\n if ('string' !== typeof name || 'function' !== typeof fn)\n throw new Error('Wrong parameters');\n\n instance.on(eventName(name), adapt(fn));\n };\n\n $.unsubscribe = function (name, fn) {\n deprecated();\n if ('string' !== typeof name || 'function' !== typeof fn)\n throw new Error('Wrong arguments');\n window.Parsley.off(eventName(name), fn.parsleyAdaptedCallback);\n };\n\n $.unsubscribeTo = function (instance, name) {\n deprecated();\n if (!(instance instanceof parsley_field) && !(instance instanceof ParsleyForm))\n throw new Error('Must give Parsley instance');\n instance.off(eventName(name));\n };\n\n $.unsubscribeAll = function (name) {\n deprecated();\n window.Parsley.off(eventName(name));\n $('form,input,textarea,select').each(function () {\n var instance = $(this).data('Parsley');\n if (instance) {\n instance.off(eventName(name));\n }\n });\n };\n\n // $.emit is deprecated. Use jQuery events instead.\n $.emit = function (name, instance) {\n deprecated();\n var instanceGiven = (instance instanceof parsley_field) || (instance instanceof ParsleyForm);\n var args = Array.prototype.slice.call(arguments, instanceGiven ? 2 : 1);\n args.unshift(eventName(name));\n if (!instanceGiven) {\n instance = window.Parsley;\n }\n instance.trigger(...args);\n };\n\n var pubsub = {};\n\n $.extend(true, Parsley, {\n asyncValidators: {\n 'default': {\n fn: function (xhr) {\n // By default, only status 2xx are deemed successful.\n // Note: we use status instead of state() because responses with status 200\n // but invalid messages (e.g. an empty body for content type set to JSON) will\n // result in state() === 'rejected'.\n return xhr.status >= 200 && xhr.status < 300;\n },\n url: false\n },\n reverse: {\n fn: function (xhr) {\n // If reverse option is set, a failing ajax request is considered successful\n return xhr.status < 200 || xhr.status >= 300;\n },\n url: false\n }\n },\n\n addAsyncValidator: function (name, fn, url, options) {\n Parsley.asyncValidators[name] = {\n fn: fn,\n url: url || false,\n options: options || {}\n };\n\n return this;\n }\n\n });\n\n Parsley.addValidator('remote', {\n requirementType: {\n '': 'string',\n 'validator': 'string',\n 'reverse': 'boolean',\n 'options': 'object'\n },\n\n validateString: function (value, url, options, instance) {\n var data = {};\n var ajaxOptions;\n var csr;\n var validator = options.validator || (true === options.reverse ? 'reverse' : 'default');\n\n if ('undefined' === typeof Parsley.asyncValidators[validator])\n throw new Error('Calling an undefined async validator: `' + validator + '`');\n\n url = Parsley.asyncValidators[validator].url || url;\n\n // Fill current value\n if (url.indexOf('{value}') > -1) {\n url = url.replace('{value}', encodeURIComponent(value));\n } else {\n data[instance.$element.attr('name') || instance.$element.attr('id')] = value;\n }\n\n // Merge options passed in from the function with the ones in the attribute\n var remoteOptions = $.extend(true, options.options || {} , Parsley.asyncValidators[validator].options);\n\n // All `$.ajax(options)` could be overridden or extended directly from DOM in `data-parsley-remote-options`\n ajaxOptions = $.extend(true, {}, {\n url: url,\n data: data,\n type: 'GET'\n }, remoteOptions);\n\n // Generate store key based on ajax options\n instance.trigger('field:ajaxoptions', instance, ajaxOptions);\n\n csr = $.param(ajaxOptions);\n\n // Initialise querry cache\n if ('undefined' === typeof Parsley._remoteCache)\n Parsley._remoteCache = {};\n\n // Try to retrieve stored xhr\n var xhr = Parsley._remoteCache[csr] = Parsley._remoteCache[csr] || $.ajax(ajaxOptions);\n\n var handleXhr = function () {\n var result = Parsley.asyncValidators[validator].fn.call(instance, xhr, url, options);\n if (!result) // Map falsy results to rejected promise\n result = $.Deferred().reject();\n return $.when(result);\n };\n\n return xhr.then(handleXhr, handleXhr);\n },\n\n priority: -1\n });\n\n Parsley.on('form:submit', function () {\n Parsley._remoteCache = {};\n });\n\n window.ParsleyExtend.addAsyncValidator = function () {\n ParsleyUtils.warnOnce('Accessing the method `addAsyncValidator` through an instance is deprecated. Simply call `Parsley.addAsyncValidator(...)`');\n return Parsley.addAsyncValidator(...arguments);\n };\n\n // This is included with the Parsley library itself,\n // thus there is no use in adding it to your project.\n Parsley.addMessages('en', {\n defaultMessage: \"This value seems to be invalid.\",\n type: {\n email: \"This value should be a valid email.\",\n url: \"This value should be a valid url.\",\n number: \"This value should be a valid number.\",\n integer: \"This value should be a valid integer.\",\n digits: \"This value should be digits.\",\n alphanum: \"This value should be alphanumeric.\"\n },\n notblank: \"This value should not be blank.\",\n required: \"This value is required.\",\n pattern: \"This value seems to be invalid.\",\n min: \"This value should be greater than or equal to %s.\",\n max: \"This value should be lower than or equal to %s.\",\n range: \"This value should be between %s and %s.\",\n minlength: \"This value is too short. It should have %s characters or more.\",\n maxlength: \"This value is too long. It should have %s characters or fewer.\",\n length: \"This value length is invalid. It should be between %s and %s characters long.\",\n mincheck: \"You must select at least %s choices.\",\n maxcheck: \"You must select %s choices or fewer.\",\n check: \"You must select between %s and %s choices.\",\n equalto: \"This value should be the same.\"\n });\n\n Parsley.setLocale('en');\n\n var parsley = Parsley;\n\n return parsley;\n\n}));\n","import $ from 'jquery';\nimport ParsleyField from './field';\nimport ParsleyForm from './form';\nimport ParsleyUtils from './utils';\n\nvar o = $({});\nvar deprecated = function () {\n ParsleyUtils.warnOnce(\"Parsley's pubsub module is deprecated; use the 'on' and 'off' methods on parsley instances or window.Parsley\");\n};\n\n// Returns an event handler that calls `fn` with the arguments it expects\nfunction adapt(fn, context) {\n // Store to allow unbinding\n if (!fn.parsleyAdaptedCallback) {\n fn.parsleyAdaptedCallback = function () {\n var args = Array.prototype.slice.call(arguments, 0);\n args.unshift(this);\n fn.apply(context || o, args);\n };\n }\n return fn.parsleyAdaptedCallback;\n}\n\nvar eventPrefix = 'parsley:';\n// Converts 'parsley:form:validate' into 'form:validate'\nfunction eventName(name) {\n if (name.lastIndexOf(eventPrefix, 0) === 0)\n return name.substr(eventPrefix.length);\n return name;\n}\n\n// $.listen is deprecated. Use Parsley.on instead.\n$.listen = function (name, callback) {\n var context;\n deprecated();\n if ('object' === typeof arguments[1] && 'function' === typeof arguments[2]) {\n context = arguments[1];\n callback = arguments[2];\n }\n\n if ('function' !== typeof callback)\n throw new Error('Wrong parameters');\n\n window.Parsley.on(eventName(name), adapt(callback, context));\n};\n\n$.listenTo = function (instance, name, fn) {\n deprecated();\n if (!(instance instanceof ParsleyField) && !(instance instanceof ParsleyForm))\n throw new Error('Must give Parsley instance');\n\n if ('string' !== typeof name || 'function' !== typeof fn)\n throw new Error('Wrong parameters');\n\n instance.on(eventName(name), adapt(fn));\n};\n\n$.unsubscribe = function (name, fn) {\n deprecated();\n if ('string' !== typeof name || 'function' !== typeof fn)\n throw new Error('Wrong arguments');\n window.Parsley.off(eventName(name), fn.parsleyAdaptedCallback);\n};\n\n$.unsubscribeTo = function (instance, name) {\n deprecated();\n if (!(instance instanceof ParsleyField) && !(instance instanceof ParsleyForm))\n throw new Error('Must give Parsley instance');\n instance.off(eventName(name));\n};\n\n$.unsubscribeAll = function (name) {\n deprecated();\n window.Parsley.off(eventName(name));\n $('form,input,textarea,select').each(function () {\n var instance = $(this).data('Parsley');\n if (instance) {\n instance.off(eventName(name));\n }\n });\n};\n\n// $.emit is deprecated. Use jQuery events instead.\n$.emit = function (name, instance) {\n deprecated();\n var instanceGiven = (instance instanceof ParsleyField) || (instance instanceof ParsleyForm);\n var args = Array.prototype.slice.call(arguments, instanceGiven ? 2 : 1);\n args.unshift(eventName(name));\n if (!instanceGiven) {\n instance = window.Parsley;\n }\n instance.trigger(...args);\n};\n\nexport default {};\n","import $ from 'jquery';\n\nvar globalID = 1;\nvar pastWarnings = {};\n\nvar ParsleyUtils = {\n // Parsley DOM-API\n // returns object from dom attributes and values\n attr: function ($element, namespace, obj) {\n var i;\n var attribute;\n var attributes;\n var regex = new RegExp('^' + namespace, 'i');\n\n if ('undefined' === typeof obj)\n obj = {};\n else {\n // Clear all own properties. This won't affect prototype's values\n for (i in obj) {\n if (obj.hasOwnProperty(i))\n delete obj[i];\n }\n }\n\n if ('undefined' === typeof $element || 'undefined' === typeof $element[0])\n return obj;\n\n attributes = $element[0].attributes;\n for (i = attributes.length; i--; ) {\n attribute = attributes[i];\n\n if (attribute && attribute.specified && regex.test(attribute.name)) {\n obj[this.camelize(attribute.name.slice(namespace.length))] = this.deserializeValue(attribute.value);\n }\n }\n\n return obj;\n },\n\n checkAttr: function ($element, namespace, checkAttr) {\n return $element.is('[' + namespace + checkAttr + ']');\n },\n\n setAttr: function ($element, namespace, attr, value) {\n $element[0].setAttribute(this.dasherize(namespace + attr), String(value));\n },\n\n generateID: function () {\n return '' + globalID++;\n },\n\n /** Third party functions **/\n // Zepto deserialize function\n deserializeValue: function (value) {\n var num;\n\n try {\n return value ?\n value == \"true\" ||\n (value == \"false\" ? false :\n value == \"null\" ? null :\n !isNaN(num = Number(value)) ? num :\n /^[\\[\\{]/.test(value) ? $.parseJSON(value) :\n value)\n : value;\n } catch (e) { return value; }\n },\n\n // Zepto camelize function\n camelize: function (str) {\n return str.replace(/-+(.)?/g, function (match, chr) {\n return chr ? chr.toUpperCase() : '';\n });\n },\n\n // Zepto dasherize function\n dasherize: function (str) {\n return str.replace(/::/g, '/')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')\n .replace(/([a-z\\d])([A-Z])/g, '$1_$2')\n .replace(/_/g, '-')\n .toLowerCase();\n },\n\n warn: function () {\n if (window.console && 'function' === typeof window.console.warn)\n window.console.warn(...arguments);\n },\n\n warnOnce: function(msg) {\n if (!pastWarnings[msg]) {\n pastWarnings[msg] = true;\n this.warn(...arguments);\n }\n },\n\n _resetWarnings: function () {\n pastWarnings = {};\n },\n\n trimString: function(string) {\n return string.replace(/^\\s+|\\s+$/g, '');\n },\n\n namespaceEvents: function(events, namespace) {\n events = this.trimString(events || '').split(/\\s+/);\n if (!events[0])\n return '';\n return $.map(events, evt => { return `${evt}.${namespace}`; }).join(' ');\n },\n\n // Object.create polyfill, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create#Polyfill\n objectCreate: Object.create || (function () {\n var Object = function () {};\n return function (prototype) {\n if (arguments.length > 1) {\n throw Error('Second argument not supported');\n }\n if (typeof prototype != 'object') {\n throw TypeError('Argument must be an object');\n }\n Object.prototype = prototype;\n var result = new Object();\n Object.prototype = null;\n return result;\n };\n })()\n};\n\nexport default ParsleyUtils;\n","// All these options could be overriden and specified directly in DOM using\n// `data-parsley-` default DOM-API\n// eg: `inputs` can be set in DOM using `data-parsley-inputs=\"input, textarea\"`\n// eg: `data-parsley-stop-on-first-failing-constraint=\"false\"`\n\nvar ParsleyDefaults = {\n // ### General\n\n // Default data-namespace for DOM API\n namespace: 'data-parsley-',\n\n // Supported inputs by default\n inputs: 'input, textarea, select',\n\n // Excluded inputs by default\n excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden]',\n\n // Stop validating field on highest priority failing constraint\n priorityEnabled: true,\n\n // ### Field only\n\n // identifier used to group together inputs (e.g. radio buttons...)\n multiple: null,\n\n // identifier (or array of identifiers) used to validate only a select group of inputs\n group: null,\n\n // ### UI\n // Enable\\Disable error messages\n uiEnabled: true,\n\n // Key events threshold before validation\n validationThreshold: 3,\n\n // Focused field on form validation error. 'first'|'last'|'none'\n focus: 'first',\n\n // event(s) that will trigger validation before first failure. eg: `input`...\n trigger: false,\n\n // event(s) that will trigger validation after first failure.\n triggerAfterFailure: 'input',\n\n // Class that would be added on every failing validation Parsley field\n errorClass: 'parsley-error',\n\n // Same for success validation\n successClass: 'parsley-success',\n\n // Return the `$element` that will receive these above success or error classes\n // Could also be (and given directly from DOM) a valid selector like `'#div'`\n classHandler: function (ParsleyField) {},\n\n // Return the `$element` where errors will be appended\n // Could also be (and given directly from DOM) a valid selector like `'#div'`\n errorsContainer: function (ParsleyField) {},\n\n // ul elem that would receive errors' list\n errorsWrapper: '<ul class=\"parsley-errors-list\"></ul>',\n\n // li elem that would receive error message\n errorTemplate: '<li></li>'\n};\n\nexport default ParsleyDefaults;\n","import $ from 'jquery';\nimport ParsleyUtils from './utils';\n\nvar ParsleyAbstract = function () {};\n\nParsleyAbstract.prototype = {\n asyncSupport: true, // Deprecated\n\n actualizeOptions: function () {\n ParsleyUtils.attr(this.$element, this.options.namespace, this.domOptions);\n if (this.parent && this.parent.actualizeOptions)\n this.parent.actualizeOptions();\n return this;\n },\n\n _resetOptions: function (initOptions) {\n this.domOptions = ParsleyUtils.objectCreate(this.parent.options);\n this.options = ParsleyUtils.objectCreate(this.domOptions);\n // Shallow copy of ownProperties of initOptions:\n for (var i in initOptions) {\n if (initOptions.hasOwnProperty(i))\n this.options[i] = initOptions[i];\n }\n this.actualizeOptions();\n },\n\n _listeners: null,\n\n // Register a callback for the given event name\n // Callback is called with context as the first argument and the `this`\n // The context is the current parsley instance, or window.Parsley if global\n // A return value of `false` will interrupt the calls\n on: function (name, fn) {\n this._listeners = this._listeners || {};\n var queue = this._listeners[name] = this._listeners[name] || [];\n queue.push(fn);\n\n return this;\n },\n\n // Deprecated. Use `on` instead\n subscribe: function(name, fn) {\n $.listenTo(this, name.toLowerCase(), fn);\n },\n\n // Unregister a callback (or all if none is given) for the given event name\n off: function (name, fn) {\n var queue = this._listeners && this._listeners[name];\n if (queue) {\n if (!fn) {\n delete this._listeners[name];\n } else {\n for (var i = queue.length; i--; )\n if (queue[i] === fn)\n queue.splice(i, 1);\n }\n }\n return this;\n },\n\n // Deprecated. Use `off`\n unsubscribe: function(name, fn) {\n $.unsubscribeTo(this, name.toLowerCase());\n },\n\n // Trigger an event of the given name\n // A return value of `false` interrupts the callback chain\n // Returns false if execution was interrupted\n trigger: function (name, target, extraArg) {\n target = target || this;\n var queue = this._listeners && this._listeners[name];\n var result;\n var parentResult;\n if (queue) {\n for (var i = queue.length; i--; ) {\n result = queue[i].call(target, target, extraArg);\n if (result === false) return result;\n }\n }\n if (this.parent) {\n return this.parent.trigger(name, target, extraArg);\n }\n return true;\n },\n\n // Reset UI\n reset: function () {\n // Field case: just emit a reset event for UI\n if ('ParsleyForm' !== this.__class__) {\n this._resetUI();\n return this._trigger('reset');\n }\n\n // Form case: emit a reset event for each field\n for (var i = 0; i < this.fields.length; i++)\n this.fields[i].reset();\n\n this._trigger('reset');\n },\n\n // Destroy Parsley instance (+ UI)\n destroy: function () {\n // Field case: emit destroy event to clean UI and then destroy stored instance\n this._destroyUI();\n if ('ParsleyForm' !== this.__class__) {\n this.$element.removeData('Parsley');\n this.$element.removeData('ParsleyFieldMultiple');\n this._trigger('destroy');\n\n return;\n }\n\n // Form case: destroy all its fields and then destroy stored instance\n for (var i = 0; i < this.fields.length; i++)\n this.fields[i].destroy();\n\n this.$element.removeData('Parsley');\n this._trigger('destroy');\n },\n\n asyncIsValid: function (group, force) {\n ParsleyUtils.warnOnce(\"asyncIsValid is deprecated; please use whenValid instead\");\n return this.whenValid({group, force});\n },\n\n _findRelated: function () {\n return this.options.multiple ?\n this.parent.$element.find(`[${this.options.namespace}multiple=\"${this.options.multiple}\"]`)\n : this.$element;\n }\n};\n\nexport default ParsleyAbstract;\n","import $ from 'jquery';\nimport ParsleyUtils from './utils';\n\nvar requirementConverters = {\n string: function(string) {\n return string;\n },\n integer: function(string) {\n if (isNaN(string))\n throw 'Requirement is not an integer: \"' + string + '\"';\n return parseInt(string, 10);\n },\n number: function(string) {\n if (isNaN(string))\n throw 'Requirement is not a number: \"' + string + '\"';\n return parseFloat(string);\n },\n reference: function(string) { // Unused for now\n var result = $(string);\n if (result.length === 0)\n throw 'No such reference: \"' + string + '\"';\n return result;\n },\n boolean: function(string) {\n return string !== 'false';\n },\n object: function(string) {\n return ParsleyUtils.deserializeValue(string);\n },\n regexp: function(regexp) {\n var flags = '';\n\n // Test if RegExp is literal, if not, nothing to be done, otherwise, we need to isolate flags and pattern\n if (/^\\/.*\\/(?:[gimy]*)$/.test(regexp)) {\n // Replace the regexp literal string with the first match group: ([gimy]*)\n // If no flag is present, this will be a blank string\n flags = regexp.replace(/.*\\/([gimy]*)$/, '$1');\n // Again, replace the regexp literal string with the first match group:\n // everything excluding the opening and closing slashes and the flags\n regexp = regexp.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1');\n } else {\n // Anchor regexp:\n regexp = '^' + regexp + '$';\n }\n return new RegExp(regexp, flags);\n }\n};\n\nvar convertArrayRequirement = function(string, length) {\n var m = string.match(/^\\s*\\[(.*)\\]\\s*$/);\n if (!m)\n throw 'Requirement is not an array: \"' + string + '\"';\n var values = m[1].split(',').map(ParsleyUtils.trimString);\n if (values.length !== length)\n throw 'Requirement has ' + values.length + ' values when ' + length + ' are needed';\n return values;\n};\n\nvar convertRequirement = function(requirementType, string) {\n var converter = requirementConverters[requirementType || 'string'];\n if (!converter)\n throw 'Unknown requirement specification: \"' + requirementType + '\"';\n return converter(string);\n};\n\nvar convertExtraOptionRequirement = function(requirementSpec, string, extraOptionReader) {\n var main = null;\n var extra = {};\n for (var key in requirementSpec) {\n if (key) {\n var value = extraOptionReader(key);\n if ('string' === typeof value)\n value = convertRequirement(requirementSpec[key], value);\n extra[key] = value;\n } else {\n main = convertRequirement(requirementSpec[key], string);\n }\n }\n return [main, extra];\n};\n\n// A Validator needs to implement the methods `validate` and `parseRequirements`\n\nvar ParsleyValidator = function(spec) {\n $.extend(true, this, spec);\n};\n\nParsleyValidator.prototype = {\n // Returns `true` iff the given `value` is valid according the given requirements.\n validate: function(value, requirementFirstArg) {\n if (this.fn) { // Legacy style validator\n\n if (arguments.length > 3) // If more args then value, requirement, instance...\n requirementFirstArg = [].slice.call(arguments, 1, -1); // Skip first arg (value) and last (instance), combining the rest\n return this.fn.call(this, value, requirementFirstArg);\n }\n\n if ($.isArray(value)) {\n if (!this.validateMultiple)\n throw 'Validator `' + this.name + '` does not handle multiple values';\n return this.validateMultiple(...arguments);\n } else {\n if (this.validateNumber) {\n if (isNaN(value))\n return false;\n arguments[0] = parseFloat(arguments[0]);\n return this.validateNumber(...arguments);\n }\n if (this.validateString) {\n return this.validateString(...arguments);\n }\n throw 'Validator `' + this.name + '` only handles multiple values';\n }\n },\n\n // Parses `requirements` into an array of arguments,\n // according to `this.requirementType`\n parseRequirements: function(requirements, extraOptionReader) {\n if ('string' !== typeof requirements) {\n // Assume requirement already parsed\n // but make sure we return an array\n return $.isArray(requirements) ? requirements : [requirements];\n }\n var type = this.requirementType;\n if ($.isArray(type)) {\n var values = convertArrayRequirement(requirements, type.length);\n for (var i = 0; i < values.length; i++)\n values[i] = convertRequirement(type[i], values[i]);\n return values;\n } else if ($.isPlainObject(type)) {\n return convertExtraOptionRequirement(type, requirements, extraOptionReader);\n } else {\n return [convertRequirement(type, requirements)];\n }\n },\n // Defaults:\n requirementType: 'string',\n\n priority: 2\n\n};\n\nexport default ParsleyValidator;\n","import $ from 'jquery';\nimport ParsleyUtils from './utils';\nimport ParsleyDefaults from './defaults';\nimport ParsleyValidator from './validator';\n\nvar ParsleyValidatorRegistry = function (validators, catalog) {\n this.__class__ = 'ParsleyValidatorRegistry';\n\n // Default Parsley locale is en\n this.locale = 'en';\n\n this.init(validators || {}, catalog || {});\n};\n\nvar typeRegexes = {\n email: /^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))$/i,\n\n // Follow https://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers\n number: /^-?(\\d*\\.)?\\d+(e[-+]?\\d+)?$/i,\n\n integer: /^-?\\d+$/,\n\n digits: /^\\d+$/,\n\n alphanum: /^\\w+$/i,\n\n url: new RegExp(\n \"^\" +\n // protocol identifier\n \"(?:(?:https?|ftp)://)?\" + // ** mod: make scheme optional\n // user:pass authentication\n \"(?:\\\\S+(?::\\\\S*)?@)?\" +\n \"(?:\" +\n // IP address exclusion\n // private & local networks\n // \"(?!(?:10|127)(?:\\\\.\\\\d{1,3}){3})\" + // ** mod: allow local networks\n // \"(?!(?:169\\\\.254|192\\\\.168)(?:\\\\.\\\\d{1,3}){2})\" + // ** mod: allow local networks\n // \"(?!172\\\\.(?:1[6-9]|2\\\\d|3[0-1])(?:\\\\.\\\\d{1,3}){2})\" + // ** mod: allow local networks\n // IP address dotted notation octets\n // excludes loopback network 0.0.0.0\n // excludes reserved space >= 224.0.0.0\n // excludes network & broacast addresses\n // (first & last IP address of each class)\n \"(?:[1-9]\\\\d?|1\\\\d\\\\d|2[01]\\\\d|22[0-3])\" +\n \"(?:\\\\.(?:1?\\\\d{1,2}|2[0-4]\\\\d|25[0-5])){2}\" +\n \"(?:\\\\.(?:[1-9]\\\\d?|1\\\\d\\\\d|2[0-4]\\\\d|25[0-4]))\" +\n \"|\" +\n // host name\n \"(?:(?:[a-z\\\\u00a1-\\\\uffff0-9]-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)\" +\n // domain name\n \"(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff0-9]-*)*[a-z\\\\u00a1-\\\\uffff0-9]+)*\" +\n // TLD identifier\n \"(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff]{2,}))\" +\n \")\" +\n // port number\n \"(?::\\\\d{2,5})?\" +\n // resource path\n \"(?:/\\\\S*)?\" +\n \"$\", 'i'\n )\n};\ntypeRegexes.range = typeRegexes.number;\n\n// See http://stackoverflow.com/a/10454560/8279\nvar decimalPlaces = num => {\n var match = ('' + num).match(/(?:\\.(\\d+))?(?:[eE]([+-]?\\d+))?$/);\n if (!match) { return 0; }\n return Math.max(\n 0,\n // Number of digits right of decimal point.\n (match[1] ? match[1].length : 0) -\n // Adjust for scientific notation.\n (match[2] ? +match[2] : 0));\n};\n\nParsleyValidatorRegistry.prototype = {\n init: function (validators, catalog) {\n this.catalog = catalog;\n // Copy prototype's validators:\n this.validators = $.extend({}, this.validators);\n\n for (var name in validators)\n this.addValidator(name, validators[name].fn, validators[name].priority);\n\n window.Parsley.trigger('parsley:validator:init');\n },\n\n // Set new messages locale if we have dictionary loaded in ParsleyConfig.i18n\n setLocale: function (locale) {\n if ('undefined' === typeof this.catalog[locale])\n throw new Error(locale + ' is not available in the catalog');\n\n this.locale = locale;\n\n return this;\n },\n\n // Add a new messages catalog for a given locale. Set locale for this catalog if set === `true`\n addCatalog: function (locale, messages, set) {\n if ('object' === typeof messages)\n this.catalog[locale] = messages;\n\n if (true === set)\n return this.setLocale(locale);\n\n return this;\n },\n\n // Add a specific message for a given constraint in a given locale\n addMessage: function (locale, name, message) {\n if ('undefined' === typeof this.catalog[locale])\n this.catalog[locale] = {};\n\n this.catalog[locale][name] = message;\n\n return this;\n },\n\n // Add messages for a given locale\n addMessages: function (locale, nameMessageObject) {\n for (var name in nameMessageObject)\n this.addMessage(locale, name, nameMessageObject[name]);\n\n return this;\n },\n\n // Add a new validator\n //\n // addValidator('custom', {\n // requirementType: ['integer', 'integer'],\n // validateString: function(value, from, to) {},\n // priority: 22,\n // messages: {\n // en: \"Hey, that's no good\",\n // fr: \"Aye aye, pas bon du tout\",\n // }\n // })\n //\n // Old API was addValidator(name, function, priority)\n //\n addValidator: function (name, arg1, arg2) {\n if (this.validators[name])\n ParsleyUtils.warn('Validator \"' + name + '\" is already defined.');\n else if (ParsleyDefaults.hasOwnProperty(name)) {\n ParsleyUtils.warn('\"' + name + '\" is a restricted keyword and is not a valid validator name.');\n return;\n }\n return this._setValidator(...arguments);\n },\n\n updateValidator: function (name, arg1, arg2) {\n if (!this.validators[name]) {\n ParsleyUtils.warn('Validator \"' + name + '\" is not already defined.');\n return this.addValidator(...arguments);\n }\n return this._setValidator(this, arguments);\n },\n\n removeValidator: function (name) {\n if (!this.validators[name])\n ParsleyUtils.warn('Validator \"' + name + '\" is not defined.');\n\n delete this.validators[name];\n\n return this;\n },\n\n _setValidator: function (name, validator, priority) {\n if ('object' !== typeof validator) {\n // Old style validator, with `fn` and `priority`\n validator = {\n fn: validator,\n priority: priority\n };\n }\n if (!validator.validate) {\n validator = new ParsleyValidator(validator);\n }\n this.validators[name] = validator;\n\n for (var locale in validator.messages || {})\n this.addMessage(locale, name, validator.messages[locale]);\n\n return this;\n },\n\n getErrorMessage: function (constraint) {\n var message;\n\n // Type constraints are a bit different, we have to match their requirements too to find right error message\n if ('type' === constraint.name) {\n var typeMessages = this.catalog[this.locale][constraint.name] || {};\n message = typeMessages[constraint.requirements];\n } else\n message = this.formatMessage(this.catalog[this.locale][constraint.name], constraint.requirements);\n\n return message || this.catalog[this.locale].defaultMessage || this.catalog.en.defaultMessage;\n },\n\n // Kind of light `sprintf()` implementation\n formatMessage: function (string, parameters) {\n if ('object' === typeof parameters) {\n for (var i in parameters)\n string = this.formatMessage(string, parameters[i]);\n\n return string;\n }\n\n return 'string' === typeof string ? string.replace(/%s/i, parameters) : '';\n },\n\n // Here is the Parsley default validators list.\n // A validator is an object with the following key values:\n // - priority: an integer\n // - requirement: 'string' (default), 'integer', 'number', 'regexp' or an Array of these\n // - validateString, validateMultiple, validateNumber: functions returning `true`, `false` or a promise\n // Alternatively, a validator can be a function that returns such an object\n //\n validators: {\n notblank: {\n validateString: function(value) {\n return /\\S/.test(value);\n },\n priority: 2\n },\n required: {\n validateMultiple: function(values) {\n return values.length > 0;\n },\n validateString: function(value) {\n return /\\S/.test(value);\n },\n priority: 512\n },\n type: {\n validateString: function(value, type, {step = '1', base = 0} = {}) {\n var regex = typeRegexes[type];\n if (!regex) {\n throw new Error('validator type `' + type + '` is not supported');\n }\n if (!regex.test(value))\n return false;\n if ('number' === type) {\n if (!/^any$/i.test(step || '')) {\n var nb = Number(value);\n var decimals = Math.max(decimalPlaces(step), decimalPlaces(base));\n if (decimalPlaces(nb) > decimals) // Value can't have too many decimals\n return false;\n // Be careful of rounding errors by using integers.\n var toInt = f => { return Math.round(f * Math.pow(10, decimals)); };\n if ((toInt(nb) - toInt(base)) % toInt(step) != 0)\n return false;\n }\n }\n return true;\n },\n requirementType: {\n '': 'string',\n step: 'string',\n base: 'number'\n },\n priority: 256\n },\n pattern: {\n validateString: function(value, regexp) {\n return regexp.test(value);\n },\n requirementType: 'regexp',\n priority: 64\n },\n minlength: {\n validateString: function (value, requirement) {\n return value.length >= requirement;\n },\n requirementType: 'integer',\n priority: 30\n },\n maxlength: {\n validateString: function (value, requirement) {\n return value.length <= requirement;\n },\n requirementType: 'integer',\n priority: 30\n },\n length: {\n validateString: function (value, min, max) {\n return value.length >= min && value.length <= max;\n },\n requirementType: ['integer', 'integer'],\n priority: 30\n },\n mincheck: {\n validateMultiple: function (values, requirement) {\n return values.length >= requirement;\n },\n requirementType: 'integer',\n priority: 30\n },\n maxcheck: {\n validateMultiple: function (values, requirement) {\n return values.length <= requirement;\n },\n requirementType: 'integer',\n priority: 30\n },\n check: {\n validateMultiple: function (values, min, max) {\n return values.length >= min && values.length <= max;\n },\n requirementType: ['integer', 'integer'],\n priority: 30\n },\n min: {\n validateNumber: function (value, requirement) {\n return value >= requirement;\n },\n requirementType: 'number',\n priority: 30\n },\n max: {\n validateNumber: function (value, requirement) {\n return value <= requirement;\n },\n requirementType: 'number',\n priority: 30\n },\n range: {\n validateNumber: function (value, min, max) {\n return value >= min && value <= max;\n },\n requirementType: ['number', 'number'],\n priority: 30\n },\n equalto: {\n validateString: function (value, refOrValue) {\n var $reference = $(refOrValue);\n if ($reference.length)\n return value === $reference.val();\n else\n return value === refOrValue;\n },\n priority: 256\n }\n }\n};\n\nexport default ParsleyValidatorRegistry;\n","import $ from 'jquery';\nimport ParsleyUtils from './utils';\n\nvar ParsleyUI = {};\n\nvar diffResults = function (newResult, oldResult, deep) {\n var added = [];\n var kept = [];\n\n for (var i = 0; i < newResult.length; i++) {\n var found = false;\n\n for (var j = 0; j < oldResult.length; j++)\n if (newResult[i].assert.name === oldResult[j].assert.name) {\n found = true;\n break;\n }\n\n if (found)\n kept.push(newResult[i]);\n else\n added.push(newResult[i]);\n }\n\n return {\n kept: kept,\n added: added,\n removed: !deep ? diffResults(oldResult, newResult, true).added : []\n };\n};\n\nParsleyUI.Form = {\n\n _actualizeTriggers: function () {\n this.$element.on('submit.Parsley', evt => { this.onSubmitValidate(evt); });\n this.$element.on('click.Parsley', 'input[type=\"submit\"], button[type=\"submit\"]', evt => { this.onSubmitButton(evt); });\n\n // UI could be disabled\n if (false === this.options.uiEnabled)\n return;\n\n this.$element.attr('novalidate', '');\n },\n\n focus: function () {\n this._focusedField = null;\n\n if (true === this.validationResult || 'none' === this.options.focus)\n return null;\n\n for (var i = 0; i < this.fields.length; i++) {\n var field = this.fields[i];\n if (true !== field.validationResult && field.validationResult.length > 0 && 'undefined' === typeof field.options.noFocus) {\n this._focusedField = field.$element;\n if ('first' === this.options.focus)\n break;\n }\n }\n\n if (null === this._focusedField)\n return null;\n\n return this._focusedField.focus();\n },\n\n _destroyUI: function () {\n // Reset all event listeners\n this.$element.off('.Parsley');\n }\n\n};\n\nParsleyUI.Field = {\n\n _reflowUI: function () {\n this._buildUI();\n\n // If this field doesn't have an active UI don't bother doing something\n if (!this._ui)\n return;\n\n // Diff between two validation results\n var diff = diffResults(this.validationResult, this._ui.lastValidationResult);\n\n // Then store current validation result for next reflow\n this._ui.lastValidationResult = this.validationResult;\n\n // Handle valid / invalid / none field class\n this._manageStatusClass();\n\n // Add, remove, updated errors messages\n this._manageErrorsMessages(diff);\n\n // Triggers impl\n this._actualizeTriggers();\n\n // If field is not valid for the first time, bind keyup trigger to ease UX and quickly inform user\n if ((diff.kept.length || diff.added.length) && !this._failedOnce) {\n this._failedOnce = true;\n this._actualizeTriggers();\n }\n },\n\n // Returns an array of field's error message(s)\n getErrorsMessages: function () {\n // No error message, field is valid\n if (true === this.validationResult)\n return [];\n\n var messages = [];\n\n for (var i = 0; i < this.validationResult.length; i++)\n messages.push(this.validationResult[i].errorMessage ||\n this._getErrorMessage(this.validationResult[i].assert));\n\n return messages;\n },\n\n // It's a goal of Parsley that this method is no longer required [#1073]\n addError: function (name, {message, assert, updateClass = true} = {}) {\n this._buildUI();\n this._addError(name, {message, assert});\n\n if (updateClass)\n this._errorClass();\n },\n\n // It's a goal of Parsley that this method is no longer required [#1073]\n updateError: function (name, {message, assert, updateClass = true} = {}) {\n this._buildUI();\n this._updateError(name, {message, assert});\n\n if (updateClass)\n this._errorClass();\n },\n\n // It's a goal of Parsley that this method is no longer required [#1073]\n removeError: function (name, {updateClass = true} = {}) {\n this._buildUI();\n this._removeError(name);\n\n // edge case possible here: remove a standard Parsley error that is still failing in this.validationResult\n // but highly improbable cuz' manually removing a well Parsley handled error makes no sense.\n if (updateClass)\n this._manageStatusClass();\n },\n\n _manageStatusClass: function () {\n if (this.hasConstraints() && this.needsValidation() && true === this.validationResult)\n this._successClass();\n else if (this.validationResult.length > 0)\n this._errorClass();\n else\n this._resetClass();\n },\n\n _manageErrorsMessages: function (diff) {\n if ('undefined' !== typeof this.options.errorsMessagesDisabled)\n return;\n\n // Case where we have errorMessage option that configure an unique field error message, regardless failing validators\n if ('undefined' !== typeof this.options.errorMessage) {\n if ((diff.added.length || diff.kept.length)) {\n this._insertErrorWrapper();\n\n if (0 === this._ui.$errorsWrapper.find('.parsley-custom-error-message').length)\n this._ui.$errorsWrapper\n .append(\n $(this.options.errorTemplate)\n .addClass('parsley-custom-error-message')\n );\n\n return this._ui.$errorsWrapper\n .addClass('filled')\n .find('.parsley-custom-error-message')\n .html(this.options.errorMessage);\n }\n\n return this._ui.$errorsWrapper\n .removeClass('filled')\n .find('.parsley-custom-error-message')\n .remove();\n }\n\n // Show, hide, update failing constraints messages\n for (var i = 0; i < diff.removed.length; i++)\n this._removeError(diff.removed[i].assert.name);\n\n for (i = 0; i < diff.added.length; i++)\n this._addError(diff.added[i].assert.name, {message: diff.added[i].errorMessage, assert: diff.added[i].assert});\n\n for (i = 0; i < diff.kept.length; i++)\n this._updateError(diff.kept[i].assert.name, {message: diff.kept[i].errorMessage, assert: diff.kept[i].assert});\n },\n\n\n _addError: function (name, {message, assert}) {\n this._insertErrorWrapper();\n this._ui.$errorsWrapper\n .addClass('filled')\n .append(\n $(this.options.errorTemplate)\n .addClass('parsley-' + name)\n .html(message || this._getErrorMessage(assert))\n );\n },\n\n _updateError: function (name, {message, assert}) {\n this._ui.$errorsWrapper\n .addClass('filled')\n .find('.parsley-' + name)\n .html(message || this._getErrorMessage(assert));\n },\n\n _removeError: function (name) {\n this._ui.$errorsWrapper\n .removeClass('filled')\n .find('.parsley-' + name)\n .remove();\n },\n\n _getErrorMessage: function (constraint) {\n var customConstraintErrorMessage = constraint.name + 'Message';\n\n if ('undefined' !== typeof this.options[customConstraintErrorMessage])\n return window.Parsley.formatMessage(this.options[customConstraintErrorMessage], constraint.requirements);\n\n return window.Parsley.getErrorMessage(constraint);\n },\n\n _buildUI: function () {\n // UI could be already built or disabled\n if (this._ui || false === this.options.uiEnabled)\n return;\n\n var _ui = {};\n\n // Give field its Parsley id in DOM\n this.$element.attr(this.options.namespace + 'id', this.__id__);\n\n /** Generate important UI elements and store them in this **/\n // $errorClassHandler is the $element that woul have parsley-error and parsley-success classes\n _ui.$errorClassHandler = this._manageClassHandler();\n\n // $errorsWrapper is a div that would contain the various field errors, it will be appended into $errorsContainer\n _ui.errorsWrapperId = 'parsley-id-' + (this.options.multiple ? 'multiple-' + this.options.multiple : this.__id__);\n _ui.$errorsWrapper = $(this.options.errorsWrapper).attr('id', _ui.errorsWrapperId);\n\n // ValidationResult UI storage to detect what have changed bwt two validations, and update DOM accordingly\n _ui.lastValidationResult = [];\n _ui.validationInformationVisible = false;\n\n // Store it in this for later\n this._ui = _ui;\n },\n\n // Determine which element will have `parsley-error` and `parsley-success` classes\n _manageClassHandler: function () {\n // An element selector could be passed through DOM with `data-parsley-class-handler=#foo`\n if ('string' === typeof this.options.classHandler && $(this.options.classHandler).length)\n return $(this.options.classHandler);\n\n // Class handled could also be determined by function given in Parsley options\n var $handler = this.options.classHandler.call(this, this);\n\n // If this function returned a valid existing DOM element, go for it\n if ('undefined' !== typeof $handler && $handler.length)\n return $handler;\n\n // Otherwise, if simple element (input, texatrea, select...) it will perfectly host the classes\n if (!this.options.multiple || this.$element.is('select'))\n return this.$element;\n\n // But if multiple element (radio, checkbox), that would be their parent\n return this.$element.parent();\n },\n\n _insertErrorWrapper: function () {\n var $errorsContainer;\n\n // Nothing to do if already inserted\n if (0 !== this._ui.$errorsWrapper.parent().length)\n return this._ui.$errorsWrapper.parent();\n\n if ('string' === typeof this.options.errorsContainer) {\n if ($(this.options.errorsContainer).length)\n return $(this.options.errorsContainer).append(this._ui.$errorsWrapper);\n else\n ParsleyUtils.warn('The errors container `' + this.options.errorsContainer + '` does not exist in DOM');\n } else if ('function' === typeof this.options.errorsContainer)\n $errorsContainer = this.options.errorsContainer.call(this, this);\n\n if ('undefined' !== typeof $errorsContainer && $errorsContainer.length)\n return $errorsContainer.append(this._ui.$errorsWrapper);\n\n var $from = this.$element;\n if (this.options.multiple)\n $from = $from.parent();\n return $from.after(this._ui.$errorsWrapper);\n },\n\n _actualizeTriggers: function () {\n var $toBind = this._findRelated();\n\n // Remove Parsley events already bound on this field\n $toBind.off('.Parsley');\n if (this._failedOnce)\n $toBind.on(ParsleyUtils.namespaceEvents(this.options.triggerAfterFailure, 'Parsley'), () => {\n this.validate();\n });\n else {\n $toBind.on(ParsleyUtils.namespaceEvents(this.options.trigger, 'Parsley'), event => {\n this._eventValidate(event);\n });\n }\n },\n\n _eventValidate: function (event) {\n // For keyup, keypress, keydown, input... events that could be a little bit obstrusive\n // do not validate if val length < min threshold on first validation. Once field have been validated once and info\n // about success or failure have been displayed, always validate with this trigger to reflect every yalidation change.\n if (/key|input/.test(event.type))\n if (!(this._ui && this._ui.validationInformationVisible) && this.getValue().length <= this.options.validationThreshold)\n return;\n\n this.validate();\n },\n\n _resetUI: function () {\n // Reset all event listeners\n this._failedOnce = false;\n this._actualizeTriggers();\n\n // Nothing to do if UI never initialized for this field\n if ('undefined' === typeof this._ui)\n return;\n\n // Reset all errors' li\n this._ui.$errorsWrapper\n .removeClass('filled')\n .children()\n .remove();\n\n // Reset validation class\n this._resetClass();\n\n // Reset validation flags and last validation result\n this._ui.lastValidationResult = [];\n this._ui.validationInformationVisible = false;\n },\n\n _destroyUI: function () {\n this._resetUI();\n\n if ('undefined' !== typeof this._ui)\n this._ui.$errorsWrapper.remove();\n\n delete this._ui;\n },\n\n _successClass: function () {\n this._ui.validationInformationVisible = true;\n this._ui.$errorClassHandler.removeClass(this.options.errorClass).addClass(this.options.successClass);\n },\n _errorClass: function () {\n this._ui.validationInformationVisible = true;\n this._ui.$errorClassHandler.removeClass(this.options.successClass).addClass(this.options.errorClass);\n },\n _resetClass: function () {\n this._ui.$errorClassHandler.removeClass(this.options.successClass).removeClass(this.options.errorClass);\n }\n};\n\nexport default ParsleyUI;\n","import $ from 'jquery';\nimport ParsleyAbstract from './abstract';\nimport ParsleyUtils from './utils';\n\nvar ParsleyForm = function (element, domOptions, options) {\n this.__class__ = 'ParsleyForm';\n this.__id__ = ParsleyUtils.generateID();\n\n this.$element = $(element);\n this.domOptions = domOptions;\n this.options = options;\n this.parent = window.Parsley;\n\n this.fields = [];\n this.validationResult = null;\n};\n\nvar statusMapping = {pending: null, resolved: true, rejected: false};\n\nParsleyForm.prototype = {\n onSubmitValidate: function (event) {\n // This is a Parsley generated submit event, do not validate, do not prevent, simply exit and keep normal behavior\n if (true === event.parsley)\n return;\n\n // If we didn't come here through a submit button, use the first one in the form\n var $submitSource = this._$submitSource || this.$element.find('input[type=\"submit\"], button[type=\"submit\"]').first();\n this._$submitSource = null;\n this.$element.find('.parsley-synthetic-submit-button').prop('disabled', true);\n if ($submitSource.is('[formnovalidate]'))\n return;\n\n var promise = this.whenValidate({event});\n\n if ('resolved' === promise.state() && false !== this._trigger('submit')) {\n // All good, let event go through. We make this distinction because browsers\n // differ in their handling of `submit` being called from inside a submit event [#1047]\n } else {\n // Rejected or pending: cancel this submit\n event.stopImmediatePropagation();\n event.preventDefault();\n if ('pending' === promise.state())\n promise.done(() => { this._submit($submitSource); });\n }\n },\n\n onSubmitButton: function(event) {\n this._$submitSource = $(event.target);\n },\n // internal\n // _submit submits the form, this time without going through the validations.\n // Care must be taken to \"fake\" the actual submit button being clicked.\n _submit: function ($submitSource) {\n if (false === this._trigger('submit'))\n return;\n // Add submit button's data\n if ($submitSource) {\n var $synthetic = this.$element.find('.parsley-synthetic-submit-button').prop('disabled', false);\n if (0 === $synthetic.length)\n $synthetic = $('<input class=\"parsley-synthetic-submit-button\" type=\"hidden\">').appendTo(this.$element);\n $synthetic.attr({\n name: $submitSource.attr('name'),\n value: $submitSource.attr('value')\n });\n }\n\n this.$element.trigger($.extend($.Event('submit'), {parsley: true}));\n },\n\n // Performs validation on fields while triggering events.\n // @returns `true` if all validations succeeds, `false`\n // if a failure is immediately detected, or `null`\n // if dependant on a promise.\n // Consider using `whenValidate` instead.\n validate: function (options) {\n if (arguments.length >= 1 && !$.isPlainObject(options)) {\n ParsleyUtils.warnOnce('Calling validate on a parsley form without passing arguments as an object is deprecated.');\n var [group, force, event] = arguments;\n options = {group, force, event};\n }\n return statusMapping[ this.whenValidate(options).state() ];\n },\n\n whenValidate: function ({group, force, event} = {}) {\n this.submitEvent = event;\n if (event) {\n this.submitEvent = $.extend({}, event, {preventDefault: () => {\n ParsleyUtils.warnOnce(\"Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`\");\n this.validationResult = false;\n }});\n }\n this.validationResult = true;\n\n // fire validate event to eventually modify things before very validation\n this._trigger('validate');\n\n // Refresh form DOM options and form's fields that could have changed\n this._refreshFields();\n\n var promises = this._withoutReactualizingFormOptions(() => {\n return $.map(this.fields, field => {\n return field.whenValidate({force, group});\n });\n });\n\n var promiseBasedOnValidationResult = () => {\n var r = $.Deferred();\n if (false === this.validationResult)\n r.reject();\n return r.resolve().promise();\n };\n\n return $.when(...promises)\n .done( () => { this._trigger('success'); })\n .fail( () => {\n this.validationResult = false;\n this.focus();\n this._trigger('error');\n })\n .always(() => { this._trigger('validated'); })\n .pipe( promiseBasedOnValidationResult, promiseBasedOnValidationResult);\n },\n\n // Iterate over refreshed fields, and stop on first failure.\n // Returns `true` if all fields are valid, `false` if a failure is detected\n // or `null` if the result depends on an unresolved promise.\n // Prefer using `whenValid` instead.\n isValid: function (options) {\n if (arguments.length >= 1 && !$.isPlainObject(options)) {\n ParsleyUtils.warnOnce('Calling isValid on a parsley form without passing arguments as an object is deprecated.');\n var [group, force] = arguments;\n options = {group, force};\n }\n return statusMapping[ this.whenValid(options).state() ];\n },\n\n // Iterate over refreshed fields and validate them.\n // Returns a promise.\n // A validation that immediately fails will interrupt the validations.\n whenValid: function ({group, force} = {}) {\n this._refreshFields();\n\n var promises = this._withoutReactualizingFormOptions(() => {\n return $.map(this.fields, field => {\n return field.whenValid({group, force});\n });\n });\n return $.when(...promises);\n },\n\n _refreshFields: function () {\n return this.actualizeOptions()._bindFields();\n },\n\n _bindFields: function () {\n var oldFields = this.fields;\n\n this.fields = [];\n this.fieldsMappedById = {};\n\n this._withoutReactualizingFormOptions(() => {\n this.$element\n .find(this.options.inputs)\n .not(this.options.excluded)\n .each((_, element) => {\n var fieldInstance = new window.Parsley.Factory(element, {}, this);\n\n // Only add valid and not excluded `ParsleyField` and `ParsleyFieldMultiple` children\n if (('ParsleyField' === fieldInstance.__class__ || 'ParsleyFieldMultiple' === fieldInstance.__class__) && (true !== fieldInstance.options.excluded))\n if ('undefined' === typeof this.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__]) {\n this.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__] = fieldInstance;\n this.fields.push(fieldInstance);\n }\n });\n\n $(oldFields).not(this.fields).each((_, field) => {\n field._trigger('reset');\n });\n });\n return this;\n },\n\n // Internal only.\n // Looping on a form's fields to do validation or similar\n // will trigger reactualizing options on all of them, which\n // in turn will reactualize the form's options.\n // To avoid calling actualizeOptions so many times on the form\n // for nothing, _withoutReactualizingFormOptions temporarily disables\n // the method actualizeOptions on this form while `fn` is called.\n _withoutReactualizingFormOptions: function (fn) {\n var oldActualizeOptions = this.actualizeOptions;\n this.actualizeOptions = function () { return this; };\n var result = fn();\n this.actualizeOptions = oldActualizeOptions;\n return result;\n },\n\n // Internal only.\n // Shortcut to trigger an event\n // Returns true iff event is not interrupted and default not prevented.\n _trigger: function (eventName) {\n return this.trigger('form:' + eventName);\n }\n\n};\n\nexport default ParsleyForm;\n","import $ from 'jquery';\nimport ParsleyUtils from '../utils';\nimport ParsleyValidator from '../validator';\n\n\nvar ConstraintFactory = function (parsleyField, name, requirements, priority, isDomConstraint) {\n if (!/ParsleyField/.test(parsleyField.__class__))\n throw new Error('ParsleyField or ParsleyFieldMultiple instance expected');\n\n var validatorSpec = window.Parsley._validatorRegistry.validators[name];\n var validator = new ParsleyValidator(validatorSpec);\n\n $.extend(this, {\n validator: validator,\n name: name,\n requirements: requirements,\n priority: priority || parsleyField.options[name + 'Priority'] || validator.priority,\n isDomConstraint: true === isDomConstraint\n });\n this._parseRequirements(parsleyField.options);\n};\n\nvar capitalize = function(str) {\n var cap = str[0].toUpperCase();\n return cap + str.slice(1);\n};\n\nConstraintFactory.prototype = {\n validate: function(value, instance) {\n var args = this.requirementList.slice(0); // Make copy\n args.unshift(value);\n args.push(instance);\n return this.validator.validate.apply(this.validator, args);\n },\n\n _parseRequirements: function(options) {\n this.requirementList = this.validator.parseRequirements(this.requirements, key => {\n return options[this.name + capitalize(key)];\n });\n }\n};\n\nexport default ConstraintFactory;\n\n","import $ from 'jquery';\nimport ConstraintFactory from './factory/constraint';\nimport ParsleyUI from './ui';\nimport ParsleyUtils from './utils';\n\nvar ParsleyField = function (field, domOptions, options, parsleyFormInstance) {\n this.__class__ = 'ParsleyField';\n this.__id__ = ParsleyUtils.generateID();\n\n this.$element = $(field);\n\n // Set parent if we have one\n if ('undefined' !== typeof parsleyFormInstance) {\n this.parent = parsleyFormInstance;\n }\n\n this.options = options;\n this.domOptions = domOptions;\n\n // Initialize some properties\n this.constraints = [];\n this.constraintsByName = {};\n this.validationResult = [];\n\n // Bind constraints\n this._bindConstraints();\n};\n\nvar statusMapping = {pending: null, resolved: true, rejected: false};\n\nParsleyField.prototype = {\n // # Public API\n // Validate field and trigger some events for mainly `ParsleyUI`\n // @returns `true`, an array of the validators that failed, or\n // `null` if validation is not finished. Prefer using whenValidate\n validate: function (options) {\n if (arguments.length >= 1 && !$.isPlainObject(options)) {\n ParsleyUtils.warnOnce('Calling validate on a parsley field without passing arguments as an object is deprecated.');\n options = {options};\n }\n var promise = this.whenValidate(options);\n if (!promise) // If excluded with `group` option\n return true;\n switch (promise.state()) {\n case 'pending': return null;\n case 'resolved': return true;\n case 'rejected': return this.validationResult;\n }\n },\n\n // Validate field and trigger some events for mainly `ParsleyUI`\n // @returns a promise that succeeds only when all validations do\n // or `undefined` if field is not in the given `group`.\n whenValidate: function ({force, group} = {}) {\n // do not validate a field if not the same as given validation group\n this.refreshConstraints();\n if (group && !this._isInGroup(group))\n return;\n\n this.value = this.getValue();\n\n // Field Validate event. `this.value` could be altered for custom needs\n this._trigger('validate');\n\n return this.whenValid({force, value: this.value, _refreshed: true})\n .always(() => { this._reflowUI(); })\n .done(() => { this._trigger('success'); })\n .fail(() => { this._trigger('error'); })\n .always(() => { this._trigger('validated'); });\n },\n\n hasConstraints: function () {\n return 0 !== this.constraints.length;\n },\n\n // An empty optional field does not need validation\n needsValidation: function (value) {\n if ('undefined' === typeof value)\n value = this.getValue();\n\n // If a field is empty and not required, it is valid\n // Except if `data-parsley-validate-if-empty` explicitely added, useful for some custom validators\n if (!value.length && !this._isRequired() && 'undefined' === typeof this.options.validateIfEmpty)\n return false;\n\n return true;\n },\n\n _isInGroup: function (group) {\n if ($.isArray(this.options.group))\n return -1 !== $.inArray(group, this.options.group);\n return this.options.group === group;\n },\n\n // Just validate field. Do not trigger any event.\n // Returns `true` iff all constraints pass, `false` if there are failures,\n // or `null` if the result can not be determined yet (depends on a promise)\n // See also `whenValid`.\n isValid: function (options) {\n if (arguments.length >= 1 && !$.isPlainObject(options)) {\n ParsleyUtils.warnOnce('Calling isValid on a parsley field without passing arguments as an object is deprecated.');\n var [force, value] = arguments;\n options = {force, value};\n }\n var promise = this.whenValid(options);\n if (!promise) // Excluded via `group`\n return true;\n return statusMapping[promise.state()];\n },\n\n // Just validate field. Do not trigger any event.\n // @returns a promise that succeeds only when all validations do\n // or `undefined` if the field is not in the given `group`.\n // The argument `force` will force validation of empty fields.\n // If a `value` is given, it will be validated instead of the value of the input.\n whenValid: function ({force = false, value, group, _refreshed} = {}) {\n // Recompute options and rebind constraints to have latest changes\n if (!_refreshed)\n this.refreshConstraints();\n // do not validate a field if not the same as given validation group\n if (group && !this._isInGroup(group))\n return;\n\n this.validationResult = true;\n\n // A field without constraint is valid\n if (!this.hasConstraints())\n return $.when();\n\n // Value could be passed as argument, needed to add more power to 'parsley:field:validate'\n if ('undefined' === typeof value || null === value)\n value = this.getValue();\n\n if (!this.needsValidation(value) && true !== force)\n return $.when();\n\n var groupedConstraints = this._getGroupedConstraints();\n var promises = [];\n $.each(groupedConstraints, (_, constraints) => {\n // Process one group of constraints at a time, we validate the constraints\n // and combine the promises together.\n var promise = $.when(\n ...$.map(constraints, constraint => this._validateConstraint(value, constraint))\n );\n promises.push(promise);\n if (promise.state() === 'rejected')\n return false; // Interrupt processing if a group has already failed\n });\n return $.when.apply($, promises);\n },\n\n // @returns a promise\n _validateConstraint: function(value, constraint) {\n var result = constraint.validate(value, this);\n // Map false to a failed promise\n if (false === result)\n result = $.Deferred().reject();\n // Make sure we return a promise and that we record failures\n return $.when(result).fail(errorMessage => {\n if (true === this.validationResult)\n this.validationResult = [];\n this.validationResult.push({\n assert: constraint,\n errorMessage: 'string' === typeof errorMessage && errorMessage\n });\n });\n },\n\n // @returns Parsley field computed value that could be overrided or configured in DOM\n getValue: function () {\n var value;\n\n // Value could be overriden in DOM or with explicit options\n if ('function' === typeof this.options.value)\n value = this.options.value(this);\n else if ('undefined' !== typeof this.options.value)\n value = this.options.value;\n else\n value = this.$element.val();\n\n // Handle wrong DOM or configurations\n if ('undefined' === typeof value || null === value)\n return '';\n\n return this._handleWhitespace(value);\n },\n\n // Actualize options that could have change since previous validation\n // Re-bind accordingly constraints (could be some new, removed or updated)\n refreshConstraints: function () {\n return this.actualizeOptions()._bindConstraints();\n },\n\n /**\n * Add a new constraint to a field\n *\n * @param {String} name\n * @param {Mixed} requirements optional\n * @param {Number} priority optional\n * @param {Boolean} isDomConstraint optional\n */\n addConstraint: function (name, requirements, priority, isDomConstraint) {\n\n if (window.Parsley._validatorRegistry.validators[name]) {\n var constraint = new ConstraintFactory(this, name, requirements, priority, isDomConstraint);\n\n // if constraint already exist, delete it and push new version\n if ('undefined' !== this.constraintsByName[constraint.name])\n this.removeConstraint(constraint.name);\n\n this.constraints.push(constraint);\n this.constraintsByName[constraint.name] = constraint;\n }\n\n return this;\n },\n\n // Remove a constraint\n removeConstraint: function (name) {\n for (var i = 0; i < this.constraints.length; i++)\n if (name === this.constraints[i].name) {\n this.constraints.splice(i, 1);\n break;\n }\n delete this.constraintsByName[name];\n return this;\n },\n\n // Update a constraint (Remove + re-add)\n updateConstraint: function (name, parameters, priority) {\n return this.removeConstraint(name)\n .addConstraint(name, parameters, priority);\n },\n\n // # Internals\n\n // Internal only.\n // Bind constraints from config + options + DOM\n _bindConstraints: function () {\n var constraints = [];\n var constraintsByName = {};\n\n // clean all existing DOM constraints to only keep javascript user constraints\n for (var i = 0; i < this.constraints.length; i++)\n if (false === this.constraints[i].isDomConstraint) {\n constraints.push(this.constraints[i]);\n constraintsByName[this.constraints[i].name] = this.constraints[i];\n }\n\n this.constraints = constraints;\n this.constraintsByName = constraintsByName;\n\n // then re-add Parsley DOM-API constraints\n for (var name in this.options)\n this.addConstraint(name, this.options[name], undefined, true);\n\n // finally, bind special HTML5 constraints\n return this._bindHtml5Constraints();\n },\n\n // Internal only.\n // Bind specific HTML5 constraints to be HTML5 compliant\n _bindHtml5Constraints: function () {\n // html5 required\n if (this.$element.hasClass('required') || this.$element.attr('required'))\n this.addConstraint('required', true, undefined, true);\n\n // html5 pattern\n if ('string' === typeof this.$element.attr('pattern'))\n this.addConstraint('pattern', this.$element.attr('pattern'), undefined, true);\n\n // range\n if ('undefined' !== typeof this.$element.attr('min') && 'undefined' !== typeof this.$element.attr('max'))\n this.addConstraint('range', [this.$element.attr('min'), this.$element.attr('max')], undefined, true);\n\n // HTML5 min\n else if ('undefined' !== typeof this.$element.attr('min'))\n this.addConstraint('min', this.$element.attr('min'), undefined, true);\n\n // HTML5 max\n else if ('undefined' !== typeof this.$element.attr('max'))\n this.addConstraint('max', this.$element.attr('max'), undefined, true);\n\n\n // length\n if ('undefined' !== typeof this.$element.attr('minlength') && 'undefined' !== typeof this.$element.attr('maxlength'))\n this.addConstraint('length', [this.$element.attr('minlength'), this.$element.attr('maxlength')], undefined, true);\n\n // HTML5 minlength\n else if ('undefined' !== typeof this.$element.attr('minlength'))\n this.addConstraint('minlength', this.$element.attr('minlength'), undefined, true);\n\n // HTML5 maxlength\n else if ('undefined' !== typeof this.$element.attr('maxlength'))\n this.addConstraint('maxlength', this.$element.attr('maxlength'), undefined, true);\n\n\n // html5 types\n var type = this.$element.attr('type');\n\n if ('undefined' === typeof type)\n return this;\n\n // Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise\n if ('number' === type) {\n return this.addConstraint('type', ['number', {\n step: this.$element.attr('step'),\n base: this.$element.attr('min') || this.$element.attr('value')\n }], undefined, true);\n // Regular other HTML5 supported types\n } else if (/^(email|url|range)$/i.test(type)) {\n return this.addConstraint('type', type, undefined, true);\n }\n return this;\n },\n\n // Internal only.\n // Field is required if have required constraint without `false` value\n _isRequired: function () {\n if ('undefined' === typeof this.constraintsByName.required)\n return false;\n\n return false !== this.constraintsByName.required.requirements;\n },\n\n // Internal only.\n // Shortcut to trigger an event\n _trigger: function (eventName) {\n return this.trigger('field:' + eventName);\n },\n\n // Internal only\n // Handles whitespace in a value\n // Use `data-parsley-whitespace=\"squish\"` to auto squish input value\n // Use `data-parsley-whitespace=\"trim\"` to auto trim input value\n _handleWhitespace: function (value) {\n if (true === this.options.trimValue)\n ParsleyUtils.warnOnce('data-parsley-trim-value=\"true\" is deprecated, please use data-parsley-whitespace=\"trim\"');\n\n if ('squish' === this.options.whitespace)\n value = value.replace(/\\s{2,}/g, ' ');\n\n if (('trim' === this.options.whitespace) || ('squish' === this.options.whitespace) || (true === this.options.trimValue))\n value = ParsleyUtils.trimString(value);\n\n return value;\n },\n\n // Internal only.\n // Returns the constraints, grouped by descending priority.\n // The result is thus an array of arrays of constraints.\n _getGroupedConstraints: function () {\n if (false === this.options.priorityEnabled)\n return [this.constraints];\n\n var groupedConstraints = [];\n var index = {};\n\n // Create array unique of priorities\n for (var i = 0; i < this.constraints.length; i++) {\n var p = this.constraints[i].priority;\n if (!index[p])\n groupedConstraints.push(index[p] = []);\n index[p].push(this.constraints[i]);\n }\n // Sort them by priority DESC\n groupedConstraints.sort(function (a, b) { return b[0].priority - a[0].priority; });\n\n return groupedConstraints;\n }\n\n};\n\nexport default ParsleyField;\n","import $ from 'jquery';\n\nvar ParsleyMultiple = function () {\n this.__class__ = 'ParsleyFieldMultiple';\n};\n\nParsleyMultiple.prototype = {\n // Add new `$element` sibling for multiple field\n addElement: function ($element) {\n this.$elements.push($element);\n\n return this;\n },\n\n // See `ParsleyField.refreshConstraints()`\n refreshConstraints: function () {\n var fieldConstraints;\n\n this.constraints = [];\n\n // Select multiple special treatment\n if (this.$element.is('select')) {\n this.actualizeOptions()._bindConstraints();\n\n return this;\n }\n\n // Gather all constraints for each input in the multiple group\n for (var i = 0; i < this.$elements.length; i++) {\n\n // Check if element have not been dynamically removed since last binding\n if (!$('html').has(this.$elements[i]).length) {\n this.$elements.splice(i, 1);\n continue;\n }\n\n fieldConstraints = this.$elements[i].data('ParsleyFieldMultiple').refreshConstraints().constraints;\n\n for (var j = 0; j < fieldConstraints.length; j++)\n this.addConstraint(fieldConstraints[j].name, fieldConstraints[j].requirements, fieldConstraints[j].priority, fieldConstraints[j].isDomConstraint);\n }\n\n return this;\n },\n\n // See `ParsleyField.getValue()`\n getValue: function () {\n // Value could be overriden in DOM\n if ('function' === typeof this.options.value)\n value = this.options.value(this);\n else if ('undefined' !== typeof this.options.value)\n return this.options.value;\n\n // Radio input case\n if (this.$element.is('input[type=radio]'))\n return this._findRelated().filter(':checked').val() || '';\n\n // checkbox input case\n if (this.$element.is('input[type=checkbox]')) {\n var values = [];\n\n this._findRelated().filter(':checked').each(function () {\n values.push($(this).val());\n });\n\n return values;\n }\n\n // Select multiple case\n if (this.$element.is('select') && null === this.$element.val())\n return [];\n\n // Default case that should never happen\n return this.$element.val();\n },\n\n _init: function () {\n this.$elements = [this.$element];\n\n return this;\n }\n};\n\nexport default ParsleyMultiple;\n","import $ from 'jquery';\nimport ParsleyUtils from './utils';\nimport ParsleyAbstract from './abstract';\nimport ParsleyForm from './form';\nimport ParsleyField from './field';\nimport ParsleyMultiple from './multiple';\n\nvar ParsleyFactory = function (element, options, parsleyFormInstance) {\n this.$element = $(element);\n\n // If the element has already been bound, returns its saved Parsley instance\n var savedparsleyFormInstance = this.$element.data('Parsley');\n if (savedparsleyFormInstance) {\n\n // If the saved instance has been bound without a ParsleyForm parent and there is one given in this call, add it\n if ('undefined' !== typeof parsleyFormInstance && savedparsleyFormInstance.parent === window.Parsley) {\n savedparsleyFormInstance.parent = parsleyFormInstance;\n savedparsleyFormInstance._resetOptions(savedparsleyFormInstance.options);\n }\n\n return savedparsleyFormInstance;\n }\n\n // Parsley must be instantiated with a DOM element or jQuery $element\n if (!this.$element.length)\n throw new Error('You must bind Parsley on an existing element.');\n\n if ('undefined' !== typeof parsleyFormInstance && 'ParsleyForm' !== parsleyFormInstance.__class__)\n throw new Error('Parent instance must be a ParsleyForm instance');\n\n this.parent = parsleyFormInstance || window.Parsley;\n return this.init(options);\n};\n\nParsleyFactory.prototype = {\n init: function (options) {\n this.__class__ = 'Parsley';\n this.__version__ = '@@version';\n this.__id__ = ParsleyUtils.generateID();\n\n // Pre-compute options\n this._resetOptions(options);\n\n // A ParsleyForm instance is obviously a `<form>` element but also every node that is not an input and has the `data-parsley-validate` attribute\n if (this.$element.is('form') || (ParsleyUtils.checkAttr(this.$element, this.options.namespace, 'validate') && !this.$element.is(this.options.inputs)))\n return this.bind('parsleyForm');\n\n // Every other element is bound as a `ParsleyField` or `ParsleyFieldMultiple`\n return this.isMultiple() ? this.handleMultiple() : this.bind('parsleyField');\n },\n\n isMultiple: function () {\n return (this.$element.is('input[type=radio], input[type=checkbox]')) || (this.$element.is('select') && 'undefined' !== typeof this.$element.attr('multiple'));\n },\n\n // Multiples fields are a real nightmare :(\n // Maybe some refactoring would be appreciated here...\n handleMultiple: function () {\n var name;\n var multiple;\n var parsleyMultipleInstance;\n\n // Handle multiple name\n if (this.options.multiple)\n ; // We already have our 'multiple' identifier\n else if ('undefined' !== typeof this.$element.attr('name') && this.$element.attr('name').length)\n this.options.multiple = name = this.$element.attr('name');\n else if ('undefined' !== typeof this.$element.attr('id') && this.$element.attr('id').length)\n this.options.multiple = this.$element.attr('id');\n\n // Special select multiple input\n if (this.$element.is('select') && 'undefined' !== typeof this.$element.attr('multiple')) {\n this.options.multiple = this.options.multiple || this.__id__;\n return this.bind('parsleyFieldMultiple');\n\n // Else for radio / checkboxes, we need a `name` or `data-parsley-multiple` to properly bind it\n } else if (!this.options.multiple) {\n ParsleyUtils.warn('To be bound by Parsley, a radio, a checkbox and a multiple select input must have either a name or a multiple option.', this.$element);\n return this;\n }\n\n // Remove special chars\n this.options.multiple = this.options.multiple.replace(/(:|\\.|\\[|\\]|\\{|\\}|\\$)/g, '');\n\n // Add proper `data-parsley-multiple` to siblings if we have a valid multiple name\n if ('undefined' !== typeof name) {\n $('input[name=\"' + name + '\"]').each((i, input) => {\n if ($(input).is('input[type=radio], input[type=checkbox]'))\n $(input).attr(this.options.namespace + 'multiple', this.options.multiple);\n });\n }\n\n // Check here if we don't already have a related multiple instance saved\n var $previouslyRelated = this._findRelated();\n for (var i = 0; i < $previouslyRelated.length; i++) {\n parsleyMultipleInstance = $($previouslyRelated.get(i)).data('Parsley');\n if ('undefined' !== typeof parsleyMultipleInstance) {\n\n if (!this.$element.data('ParsleyFieldMultiple')) {\n parsleyMultipleInstance.addElement(this.$element);\n }\n\n break;\n }\n }\n\n // Create a secret ParsleyField instance for every multiple field. It will be stored in `data('ParsleyFieldMultiple')`\n // And will be useful later to access classic `ParsleyField` stuff while being in a `ParsleyFieldMultiple` instance\n this.bind('parsleyField', true);\n\n return parsleyMultipleInstance || this.bind('parsleyFieldMultiple');\n },\n\n // Return proper `ParsleyForm`, `ParsleyField` or `ParsleyFieldMultiple`\n bind: function (type, doNotStore) {\n var parsleyInstance;\n\n switch (type) {\n case 'parsleyForm':\n parsleyInstance = $.extend(\n new ParsleyForm(this.$element, this.domOptions, this.options),\n window.ParsleyExtend\n )._bindFields();\n break;\n case 'parsleyField':\n parsleyInstance = $.extend(\n new ParsleyField(this.$element, this.domOptions, this.options, this.parent),\n window.ParsleyExtend\n );\n break;\n case 'parsleyFieldMultiple':\n parsleyInstance = $.extend(\n new ParsleyField(this.$element, this.domOptions, this.options, this.parent),\n new ParsleyMultiple(),\n window.ParsleyExtend\n )._init();\n break;\n default:\n throw new Error(type + 'is not a supported Parsley type');\n }\n\n if (this.options.multiple)\n ParsleyUtils.setAttr(this.$element, this.options.namespace, 'multiple', this.options.multiple);\n\n if ('undefined' !== typeof doNotStore) {\n this.$element.data('ParsleyFieldMultiple', parsleyInstance);\n\n return parsleyInstance;\n }\n\n // Store the freshly bound instance in a DOM element for later access using jQuery `data()`\n this.$element.data('Parsley', parsleyInstance);\n\n // Tell the world we have a new ParsleyForm or ParsleyField instance!\n parsleyInstance._actualizeTriggers();\n parsleyInstance._trigger('init');\n\n return parsleyInstance;\n }\n};\n\nexport default ParsleyFactory;\n","import $ from 'jquery';\nimport ParsleyUtils from './utils';\nimport ParsleyDefaults from './defaults';\nimport ParsleyAbstract from './abstract';\nimport ParsleyValidatorRegistry from './validator_registry';\nimport ParsleyUI from './ui';\nimport ParsleyForm from './form';\nimport ParsleyField from './field';\nimport ParsleyMultiple from './multiple';\nimport ParsleyFactory from './factory';\n\nvar vernums = $.fn.jquery.split('.');\nif (parseInt(vernums[0]) <= 1 && parseInt(vernums[1]) < 8) {\n throw \"The loaded version of jQuery is too old. Please upgrade to 1.8.x or better.\";\n}\nif (!vernums.forEach) {\n ParsleyUtils.warn('Parsley requires ES5 to run properly. Please include https://github.com/es-shims/es5-shim');\n}\n// Inherit `on`, `off` & `trigger` to Parsley:\nvar Parsley = $.extend(new ParsleyAbstract(), {\n $element: $(document),\n actualizeOptions: null,\n _resetOptions: null,\n Factory: ParsleyFactory,\n version: '@@version'\n });\n\n// Supplement ParsleyField and Form with ParsleyAbstract\n// This way, the constructors will have access to those methods\n$.extend(ParsleyField.prototype, ParsleyUI.Field, ParsleyAbstract.prototype);\n$.extend(ParsleyForm.prototype, ParsleyUI.Form, ParsleyAbstract.prototype);\n// Inherit actualizeOptions and _resetOptions:\n$.extend(ParsleyFactory.prototype, ParsleyAbstract.prototype);\n\n// ### jQuery API\n// `$('.elem').parsley(options)` or `$('.elem').psly(options)`\n$.fn.parsley = $.fn.psly = function (options) {\n if (this.length > 1) {\n var instances = [];\n\n this.each(function () {\n instances.push($(this).parsley(options));\n });\n\n return instances;\n }\n\n // Return undefined if applied to non existing DOM element\n if (!$(this).length) {\n ParsleyUtils.warn('You must bind Parsley on an existing element.');\n\n return;\n }\n\n return new ParsleyFactory(this, options);\n};\n\n// ### ParsleyField and ParsleyForm extension\n// Ensure the extension is now defined if it wasn't previously\nif ('undefined' === typeof window.ParsleyExtend)\n window.ParsleyExtend = {};\n\n// ### Parsley config\n// Inherit from ParsleyDefault, and copy over any existing values\nParsley.options = $.extend(ParsleyUtils.objectCreate(ParsleyDefaults), window.ParsleyConfig);\nwindow.ParsleyConfig = Parsley.options; // Old way of accessing global options\n\n// ### Globals\nwindow.Parsley = window.psly = Parsley;\nwindow.ParsleyUtils = ParsleyUtils;\n\n// ### Define methods that forward to the registry, and deprecate all access except through window.Parsley\nvar registry = window.Parsley._validatorRegistry = new ParsleyValidatorRegistry(window.ParsleyConfig.validators, window.ParsleyConfig.i18n);\nwindow.ParsleyValidator = {};\n$.each('setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator'.split(' '), function (i, method) {\n window.Parsley[method] = $.proxy(registry, method);\n window.ParsleyValidator[method] = function () {\n ParsleyUtils.warnOnce(`Accessing the method '${method}' through ParsleyValidator is deprecated. Simply call 'window.Parsley.${method}(...)'`);\n return window.Parsley[method](...arguments);\n };\n});\n\n// ### ParsleyUI\n// Deprecated global object\nwindow.Parsley.UI = ParsleyUI;\nwindow.ParsleyUI = {\n removeError: function (instance, name, doNotUpdateClass) {\n var updateClass = true !== doNotUpdateClass;\n ParsleyUtils.warnOnce(`Accessing ParsleyUI is deprecated. Call 'removeError' on the instance directly. Please comment in issue 1073 as to your need to call this method.`);\n return instance.removeError(name, {updateClass});\n },\n getErrorsMessages: function (instance) {\n ParsleyUtils.warnOnce(`Accessing ParsleyUI is deprecated. Call 'getErrorsMessages' on the instance directly.`);\n return instance.getErrorsMessages();\n }\n};\n$.each('addError updateError'.split(' '), function (i, method) {\n window.ParsleyUI[method] = function (instance, name, message, assert, doNotUpdateClass) {\n var updateClass = true !== doNotUpdateClass;\n ParsleyUtils.warnOnce(`Accessing ParsleyUI is deprecated. Call '${method}' on the instance directly. Please comment in issue 1073 as to your need to call this method.`);\n return instance[method](name, {message, assert, updateClass});\n };\n});\n\n// Alleviate glaring Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=1250521\n// See also https://github.com/guillaumepotier/Parsley.js/issues/1068\nif (/firefox/i.test(navigator.userAgent)) {\n $(document).on('change', 'select', evt => {\n $(evt.target).trigger('input');\n });\n}\n\n// ### PARSLEY auto-binding\n// Prevent it by setting `ParsleyConfig.autoBind` to `false`\nif (false !== window.ParsleyConfig.autoBind) {\n $(function () {\n // Works only on `data-parsley-validate`.\n if ($('[data-parsley-validate]').length)\n $('[data-parsley-validate]').parsley();\n });\n}\n\nexport default Parsley;\n","import $ from 'jquery';\n\nimport Parsley from './main';\n\n$.extend(true, Parsley, {\n asyncValidators: {\n 'default': {\n fn: function (xhr) {\n // By default, only status 2xx are deemed successful.\n // Note: we use status instead of state() because responses with status 200\n // but invalid messages (e.g. an empty body for content type set to JSON) will\n // result in state() === 'rejected'.\n return xhr.status >= 200 && xhr.status < 300;\n },\n url: false\n },\n reverse: {\n fn: function (xhr) {\n // If reverse option is set, a failing ajax request is considered successful\n return xhr.status < 200 || xhr.status >= 300;\n },\n url: false\n }\n },\n\n addAsyncValidator: function (name, fn, url, options) {\n Parsley.asyncValidators[name] = {\n fn: fn,\n url: url || false,\n options: options || {}\n };\n\n return this;\n }\n\n});\n\nParsley.addValidator('remote', {\n requirementType: {\n '': 'string',\n 'validator': 'string',\n 'reverse': 'boolean',\n 'options': 'object'\n },\n\n validateString: function (value, url, options, instance) {\n var data = {};\n var ajaxOptions;\n var csr;\n var validator = options.validator || (true === options.reverse ? 'reverse' : 'default');\n\n if ('undefined' === typeof Parsley.asyncValidators[validator])\n throw new Error('Calling an undefined async validator: `' + validator + '`');\n\n url = Parsley.asyncValidators[validator].url || url;\n\n // Fill current value\n if (url.indexOf('{value}') > -1) {\n url = url.replace('{value}', encodeURIComponent(value));\n } else {\n data[instance.$element.attr('name') || instance.$element.attr('id')] = value;\n }\n\n // Merge options passed in from the function with the ones in the attribute\n var remoteOptions = $.extend(true, options.options || {} , Parsley.asyncValidators[validator].options);\n\n // All `$.ajax(options)` could be overridden or extended directly from DOM in `data-parsley-remote-options`\n ajaxOptions = $.extend(true, {}, {\n url: url,\n data: data,\n type: 'GET'\n }, remoteOptions);\n\n // Generate store key based on ajax options\n instance.trigger('field:ajaxoptions', instance, ajaxOptions);\n\n csr = $.param(ajaxOptions);\n\n // Initialise querry cache\n if ('undefined' === typeof Parsley._remoteCache)\n Parsley._remoteCache = {};\n\n // Try to retrieve stored xhr\n var xhr = Parsley._remoteCache[csr] = Parsley._remoteCache[csr] || $.ajax(ajaxOptions);\n\n var handleXhr = function () {\n var result = Parsley.asyncValidators[validator].fn.call(instance, xhr, url, options);\n if (!result) // Map falsy results to rejected promise\n result = $.Deferred().reject();\n return $.when(result);\n };\n\n return xhr.then(handleXhr, handleXhr);\n },\n\n priority: -1\n});\n\nParsley.on('form:submit', function () {\n Parsley._remoteCache = {};\n});\n\nwindow.ParsleyExtend.addAsyncValidator = function () {\n ParsleyUtils.warnOnce('Accessing the method `addAsyncValidator` through an instance is deprecated. Simply call `Parsley.addAsyncValidator(...)`');\n return Parsley.addAsyncValidator(...arguments);\n};\n","// This is included with the Parsley library itself,\n// thus there is no use in adding it to your project.\nimport Parsley from '../parsley/main';\n\nParsley.addMessages('en', {\n defaultMessage: \"This value seems to be invalid.\",\n type: {\n email: \"This value should be a valid email.\",\n url: \"This value should be a valid url.\",\n number: \"This value should be a valid number.\",\n integer: \"This value should be a valid integer.\",\n digits: \"This value should be digits.\",\n alphanum: \"This value should be alphanumeric.\"\n },\n notblank: \"This value should not be blank.\",\n required: \"This value is required.\",\n pattern: \"This value seems to be invalid.\",\n min: \"This value should be greater than or equal to %s.\",\n max: \"This value should be lower than or equal to %s.\",\n range: \"This value should be between %s and %s.\",\n minlength: \"This value is too short. It should have %s characters or more.\",\n maxlength: \"This value is too long. It should have %s characters or fewer.\",\n length: \"This value length is invalid. It should be between %s and %s characters long.\",\n mincheck: \"You must select at least %s choices.\",\n maxcheck: \"You must select %s choices or fewer.\",\n check: \"You must select between %s and %s choices.\",\n equalto: \"This value should be the same.\"\n});\n\nParsley.setLocale('en');\n","import $ from 'jquery';\nimport Parsley from './parsley/main';\nimport './parsley/pubsub';\nimport './parsley/remote';\nimport './i18n/en';\n\nexport default Parsley;\n"],"sourceRoot":"/source/"}
|
classes/class.archive.config.php
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @copyright 2016 Snap Creek LLC
|
4 |
+
*/
|
5 |
+
|
6 |
+
// Exit if accessed directly
|
7 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
8 |
+
|
9 |
+
class DUP_Archive_Config
|
10 |
+
{
|
11 |
+
//READ-ONLY: COMPARE VALUES
|
12 |
+
public $created;
|
13 |
+
public $version_dup;
|
14 |
+
public $version_wp;
|
15 |
+
public $version_db;
|
16 |
+
public $version_php;
|
17 |
+
public $version_os;
|
18 |
+
public $dbInfo;
|
19 |
+
//READ-ONLY: GENERAL
|
20 |
+
public $url_old;
|
21 |
+
public $opts_delete;
|
22 |
+
public $blogname;
|
23 |
+
public $wproot;
|
24 |
+
public $wplogin_url;
|
25 |
+
public $relative_content_dir;
|
26 |
+
public $exportOnlyDB;
|
27 |
+
public $installSiteOverwriteOn;
|
28 |
+
|
29 |
+
//PRE-FILLED: GENERAL
|
30 |
+
public $secure_on;
|
31 |
+
public $secure_pass;
|
32 |
+
public $skipscan;
|
33 |
+
public $dbhost;
|
34 |
+
public $dbname;
|
35 |
+
public $dbuser;
|
36 |
+
public $dbpass;
|
37 |
+
|
38 |
+
// MULTISITE
|
39 |
+
public $mu_mode;
|
40 |
+
|
41 |
+
public $wp_tableprefix;
|
42 |
+
}
|
classes/class.db.php
CHANGED
@@ -8,14 +8,11 @@
|
|
8 |
* @package Duplicator
|
9 |
* @subpackage classes/utilities
|
10 |
* @copyright (c) 2017, Snapcreek LLC
|
11 |
-
* @since 1.1.32
|
12 |
*
|
13 |
*/
|
14 |
|
15 |
// Exit if accessed directly
|
16 |
-
if (!defined('DUPLICATOR_VERSION'))
|
17 |
-
exit;
|
18 |
-
}
|
19 |
|
20 |
class DUP_DB extends wpdb
|
21 |
{
|
@@ -78,44 +75,43 @@ class DUP_DB extends wpdb
|
|
78 |
*
|
79 |
* @return boolean|string
|
80 |
*/
|
81 |
-
public static function getWindowsMySqlDumpRealPath()
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
|
|
98 |
}
|
99 |
}
|
100 |
}
|
|
|
101 |
|
102 |
-
|
103 |
-
|
104 |
|
105 |
-
|
106 |
-
|
107 |
-
} catch(Exception $ex) {
|
108 |
-
return false;
|
109 |
-
}
|
110 |
}
|
111 |
|
112 |
-
|
113 |
* Returns the mysqldump path if the server is enabled to execute it otherwise false
|
114 |
*
|
115 |
* @return boolean|string
|
116 |
*/
|
117 |
public static function getMySqlDumpPath()
|
118 |
{
|
|
|
119 |
//Is shell_exec possible
|
120 |
if (!DUP_Util::hasShellExec()) {
|
121 |
return false;
|
@@ -124,20 +120,19 @@ class DUP_DB extends wpdb
|
|
124 |
$custom_mysqldump_path = DUP_Settings::Get('package_mysqldump_path');
|
125 |
$custom_mysqldump_path = (strlen($custom_mysqldump_path)) ? $custom_mysqldump_path : '';
|
126 |
|
127 |
-
//
|
128 |
if (DUP_Util::isWindows()) {
|
129 |
$paths = array(
|
130 |
$custom_mysqldump_path,
|
131 |
-
|
132 |
'C:/xampp/mysql/bin/mysqldump.exe',
|
133 |
'C:/Program Files/xampp/mysql/bin/mysqldump',
|
134 |
'C:/Program Files/MySQL/MySQL Server 6.0/bin/mysqldump',
|
135 |
'C:/Program Files/MySQL/MySQL Server 5.5/bin/mysqldump',
|
136 |
-
'C:/Program Files/MySQL/MySQL Server 5.4/bin/mysqldump'
|
137 |
-
'C:/wamp64/bin/mysql/mysql5.7.21/bin',
|
138 |
);
|
139 |
|
140 |
-
|
141 |
} else {
|
142 |
$path1 = '';
|
143 |
$path2 = '';
|
@@ -160,7 +155,7 @@ class DUP_DB extends wpdb
|
|
160 |
'/usr/mysql/bin/mysqldump',
|
161 |
'/usr/bin/mysqldump',
|
162 |
'/opt/local/lib/mysql6/bin/mysqldump',
|
163 |
-
'/opt/local/lib/mysql5/bin/mysqldump'
|
164 |
);
|
165 |
}
|
166 |
|
8 |
* @package Duplicator
|
9 |
* @subpackage classes/utilities
|
10 |
* @copyright (c) 2017, Snapcreek LLC
|
|
|
11 |
*
|
12 |
*/
|
13 |
|
14 |
// Exit if accessed directly
|
15 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
|
|
|
|
16 |
|
17 |
class DUP_DB extends wpdb
|
18 |
{
|
75 |
*
|
76 |
* @return boolean|string
|
77 |
*/
|
78 |
+
public static function getWindowsMySqlDumpRealPath() {
|
79 |
+
if(function_exists('php_ini_loaded_file'))
|
80 |
+
{
|
81 |
+
$get_php_ini_path = php_ini_loaded_file();
|
82 |
+
if(file_exists($get_php_ini_path))
|
83 |
+
{
|
84 |
+
$search = array(
|
85 |
+
dirname(dirname($get_php_ini_path)).'/mysql/bin/mysqldump.exe',
|
86 |
+
dirname(dirname(dirname($get_php_ini_path))).'/mysql/bin/mysqldump.exe',
|
87 |
+
dirname(dirname($get_php_ini_path)).'/mysql/bin/mysqldump',
|
88 |
+
dirname(dirname(dirname($get_php_ini_path))).'/mysql/bin/mysqldump',
|
89 |
+
);
|
90 |
+
|
91 |
+
foreach($search as $mysqldump)
|
92 |
+
{
|
93 |
+
if(file_exists($mysqldump))
|
94 |
+
{
|
95 |
+
return str_replace("\\","/",$mysqldump);
|
96 |
}
|
97 |
}
|
98 |
}
|
99 |
+
}
|
100 |
|
101 |
+
unset($search);
|
102 |
+
unset($get_php_ini_path);
|
103 |
|
104 |
+
return false;
|
|
|
|
|
|
|
|
|
105 |
}
|
106 |
|
107 |
+
/**
|
108 |
* Returns the mysqldump path if the server is enabled to execute it otherwise false
|
109 |
*
|
110 |
* @return boolean|string
|
111 |
*/
|
112 |
public static function getMySqlDumpPath()
|
113 |
{
|
114 |
+
|
115 |
//Is shell_exec possible
|
116 |
if (!DUP_Util::hasShellExec()) {
|
117 |
return false;
|
120 |
$custom_mysqldump_path = DUP_Settings::Get('package_mysqldump_path');
|
121 |
$custom_mysqldump_path = (strlen($custom_mysqldump_path)) ? $custom_mysqldump_path : '';
|
122 |
|
123 |
+
//Common Windows Paths
|
124 |
if (DUP_Util::isWindows()) {
|
125 |
$paths = array(
|
126 |
$custom_mysqldump_path,
|
127 |
+
self::getWindowsMySqlDumpRealPath(),
|
128 |
'C:/xampp/mysql/bin/mysqldump.exe',
|
129 |
'C:/Program Files/xampp/mysql/bin/mysqldump',
|
130 |
'C:/Program Files/MySQL/MySQL Server 6.0/bin/mysqldump',
|
131 |
'C:/Program Files/MySQL/MySQL Server 5.5/bin/mysqldump',
|
132 |
+
'C:/Program Files/MySQL/MySQL Server 5.4/bin/mysqldump'
|
|
|
133 |
);
|
134 |
|
135 |
+
//Common Linux Paths
|
136 |
} else {
|
137 |
$path1 = '';
|
138 |
$path2 = '';
|
155 |
'/usr/mysql/bin/mysqldump',
|
156 |
'/usr/bin/mysqldump',
|
157 |
'/opt/local/lib/mysql6/bin/mysqldump',
|
158 |
+
'/opt/local/lib/mysql5/bin/mysqldump'
|
159 |
);
|
160 |
}
|
161 |
|
classes/class.io.php
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @copyright 2018 Snap Creek LLC
|
4 |
+
* Class for all IO operations
|
5 |
+
*/
|
6 |
+
|
7 |
+
// Exit if accessed directly
|
8 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
9 |
+
|
10 |
+
class DUP_IO
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Safely deletes a file
|
14 |
+
*
|
15 |
+
* @param string $file The full filepath to the file
|
16 |
+
*
|
17 |
+
* @return TRUE on success or if file does not exist. FALSE on failure
|
18 |
+
*/
|
19 |
+
public static function deleteFile($file)
|
20 |
+
{
|
21 |
+
if (file_exists($file)) {
|
22 |
+
if (@unlink($file) === false) {
|
23 |
+
DUP_Log::Info("Could not delete file: {$file}");
|
24 |
+
return false;
|
25 |
+
}
|
26 |
+
}
|
27 |
+
return true;
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Removes a directory recursively except for the root of a WP Site
|
32 |
+
*
|
33 |
+
* @param string $directory The full filepath to the directory to remove
|
34 |
+
*
|
35 |
+
* @return TRUE on success FALSE on failure
|
36 |
+
*/
|
37 |
+
public static function deleteTree($directory)
|
38 |
+
{
|
39 |
+
$success = true;
|
40 |
+
|
41 |
+
if(!file_exists("{$directory}/wp-config.php")) {
|
42 |
+
$filenames = array_diff(scandir($directory), array('.', '..'));
|
43 |
+
|
44 |
+
foreach ($filenames as $filename) {
|
45 |
+
if (is_dir("$directory/$filename")) {
|
46 |
+
$success = self::deleteTree("$directory/$filename");
|
47 |
+
} else {
|
48 |
+
$success = @unlink("$directory/$filename");
|
49 |
+
}
|
50 |
+
|
51 |
+
if ($success === false) {
|
52 |
+
break;
|
53 |
+
}
|
54 |
+
}
|
55 |
+
} else {
|
56 |
+
return false;
|
57 |
+
}
|
58 |
+
|
59 |
+
return $success && @rmdir($directory);
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Safely copies a file to a directory
|
64 |
+
*
|
65 |
+
* @param string $source_file The full filepath to the file to copy
|
66 |
+
* @param string $dest_dir The full path to the destination directory were the file will be copied
|
67 |
+
* @param string $delete_first Delete file before copying the new one
|
68 |
+
*
|
69 |
+
* @return TRUE on success or if file does not exist. FALSE on failure
|
70 |
+
*/
|
71 |
+
public static function copyFile($source_file, $dest_dir, $delete_first = false)
|
72 |
+
{
|
73 |
+
//Create directory
|
74 |
+
if (file_exists($dest_dir) == false)
|
75 |
+
{
|
76 |
+
if (self::createDir($dest_dir, 0755, true) === false)
|
77 |
+
{
|
78 |
+
DUP_PRO_LOG::traceError("Error creating $dest_dir.");
|
79 |
+
return false;
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
//Remove file with same name before copy
|
84 |
+
$filename = basename($source_file);
|
85 |
+
$dest_filepath = $dest_dir . "/$filename";
|
86 |
+
if($delete_first)
|
87 |
+
{
|
88 |
+
self::deleteFile($dest_filepath);
|
89 |
+
}
|
90 |
+
|
91 |
+
return copy($source_file, $dest_filepath);
|
92 |
+
}
|
93 |
+
}
|
classes/class.logging.php
CHANGED
@@ -1,58 +1,223 @@
|
|
1 |
<?php
|
2 |
-
|
|
|
3 |
|
4 |
/**
|
5 |
* Helper Class for logging
|
6 |
-
* @package
|
7 |
*/
|
8 |
-
class
|
9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
/**
|
11 |
* The file handle used to write to the log file
|
12 |
-
* @var file resource
|
13 |
*/
|
14 |
-
|
15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
/**
|
17 |
* Open a log file connection for writing
|
18 |
* @param string $name Name of the log file to create
|
19 |
*/
|
20 |
-
static
|
21 |
-
|
22 |
-
|
|
|
|
|
23 |
}
|
24 |
-
|
25 |
/**
|
26 |
* Close the log file connection
|
27 |
*/
|
28 |
-
static
|
29 |
-
|
|
|
30 |
}
|
31 |
-
|
32 |
/**
|
33 |
* General information logging
|
34 |
* @param string $msg The message to log
|
35 |
-
*
|
36 |
-
* REPLACE TO DEBUG: Memory
|
37 |
-
*
|
38 |
-
*
|
39 |
*/
|
40 |
-
static
|
41 |
-
|
42 |
-
|
43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
}
|
45 |
-
|
46 |
/**
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
static
|
52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
$source = self::getStack(debug_backtrace());
|
54 |
-
|
55 |
-
$err_msg
|
56 |
$err_msg .= "DUPLICATOR ERROR\n";
|
57 |
$err_msg .= "Please try again! If the error persists see the Duplicator 'Help' menu.\n";
|
58 |
$err_msg .= "---------------------------------------------------------------------------------\n";
|
@@ -62,25 +227,67 @@ class DUP_Log {
|
|
62 |
}
|
63 |
$err_msg .= "TRACE:\n{$source}";
|
64 |
$err_msg .= "==================================================================================\n\n";
|
65 |
-
@fwrite(self::$logFileHandle, "{$err_msg}");
|
66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
}
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
* The current strack trace of a PHP call
|
72 |
* @param $stacktrace The current debug stack
|
73 |
-
* @return string
|
74 |
-
*/
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
|
|
82 |
return $output;
|
83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
}
|
86 |
-
|
1 |
<?php
|
2 |
+
// Exit if accessed directly
|
3 |
+
if (!defined('DUPLICATOR_VERSION')) exit;
|
4 |
|
5 |
/**
|
6 |
* Helper Class for logging
|
7 |
+
* @package Duplicator\classes
|
8 |
*/
|
9 |
+
abstract class Dup_ErrorBehavior
|
10 |
+
{
|
11 |
+
const LogOnly = 0;
|
12 |
+
const ThrowException = 1;
|
13 |
+
const Quit = 2;
|
14 |
+
|
15 |
+
}
|
16 |
+
|
17 |
+
class DUP_Log
|
18 |
+
{
|
19 |
+
static $debugging = true;
|
20 |
+
private static $traceEnabled;
|
21 |
+
|
22 |
/**
|
23 |
* The file handle used to write to the log file
|
24 |
+
* @var file resource
|
25 |
*/
|
26 |
+
public static $logFileHandle = null;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Init this static object
|
30 |
+
*/
|
31 |
+
public static function Init()
|
32 |
+
{
|
33 |
+
self::$traceEnabled = (DUP_Settings::Get('trace_log_enabled') == 1);
|
34 |
+
}
|
35 |
+
|
36 |
/**
|
37 |
* Open a log file connection for writing
|
38 |
* @param string $name Name of the log file to create
|
39 |
*/
|
40 |
+
public static function Open($name)
|
41 |
+
{
|
42 |
+
if (!isset($name)) throw new Exception("A name value is required to open a file log.");
|
43 |
+
//self::$logFileHandle = @fopen(DUPLICATOR_SSDIR_PATH . "/{$name}.log", "c+");
|
44 |
+
self::$logFileHandle = @fopen(DUPLICATOR_SSDIR_PATH."/{$name}.log", "a+");
|
45 |
}
|
46 |
+
|
47 |
/**
|
48 |
* Close the log file connection
|
49 |
*/
|
50 |
+
public static function Close()
|
51 |
+
{
|
52 |
+
@fclose(self::$logFileHandle);
|
53 |
}
|
54 |
+
|
55 |
/**
|
56 |
* General information logging
|
57 |
* @param string $msg The message to log
|
58 |
+
*
|
59 |
+
* REPLACE TO DEBUG: Memory consumption as script runs
|
60 |
+
* $results = DUP_Util::byteSize(memory_get_peak_usage(true)) . "\t" . $msg;
|
61 |
+
* @fwrite(self::$logFileHandle, "{$results} \n");
|
62 |
*/
|
63 |
+
public static function Info($msg)
|
64 |
+
{
|
65 |
+
self::Trace($msg);
|
66 |
+
|
67 |
+
@fwrite(self::$logFileHandle, "{$msg} \n");
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Does the trace file exists
|
72 |
+
*
|
73 |
+
* @return bool Returns true if an active trace file exists
|
74 |
+
*/
|
75 |
+
public static function TraceFileExists()
|
76 |
+
{
|
77 |
+
$file_path = self::getTraceFilepath();
|
78 |
+
|
79 |
+
return file_exists($file_path);
|
80 |
}
|
81 |
+
|
82 |
/**
|
83 |
+
* Gets the current file size of the active trace file
|
84 |
+
*
|
85 |
+
* @return string Returns a human readable file size of the active trace file
|
86 |
+
*/
|
87 |
+
public static function getTraceStatus()
|
88 |
+
{
|
89 |
+
$file_path = DUP_Log::getTraceFilepath();
|
90 |
+
$backup_path = DUP_Log::getBackupTraceFilepath();
|
91 |
+
|
92 |
+
if (file_exists($file_path)) {
|
93 |
+
$filesize = filesize($file_path);
|
94 |
+
|
95 |
+
if (file_exists($backup_path)) {
|
96 |
+
$filesize += filesize($backup_path);
|
97 |
+
}
|
98 |
+
|
99 |
+
$message = sprintf('%1$s', DUP_Util::byteSize($filesize));
|
100 |
+
} else {
|
101 |
+
$message = esc_html__('No Log', 'duplicator');
|
102 |
+
}
|
103 |
+
|
104 |
+
return $message;
|
105 |
+
}
|
106 |
+
|
107 |
+
// RSR TODO: Swap trace logic out for real trace later
|
108 |
+
public static function Trace($message, $calling_function_override = null)
|
109 |
+
{
|
110 |
+
|
111 |
+
if (self::$traceEnabled) {
|
112 |
+
$unique_id = sprintf("%08x", abs(crc32($_SERVER['REMOTE_ADDR'].$_SERVER['REQUEST_TIME'].$_SERVER['REMOTE_PORT'])));
|
113 |
+
|
114 |
+
if ($calling_function_override == null) {
|
115 |
+
$calling_function = SnapLibUtil::getCallingFunctionName();
|
116 |
+
} else {
|
117 |
+
$calling_function = $calling_function_override;
|
118 |
+
}
|
119 |
+
|
120 |
+
if (is_object($message)) {
|
121 |
+
$ov = get_object_vars($message);
|
122 |
+
$message = print_r($ov, true);
|
123 |
+
} else if (is_array($message)) {
|
124 |
+
$message = print_r($message, true);
|
125 |
+
}
|
126 |
+
|
127 |
+
$logging_message = "{$unique_id}|{$calling_function} | {$message}";
|
128 |
+
$ticks = time() + ((int) get_option('gmt_offset') * 3600);
|
129 |
+
$formatted_time = date('d-m-H:i:s', $ticks);
|
130 |
+
$formatted_logging_message = "{$formatted_time}|DUP|{$logging_message} \r\n";
|
131 |
+
|
132 |
+
// Always write to error log - if they don't want the info they can turn off WordPress error logging or tracing
|
133 |
+
self::ErrLog($logging_message);
|
134 |
+
|
135 |
+
// Everything goes to the plugin log, whether it's part of package generation or not.
|
136 |
+
self::WriteToTrace($formatted_logging_message);
|
137 |
+
}
|
138 |
+
}
|
139 |
+
|
140 |
+
public static function errLog($message)
|
141 |
+
{
|
142 |
+
$message = 'DUP:'.$message;
|
143 |
+
error_log($message);
|
144 |
+
}
|
145 |
+
|
146 |
+
public static function TraceObject($msg, $o, $log_private_members = true)
|
147 |
+
{
|
148 |
+
|
149 |
+
if (self::$traceEnabled) {
|
150 |
+
|
151 |
+
if (!$log_private_members) {
|
152 |
+
$o = get_object_vars($o);
|
153 |
+
}
|
154 |
+
|
155 |
+
self::Trace($msg.':'.print_r($o, true));
|
156 |
+
}
|
157 |
+
}
|
158 |
+
|
159 |
+
public static function GetDefaultKey()
|
160 |
+
{
|
161 |
+
$auth_key = defined('AUTH_KEY') ? AUTH_KEY : 'atk';
|
162 |
+
$auth_key .= defined('DB_HOST') ? DB_HOST : 'dbh';
|
163 |
+
$auth_key .= defined('DB_NAME') ? DB_NAME : 'dbn';
|
164 |
+
$auth_key .= defined('DB_USER') ? DB_USER : 'dbu';
|
165 |
+
|
166 |
+
return hash('md5', $auth_key);
|
167 |
+
}
|
168 |
+
|
169 |
+
public static function GetBackupTraceFilepath()
|
170 |
+
{
|
171 |
+
$default_key = self::getDefaultKey();
|
172 |
+
$backup_log_filename = "dup_$default_key.log1";
|
173 |
+
$backup_path = DUPLICATOR_SSDIR_PATH."/".$backup_log_filename;
|
174 |
+
|
175 |
+
return $backup_path;
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Gets the active trace file path
|
180 |
+
*
|
181 |
+
* @return string Returns the full path to the active trace file (i.e. dup-pro_hash.log)
|
182 |
+
*/
|
183 |
+
public static function GetTraceFilepath()
|
184 |
+
{
|
185 |
+
$default_key = self::getDefaultKey();
|
186 |
+
$log_filename = "dup_$default_key.log";
|
187 |
+
$file_path = DUPLICATOR_SSDIR_PATH."/".$log_filename;
|
188 |
+
|
189 |
+
return $file_path;
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Deletes the trace log and backup trace log files
|
194 |
+
*
|
195 |
+
* @return null
|
196 |
+
*/
|
197 |
+
public static function DeleteTraceLog()
|
198 |
+
{
|
199 |
+
$file_path = self::GetTraceFilepath();
|
200 |
+
$backup_path = self::GetBackupTraceFilepath();
|
201 |
+
|
202 |
+
self::trace("deleting $file_path");
|
203 |
+
@unlink($file_path);
|
204 |
+
self::trace("deleting $backup_path");
|
205 |
+
@unlink($backup_path);
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* Called when an error is detected and no further processing should occur
|
210 |
+
* @param string $msg The message to log
|
211 |
+
* @param string $details Additional details to help resolve the issue if possible
|
212 |
+
*/
|
213 |
+
public static function Error($msg, $detail, $behavior = Dup_ErrorBehavior::Quit)
|
214 |
+
{
|
215 |
+
|
216 |
+
error_log($msg.' DETAIL:'.$detail);
|
217 |
+
|
218 |
$source = self::getStack(debug_backtrace());
|
219 |
+
|
220 |
+
$err_msg = "\n==================================================================================\n";
|
221 |
$err_msg .= "DUPLICATOR ERROR\n";
|
222 |
$err_msg .= "Please try again! If the error persists see the Duplicator 'Help' menu.\n";
|
223 |
$err_msg .= "---------------------------------------------------------------------------------\n";
|
227 |
}
|
228 |
$err_msg .= "TRACE:\n{$source}";
|
229 |
$err_msg .= "==================================================================================\n\n";
|
230 |
+
@fwrite(self::$logFileHandle, "{$err_msg}");
|
231 |
+
|
232 |
+
switch ($behavior) {
|
233 |
+
|
234 |
+
case Dup_ErrorBehavior::ThrowException:
|
235 |
+
DUP_LOG::trace("throwing exception");
|
236 |
+
throw new Exception("DUPLICATOR ERROR: Please see the 'Package Log' file link below.");
|
237 |
+
break;
|
238 |
+
|
239 |
+
case Dup_ErrorBehavior::Quit:
|
240 |
+
DUP_LOG::trace("quitting");
|
241 |
+
die("DUPLICATOR ERROR: Please see the 'Package Log' file link below.");
|
242 |
+
break;
|
243 |
+
|
244 |
+
default:
|
245 |
+
// Nothing
|
246 |
+
}
|
247 |
}
|
248 |
+
|
249 |
+
/**
|
250 |
+
* The current stack trace of a PHP call
|
|
|
251 |
* @param $stacktrace The current debug stack
|
252 |
+
* @return string
|
253 |
+
*/
|
254 |
+
public static function getStack($stacktrace)
|
255 |
+
{
|
256 |
+
$output = "";
|
257 |
+
$i = 1;
|
258 |
+
foreach ($stacktrace as $node) {
|
259 |
+
$output .= "\t $i. ".basename($node['file'])." : ".$node['function']." (".$node['line'].")\n";
|
260 |
+
$i++;
|
261 |
+
}
|
262 |
return $output;
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Manages writing the active or backup log based on the size setting
|
267 |
+
*
|
268 |
+
* @return null
|
269 |
+
*/
|
270 |
+
private static function WriteToTrace($formatted_logging_message)
|
271 |
+
{
|
272 |
+
$log_filepath = self::GetTraceFilepath();
|
273 |
+
|
274 |
+
if (@filesize($log_filepath) > DUPLICATOR_MAX_LOG_SIZE) {
|
275 |
+
$backup_log_filepath = self::GetBackupTraceFilepath();
|
276 |
|
277 |
+
if (file_exists($backup_log_filepath)) {
|
278 |
+
if (@unlink($backup_log_filepath) === false) {
|
279 |
+
DUP_PRO_Low_U::errLog("Couldn't delete backup log $backup_log_filepath");
|
280 |
+
}
|
281 |
+
}
|
282 |
+
|
283 |
+
if (@rename($log_filepath, $backup_log_filepath) === false) {
|
284 |
+
self::errLog("Couldn't rename log $log_filepath to $backup_log_filepath");
|
285 |
+
}
|
286 |
+
}
|
287 |
+
|
288 |
+
if (@file_put_contents($log_filepath, $formatted_logging_message, FILE_APPEND) === false) {
|
289 |
+
// Not en error worth reporting
|
290 |
+
}
|
291 |
+
}
|
292 |
}
|
293 |
+
DUP_Log::Init();
|
classes/class.password.php
CHANGED
@@ -24,6 +24,10 @@
|
|
24 |
# Obviously, since this code is in the public domain, the above are not
|
25 |
# requirements (there can be none), but merely suggestions.
|
26 |
#
|
|
|
|
|
|
|
|
|
27 |
class DUP_PasswordHash
|
28 |
{
|
29 |
|
24 |
# Obviously, since this code is in the public domain, the above are not
|
25 |
# requirements (there can be none), but merely suggestions.
|
26 |
#
|
27 |
+
|
28 |
+
// Exit if accessed directly
|
29 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
30 |
+
|
31 |
class DUP_PasswordHash
|
32 |
{
|
33 |
|
classes/class.server.php
CHANGED
@@ -1,4 +1,6 @@
|
|
1 |
<?php
|
|
|
|
|
2 |
/**
|
3 |
* Used to get various pieces of information about the server environment
|
4 |
*
|
@@ -6,63 +8,89 @@
|
|
6 |
* @link http://www.php-fig.org/psr/psr-2
|
7 |
*
|
8 |
* @package Duplicator
|
9 |
-
* @subpackage classes/
|
10 |
* @copyright (c) 2017, Snapcreek LLC
|
11 |
-
*
|
12 |
-
*
|
13 |
*/
|
14 |
-
require_once (DUPLICATOR_PLUGIN_PATH.'classes/utilities/class.u.php');
|
15 |
|
16 |
// Exit if accessed directly
|
17 |
-
if (!defined('DUPLICATOR_VERSION'))
|
18 |
-
|
19 |
-
|
|
|
|
|
20 |
|
21 |
-
|
22 |
-
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
|
24 |
/**
|
25 |
-
* Gets the system requirements which must pass to
|
26 |
*
|
27 |
* @return array An array of requirements
|
28 |
*/
|
29 |
-
public static function getRequirements()
|
30 |
-
{
|
31 |
global $wpdb;
|
32 |
$dup_tests = array();
|
33 |
|
34 |
//PHP SUPPORT
|
35 |
-
$safe_ini
|
36 |
$dup_tests['PHP']['SAFE_MODE'] = $safe_ini != 'on' || $safe_ini != 'yes' || $safe_ini != 'true' || ini_get("safe_mode") != 1 ? 'Pass' : 'Fail';
|
37 |
-
$dup_tests['PHP']['VERSION']
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
|
|
|
|
|
|
|
|
43 |
|
44 |
//REQUIRED PATHS
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
|
49 |
-
|
50 |
$dup_tests['IO']['SSTMP'] = is_writeable(DUPLICATOR_SSDIR_PATH_TMP) ? 'Pass' : 'Fail';
|
51 |
-
$dup_tests['IO']['ALL']
|
52 |
|
53 |
//SERVER SUPPORT
|
54 |
-
$dup_tests['SRV']['MYSQLi']
|
55 |
$dup_tests['SRV']['MYSQL_VER'] = version_compare(DUP_DB::getVersion(), '5.0', '>=') ? 'Pass' : 'Fail';
|
56 |
-
$dup_tests['SRV']['ALL']
|
57 |
|
58 |
//RESERVED FILES
|
59 |
$dup_tests['RES']['INSTALL'] = !(self::hasInstallerFiles()) ? 'Pass' : 'Fail';
|
60 |
-
$dup_tests['Success']
|
61 |
-
|
62 |
-
|
63 |
-
&& $dup_tests['RES']['INSTALL'] == 'Pass';
|
64 |
-
|
65 |
-
$dup_tests['Warning'] = $dup_tests['IO']['WPROOT'] == 'Warn';
|
66 |
|
67 |
return $dup_tests;
|
68 |
}
|
@@ -72,12 +100,11 @@ class DUP_Server
|
|
72 |
*
|
73 |
* @return array An array of system checks
|
74 |
*/
|
75 |
-
public static function getChecks()
|
76 |
-
{
|
77 |
$checks = array();
|
78 |
|
79 |
//PHP/SYSTEM SETTINGS
|
80 |
-
|
81 |
$php_test0 = false;
|
82 |
foreach ($GLOBALS['DUPLICATOR_SERVER_LIST'] as $value) {
|
83 |
if (stristr($_SERVER['SERVER_SOFTWARE'], $value)) {
|
@@ -92,21 +119,21 @@ class DUP_Server
|
|
92 |
$php_test2 = ($php_test2 > DUPLICATOR_SCAN_TIMEOUT) || (strcmp($php_test2, 'Off') == 0 || $php_test2 == 0) ? true : false;
|
93 |
$php_test3 = function_exists('mysqli_connect');
|
94 |
$php_test4 = DUP_Util::$on_php_53_plus ? true : false;
|
95 |
-
|
96 |
-
|
97 |
$checks['SRV']['PHP']['openbase'] = $php_test1;
|
98 |
-
$checks['SRV']['PHP']['maxtime']
|
99 |
-
$checks['SRV']['PHP']['mysqli']
|
100 |
-
$checks['SRV']['PHP']['version']
|
101 |
-
$checks['SRV']['PHP']['ALL']
|
102 |
|
103 |
//WORDPRESS SETTINGS
|
104 |
global $wp_version;
|
105 |
$wp_test1 = version_compare($wp_version, DUPLICATOR_SCAN_MIN_WP) >= 0 ? true : false;
|
106 |
|
107 |
//Core Files
|
108 |
-
$files
|
109 |
-
$files['wp-config.php'] = file_exists(DUP_Util::safePath(DUPLICATOR_WPROOTPATH.'/wp-config.php'));
|
110 |
|
111 |
/** searching wp-config in working word press is not worthy
|
112 |
* if this script is executing that means wp-config.php exists :)
|
@@ -118,26 +145,30 @@ class DUP_Server
|
|
118 |
if (isset($_POST['file_notice']) && isset($_POST['dir_notice'])) {
|
119 |
//means if there are core directories excluded or core files excluded return false
|
120 |
if ((bool) $_POST['file_notice'] || (bool) $_POST['dir_notice'])
|
121 |
-
|
122 |
-
else
|
|
|
123 |
}else {
|
124 |
$wp_test2 = $files['wp-config.php'];
|
125 |
}
|
126 |
|
127 |
//Cache
|
128 |
-
|
129 |
-
$
|
130 |
-
$
|
131 |
-
$
|
|
|
132 |
$cach_filtered = in_array($cache_path, explode(';', $Package->Archive->FilterDirs));
|
133 |
-
$wp_test3
|
134 |
-
|
|
|
135 |
|
136 |
$checks['SRV']['WP']['version'] = $wp_test1;
|
137 |
-
$checks['SRV']['WP']['core']
|
138 |
-
$checks['SRV']['WP']['cache']
|
139 |
-
$checks['SRV']['WP']['ismu']
|
140 |
-
$checks['SRV']['WP']['ALL']
|
|
|
141 |
|
142 |
return $checks;
|
143 |
}
|
@@ -147,38 +178,45 @@ class DUP_Server
|
|
147 |
*
|
148 |
* @return bool True if any reserved files are found
|
149 |
*/
|
150 |
-
public static function hasInstallerFiles()
|
151 |
-
{
|
152 |
$files = self::getInstallerFiles();
|
153 |
foreach ($files as $file => $path) {
|
154 |
-
if (false !==
|
155 |
$glob_files = glob($path);
|
156 |
if (!empty($glob_files)) {
|
157 |
return true;
|
158 |
}
|
159 |
-
} elseif (file_exists($path))
|
|
|
160 |
}
|
161 |
return false;
|
162 |
}
|
163 |
-
|
164 |
/**
|
165 |
* Gets a list of all the installer files by name and full path
|
166 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
167 |
* @return array [file_name, file_path]
|
168 |
*/
|
169 |
-
public static function getInstallerFiles()
|
170 |
-
{
|
171 |
// alphanumeric 7 time, then -(dash), then 8 digits
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
'dup-
|
181 |
-
|
|
|
182 |
}
|
183 |
|
184 |
/**
|
@@ -186,8 +224,7 @@ class DUP_Server
|
|
186 |
*
|
187 |
* @return string IP of the client machine
|
188 |
*/
|
189 |
-
public static function getClientIP()
|
190 |
-
{
|
191 |
if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) {
|
192 |
return $_SERVER["HTTP_X_FORWARDED_FOR"];
|
193 |
} else if (array_key_exists('REMOTE_ADDR', $_SERVER)) {
|
@@ -199,12 +236,11 @@ class DUP_Server
|
|
199 |
}
|
200 |
|
201 |
/**
|
202 |
-
* Get PHP memory
|
203 |
*
|
204 |
-
* @return string Returns human readable memory
|
205 |
*/
|
206 |
-
public static function getPHPMemory($peak = false)
|
207 |
-
{
|
208 |
if ($peak) {
|
209 |
$result = 'Unable to read PHP peak memory usage';
|
210 |
if (function_exists('memory_get_peak_usage')) {
|
@@ -218,5 +254,5 @@ class DUP_Server
|
|
218 |
}
|
219 |
return $result;
|
220 |
}
|
221 |
-
|
222 |
-
|
1 |
<?php
|
2 |
+
require_once (DUPLICATOR_PLUGIN_PATH . 'classes/utilities/class.u.php');
|
3 |
+
|
4 |
/**
|
5 |
* Used to get various pieces of information about the server environment
|
6 |
*
|
8 |
* @link http://www.php-fig.org/psr/psr-2
|
9 |
*
|
10 |
* @package Duplicator
|
11 |
+
* @subpackage classes/utilities
|
12 |
* @copyright (c) 2017, Snapcreek LLC
|
13 |
+
*
|
|
|
14 |
*/
|
|
|
15 |
|
16 |
// Exit if accessed directly
|
17 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
18 |
+
|
19 |
+
class DUP_Server {
|
20 |
+
|
21 |
+
const LockFileName = 'lockfile.txt';
|
22 |
|
23 |
+
// Possibly use in the future if we want to prevent double building
|
24 |
+
public static function isEngineLocked() {
|
25 |
+
if (self::setEngineLock(true)) {
|
26 |
+
self::setEngineLock(false);
|
27 |
+
$locked = false;
|
28 |
+
} else {
|
29 |
+
$locked = true;
|
30 |
+
}
|
31 |
+
}
|
32 |
+
|
33 |
+
// Possibly use in the future if we want to prevent double building
|
34 |
+
public static function setEngineLock($shouldLock) {
|
35 |
+
$success = false;
|
36 |
+
|
37 |
+
$locking_file = @fopen(self::LockFileName, 'c+');
|
38 |
+
|
39 |
+
if ($locking_file != false) {
|
40 |
+
if ($shouldLock) {
|
41 |
+
$success = @flock($locking_file, LOCK_EX | LOCK_NB);
|
42 |
+
} else {
|
43 |
+
$success = @flock($locking_file, LOCK_UN);
|
44 |
+
}
|
45 |
+
|
46 |
+
@fclose($locking_file);
|
47 |
+
}
|
48 |
+
|
49 |
+
return $success;
|
50 |
+
}
|
51 |
|
52 |
/**
|
53 |
+
* Gets the system requirements which must pass to build a package
|
54 |
*
|
55 |
* @return array An array of requirements
|
56 |
*/
|
57 |
+
public static function getRequirements() {
|
|
|
58 |
global $wpdb;
|
59 |
$dup_tests = array();
|
60 |
|
61 |
//PHP SUPPORT
|
62 |
+
$safe_ini = strtolower(ini_get('safe_mode'));
|
63 |
$dup_tests['PHP']['SAFE_MODE'] = $safe_ini != 'on' || $safe_ini != 'yes' || $safe_ini != 'true' || ini_get("safe_mode") != 1 ? 'Pass' : 'Fail';
|
64 |
+
$dup_tests['PHP']['VERSION'] = DUP_Util::$on_php_529_plus ? 'Pass' : 'Fail';
|
65 |
+
|
66 |
+
if (DUP_Settings::Get('archive_build_mode') == DUP_Archive_Build_Mode::ZipArchive) {
|
67 |
+
$dup_tests['PHP']['ZIP'] = class_exists('ZipArchive') ? 'Pass' : 'Fail';
|
68 |
+
}
|
69 |
+
|
70 |
+
$dup_tests['PHP']['FUNC_1'] = function_exists("file_get_contents") ? 'Pass' : 'Fail';
|
71 |
+
$dup_tests['PHP']['FUNC_2'] = function_exists("file_put_contents") ? 'Pass' : 'Fail';
|
72 |
+
$dup_tests['PHP']['FUNC_3'] = function_exists("mb_strlen") ? 'Pass' : 'Fail';
|
73 |
+
$dup_tests['PHP']['ALL'] = !in_array('Fail', $dup_tests['PHP']) ? 'Pass' : 'Fail';
|
74 |
|
75 |
//REQUIRED PATHS
|
76 |
+
$handle_test = @opendir(DUPLICATOR_WPROOTPATH);
|
77 |
+
$dup_tests['IO']['WPROOT'] = is_writeable(DUPLICATOR_WPROOTPATH) && $handle_test ? 'Pass' : 'Warn';
|
78 |
+
@closedir($handle_test);
|
79 |
|
80 |
+
$dup_tests['IO']['SSDIR'] = (file_exists(DUPLICATOR_SSDIR_PATH) && is_writeable(DUPLICATOR_SSDIR_PATH)) ? 'Pass' : 'Fail';
|
81 |
$dup_tests['IO']['SSTMP'] = is_writeable(DUPLICATOR_SSDIR_PATH_TMP) ? 'Pass' : 'Fail';
|
82 |
+
$dup_tests['IO']['ALL'] = !in_array('Fail', $dup_tests['IO']) ? 'Pass' : 'Fail';
|
83 |
|
84 |
//SERVER SUPPORT
|
85 |
+
$dup_tests['SRV']['MYSQLi'] = function_exists('mysqli_connect') ? 'Pass' : 'Fail';
|
86 |
$dup_tests['SRV']['MYSQL_VER'] = version_compare(DUP_DB::getVersion(), '5.0', '>=') ? 'Pass' : 'Fail';
|
87 |
+
$dup_tests['SRV']['ALL'] = !in_array('Fail', $dup_tests['SRV']) ? 'Pass' : 'Fail';
|
88 |
|
89 |
//RESERVED FILES
|
90 |
$dup_tests['RES']['INSTALL'] = !(self::hasInstallerFiles()) ? 'Pass' : 'Fail';
|
91 |
+
$dup_tests['Success'] = $dup_tests['PHP']['ALL'] == 'Pass' && $dup_tests['IO']['ALL'] == 'Pass' && $dup_tests['SRV']['ALL'] == 'Pass' && $dup_tests['RES']['INSTALL'] == 'Pass';
|
92 |
+
|
93 |
+
$dup_tests['Warning'] = $dup_tests['IO']['WPROOT'] == 'Warn';
|
|
|
|
|
|
|
94 |
|
95 |
return $dup_tests;
|
96 |
}
|
100 |
*
|
101 |
* @return array An array of system checks
|
102 |
*/
|
103 |
+
public static function getChecks() {
|
|
|
104 |
$checks = array();
|
105 |
|
106 |
//PHP/SYSTEM SETTINGS
|
107 |
+
//Web Server
|
108 |
$php_test0 = false;
|
109 |
foreach ($GLOBALS['DUPLICATOR_SERVER_LIST'] as $value) {
|
110 |
if (stristr($_SERVER['SERVER_SOFTWARE'], $value)) {
|
119 |
$php_test2 = ($php_test2 > DUPLICATOR_SCAN_TIMEOUT) || (strcmp($php_test2, 'Off') == 0 || $php_test2 == 0) ? true : false;
|
120 |
$php_test3 = function_exists('mysqli_connect');
|
121 |
$php_test4 = DUP_Util::$on_php_53_plus ? true : false;
|
122 |
+
|
123 |
+
$checks['SRV']['PHP']['websrv'] = $php_test0;
|
124 |
$checks['SRV']['PHP']['openbase'] = $php_test1;
|
125 |
+
$checks['SRV']['PHP']['maxtime'] = $php_test2;
|
126 |
+
$checks['SRV']['PHP']['mysqli'] = $php_test3;
|
127 |
+
$checks['SRV']['PHP']['version'] = $php_test4;
|
128 |
+
$checks['SRV']['PHP']['ALL'] = ($php_test0 && $php_test1 && $php_test2 && $php_test3 && $php_test4) ? 'Good' : 'Warn';
|
129 |
|
130 |
//WORDPRESS SETTINGS
|
131 |
global $wp_version;
|
132 |
$wp_test1 = version_compare($wp_version, DUPLICATOR_SCAN_MIN_WP) >= 0 ? true : false;
|
133 |
|
134 |
//Core Files
|
135 |
+
$files = array();
|
136 |
+
$files['wp-config.php'] = file_exists(DUP_Util::safePath(DUPLICATOR_WPROOTPATH . '/wp-config.php'));
|
137 |
|
138 |
/** searching wp-config in working word press is not worthy
|
139 |
* if this script is executing that means wp-config.php exists :)
|
145 |
if (isset($_POST['file_notice']) && isset($_POST['dir_notice'])) {
|
146 |
//means if there are core directories excluded or core files excluded return false
|
147 |
if ((bool) $_POST['file_notice'] || (bool) $_POST['dir_notice'])
|
148 |
+
$wp_test2 = false;
|
149 |
+
else
|
150 |
+
$wp_test2 = true;
|
151 |
}else {
|
152 |
$wp_test2 = $files['wp-config.php'];
|
153 |
}
|
154 |
|
155 |
//Cache
|
156 |
+
/*
|
157 |
+
$Package = DUP_Package::getActive();
|
158 |
+
$cache_path = DUP_Util::safePath(WP_CONTENT_DIR) . '/cache';
|
159 |
+
$dirEmpty = DUP_Util::isDirectoryEmpty($cache_path);
|
160 |
+
$dirSize = DUP_Util::getDirectorySize($cache_path);
|
161 |
$cach_filtered = in_array($cache_path, explode(';', $Package->Archive->FilterDirs));
|
162 |
+
$wp_test3 = ($cach_filtered || $dirEmpty || $dirSize < DUPLICATOR_SCAN_CACHESIZE ) ? true : false;
|
163 |
+
*/
|
164 |
+
$wp_test4 = is_multisite();
|
165 |
|
166 |
$checks['SRV']['WP']['version'] = $wp_test1;
|
167 |
+
$checks['SRV']['WP']['core'] = $wp_test2;
|
168 |
+
// $checks['SRV']['WP']['cache'] = $wp_test3;
|
169 |
+
$checks['SRV']['WP']['ismu'] = $wp_test4;
|
170 |
+
// $checks['SRV']['WP']['ALL'] = $wp_test1 && $wp_test2 && $wp_test3 && !$wp_test4 ? 'Good' : 'Warn';
|
171 |
+
$checks['SRV']['WP']['ALL'] = $wp_test1 && $wp_test2 && !$wp_test4 ? 'Good' : 'Warn';
|
172 |
|
173 |
return $checks;
|
174 |
}
|
178 |
*
|
179 |
* @return bool True if any reserved files are found
|
180 |
*/
|
181 |
+
public static function hasInstallerFiles() {
|
|
|
182 |
$files = self::getInstallerFiles();
|
183 |
foreach ($files as $file => $path) {
|
184 |
+
if (false !== strpos($path, '*')) {
|
185 |
$glob_files = glob($path);
|
186 |
if (!empty($glob_files)) {
|
187 |
return true;
|
188 |
}
|
189 |
+
} elseif (file_exists($path))
|
190 |
+
return true;
|
191 |
}
|
192 |
return false;
|
193 |
}
|
194 |
+
|
195 |
/**
|
196 |
* Gets a list of all the installer files by name and full path
|
197 |
+
*
|
198 |
+
* @remarks
|
199 |
+
* FILES: installer.php, installer-backup.php, dup-installer-bootlog__[HASH].txt
|
200 |
+
* DIRS: dup-installer
|
201 |
+
* DEV FILES: wp-config.orig
|
202 |
+
* Last set is for lazy developer cleanup files that a developer may have
|
203 |
+
* accidently left around lets be proactive for the user just in case.
|
204 |
+
*
|
205 |
* @return array [file_name, file_path]
|
206 |
*/
|
207 |
+
public static function getInstallerFiles() {
|
|
|
208 |
// alphanumeric 7 time, then -(dash), then 8 digits
|
209 |
+
|
210 |
+
$retArr = array(
|
211 |
+
basename(DUPLICATOR_INSTALLER_DIRECTORY) . ' ' . esc_html__('(directory)', 'duplicator') => DUPLICATOR_INSTALLER_DIRECTORY,
|
212 |
+
DUPLICATOR_INSTALL_PHP => DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_PHP,
|
213 |
+
DUPLICATOR_INSTALL_BAK => DUPLICATOR_WPROOTPATH . DUPLICATOR_INSTALL_BAK,
|
214 |
+
'dup-installer-bootlog__[HASH].txt' => DUPLICATOR_WPROOTPATH .'dup-installer-bootlog__'.DUPLICATOR_INSTALLER_HASH_PATTERN.'.txt',
|
215 |
+
);
|
216 |
+
if (DUPLICATOR_INSTALL_SITE_OVERWRITE_ON) {
|
217 |
+
$retArr['dup-wp-config-arc__[HASH].txt'] = DUPLICATOR_WPROOTPATH . 'dup-wp-config-arc__'.DUPLICATOR_INSTALLER_HASH_PATTERN.'.txt';
|
218 |
+
}
|
219 |
+
return $retArr;
|
220 |
}
|
221 |
|
222 |
/**
|
224 |
*
|
225 |
* @return string IP of the client machine
|
226 |
*/
|
227 |
+
public static function getClientIP() {
|
|
|
228 |
if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) {
|
229 |
return $_SERVER["HTTP_X_FORWARDED_FOR"];
|
230 |
} else if (array_key_exists('REMOTE_ADDR', $_SERVER)) {
|
236 |
}
|
237 |
|
238 |
/**
|
239 |
+
* Get PHP memory usage
|
240 |
*
|
241 |
+
* @return string Returns human readable memory usage.
|
242 |
*/
|
243 |
+
public static function getPHPMemory($peak = false) {
|
|
|
244 |
if ($peak) {
|
245 |
$result = 'Unable to read PHP peak memory usage';
|
246 |
if (function_exists('memory_get_peak_usage')) {
|
254 |
}
|
255 |
return $result;
|
256 |
}
|
257 |
+
|
258 |
+
}
|
classes/class.settings.php
CHANGED
@@ -1,10 +1,20 @@
|
|
1 |
<?php
|
2 |
-
|
|
|
3 |
|
4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
class DUP_Settings
|
6 |
{
|
7 |
-
|
8 |
const OPT_SETTINGS = 'duplicator_settings';
|
9 |
|
10 |
public static $Data;
|
@@ -30,12 +40,12 @@ class DUP_Settings
|
|
30 |
public static function Get($key = '') {
|
31 |
$result = null;
|
32 |
if (isset(self::$Data[$key])) {
|
33 |
-
$result = self::$Data[$key];
|
34 |
} else {
|
35 |
$defaults = self::GetAllDefaults();
|
36 |
if (isset($defaults[$key])) {
|
37 |
$result = $defaults[$key];
|
38 |
-
}
|
39 |
}
|
40 |
return $result;
|
41 |
}
|
@@ -79,38 +89,20 @@ class DUP_Settings
|
|
79 |
self::$Data = $defaults;
|
80 |
return self::Save();
|
81 |
}
|
82 |
-
|
83 |
-
/**
|
84 |
-
* LegacyClean: Cleans up legacy data
|
85 |
-
*/
|
86 |
-
public static function LegacyClean() {
|
87 |
-
global $wpdb;
|
88 |
-
|
89 |
-
//PRE 5.0
|
90 |
-
$table = $wpdb->prefix."duplicator";
|
91 |
-
$wpdb->query("DROP TABLE IF EXISTS $table");
|
92 |
-
delete_option('duplicator_pack_passcount');
|
93 |
-
delete_option('duplicator_add1_passcount');
|
94 |
-
delete_option('duplicator_add1_clicked');
|
95 |
-
delete_option('duplicator_options');
|
96 |
-
|
97 |
-
//PRE 5.n
|
98 |
-
//Next version here if needed
|
99 |
-
}
|
100 |
-
|
101 |
/**
|
102 |
* DeleteWPOption: Cleans up legacy data
|
103 |
*/
|
104 |
public static function DeleteWPOption($optionName) {
|
105 |
-
|
106 |
if ( in_array($optionName, $GLOBALS['DUPLICATOR_OPTS_DELETE']) ) {
|
107 |
-
return delete_option($optionName);
|
108 |
}
|
109 |
return false;
|
110 |
}
|
111 |
-
|
112 |
-
|
113 |
-
public static function GetAllDefaults() {
|
114 |
$default = array();
|
115 |
$default['version'] = self::$Version;
|
116 |
|
@@ -120,7 +112,7 @@ class DUP_Settings
|
|
120 |
$default['uninstall_files'] = isset(self::$Data['uninstall_files']) ? self::$Data['uninstall_files'] : true;
|
121 |
//Flag used to remove all tables
|
122 |
$default['uninstall_tables'] = isset(self::$Data['uninstall_tables']) ? self::$Data['uninstall_tables'] : true;
|
123 |
-
|
124 |
//Flag used to show debug info
|
125 |
$default['package_debug'] = isset(self::$Data['package_debug']) ? self::$Data['package_debug'] : false;
|
126 |
//Flag used to enable mysqldump
|
@@ -131,10 +123,15 @@ class DUP_Settings
|
|
131 |
$default['package_phpdump_qrylimit'] = isset(self::$Data['package_phpdump_qrylimit']) ? self::$Data['package_phpdump_qrylimit'] : "100";
|
132 |
//Optional mysqldump search path
|
133 |
$default['package_zip_flush'] = isset(self::$Data['package_zip_flush']) ? self::$Data['package_zip_flush'] : false;
|
134 |
-
|
135 |
//Flag for .htaccess file
|
136 |
$default['storage_htaccess_off'] = isset(self::$Data['storage_htaccess_off']) ? self::$Data['storage_htaccess_off'] : false;
|
137 |
-
|
|
|
|
|
|
|
|
|
|
|
138 |
return $default;
|
139 |
}
|
140 |
}
|
1 |
<?php
|
2 |
+
// Exit if accessed directly
|
3 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
4 |
|
5 |
|
6 |
+
abstract class DUP_Archive_Build_Mode
|
7 |
+
{
|
8 |
+
const Unconfigured = -1;
|
9 |
+
const Auto = 0; // should no longer be used
|
10 |
+
// const Shell_Exec = 1;
|
11 |
+
const ZipArchive = 2;
|
12 |
+
const DupArchive = 3;
|
13 |
+
}
|
14 |
+
|
15 |
class DUP_Settings
|
16 |
{
|
17 |
+
|
18 |
const OPT_SETTINGS = 'duplicator_settings';
|
19 |
|
20 |
public static $Data;
|
40 |
public static function Get($key = '') {
|
41 |
$result = null;
|
42 |
if (isset(self::$Data[$key])) {
|
43 |
+
$result = self::$Data[$key];
|
44 |
} else {
|
45 |
$defaults = self::GetAllDefaults();
|
46 |
if (isset($defaults[$key])) {
|
47 |
$result = $defaults[$key];
|
48 |
+
}
|
49 |
}
|
50 |
return $result;
|
51 |
}
|
89 |
self::$Data = $defaults;
|
90 |
return self::Save();
|
91 |
}
|
92 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
/**
|
94 |
* DeleteWPOption: Cleans up legacy data
|
95 |
*/
|
96 |
public static function DeleteWPOption($optionName) {
|
97 |
+
|
98 |
if ( in_array($optionName, $GLOBALS['DUPLICATOR_OPTS_DELETE']) ) {
|
99 |
+
return delete_option($optionName);
|
100 |
}
|
101 |
return false;
|
102 |
}
|
103 |
+
|
104 |
+
|
105 |
+
public static function GetAllDefaults() {
|
106 |
$default = array();
|
107 |
$default['version'] = self::$Version;
|
108 |
|
112 |
$default['uninstall_files'] = isset(self::$Data['uninstall_files']) ? self::$Data['uninstall_files'] : true;
|
113 |
//Flag used to remove all tables
|
114 |
$default['uninstall_tables'] = isset(self::$Data['uninstall_tables']) ? self::$Data['uninstall_tables'] : true;
|
115 |
+
|
116 |
//Flag used to show debug info
|
117 |
$default['package_debug'] = isset(self::$Data['package_debug']) ? self::$Data['package_debug'] : false;
|
118 |
//Flag used to enable mysqldump
|
123 |
$default['package_phpdump_qrylimit'] = isset(self::$Data['package_phpdump_qrylimit']) ? self::$Data['package_phpdump_qrylimit'] : "100";
|
124 |
//Optional mysqldump search path
|
125 |
$default['package_zip_flush'] = isset(self::$Data['package_zip_flush']) ? self::$Data['package_zip_flush'] : false;
|
126 |
+
|
127 |
//Flag for .htaccess file
|
128 |
$default['storage_htaccess_off'] = isset(self::$Data['storage_htaccess_off']) ? self::$Data['storage_htaccess_off'] : false;
|
129 |
+
|
130 |
+
// Initial archive build mode
|
131 |
+
$default['archive_build_mode'] = isset(self::$Data['archive_build_mode']) ? self::$Data['archive_build_mode'] : DUP_Archive_Build_Mode::ZipArchive;
|
132 |
+
|
133 |
+
$default['active_package_id'] = -1;
|
134 |
+
|
135 |
return $default;
|
136 |
}
|
137 |
}
|
classes/package/class.pack.archive.filters.php
CHANGED
@@ -1,84 +1,86 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* The base class for all filter types Directories/Files/Extentions
|
4 |
-
*
|
5 |
-
* @package Duplicator
|
6 |
-
* @subpackage classes/package
|
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 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
*
|
54 |
-
*
|
55 |
-
*
|
56 |
-
*
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
//Contains all
|
63 |
-
public $
|
64 |
-
//Contains all
|
65 |
-
public $
|
66 |
-
|
67 |
-
public $
|
68 |
-
public $
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
$this->
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* The base class for all filter types Directories/Files/Extentions
|
4 |
+
*
|
5 |
+
* @package Duplicator
|
6 |
+
* @subpackage classes/package
|
7 |
+
*
|
8 |
+
*/
|
9 |
+
|
10 |
+
// Exit if accessed directly
|
11 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
12 |
+
|
13 |
+
class DUP_Archive_Filter_Scope_Base
|
14 |
+
{
|
15 |
+
//All internal storage items that duplicator decides to filter
|
16 |
+
public $Core = array();
|
17 |
+
//Global filter items added from settings
|
18 |
+
public $Global = array();
|
19 |
+
//Items when creating a package or template that a user decides to filter
|
20 |
+
public $Instance = array();
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* The filter types that belong to directories
|
25 |
+
*
|
26 |
+
* @package Duplicator
|
27 |
+
* @subpackage classes/package
|
28 |
+
*
|
29 |
+
*/
|
30 |
+
class DUP_Archive_Filter_Scope_Directory extends DUP_Archive_Filter_Scope_Base
|
31 |
+
{
|
32 |
+
//Items that are not readable
|
33 |
+
public $Warning = array();
|
34 |
+
//Items that are not readable
|
35 |
+
public $Unreadable = array();
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* The filter types that belong to files
|
40 |
+
*
|
41 |
+
* @package Duplicator
|
42 |
+
* @subpackage classes/package
|
43 |
+
*
|
44 |
+
*/
|
45 |
+
class DUP_Archive_Filter_Scope_File extends DUP_Archive_Filter_Scope_Directory
|
46 |
+
{
|
47 |
+
//Items that are too large
|
48 |
+
public $Size = array();
|
49 |
+
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* The filter information object which store all information about the filtered
|
54 |
+
* data that is gathered to the execution of a scan process
|
55 |
+
*
|
56 |
+
* @package Duplicator
|
57 |
+
* @subpackage classes/package
|
58 |
+
*
|
59 |
+
*/
|
60 |
+
class DUP_Archive_Filter_Info
|
61 |
+
{
|
62 |
+
//Contains all folder filter info
|
63 |
+
public $Dirs = array();
|
64 |
+
//Contains all file filter info
|
65 |
+
public $Files = array();
|
66 |
+
//Contains all extensions filter info
|
67 |
+
public $Exts = array();
|
68 |
+
public $UDirCount = 0;
|
69 |
+
public $UFileCount = 0;
|
70 |
+
public $UExtCount = 0;
|
71 |
+
public $TreeSize;
|
72 |
+
public $TreeWarning;
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Init this object
|
76 |
+
*/
|
77 |
+
public function __construct()
|
78 |
+
{
|
79 |
+
$this->Dirs = new DUP_Archive_Filter_Scope_Directory();
|
80 |
+
$this->Files = new DUP_Archive_Filter_Scope_File();
|
81 |
+
$this->Exts = new DUP_Archive_Filter_Scope_Base();
|
82 |
+
$this->TreeSize = array();
|
83 |
+
$this->TreeWarning = array();
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
classes/package/class.pack.archive.php
CHANGED
@@ -1,605 +1,661 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.archive.
|
6 |
-
require_once (DUPLICATOR_PLUGIN_PATH.'
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
*
|
12 |
-
*
|
13 |
-
*
|
14 |
-
* @
|
15 |
-
*
|
16 |
-
* @
|
17 |
-
* @
|
18 |
-
* @
|
19 |
-
*
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
public $
|
28 |
-
|
29 |
-
|
30 |
-
public $
|
31 |
-
|
32 |
-
|
33 |
-
public $
|
34 |
-
public $
|
35 |
-
public $
|
36 |
-
public $
|
37 |
-
public $
|
38 |
-
public $
|
39 |
-
public $
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
private $
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
$this->
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
$this->wpCorePaths[] = DUP_Util::safePath(
|
61 |
-
$this->wpCorePaths[] = DUP_Util::safePath(WP_CONTENT_DIR . "/
|
62 |
-
$this->wpCorePaths[] = DUP_Util::safePath(
|
63 |
-
$this->wpCorePaths[] = DUP_Util::safePath(get_theme_root());
|
64 |
-
$this->wpCorePaths[] = DUP_Util::safePath("{$rootPath}/wp-includes");
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
*
|
72 |
-
*
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
*
|
135 |
-
*
|
136 |
-
*
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
$
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
*
|
180 |
-
*
|
181 |
-
*
|
182 |
-
*
|
183 |
-
*
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
$
|
189 |
-
$
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
*
|
208 |
-
*
|
209 |
-
*
|
210 |
-
*
|
211 |
-
*
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
);
|
544 |
-
}
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
$
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// Exit if accessed directly
|
3 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
4 |
+
|
5 |
+
require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/duparchive/class.pack.archive.duparchive.php');
|
6 |
+
require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.archive.filters.php');
|
7 |
+
require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.archive.zip.php');
|
8 |
+
require_once (DUPLICATOR_PLUGIN_PATH.'lib/forceutf8/Encoding.php');
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class for handling archive setup and build process
|
12 |
+
*
|
13 |
+
* Standard: PSR-2 (almost)
|
14 |
+
* @link http://www.php-fig.org/psr/psr-2
|
15 |
+
*
|
16 |
+
* @package DUP
|
17 |
+
* @subpackage classes/package
|
18 |
+
* @copyright (c) 2017, Snapcreek LLC
|
19 |
+
* @license https://opensource.org/licenses/GPL-3.0 GNU Public License
|
20 |
+
*
|
21 |
+
*/
|
22 |
+
class DUP_Archive
|
23 |
+
{
|
24 |
+
//PUBLIC
|
25 |
+
public $FilterDirs;
|
26 |
+
public $FilterFiles;
|
27 |
+
public $FilterExts;
|
28 |
+
public $FilterDirsAll = array();
|
29 |
+
public $FilterFilesAll = array();
|
30 |
+
public $FilterExtsAll = array();
|
31 |
+
public $FilterOn;
|
32 |
+
public $ExportOnlyDB;
|
33 |
+
public $File;
|
34 |
+
public $Format;
|
35 |
+
public $PackDir;
|
36 |
+
public $Size = 0;
|
37 |
+
public $Dirs = array();
|
38 |
+
public $Files = array();
|
39 |
+
public $FilterInfo;
|
40 |
+
public $RecursiveLinks = array();
|
41 |
+
|
42 |
+
//PROTECTED
|
43 |
+
protected $Package;
|
44 |
+
private $tmpFilterDirsAll = array();
|
45 |
+
private $wpCorePaths = array();
|
46 |
+
private $wpCoreExactPaths = array();
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Init this object
|
50 |
+
*/
|
51 |
+
public function __construct($package)
|
52 |
+
{
|
53 |
+
$this->Package = $package;
|
54 |
+
$this->FilterOn = false;
|
55 |
+
$this->ExportOnlyDB = false;
|
56 |
+
$this->FilterInfo = new DUP_Archive_Filter_Info();
|
57 |
+
|
58 |
+
$rootPath = DUP_Util::safePath(rtrim(DUPLICATOR_WPROOTPATH, '//'));
|
59 |
+
|
60 |
+
$this->wpCorePaths[] = DUP_Util::safePath("{$rootPath}/wp-admin");
|
61 |
+
$this->wpCorePaths[] = DUP_Util::safePath(WP_CONTENT_DIR . "/uploads");
|
62 |
+
$this->wpCorePaths[] = DUP_Util::safePath(WP_CONTENT_DIR . "/languages");
|
63 |
+
$this->wpCorePaths[] = DUP_Util::safePath(get_theme_root());
|
64 |
+
$this->wpCorePaths[] = DUP_Util::safePath("{$rootPath}/wp-includes");
|
65 |
+
|
66 |
+
$this->wpCoreExactPaths[] = DUP_Util::safePath("{$rootPath}");
|
67 |
+
$this->wpCoreExactPaths[] = DUP_Util::safePath(WP_CONTENT_DIR);
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Builds the archive based on the archive type
|
72 |
+
*
|
73 |
+
* @param obj $package The package object that started this process
|
74 |
+
*
|
75 |
+
* @return null
|
76 |
+
*/
|
77 |
+
public function build($package, $rethrow_exception = false)
|
78 |
+
{
|
79 |
+
DUP_LOG::trace("b1");
|
80 |
+
$this->Package = $package;
|
81 |
+
if (!isset($this->PackDir) && !is_dir($this->PackDir)) throw new Exception("The 'PackDir' property must be a valid directory.");
|
82 |
+
if (!isset($this->File)) throw new Exception("A 'File' property must be set.");
|
83 |
+
|
84 |
+
DUP_LOG::trace("b2");
|
85 |
+
$completed = false;
|
86 |
+
|
87 |
+
switch ($this->Format) {
|
88 |
+
case 'TAR': break;
|
89 |
+
case 'TAR-GZIP': break;
|
90 |
+
case 'DAF':
|
91 |
+
$completed = DUP_DupArchive::create($this, $this->Package->BuildProgress, $this->Package);
|
92 |
+
|
93 |
+
$this->Package->Update();
|
94 |
+
break;
|
95 |
+
|
96 |
+
default:
|
97 |
+
if (class_exists('ZipArchive')) {
|
98 |
+
$this->Format = 'ZIP';
|
99 |
+
DUP_Zip::create($this, $this->Package->BuildProgress);
|
100 |
+
$completed = true;
|
101 |
+
}
|
102 |
+
break;
|
103 |
+
}
|
104 |
+
|
105 |
+
DUP_LOG::Trace("Completed build or build thread");
|
106 |
+
|
107 |
+
if($this->Package->BuildProgress === null) {
|
108 |
+
// Zip path
|
109 |
+
DUP_LOG::Trace("Completed Zip");
|
110 |
+
$storePath = "{$this->Package->StorePath}/{$this->File}";
|
111 |
+
$this->Size = @filesize($storePath);
|
112 |
+
$this->Package->setStatus(DUP_PackageStatus::ARCDONE);
|
113 |
+
} else if($completed) {
|
114 |
+
// Completed DupArchive path
|
115 |
+
DUP_LOG::Trace("Completed DupArchive build");
|
116 |
+
if ($this->Package->BuildProgress->failed) {
|
117 |
+
DUP_LOG::Trace("Error building DupArchive");
|
118 |
+
$this->Package->setStatus(DUP_PackageStatus::ERROR);
|
119 |
+
} else {
|
120 |
+
$filepath = DUP_Util::safePath("{$this->Package->StorePath}/{$this->File}");
|
121 |
+
$this->Size = @filesize($filepath);
|
122 |
+
$this->Package->setStatus(DUP_PackageStatus::ARCDONE);
|
123 |
+
DUP_LOG::Trace("Done building archive");
|
124 |
+
}
|
125 |
+
} else {
|
126 |
+
DUP_Log::trace("DupArchive chunk done but package not completed yet");
|
127 |
+
}
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Builds a list of files and directories to be included in the archive
|
132 |
+
*
|
133 |
+
* Get the directory size recursively, but don't calc the snapshot directory, exclusion directories
|
134 |
+
* @link http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx Windows filename restrictions
|
135 |
+
*
|
136 |
+
* @return obj Returns a DUP_Archive object
|
137 |
+
*/
|
138 |
+
public function getScannerData()
|
139 |
+
{
|
140 |
+
$this->createFilterInfo();
|
141 |
+
$rootPath = DUP_Util::safePath(rtrim(DUPLICATOR_WPROOTPATH, '//'));
|
142 |
+
$rootPath = (trim($rootPath) == '') ? '/' : $rootPath;
|
143 |
+
|
144 |
+
//If the root directory is a filter then skip it all
|
145 |
+
if (in_array($this->PackDir, $this->FilterDirsAll) || $this->Package->Archive->ExportOnlyDB) {
|
146 |
+
$this->Dirs = array();
|
147 |
+
} else {
|
148 |
+
$this->Dirs[] = $this->PackDir;
|
149 |
+
$this->getFileLists($rootPath);
|
150 |
+
$this->setDirFilters();
|
151 |
+
$this->setFileFilters();
|
152 |
+
$this->setTreeFilters();
|
153 |
+
}
|
154 |
+
|
155 |
+
$this->FilterDirsAll = array_merge($this->FilterDirsAll, $this->FilterInfo->Dirs->Unreadable);
|
156 |
+
$this->FilterFilesAll = array_merge($this->FilterFilesAll, $this->FilterInfo->Files->Unreadable);
|
157 |
+
sort($this->FilterDirsAll);
|
158 |
+
|
159 |
+
return $this;
|
160 |
+
}
|
161 |
+
|
162 |
+
/**
|
163 |
+
* Save any property of this class through reflection
|
164 |
+
*
|
165 |
+
* @param $property A valid public property in this class
|
166 |
+
* @param $value The value for the new dynamic property
|
167 |
+
*
|
168 |
+
* @return bool Returns true if the value has changed.
|
169 |
+
*/
|
170 |
+
public function saveActiveItem($package, $property, $value)
|
171 |
+
{
|
172 |
+
$package = DUP_Package::getActive();
|
173 |
+
$reflectionClass = new ReflectionClass($package->Archive);
|
174 |
+
$reflectionClass->getProperty($property)->setValue($package->Archive, $value);
|
175 |
+
return update_option(DUP_Package::OPT_ACTIVE, $package);
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Properly creates the directory filter list that is used for filtering directories
|
180 |
+
*
|
181 |
+
* @param string $dirs A semi-colon list of dir paths
|
182 |
+
* /path1_/path/;/path1_/path2/;
|
183 |
+
*
|
184 |
+
* @returns string A cleaned up list of directory filters
|
185 |
+
*/
|
186 |
+
public function parseDirectoryFilter($dirs = "")
|
187 |
+
{
|
188 |
+
$dirs = str_replace(array("\n", "\t", "\r"), '', $dirs);
|
189 |
+
$filters = "";
|
190 |
+
$dir_array = array_unique(explode(";", $dirs));
|
191 |
+
$clean_array = array();
|
192 |
+
foreach ($dir_array as $val) {
|
193 |
+
if (strlen($val) >= 2) {
|
194 |
+
$clean_array[] = DUP_Util::safePath(trim(rtrim($val, "/\\"))) ;
|
195 |
+
}
|
196 |
+
}
|
197 |
+
|
198 |
+
if (count($clean_array)) {
|
199 |
+
$clean_array = array_unique($clean_array);
|
200 |
+
sort($clean_array);
|
201 |
+
$filters = implode(';', $clean_array) . ';';
|
202 |
+
}
|
203 |
+
return $filters ;
|
204 |
+
}
|
205 |
+
|
206 |
+
/**
|
207 |
+
* Properly creates the file filter list that is used for filtering files
|
208 |
+
*
|
209 |
+
* @param string $dirs A semi-colon list of dir paths
|
210 |
+
* /path1_/path/file1.ext;/path1_/path2/file2.ext;
|
211 |
+
*
|
212 |
+
* @returns string A cleaned up list of file filters
|
213 |
+
*/
|
214 |
+
public function parseFileFilter($files = "")
|
215 |
+
{
|
216 |
+
$files = str_replace(array("\n", "\t", "\r"), '', $files);
|
217 |
+
$filters = "";
|
218 |
+
$file_array = array_unique(explode(";", $files));
|
219 |
+
$clean_array = array();
|
220 |
+
foreach ($file_array as $val) {
|
221 |
+
if (strlen($val) >= 2) {
|
222 |
+
$clean_array[] = DUP_Util::safePath(trim(rtrim($val, "/\\"))) ;
|
223 |
+
}
|
224 |
+
}
|
225 |
+
|
226 |
+
if (count($clean_array)) {
|
227 |
+
$clean_array = array_unique($clean_array);
|
228 |
+
sort($clean_array);
|
229 |
+
$filters = implode(';', $clean_array) . ';';
|
230 |
+
}
|
231 |
+
return $filters ;
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Properly creates the extension filter list that is used for filtering extensions
|
236 |
+
*
|
237 |
+
* @param string $dirs A semi-colon list of dir paths
|
238 |
+
* .jpg;.zip;.gif;
|
239 |
+
*
|
240 |
+
* @returns string A cleaned up list of extension filters
|
241 |
+
*/
|
242 |
+
public function parseExtensionFilter($extensions = "")
|
243 |
+
{
|
244 |
+
$filter_exts = "";
|
245 |
+
if (strlen($extensions) >= 1 && $extensions != ";") {
|
246 |
+
$filter_exts = str_replace(array(' ', '.'), '', $extensions);
|
247 |
+
$filter_exts = str_replace(",", ";", $filter_exts);
|
248 |
+
$filter_exts = DUP_Util::appendOnce($extensions, ";");
|
249 |
+
}
|
250 |
+
return $filter_exts;
|
251 |
+
}
|
252 |
+
|
253 |
+
/**
|
254 |
+
* Creates the filter info setup data used for filtering the archive
|
255 |
+
*
|
256 |
+
* @return null
|
257 |
+
*/
|
258 |
+
private function createFilterInfo()
|
259 |
+
{
|
260 |
+
//FILTER: INSTANCE ITEMS
|
261 |
+
//Add the items generated at create time
|
262 |
+
if ($this->FilterOn) {
|
263 |
+
$this->FilterInfo->Dirs->Instance = array_map('DUP_Util::safePath', explode(";", $this->FilterDirs, -1));
|
264 |
+
$this->FilterInfo->Files->Instance = array_map('DUP_Util::safePath', explode(";", $this->FilterFiles, -1));
|
265 |
+
$this->FilterInfo->Exts->Instance = explode(";", $this->FilterExts, -1);
|
266 |
+
}
|
267 |
+
|
268 |
+
//FILTER: CORE ITMES
|
269 |
+
//Filters Duplicator free packages & All pro local directories
|
270 |
+
$wp_root = rtrim(DUPLICATOR_WPROOTPATH, '/');
|
271 |
+
$upload_dir = wp_upload_dir();
|
272 |
+
$upload_dir = isset($upload_dir['basedir']) ? basename($upload_dir['basedir']) : 'uploads';
|
273 |
+
$wp_content = str_replace("\\", "/", WP_CONTENT_DIR);
|
274 |
+
$wp_content_upload = "{$wp_content}/{$upload_dir}";
|
275 |
+
$this->FilterInfo->Dirs->Core = array(
|
276 |
+
//WP-ROOT
|
277 |
+
$wp_root . '/wp-snapshots',
|
278 |
+
|
279 |
+
//WP-CONTENT
|
280 |
+
$wp_content . '/backups-dup-pro',
|
281 |
+
$wp_content . '/ai1wm-backups',
|
282 |
+
$wp_content . '/backupwordpress',
|
283 |
+
$wp_content . '/content/cache',
|
284 |
+
$wp_content . '/contents/cache',
|
285 |
+
$wp_content . '/infinitewp/backups',
|
286 |
+
$wp_content . '/managewp/backups',
|
287 |
+
$wp_content . '/old-cache',
|
288 |
+
$wp_content . '/plugins/all-in-one-wp-migration/storage',
|
289 |
+
$wp_content . '/updraft',
|
290 |
+
$wp_content . '/wishlist-backup',
|
291 |
+
$wp_content . '/wfcache',
|
292 |
+
$wp_content . '/cache',
|
293 |
+
//WP-CONTENT-UPLOADS
|
294 |
+
$wp_content_upload . '/aiowps_backups',
|
295 |
+
$wp_content_upload . '/backupbuddy_temp',
|
296 |
+
$wp_content_upload . '/backupbuddy_backups',
|
297 |
+
$wp_content_upload . '/ithemes-security/backups',
|
298 |
+
$wp_content_upload . '/mainwp/backup',
|
299 |
+
$wp_content_upload . '/pb_backupbuddy',
|
300 |
+
$wp_content_upload . '/snapshots',
|
301 |
+
$wp_content_upload . '/sucuri',
|
302 |
+
$wp_content_upload . '/wp-clone',
|
303 |
+
$wp_content_upload . '/wp_all_backup',
|
304 |
+
$wp_content_upload . '/wpbackitup_backups'
|
305 |
+
);
|
306 |
+
|
307 |
+
if ($GLOBALS['DUPLICATOR_GLOBAL_FILE_FILTERS_ON']) {
|
308 |
+
$this->FilterInfo->Files->Global = $GLOBALS['DUPLICATOR_GLOBAL_FILE_FILTERS'];
|
309 |
+
}
|
310 |
+
|
311 |
+
$this->FilterDirsAll = array_merge($this->FilterInfo->Dirs->Instance, $this->FilterInfo->Dirs->Core);
|
312 |
+
$this->FilterExtsAll = array_merge($this->FilterInfo->Exts->Instance, $this->FilterInfo->Exts->Core);
|
313 |
+
$this->FilterFilesAll = array_merge($this->FilterInfo->Files->Instance, $this->FilterInfo->Files->Global);
|
314 |
+
|
315 |
+
$this->FilterFilesAll[] = DUPLICATOR_WPROOTPATH . '.htaccess';
|
316 |
+
$this->FilterFilesAll[] = DUPLICATOR_WPROOTPATH . 'web.config';
|
317 |
+
$this->FilterFilesAll[] = DUPLICATOR_WPROOTPATH . 'wp-config.php';
|
318 |
+
|
319 |
+
$this->tmpFilterDirsAll = $this->FilterDirsAll;
|
320 |
+
|
321 |
+
//PHP 5 on windows decode patch
|
322 |
+
if (! DUP_Util::$PHP7_plus && DUP_Util::isWindows()) {
|
323 |
+
foreach ($this->tmpFilterDirsAll as $key => $value) {
|
324 |
+
if ( preg_match('/[^\x20-\x7f]/', $value)) {
|
325 |
+
$this->tmpFilterDirsAll[$key] = utf8_decode($value);
|
326 |
+
}
|
327 |
+
}
|
328 |
+
}
|
329 |
+
}
|
330 |
+
|
331 |
+
/**
|
332 |
+
* Get All Directories then filter
|
333 |
+
*
|
334 |
+
* @return null
|
335 |
+
*/
|
336 |
+
private function setDirFilters()
|
337 |
+
{
|
338 |
+
$this->FilterInfo->Dirs->Warning = array();
|
339 |
+
$this->FilterInfo->Dirs->Unreadable = array();
|
340 |
+
$this->FilterInfo->Dirs->AddonSites = array();
|
341 |
+
|
342 |
+
$utf8_key_list = array();
|
343 |
+
$unset_key_list = array();
|
344 |
+
|
345 |
+
//Filter directories invalid test checks for:
|
346 |
+
// - characters over 250
|
347 |
+
// - invlaid characters
|
348 |
+
// - empty string
|
349 |
+
// - directories ending with period (Windows incompatable)
|
350 |
+
foreach ($this->Dirs as $key => $val) {
|
351 |
+
$name = basename($val);
|
352 |
+
|
353 |
+
//Dir is not readble remove flag for removal
|
354 |
+
if (! is_readable($this->Dirs[$key])) {
|
355 |
+
$unset_key_list[] = $key;
|
356 |
+
$this->FilterInfo->Dirs->Unreadable[] = DUP_Encoding::toUTF8($val);
|
357 |
+
}
|
358 |
+
|
359 |
+
//Locate invalid directories and warn
|
360 |
+
$invalid_test = strlen($val) > 244
|
361 |
+
|| preg_match('/(\/|\*|\?|\>|\<|\:|\\|\|)/', $name)
|
362 |
+
|| trim($name) == ''
|
363 |
+
|| (strrpos($name, '.') == strlen($name) - 1 && substr($name, -1) == '.')
|
364 |
+
|| preg_match('/[^\x20-\x7f]/', $name);
|
365 |
+
|
366 |
+
if ($invalid_test) {
|
367 |
+
$utf8_key_list[] = $key;
|
368 |
+
$this->FilterInfo->Dirs->Warning[] = DUP_Encoding::toUTF8($val);
|
369 |
+
}
|
370 |
+
|
371 |
+
//Check for other WordPress installs
|
372 |
+
if ($name === 'wp-admin') {
|
373 |
+
$parent_dir = realpath(dirname($this->Dirs[$key]));
|
374 |
+
if ($parent_dir != realpath(DUPLICATOR_WPROOTPATH)) {
|
375 |
+
if (file_exists("$parent_dir/wp-includes")) {
|
376 |
+
if (file_exists("$parent_dir/wp-config.php")) {
|
377 |
+
// Ensure we aren't adding any critical directories
|
378 |
+
$parent_name = basename($parent_dir);
|
379 |
+
if (($parent_name != 'wp-includes') && ($parent_name != 'wp-content') && ($parent_name != 'wp-admin')) {
|
380 |
+
$this->FilterInfo->Dirs->AddonSites[] = str_replace("\\", '/',$parent_dir);
|
381 |
+
}
|
382 |
+
}
|
383 |
+
}
|
384 |
+
}
|
385 |
+
}
|
386 |
+
|
387 |
+
}
|
388 |
+
|
389 |
+
//Try to repair utf8 paths
|
390 |
+
foreach ($utf8_key_list as $key) {
|
391 |
+
$this->Dirs[$key] = DUP_Encoding::toUTF8($this->Dirs[$key]);
|
392 |
+
}
|
393 |
+
|
394 |
+
//Remove unreadable items outside of main loop for performance
|
395 |
+
if (count($unset_key_list)) {
|
396 |
+
foreach ($unset_key_list as $key) {
|
397 |
+
unset($this->Dirs[$key]);
|
398 |
+
}
|
399 |
+
$this->Dirs = array_values($this->Dirs);
|
400 |
+
}
|
401 |
+
|
402 |
+
}
|
403 |
+
|
404 |
+
/**
|
405 |
+
* Get all files and filter out error prone subsets
|
406 |
+
*
|
407 |
+
* @return null
|
408 |
+
*/
|
409 |
+
private function setFileFilters()
|
410 |
+
{
|
411 |
+
//Init for each call to prevent concatination from stored entity objects
|
412 |
+
$this->Size = 0;
|
413 |
+
$this->FilterInfo->Files->Size = array();
|
414 |
+
$this->FilterInfo->Files->Warning = array();
|
415 |
+
$this->FilterInfo->Files->Unreadable = array();
|
416 |
+
|
417 |
+
$utf8_key_list = array();
|
418 |
+
$unset_key_list = array();
|
419 |
+
|
420 |
+
foreach ($this->Files as $key => $filePath) {
|
421 |
+
|
422 |
+
$fileName = basename($filePath);
|
423 |
+
|
424 |
+
if (! is_readable($filePath)) {
|
425 |
+
$unset_key_list[] = $key;
|
426 |
+
$this->FilterInfo->Files->Unreadable[] = $filePath;
|
427 |
+
continue;
|
428 |
+
}
|
429 |
+
|
430 |
+
$invalid_test = strlen($filePath) > 250
|
431 |
+
|| preg_match('/(\/|\*|\?|\>|\<|\:|\\|\|)/', $fileName)
|
432 |
+
|| trim($fileName) == ""
|
433 |
+
|| preg_match('/[^\x20-\x7f]/', $fileName);
|
434 |
+
|
435 |
+
if ($invalid_test) {
|
436 |
+
$utf8_key_list[] = $key;
|
437 |
+
$filePath = DUP_Encoding::toUTF8($filePath);
|
438 |
+
$fileName = basename($filePath);
|
439 |
+
$this->FilterInfo->Files->Warning[] = array(
|
440 |
+
'name' => $fileName,
|
441 |
+
'dir' => pathinfo($filePath, PATHINFO_DIRNAME),
|
442 |
+
'path' => $filePath);
|
443 |
+
|
444 |
+
}
|
445 |
+
|
446 |
+
$fileSize = @filesize($filePath);
|
447 |
+
$fileSize = empty($fileSize) ? 0 : $fileSize;
|
448 |
+
$this->Size += $fileSize;
|
449 |
+
|
450 |
+
if ($fileSize > DUPLICATOR_SCAN_WARNFILESIZE) {
|
451 |
+
$ext = pathinfo($filePath, PATHINFO_EXTENSION);
|
452 |
+
$this->FilterInfo->Files->Size[] = array(
|
453 |
+
'ubytes' => $fileSize,
|
454 |
+
'bytes' => DUP_Util::byteSize($fileSize, 0),
|
455 |
+
'name' => $fileName,
|
456 |
+
'dir' => pathinfo($filePath, PATHINFO_DIRNAME),
|
457 |
+
'path' => $filePath);
|
458 |
+
}
|
459 |
+
}
|
460 |
+
|
461 |
+
//Try to repair utf8 paths
|
462 |
+
foreach ($utf8_key_list as $key) {
|
463 |
+
$this->Files[$key] = DUP_Encoding::toUTF8($this->Files[$key]);
|
464 |
+
}
|
465 |
+
|
466 |
+
//Remove unreadable items outside of main loop for performance
|
467 |
+
if (count($unset_key_list)) {
|
468 |
+
foreach ($unset_key_list as $key) {
|
469 |
+
unset($this->Files[$key]);
|
470 |
+
}
|
471 |
+
$this->Files = array_values($this->Files);
|
472 |
+
}
|
473 |
+
|
474 |
+
}
|
475 |
+
|
476 |
+
/**
|
477 |
+
* Recursive function to get all directories in a wp install
|
478 |
+
*
|
479 |
+
* @notes:
|
480 |
+
* Older PHP logic which is more stable on older version of PHP
|
481 |
+
* NOTE RecursiveIteratorIterator is problematic on some systems issues include:
|
482 |
+
* - error 'too many files open' for recursion
|
483 |
+
* - $file->getExtension() is not reliable as it silently fails at least in php 5.2.17
|
484 |
+
* - issues with when a file has a permission such as 705 and trying to get info (had to fallback to pathinfo)
|
485 |
+
* - basic conclusion wait on the SPL libs until after php 5.4 is a requirments
|
486 |
+
* - tight recursive loop use caution for speed
|
487 |
+
*
|
488 |
+
* @return array Returns an array of directories to include in the archive
|
489 |
+
*/
|
490 |
+
private function getFileLists($path)
|
491 |
+
{
|
492 |
+
$handle = @opendir($path);
|
493 |
+
|
494 |
+
if ($handle) {
|
495 |
+
while (($file = readdir($handle)) !== false) {
|
496 |
+
|
497 |
+
if ($file == '.' || $file == '..') {
|
498 |
+
continue;
|
499 |
+
}
|
500 |
+
|
501 |
+
$fullPath = str_replace("\\", '/', "{$path}/{$file}");
|
502 |
+
|
503 |
+
// @todo: Don't leave it like this. Convert into an option on the package to not follow symbolic links
|
504 |
+
// if (is_dir($fullPath) && (is_link($fullPath) == false))
|
505 |
+
if (is_dir($fullPath)) {
|
506 |
+
|
507 |
+
$add = true;
|
508 |
+
if(!is_link($fullPath)){
|
509 |
+
foreach ($this->tmpFilterDirsAll as $key => $val) {
|
510 |
+
$trimmedFilterDir = rtrim($val, '/');
|
511 |
+
if ($fullPath == $trimmedFilterDir || strpos($fullPath, $trimmedFilterDir . '/') !== false) {
|
512 |
+
$add = false;
|
513 |
+
unset($this->tmpFilterDirsAll[$key]);
|
514 |
+
break;
|
515 |
+
}
|
516 |
+
}
|
517 |
+
}else{
|
518 |
+
//Convert relative path of link to absolute path
|
519 |
+
chdir($fullPath);
|
520 |
+
$link_path = realpath(readlink($fullPath));
|
521 |
+
chdir(dirname(__FILE__));
|
522 |
+
|
523 |
+
$link_pos = strpos($fullPath,$link_path);
|
524 |
+
if($link_pos === 0 && (strlen($link_path) < strlen($fullPath))){
|
525 |
+
$add = false;
|
526 |
+
$this->RecursiveLinks[] = $fullPath;
|
527 |
+
$this->FilterDirsAll[] = $fullPath;
|
528 |
+
}
|
529 |
+
}
|
530 |
+
|
531 |
+
if ($add) {
|
532 |
+
$this->getFileLists($fullPath);
|
533 |
+
$this->Dirs[] = $fullPath;
|
534 |
+
}
|
535 |
+
} else {
|
536 |
+
if ( ! (in_array(pathinfo($file, PATHINFO_EXTENSION), $this->FilterExtsAll)
|
537 |
+
|| in_array($fullPath, $this->FilterFilesAll)
|
538 |
+
|| in_array($file, $this->FilterFilesAll))) {
|
539 |
+
$this->Files[] = $fullPath;
|
540 |
+
}
|
541 |
+
}
|
542 |
+
}
|
543 |
+
closedir($handle);
|
544 |
+
}
|
545 |
+
return $this->Dirs;
|
546 |
+
}
|
547 |
+
|
548 |
+
/**
|
549 |
+
* Builds a tree for both file size warnings and name check warnings
|
550 |
+
* The trees are used to apply filters from the scan screen
|
551 |
+
*
|
552 |
+
* @return null
|
553 |
+
*/
|
554 |
+
private function setTreeFilters()
|
555 |
+
{
|
556 |
+
//-------------------------
|
557 |
+
//SIZE TREE
|
558 |
+
//BUILD: File Size tree
|
559 |
+
$dir_group = DUP_Util::array_group_by($this->FilterInfo->Files->Size, "dir" );
|
560 |
+
ksort($dir_group);
|
561 |
+
foreach ($dir_group as $dir => $files) {
|
562 |
+
$sum = 0;
|
563 |
+
foreach ($files as $key => $value) {
|
564 |
+
$sum += $value['ubytes'];
|
565 |
+
}
|
566 |
+
|
567 |
+
//Locate core paths, wp-admin, wp-includes, etc.
|
568 |
+
$iscore = 0;
|
569 |
+
foreach ($this->wpCorePaths as $core_dir) {
|
570 |
+
if (strpos(DUP_Util::safePath($dir), DUP_Util::safePath($core_dir)) !== false) {
|
571 |
+
$iscore = 1;
|
572 |
+
break;
|
573 |
+
}
|
574 |
+
}
|
575 |
+
// Check root and content exact dir
|
576 |
+
if (!$iscore) {
|
577 |
+
if (in_array($dir, $this->wpCoreExactPaths)) {
|
578 |
+
$iscore = 1;
|
579 |
+
}
|
580 |
+
}
|
581 |
+
|
582 |
+
$this->FilterInfo->TreeSize[] = array(
|
583 |
+
'size' => DUP_Util::byteSize($sum, 0),
|
584 |
+
'dir' => $dir,
|
585 |
+
'sdir' => str_replace(DUPLICATOR_WPROOTPATH, '', $dir),
|
586 |
+
'iscore' => $iscore,
|
587 |
+
'files' => $files
|
588 |
+
);
|
589 |
+
}
|
590 |
+
|
591 |
+
//-------------------------
|
592 |
+
//NAME TREE
|
593 |
+
//BUILD: Warning tree for file names
|
594 |
+
$dir_group = DUP_Util::array_group_by($this->FilterInfo->Files->Warning, "dir" );
|
595 |
+
ksort($dir_group);
|
596 |
+
foreach ($dir_group as $dir => $files) {
|
597 |
+
|
598 |
+
//Locate core paths, wp-admin, wp-includes, etc.
|
599 |
+
$iscore = 0;
|
600 |
+
foreach ($this->wpCorePaths as $core_dir) {
|
601 |
+
if (strpos($dir, $core_dir) !== false) {
|
602 |
+
$iscore = 1;
|
603 |
+
break;
|
604 |
+
}
|
605 |
+
}
|
606 |
+
// Check root and content exact dir
|
607 |
+
if (!$iscore) {
|
608 |
+
if (in_array($dir, $this->wpCoreExactPaths)) {
|
609 |
+
$iscore = 1;
|
610 |
+
}
|
611 |
+
}
|
612 |
+
|
613 |
+
$this->FilterInfo->TreeWarning[] = array(
|
614 |
+
'dir' => $dir,
|
615 |
+
'sdir' => str_replace(DUPLICATOR_WPROOTPATH, '', $dir),
|
616 |
+
'iscore' => $iscore,
|
617 |
+
'count' => count($files),
|
618 |
+
'files' => $files);
|
619 |
+
}
|
620 |
+
|
621 |
+
//BUILD: Warning tree for dir names
|
622 |
+
foreach ($this->FilterInfo->Dirs->Warning as $dir) {
|
623 |
+
$add_dir = true;
|
624 |
+
foreach ($this->FilterInfo->TreeWarning as $key => $value) {
|
625 |
+
if ($value['dir'] == $dir) {
|
626 |
+
$add_dir = false;
|
627 |
+
break;
|
628 |
+
}
|
629 |
+
}
|
630 |
+
if ($add_dir) {
|
631 |
+
|
632 |
+
//Locate core paths, wp-admin, wp-includes, etc.
|
633 |
+
$iscore = 0;
|
634 |
+
foreach ($this->wpCorePaths as $core_dir) {
|
635 |
+
if (strpos(DUP_Util::safePath($dir), DUP_Util::safePath($core_dir)) !== false) {
|
636 |
+
$iscore = 1;
|
637 |
+
break;
|
638 |
+
}
|
639 |
+
}
|
640 |
+
// Check root and content exact dir
|
641 |
+
if (!$iscore) {
|
642 |
+
if (in_array($dir, $this->wpCoreExactPaths)) {
|
643 |
+
$iscore = 1;
|
644 |
+
}
|
645 |
+
}
|
646 |
+
|
647 |
+
$this->FilterInfo->TreeWarning[] = array(
|
648 |
+
'dir' => $dir,
|
649 |
+
'sdir' => str_replace(DUPLICATOR_WPROOTPATH, '', $dir),
|
650 |
+
'iscore' => $iscore,
|
651 |
+
'count' => 0);
|
652 |
+
}
|
653 |
+
}
|
654 |
+
|
655 |
+
function _sortDir($a, $b){
|
656 |
+
return strcmp($a["dir"], $b["dir"]);
|
657 |
+
}
|
658 |
+
usort($this->FilterInfo->TreeWarning, "_sortDir");
|
659 |
+
}
|
660 |
+
|
661 |
+
}
|
classes/package/class.pack.archive.zip.php
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
<?php
|
2 |
-
|
|
|
|
|
3 |
require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.archive.php');
|
4 |
|
5 |
/**
|
@@ -22,7 +24,7 @@ class DUP_Zip extends DUP_Archive
|
|
22 |
/**
|
23 |
* Creates the zip file and adds the SQL file to the archive
|
24 |
*/
|
25 |
-
public static function create(DUP_Archive $archive)
|
26 |
{
|
27 |
try {
|
28 |
$timerAllStart = DUP_Util::getMicrotime();
|
@@ -51,7 +53,13 @@ class DUP_Zip extends DUP_Archive
|
|
51 |
DUP_Log::Info("********************************************************************************");
|
52 |
$isZipOpen = (self::$zipArchive->open(self::$zipPath, ZIPARCHIVE::CREATE) === TRUE);
|
53 |
if (!$isZipOpen) {
|
54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
}
|
56 |
DUP_Log::Info("ARCHIVE DIR: ".self::$compressDir);
|
57 |
DUP_Log::Info("ARCHIVE FILE: ".basename(self::$zipPath));
|
@@ -66,12 +74,17 @@ class DUP_Zip extends DUP_Archive
|
|
66 |
DUP_Log::Info("STATS:\tDirs ".self::$scanReport->ARC->DirCount." | Files ".self::$scanReport->ARC->FileCount);
|
67 |
|
68 |
//ADD SQL
|
69 |
-
$
|
70 |
-
$isSQLInZip = self::$zipArchive->addFile(self::$sqlPath, $
|
71 |
if ($isSQLInZip) {
|
72 |
DUP_Log::Info("SQL ADDED: ".basename(self::$sqlPath));
|
73 |
} else {
|
74 |
-
|
|
|
|
|
|
|
|
|
|
|
75 |
}
|
76 |
self::$zipArchive->close();
|
77 |
self::$zipArchive->open(self::$zipPath, ZipArchive::CREATE);
|
@@ -85,7 +98,7 @@ class DUP_Zip extends DUP_Archive
|
|
85 |
} else {
|
86 |
//Don't warn when dirtory is the root path
|
87 |
if (strcmp($dir, rtrim(self::$compressDir, '/')) != 0) {
|
88 |
-
$dir_path = strlen($dir) ? "[
|
89 |
$info .= "DIR: {$dir_path}\n";
|
90 |
}
|
91 |
}
|
@@ -98,12 +111,14 @@ class DUP_Zip extends DUP_Archive
|
|
98 |
}
|
99 |
|
100 |
/* ZIP FILES: Network Flush
|
101 |
-
* This allows the process to not timeout on fcgi
|
102 |
* setups that need a response every X seconds */
|
|
|
103 |
$info = '';
|
104 |
if (self::$networkFlush) {
|
105 |
foreach (self::$scanReport->ARC->Files as $file) {
|
106 |
if (is_readable($file) && self::$zipArchive->addFile($file, ltrim(str_replace(self::$compressDir, '', $file), '/'))) {
|
|
|
107 |
self::$limitItems++;
|
108 |
self::$countFiles++;
|
109 |
} else {
|
@@ -118,6 +133,12 @@ class DUP_Zip extends DUP_Archive
|
|
118 |
DUP_Util::fcgiFlush();
|
119 |
DUP_Log::Info("Items archived [{$sumItems}] flushing response.");
|
120 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
}
|
122 |
}
|
123 |
//Normal
|
@@ -128,6 +149,12 @@ class DUP_Zip extends DUP_Archive
|
|
128 |
} else {
|
129 |
$info .= "FILE: [{$file}]\n";
|
130 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
}
|
132 |
}
|
133 |
|
@@ -144,8 +171,18 @@ class DUP_Zip extends DUP_Archive
|
|
144 |
//LOG FINAL RESULTS
|
145 |
DUP_Util::fcgiFlush();
|
146 |
$zipCloseResult = self::$zipArchive->close();
|
147 |
-
($zipCloseResult)
|
148 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
|
150 |
$timerAllEnd = DUP_Util::getMicrotime();
|
151 |
$timerAllSum = DUP_Util::elapsedTime($timerAllEnd, $timerAllStart);
|
@@ -153,11 +190,15 @@ class DUP_Zip extends DUP_Archive
|
|
153 |
|
154 |
self::$zipFileSize = @filesize(self::$zipPath);
|
155 |
DUP_Log::Info("COMPRESSED SIZE: ".DUP_Util::byteSize(self::$zipFileSize));
|
156 |
-
DUP_Log::Info("ARCHIVE RUNTIME:
|
157 |
-
DUP_Log::Info("MEMORY STACK: ".
|
158 |
} catch (Exception $e) {
|
159 |
-
|
|
|
|
|
|
|
|
|
|
|
160 |
}
|
161 |
}
|
162 |
-
}
|
163 |
-
?>
|
1 |
<?php
|
2 |
+
// Exit if accessed directly
|
3 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
4 |
+
|
5 |
require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.archive.php');
|
6 |
|
7 |
/**
|
24 |
/**
|
25 |
* Creates the zip file and adds the SQL file to the archive
|
26 |
*/
|
27 |
+
public static function create(DUP_Archive $archive, $buildProgress)
|
28 |
{
|
29 |
try {
|
30 |
$timerAllStart = DUP_Util::getMicrotime();
|
53 |
DUP_Log::Info("********************************************************************************");
|
54 |
$isZipOpen = (self::$zipArchive->open(self::$zipPath, ZIPARCHIVE::CREATE) === TRUE);
|
55 |
if (!$isZipOpen) {
|
56 |
+
$error_message = "Cannot open zip file with PHP ZipArchive.";
|
57 |
+
|
58 |
+
$buildProgress->set_failed($error_message);
|
59 |
+
|
60 |
+
DUP_Log::Error($error_message, "Path location [".self::$zipPath."]", Dup_ErrorBehavior::LogOnly);
|
61 |
+
|
62 |
+
return;
|
63 |
}
|
64 |
DUP_Log::Info("ARCHIVE DIR: ".self::$compressDir);
|
65 |
DUP_Log::Info("ARCHIVE FILE: ".basename(self::$zipPath));
|
74 |
DUP_Log::Info("STATS:\tDirs ".self::$scanReport->ARC->DirCount." | Files ".self::$scanReport->ARC->FileCount);
|
75 |
|
76 |
//ADD SQL
|
77 |
+
$sql_ark_file_path = $archive->Package->getSqlArkFilePath();
|
78 |
+
$isSQLInZip = self::$zipArchive->addFile(self::$sqlPath, $sql_ark_file_path);
|
79 |
if ($isSQLInZip) {
|
80 |
DUP_Log::Info("SQL ADDED: ".basename(self::$sqlPath));
|
81 |
} else {
|
82 |
+
$error_message = "Unable to add database.sql to archive.";
|
83 |
+
|
84 |
+
DUP_Log::Error($error_message, "SQL File Path [".self::$sqlath."]", Dup_ErrorBehavior::LogOnly);
|
85 |
+
|
86 |
+
$buildProgress->set_failed($error_message);
|
87 |
+
return;
|
88 |
}
|
89 |
self::$zipArchive->close();
|
90 |
self::$zipArchive->open(self::$zipPath, ZipArchive::CREATE);
|
98 |
} else {
|
99 |
//Don't warn when dirtory is the root path
|
100 |
if (strcmp($dir, rtrim(self::$compressDir, '/')) != 0) {
|
101 |
+
$dir_path = strlen($dir) ? "[{$dir}]" : "[Read Error] - last successful read was: [{$lastDirSuccess}]";
|
102 |
$info .= "DIR: {$dir_path}\n";
|
103 |
}
|
104 |
}
|
111 |
}
|
112 |
|
113 |
/* ZIP FILES: Network Flush
|
114 |
+
* This allows the process to not timeout on fcgi
|
115 |
* setups that need a response every X seconds */
|
116 |
+
$totalFileCount = count(self::$scanReport->ARC->Files);
|
117 |
$info = '';
|
118 |
if (self::$networkFlush) {
|
119 |
foreach (self::$scanReport->ARC->Files as $file) {
|
120 |
if (is_readable($file) && self::$zipArchive->addFile($file, ltrim(str_replace(self::$compressDir, '', $file), '/'))) {
|
121 |
+
Dup_Log::Info("Adding {$file} to zip");
|
122 |
self::$limitItems++;
|
123 |
self::$countFiles++;
|
124 |
} else {
|
133 |
DUP_Util::fcgiFlush();
|
134 |
DUP_Log::Info("Items archived [{$sumItems}] flushing response.");
|
135 |
}
|
136 |
+
|
137 |
+
if(self::$countFiles % 500 == 0) {
|
138 |
+
// Every so many files update the status so the UI can display
|
139 |
+
$archive->Package->Status = SnapLibUtil::getWorkPercent(DUP_PackageStatus::ARCSTART, DUP_PackageStatus::ARCVALIDATION, $totalFileCount, self::$countFiles);
|
140 |
+
$archive->Package->update();
|
141 |
+
}
|
142 |
}
|
143 |
}
|
144 |
//Normal
|
149 |
} else {
|
150 |
$info .= "FILE: [{$file}]\n";
|
151 |
}
|
152 |
+
|
153 |
+
if(self::$countFiles % 500 == 0) {
|
154 |
+
// Every so many files update the status so the UI can display
|
155 |
+
$archive->Package->Status = SnapLibUtil::getWorkPercent(DUP_PackageStatus::ARCSTART, DUP_PackageStatus::ARCVALIDATION, $totalFileCount, self::$countFiles);
|
156 |
+
$archive->Package->update();
|
157 |
+
}
|
158 |
}
|
159 |
}
|
160 |
|
171 |
//LOG FINAL RESULTS
|
172 |
DUP_Util::fcgiFlush();
|
173 |
$zipCloseResult = self::$zipArchive->close();
|
174 |
+
if($zipCloseResult) {
|
175 |
+
DUP_Log::Info("COMPRESSION RESULT: '{$zipCloseResult}'");
|
176 |
+
} else {
|
177 |
+
$error_message = "ZipArchive close failure.";
|
178 |
+
|
179 |
+
DUP_Log::Error($error_message,
|
180 |
+
"This hosted server may have a disk quota limit.\nCheck to make sure this archive file can be stored.",
|
181 |
+
Dup_ErrorBehavior::LogOnly);
|
182 |
+
|
183 |
+
$buildProgress->set_failed($error_message);
|
184 |
+
return;
|
185 |
+
}
|
186 |
|
187 |
$timerAllEnd = DUP_Util::getMicrotime();
|
188 |
$timerAllSum = DUP_Util::elapsedTime($timerAllEnd, $timerAllStart);
|
190 |
|
191 |
self::$zipFileSize = @filesize(self::$zipPath);
|
192 |
DUP_Log::Info("COMPRESSED SIZE: ".DUP_Util::byteSize(self::$zipFileSize));
|
193 |
+
DUP_Log::Info("ARCHIVE RUNTIME: {$timerAllSum}");
|
194 |
+
DUP_Log::Info("MEMORY STACK: ".DUP_Server::getPHPMemory());
|
195 |
} catch (Exception $e) {
|
196 |
+
$error_message = "Runtime error in class.pack.archive.zip.php constructor.";
|
197 |
+
|
198 |
+
DUP_Log::Error($error_message, "Exception: {$e}", Dup_ErrorBehavior::LogOnly);
|
199 |
+
|
200 |
+
$buildProgress->set_failed($error_message);
|
201 |
+
return;
|
202 |
}
|
203 |
}
|
204 |
+
}
|
|
classes/package/class.pack.database.php
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
<?php
|
2 |
-
|
|
|
3 |
|
4 |
class DUP_Database
|
5 |
{
|
@@ -34,15 +35,16 @@ class DUP_Database
|
|
34 |
/**
|
35 |
* Build the database script
|
36 |
*
|
37 |
-
* @param
|
38 |
*
|
39 |
* @return null
|
40 |
*/
|
41 |
-
public function build($package)
|
42 |
{
|
43 |
try {
|
44 |
|
45 |
$this->Package = $package;
|
|
|
46 |
|
47 |
$time_start = DUP_Util::getMicrotime();
|
48 |
$this->Package->setStatus(DUP_PackageStatus::DBSTART);
|
@@ -69,11 +71,19 @@ class DUP_Database
|
|
69 |
|
70 |
//Reserved file found
|
71 |
if (file_exists($reserved_db_filepath)) {
|
72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
"The file database.sql was found at [{$reserved_db_filepath}].\n"
|
74 |
-
."\tPlease remove/rename this file to continue with the package creation.");
|
75 |
}
|
76 |
|
|
|
|
|
77 |
switch ($mode) {
|
78 |
case 'MYSQLDUMP':
|
79 |
$this->mysqlDump($mysqlDumpPath);
|
@@ -87,25 +97,37 @@ class DUP_Database
|
|
87 |
$time_end = DUP_Util::getMicrotime();
|
88 |
$time_sum = DUP_Util::elapsedTime($time_end, $time_start);
|
89 |
|
90 |
-
//File below 10k
|
91 |
$sql_file_size = filesize($this->dbStorePath);
|
92 |
DUP_Log::Info("SQL FILE SIZE: ".DUP_Util::byteSize($sql_file_size)." ({$sql_file_size})");
|
93 |
-
|
94 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
}
|
96 |
|
97 |
DUP_Log::Info("SQL FILE TIME: ".date("Y-m-d H:i:s"));
|
98 |
DUP_Log::Info("SQL RUNTIME: {$time_sum}");
|
99 |
|
100 |
$this->Size = @filesize($this->dbStorePath);
|
|
|
101 |
$this->Package->setStatus(DUP_PackageStatus::DBDONE);
|
102 |
} catch (Exception $e) {
|
103 |
-
|
|
|
104 |
}
|
105 |
}
|
106 |
|
107 |
/**
|
108 |
-
* Get the database meta-data
|
109 |
*
|
110 |
* @return array Returns an array full of meta-data about the database
|
111 |
*/
|
@@ -186,6 +208,7 @@ class DUP_Database
|
|
186 |
$info['Status']['TBL_Rows'] = ($tblRowsFound) ? 'Warn' : 'Good';
|
187 |
$info['Status']['TBL_Size'] = ($tblSizeFound) ? 'Warn' : 'Good';
|
188 |
|
|
|
189 |
$info['Size'] = DUP_Util::byteSize($info['Size']) or "unknown";
|
190 |
$info['Rows'] = number_format($info['Rows']) or "unknown";
|
191 |
$info['TableList'] = $info['TableList'] or "unknown";
|
@@ -197,12 +220,12 @@ class DUP_Database
|
|
197 |
/**
|
198 |
* Build the database script using mysqldump
|
199 |
*
|
200 |
-
* @return bool Returns true if the sql script was
|
201 |
*/
|
202 |
private function mysqlDump($exePath)
|
203 |
{
|
204 |
-
|
205 |
global $wpdb;
|
|
|
206 |
|
207 |
$host = explode(':', DB_HOST);
|
208 |
$host = reset($host);
|
@@ -216,6 +239,11 @@ class DUP_Database
|
|
216 |
$cmd .= ' --single-transaction';
|
217 |
$cmd .= ' --hex-blob';
|
218 |
$cmd .= ' --skip-add-drop-table';
|
|
|
|
|
|
|
|
|
|
|
219 |
|
220 |
//Compatibility mode
|
221 |
if ($mysqlcompat_on) {
|
@@ -227,6 +255,7 @@ class DUP_Database
|
|
227 |
$tables = $wpdb->get_col('SHOW TABLES');
|
228 |
$filterTables = isset($this->FilterTables) ? explode(',', $this->FilterTables) : null;
|
229 |
$tblAllCount = count($tables);
|
|
|
230 |
|
231 |
if (is_array($filterTables) && $this->FilterOn) {
|
232 |
foreach ($tables as $key => $val) {
|
@@ -238,33 +267,113 @@ class DUP_Database
|
|
238 |
}
|
239 |
|
240 |
$cmd .= ' -u '.escapeshellarg(DB_USER);
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
$cmd .= (DB_PASSWORD) ? ' -p'.escapeshellarg(DB_PASSWORD) : '';
|
245 |
-
|
246 |
$cmd .= ' -h '.escapeshellarg($host);
|
247 |
$cmd .= (!empty($port) && is_numeric($port) ) ?
|
248 |
' -P '.$port : '';
|
249 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
250 |
$cmd .= ' '.escapeshellarg(DB_NAME);
|
251 |
$cmd .= ' 2>&1';
|
252 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
|
|
|
|
|
|
|
|
|
|
259 |
|
260 |
-
|
261 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
262 |
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
268 |
|
269 |
$sql_footer = "\n\n/* Duplicator WordPress Timestamp: ".date("Y-m-d H:i:s")."*/\n";
|
270 |
$sql_footer .= "/* ".DUPLICATOR_DB_EOF_MARKER." */\n";
|
@@ -276,21 +385,22 @@ class DUP_Database
|
|
276 |
/**
|
277 |
* Build the database script using php
|
278 |
*
|
279 |
-
* @return bool Returns true if the sql script was
|
280 |
*/
|
281 |
private function phpDump()
|
282 |
{
|
283 |
-
|
284 |
global $wpdb;
|
285 |
-
|
286 |
$wpdb->query("SET session wait_timeout = ".DUPLICATOR_DB_MAX_TIME);
|
287 |
$handle = fopen($this->dbStorePath, 'w+');
|
288 |
-
$tables
|
289 |
-
|
290 |
$filterTables = isset($this->FilterTables) ? explode(',', $this->FilterTables) : null;
|
291 |
$tblAllCount = count($tables);
|
|
|
292 |
$qryLimit = DUP_Settings::Get('package_phpdump_qrylimit');
|
293 |
-
|
294 |
if (is_array($filterTables) && $this->FilterOn) {
|
295 |
foreach ($tables as $key => $val) {
|
296 |
if (in_array($tables[$key], $filterTables)) {
|
@@ -300,43 +410,75 @@ class DUP_Database
|
|
300 |
}
|
301 |
$tblCreateCount = count($tables);
|
302 |
$tblFilterCount = $tblAllCount - $tblCreateCount;
|
303 |
-
|
304 |
DUP_Log::Info("TABLES: total:{$tblAllCount} | filtered:{$tblFilterCount} | create:{$tblCreateCount}");
|
305 |
DUP_Log::Info("FILTERED: [{$this->FilterTables}]");
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
$sql_header = "/* DUPLICATOR-LITE (PHP BUILD MODE) MYSQL SCRIPT CREATED ON : ".@date("Y-m-d H:i:s")." */\n\n";
|
310 |
-
|
311 |
$sql_header .= "SET FOREIGN_KEY_CHECKS = 0;\n\n";
|
312 |
fwrite($handle, $sql_header);
|
313 |
-
|
314 |
//BUILD CREATES:
|
315 |
//All creates must be created before inserts do to foreign key constraints
|
316 |
foreach ($tables as $table) {
|
|
|
317 |
//$sql_del = ($GLOBALS['duplicator_opts']['dbadd_drop']) ? "DROP TABLE IF EXISTS {$table};\n\n" : "";
|
318 |
//@fwrite($handle, $sql_del);
|
319 |
$create = $wpdb->get_row("SHOW CREATE TABLE `{$table}`", ARRAY_N);
|
320 |
-
|
|
|
|
|
321 |
}
|
322 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
323 |
//BUILD INSERTS:
|
324 |
//Create Insert in 100 row increments to better handle memory
|
325 |
foreach ($tables as $table) {
|
326 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
327 |
$row_count = $wpdb->get_var("SELECT Count(*) FROM `{$table}`");
|
328 |
//DUP_Log::Info("{$table} ({$row_count})");
|
329 |
-
|
330 |
if ($row_count > $qryLimit) {
|
331 |
$row_count = ceil($row_count / $qryLimit);
|
332 |
} else if ($row_count > 0) {
|
333 |
$row_count = 1;
|
334 |
}
|
335 |
-
|
336 |
if ($row_count >= 1) {
|
337 |
fwrite($handle, "\n/* INSERT TABLE DATA: {$table} */\n");
|
338 |
}
|
339 |
-
|
|
|
|
|
340 |
for ($i = 0; $i < $row_count; $i++) {
|
341 |
$sql = "";
|
342 |
$limit = $i * $qryLimit;
|
@@ -344,16 +486,16 @@ class DUP_Database
|
|
344 |
$rows = $wpdb->get_results($query, ARRAY_A);
|
345 |
if (is_array($rows)) {
|
346 |
foreach ($rows as $row) {
|
347 |
-
$sql .= "INSERT INTO `{$
|
348 |
$num_values = count($row);
|
349 |
$num_counter = 1;
|
350 |
foreach ($row as $value) {
|
351 |
if (is_null($value) || !isset($value)) {
|
352 |
($num_values == $num_counter) ? $sql .= 'NULL' : $sql .= 'NULL, ';
|
353 |
} else {
|
354 |
-
($num_values == $num_counter)
|
355 |
-
|
356 |
-
|
357 |
}
|
358 |
$num_counter++;
|
359 |
}
|
@@ -362,7 +504,7 @@ class DUP_Database
|
|
362 |
fwrite($handle, $sql);
|
363 |
}
|
364 |
}
|
365 |
-
|
366 |
//Flush buffer if enabled
|
367 |
if ($this->networkFlush) {
|
368 |
DUP_Util::fcgiFlush();
|
@@ -370,7 +512,7 @@ class DUP_Database
|
|
370 |
$sql = null;
|
371 |
$rows = null;
|
372 |
}
|
373 |
-
|
374 |
$sql_footer = "\nSET FOREIGN_KEY_CHECKS = 1; \n\n";
|
375 |
$sql_footer .= "/* Duplicator WordPress Timestamp: ".date("Y-m-d H:i:s")."*/\n";
|
376 |
$sql_footer .= "/* ".DUPLICATOR_DB_EOF_MARKER." */\n";
|
@@ -378,5 +520,32 @@ class DUP_Database
|
|
378 |
$wpdb->flush();
|
379 |
fclose($handle);
|
380 |
}
|
381 |
-
|
382 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<?php
|
2 |
+
// Exit if accessed directly
|
3 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
4 |
|
5 |
class DUP_Database
|
6 |
{
|
35 |
/**
|
36 |
* Build the database script
|
37 |
*
|
38 |
+
* @param DUP_Package $package A reference to the package that this database object belongs in
|
39 |
*
|
40 |
* @return null
|
41 |
*/
|
42 |
+
public function build($package, $errorBehavior = Dup_ErrorBehavior::Quit)
|
43 |
{
|
44 |
try {
|
45 |
|
46 |
$this->Package = $package;
|
47 |
+
do_action('duplicator_lite_build_database_before_start' , $package);
|
48 |
|
49 |
$time_start = DUP_Util::getMicrotime();
|
50 |
$this->Package->setStatus(DUP_PackageStatus::DBSTART);
|
71 |
|
72 |
//Reserved file found
|
73 |
if (file_exists($reserved_db_filepath)) {
|
74 |
+
$error_message = 'Reserved SQL file detected';
|
75 |
+
|
76 |
+
$package->BuildProgress->set_failed($error_message);
|
77 |
+
|
78 |
+
$package->Update();
|
79 |
+
|
80 |
+
DUP_Log::Error($error_message,
|
81 |
"The file database.sql was found at [{$reserved_db_filepath}].\n"
|
82 |
+
."\tPlease remove/rename this file to continue with the package creation.", $errorBehavior);
|
83 |
}
|
84 |
|
85 |
+
do_action('duplicator_lite_build_database_start' , $package);
|
86 |
+
|
87 |
switch ($mode) {
|
88 |
case 'MYSQLDUMP':
|
89 |
$this->mysqlDump($mysqlDumpPath);
|
97 |
$time_end = DUP_Util::getMicrotime();
|
98 |
$time_sum = DUP_Util::elapsedTime($time_end, $time_start);
|
99 |
|
100 |
+
//File below 10k considered incomplete
|
101 |
$sql_file_size = filesize($this->dbStorePath);
|
102 |
DUP_Log::Info("SQL FILE SIZE: ".DUP_Util::byteSize($sql_file_size)." ({$sql_file_size})");
|
103 |
+
|
104 |
+
if ($sql_file_size < 1350) {
|
105 |
+
$error_message = "SQL file size too low.";
|
106 |
+
|
107 |
+
$package->BuildProgress->set_failed($error_message);
|
108 |
+
|
109 |
+
$package->Update();
|
110 |
+
DUP_Log::Error($error_message, "File does not look complete. Check permission on file and parent directory at [{$this->dbStorePath}]", $errorBehavior);
|
111 |
+
do_action('duplicator_lite_build_database_fail' , $package);
|
112 |
+
|
113 |
+
} else {
|
114 |
+
do_action('duplicator_lite_build_database_completed' , $package);
|
115 |
}
|
116 |
|
117 |
DUP_Log::Info("SQL FILE TIME: ".date("Y-m-d H:i:s"));
|
118 |
DUP_Log::Info("SQL RUNTIME: {$time_sum}");
|
119 |
|
120 |
$this->Size = @filesize($this->dbStorePath);
|
121 |
+
|
122 |
$this->Package->setStatus(DUP_PackageStatus::DBDONE);
|
123 |
} catch (Exception $e) {
|
124 |
+
do_action('duplicator_lite_build_database_fail' , $package);
|
125 |
+
DUP_Log::Error("Runtime error in DUP_Database::Build", "Exception: {$e}", $errorBehavior);
|
126 |
}
|
127 |
}
|
128 |
|
129 |
/**
|
130 |
+
* Get the database meta-data such as tables as all there details
|
131 |
*
|
132 |
* @return array Returns an array full of meta-data about the database
|
133 |
*/
|
208 |
$info['Status']['TBL_Rows'] = ($tblRowsFound) ? 'Warn' : 'Good';
|
209 |
$info['Status']['TBL_Size'] = ($tblSizeFound) ? 'Warn' : 'Good';
|
210 |
|
211 |
+
$info['RawSize'] = $info['Size'];
|
212 |
$info['Size'] = DUP_Util::byteSize($info['Size']) or "unknown";
|
213 |
$info['Rows'] = number_format($info['Rows']) or "unknown";
|
214 |
$info['TableList'] = $info['TableList'] or "unknown";
|
220 |
/**
|
221 |
* Build the database script using mysqldump
|
222 |
*
|
223 |
+
* @return bool Returns true if the sql script was successfully created
|
224 |
*/
|
225 |
private function mysqlDump($exePath)
|
226 |
{
|
|
|
227 |
global $wpdb;
|
228 |
+
require_once (DUPLICATOR_PLUGIN_PATH.'classes/utilities/class.u.shell.php');
|
229 |
|
230 |
$host = explode(':', DB_HOST);
|
231 |
$host = reset($host);
|
239 |
$cmd .= ' --single-transaction';
|
240 |
$cmd .= ' --hex-blob';
|
241 |
$cmd .= ' --skip-add-drop-table';
|
242 |
+
$cmd .= ' --routines';
|
243 |
+
$cmd .= ' --quote-names';
|
244 |
+
$cmd .= ' --skip-comments';
|
245 |
+
$cmd .= ' --skip-set-charset';
|
246 |
+
$cmd .= ' --allow-keywords';
|
247 |
|
248 |
//Compatibility mode
|
249 |
if ($mysqlcompat_on) {
|
255 |
$tables = $wpdb->get_col('SHOW TABLES');
|
256 |
$filterTables = isset($this->FilterTables) ? explode(',', $this->FilterTables) : null;
|
257 |
$tblAllCount = count($tables);
|
258 |
+
$tblFilterOn = ($this->FilterOn) ? 'ON' : 'OFF';
|
259 |
|
260 |
if (is_array($filterTables) && $this->FilterOn) {
|
261 |
foreach ($tables as $key => $val) {
|
267 |
}
|
268 |
|
269 |
$cmd .= ' -u '.escapeshellarg(DB_USER);
|
270 |
+
$cmd .= (DB_PASSWORD) ?
|
271 |
+
' -p'.DUP_Shell_U::escapeshellargWindowsSupport(DB_PASSWORD) : '';
|
272 |
+
|
|
|
|
|
273 |
$cmd .= ' -h '.escapeshellarg($host);
|
274 |
$cmd .= (!empty($port) && is_numeric($port) ) ?
|
275 |
' -P '.$port : '';
|
276 |
+
|
277 |
+
$isPopenEnabled = DUP_Shell_U::isPopenEnabled();
|
278 |
+
|
279 |
+
if (!$isPopenEnabled) {
|
280 |
+
$cmd .= ' -r '.escapeshellarg($this->dbStorePath);
|
281 |
+
}
|
282 |
+
|
283 |
$cmd .= ' '.escapeshellarg(DB_NAME);
|
284 |
$cmd .= ' 2>&1';
|
285 |
+
|
286 |
+
if ($isPopenEnabled) {
|
287 |
+
$needToRewrite = false;
|
288 |
+
foreach ($tables as $tableName) {
|
289 |
+
$rewriteTableAs = $this->rewriteTableNameAs($tableName);
|
290 |
+
if ($tableName != $rewriteTableAs) {
|
291 |
+
$needToRewrite = true;
|
292 |
+
break;
|
293 |
+
}
|
294 |
+
}
|
295 |
|
296 |
+
if ($needToRewrite) {
|
297 |
+
$findReplaceTableNames = array(); // orignal table name => rewrite table name
|
298 |
+
|
299 |
+
foreach ($tables as $tableName) {
|
300 |
+
$rewriteTableAs = $this->rewriteTableNameAs($tableName);
|
301 |
+
if ($tableName != $rewriteTableAs) {
|
302 |
+
$findReplaceTableNames[$tableName] = $rewriteTableAs;
|
303 |
+
}
|
304 |
+
}
|
305 |
+
}
|
306 |
|
307 |
+
$firstLine = '';
|
308 |
+
DUP_LOG::trace("Executing mysql dump command by popen: $cmd");
|
309 |
+
$handle = popen($cmd, "r");
|
310 |
+
if ($handle) {
|
311 |
+
$sql_header = "/* DUPLICATOR-LITE (MYSQL-DUMP BUILD MODE) MYSQL SCRIPT CREATED ON : ".@date("Y-m-d H:i:s")." */\n\n";
|
312 |
+
file_put_contents($this->dbStorePath, $sql_header, FILE_APPEND);
|
313 |
+
while (!feof($handle)) {
|
314 |
+
$line = fgets($handle); //get ony one line
|
315 |
+
if ($line) {
|
316 |
+
if (empty($firstLine)) {
|
317 |
+
$firstLine = $line;
|
318 |
+
if (false !== stripos($line, 'Using a password on the command line interface can be insecure')) continue;
|
319 |
+
}
|
320 |
|
321 |
+
if ($needToRewrite) {
|
322 |
+
$replaceCount = 1;
|
323 |
+
|
324 |
+
if (preg_match('/CREATE TABLE `(.*?)`/', $line, $matches)) {
|
325 |
+
$tableName = $matches[1];
|
326 |
+
if (isset($findReplaceTableNames[$tableName])) {
|
327 |
+
$rewriteTableAs = $findReplaceTableNames[$tableName];
|
328 |
+
$line = str_replace('CREATE TABLE `'.$tableName.'`', 'CREATE TABLE `'.$rewriteTableAs.'`', $line, $replaceCount);
|
329 |
+
}
|
330 |
+
} elseif (preg_match('/INSERT INTO `(.*?)`/', $line, $matches)) {
|
331 |
+
$tableName = $matches[1];
|
332 |
+
if (isset($findReplaceTableNames[$tableName])) {
|
333 |
+
$rewriteTableAs = $findReplaceTableNames[$tableName];
|
334 |
+
$line = str_replace('INSERT INTO `'.$tableName.'`', 'INSERT INTO `'.$rewriteTableAs.'`', $line, $replaceCount);
|
335 |
+
}
|
336 |
+
} elseif (preg_match('/LOCK TABLES `(.*?)`/', $line, $matches)) {
|
337 |
+
$tableName = $matches[1];
|
338 |
+
if (isset($findReplaceTableNames[$tableName])) {
|
339 |
+
$rewriteTableAs = $findReplaceTableNames[$tableName];
|
340 |
+
$line = str_replace('LOCK TABLES `'.$tableName.'`', 'LOCK TABLES `'.$rewriteTableAs.'`', $line, $replaceCount);
|
341 |
+
}
|
342 |
+
}
|
343 |
+
}
|
344 |
+
|
345 |
+
file_put_contents($this->dbStorePath, $line, FILE_APPEND);
|
346 |
+
$output = "Ran from {$exePath}";
|
347 |
+
}
|
348 |
+
}
|
349 |
+
$ret = pclose($handle);
|
350 |
+
} else {
|
351 |
+
$output = '';
|
352 |
+
}
|
353 |
+
|
354 |
+
// Password bug > 5.6 (@see http://bugs.mysql.com/bug.php?id=66546)
|
355 |
+
if (empty($output) && trim($firstLine) === 'Warning: Using a password on the command line interface can be insecure.') {
|
356 |
+
$output = '';
|
357 |
+
}
|
358 |
+
} else {
|
359 |
+
DUP_LOG::trace("Executing mysql dump command $cmd");
|
360 |
+
$output = shell_exec($cmd);
|
361 |
+
|
362 |
+
// Password bug > 5.6 (@see http://bugs.mysql.com/bug.php?id=66546)
|
363 |
+
if (trim($output) === 'Warning: Using a password on the command line interface can be insecure.') {
|
364 |
+
$output = '';
|
365 |
+
}
|
366 |
+
$output = (strlen($output)) ? $output : "Ran from {$exePath}";
|
367 |
+
|
368 |
+
$tblCreateCount = count($tables);
|
369 |
+
$tblFilterCount = $tblAllCount - $tblCreateCount;
|
370 |
+
|
371 |
+
//DEBUG
|
372 |
+
//DUP_Log::Info("COMMAND: {$cmd}");
|
373 |
+
DUP_Log::Info("FILTERED: [{$this->FilterTables}]");
|
374 |
+
DUP_Log::Info("RESPONSE: {$output}");
|
375 |
+
DUP_Log::Info("TABLES: total:{$tblAllCount} | filtered:{$tblFilterCount} | create:{$tblCreateCount}");
|
376 |
+
}
|
377 |
|
378 |
$sql_footer = "\n\n/* Duplicator WordPress Timestamp: ".date("Y-m-d H:i:s")."*/\n";
|
379 |
$sql_footer .= "/* ".DUPLICATOR_DB_EOF_MARKER." */\n";
|
385 |
/**
|
386 |
* Build the database script using php
|
387 |
*
|
388 |
+
* @return bool Returns true if the sql script was successfully created
|
389 |
*/
|
390 |
private function phpDump()
|
391 |
{
|
392 |
+
|
393 |
global $wpdb;
|
394 |
+
|
395 |
$wpdb->query("SET session wait_timeout = ".DUPLICATOR_DB_MAX_TIME);
|
396 |
$handle = fopen($this->dbStorePath, 'w+');
|
397 |
+
$tables = $wpdb->get_col("SHOW FULL TABLES WHERE Table_Type != 'VIEW'");
|
398 |
+
|
399 |
$filterTables = isset($this->FilterTables) ? explode(',', $this->FilterTables) : null;
|
400 |
$tblAllCount = count($tables);
|
401 |
+
$tblFilterOn = ($this->FilterOn) ? 'ON' : 'OFF';
|
402 |
$qryLimit = DUP_Settings::Get('package_phpdump_qrylimit');
|
403 |
+
|
404 |
if (is_array($filterTables) && $this->FilterOn) {
|
405 |
foreach ($tables as $key => $val) {
|
406 |
if (in_array($tables[$key], $filterTables)) {
|
410 |
}
|
411 |
$tblCreateCount = count($tables);
|
412 |
$tblFilterCount = $tblAllCount - $tblCreateCount;
|
413 |
+
|
414 |
DUP_Log::Info("TABLES: total:{$tblAllCount} | filtered:{$tblFilterCount} | create:{$tblCreateCount}");
|
415 |
DUP_Log::Info("FILTERED: [{$this->FilterTables}]");
|
416 |
+
|
417 |
+
//Added 'NO_AUTO_VALUE_ON_ZERO' at plugin version 1.2.12 to fix :
|
418 |
+
//**ERROR** database error write 'Invalid default value for for older mysql versions
|
419 |
$sql_header = "/* DUPLICATOR-LITE (PHP BUILD MODE) MYSQL SCRIPT CREATED ON : ".@date("Y-m-d H:i:s")." */\n\n";
|
420 |
+
$sql_header .= "/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n\n";
|
421 |
$sql_header .= "SET FOREIGN_KEY_CHECKS = 0;\n\n";
|
422 |
fwrite($handle, $sql_header);
|
423 |
+
|
424 |
//BUILD CREATES:
|
425 |
//All creates must be created before inserts do to foreign key constraints
|
426 |
foreach ($tables as $table) {
|
427 |
+
$rewrite_table_as = $this->rewriteTableNameAs($table);
|
428 |
//$sql_del = ($GLOBALS['duplicator_opts']['dbadd_drop']) ? "DROP TABLE IF EXISTS {$table};\n\n" : "";
|
429 |
//@fwrite($handle, $sql_del);
|
430 |
$create = $wpdb->get_row("SHOW CREATE TABLE `{$table}`", ARRAY_N);
|
431 |
+
$count = 1;
|
432 |
+
$create_table_query = str_replace($table, $rewrite_table_as, $create[1], $count);
|
433 |
+
@fwrite($handle, "{$create_table_query};\n\n");
|
434 |
}
|
435 |
+
|
436 |
+
$procedures = $wpdb->get_col("SHOW PROCEDURE STATUS WHERE `Db` = '{$wpdb->dbname}'",1);
|
437 |
+
if(count($procedures)){
|
438 |
+
foreach ($procedures as $procedure){
|
439 |
+
@fwrite($handle, "DELIMITER ;;\n");
|
440 |
+
$create = $wpdb->get_row("SHOW CREATE PROCEDURE `{$procedure}`", ARRAY_N);
|
441 |
+
@fwrite($handle, "{$create[2]} ;;\n");
|
442 |
+
@fwrite($handle, "DELIMITER ;\n\n");
|
443 |
+
}
|
444 |
+
}
|
445 |
+
|
446 |
+
$views = $wpdb->get_col("SHOW FULL TABLES WHERE Table_Type = 'VIEW'");
|
447 |
+
if(count($views)){
|
448 |
+
foreach ($views as $view){
|
449 |
+
$create = $wpdb->get_row("SHOW CREATE VIEW `{$view}`", ARRAY_N);
|
450 |
+
@fwrite($handle, "{$create[1]};\n\n");
|
451 |
+
}
|
452 |
+
}
|
453 |
+
|
454 |
+
$table_count = count($tables);
|
455 |
+
$table_number = 0;
|
456 |
+
|
457 |
//BUILD INSERTS:
|
458 |
//Create Insert in 100 row increments to better handle memory
|
459 |
foreach ($tables as $table) {
|
460 |
+
|
461 |
+
$table_number++;
|
462 |
+
if($table_number % 2 == 0) {
|
463 |
+
$this->Package->Status = SnapLibUtil::getWorkPercent(DUP_PackageStatus::DBSTART, DUP_PackageStatus::DBDONE, $table_count, $table_number);
|
464 |
+
$this->Package->update();
|
465 |
+
}
|
466 |
+
|
467 |
$row_count = $wpdb->get_var("SELECT Count(*) FROM `{$table}`");
|
468 |
//DUP_Log::Info("{$table} ({$row_count})");
|
469 |
+
|
470 |
if ($row_count > $qryLimit) {
|
471 |
$row_count = ceil($row_count / $qryLimit);
|
472 |
} else if ($row_count > 0) {
|
473 |
$row_count = 1;
|
474 |
}
|
475 |
+
|
476 |
if ($row_count >= 1) {
|
477 |
fwrite($handle, "\n/* INSERT TABLE DATA: {$table} */\n");
|
478 |
}
|
479 |
+
|
480 |
+
$rewrite_table_as = $this->rewriteTableNameAs($table);
|
481 |
+
|
482 |
for ($i = 0; $i < $row_count; $i++) {
|
483 |
$sql = "";
|
484 |
$limit = $i * $qryLimit;
|
486 |
$rows = $wpdb->get_results($query, ARRAY_A);
|
487 |
if (is_array($rows)) {
|
488 |
foreach ($rows as $row) {
|
489 |
+
$sql .= "INSERT INTO `{$rewrite_table_as}` VALUES(";
|
490 |
$num_values = count($row);
|
491 |
$num_counter = 1;
|
492 |
foreach ($row as $value) {
|
493 |
if (is_null($value) || !isset($value)) {
|
494 |
($num_values == $num_counter) ? $sql .= 'NULL' : $sql .= 'NULL, ';
|
495 |
} else {
|
496 |
+
($num_values == $num_counter)
|
497 |
+
? $sql .= '"' . DUP_DB::escSQL($value, true) . '"'
|
498 |
+
: $sql .= '"' . DUP_DB::escSQL($value, true) . '", ';
|
499 |
}
|
500 |
$num_counter++;
|
501 |
}
|
504 |
fwrite($handle, $sql);
|
505 |
}
|
506 |
}
|
507 |
+
|
508 |
//Flush buffer if enabled
|
509 |
if ($this->networkFlush) {
|
510 |
DUP_Util::fcgiFlush();
|
512 |
$sql = null;
|
513 |
$rows = null;
|
514 |
}
|
515 |
+
|
516 |
$sql_footer = "\nSET FOREIGN_KEY_CHECKS = 1; \n\n";
|
517 |
$sql_footer .= "/* Duplicator WordPress Timestamp: ".date("Y-m-d H:i:s")."*/\n";
|
518 |
$sql_footer .= "/* ".DUPLICATOR_DB_EOF_MARKER." */\n";
|
520 |
$wpdb->flush();
|
521 |
fclose($handle);
|
522 |
}
|
523 |
+
|
524 |
+
private function rewriteTableNameAs($table) {
|
525 |
+
$table_prefix = $this->getTablePrefix();
|
526 |
+
if (!isset($this->sameNameTableExists)) {
|
527 |
+
global $wpdb;
|
528 |
+
$this->sameNameTableExists = false;
|
529 |
+
$all_tables = $wpdb->get_col("SHOW FULL TABLES WHERE Table_Type != 'VIEW'");
|
530 |
+
foreach ($all_tables as $table_name) {
|
531 |
+
if (strtolower($table_name) != $table_name && in_array(strtolower($table_name), $all_tables)) {
|
532 |
+
$this->sameNameTableExists = true;
|
533 |
+
break;
|
534 |
+
}
|
535 |
+
}
|
536 |
+
}
|
537 |
+
if (false === $this->sameNameTableExists && 0 === stripos($table, $table_prefix) && 0 !== strpos($table, $table_prefix)) {
|
538 |
+
$post_fix = substr($table, strlen($table_prefix));
|
539 |
+
$rewrite_table_name = $table_prefix.$post_fix;
|
540 |
+
} else {
|
541 |
+
$rewrite_table_name = $table;
|
542 |
+
}
|
543 |
+
return $rewrite_table_name;
|
544 |
+
}
|
545 |
+
|
546 |
+
private function getTablePrefix() {
|
547 |
+
global $wpdb;
|
548 |
+
$table_prefix = (is_multisite() && !defined('MULTISITE')) ? $wpdb->base_prefix : $wpdb->get_blog_prefix(0);
|
549 |
+
return $table_prefix;
|
550 |
+
}
|
551 |
+
}
|
classes/package/class.pack.installer.php
CHANGED
@@ -1,5 +1,10 @@
|
|
1 |
<?php
|
2 |
-
|
|
|
|
|
|
|
|
|
|
|
3 |
require_once(DUPLICATOR_PLUGIN_PATH . '/classes/class.password.php');
|
4 |
|
5 |
class DUP_Installer
|
@@ -13,7 +18,10 @@ class DUP_Installer
|
|
13 |
public $OptsDBUser;
|
14 |
public $OptsSecureOn = 0;
|
15 |
public $OptsSecurePass;
|
16 |
-
|
|
|
|
|
|
|
17 |
protected $Package;
|
18 |
|
19 |
/**
|
@@ -24,203 +32,446 @@ class DUP_Installer
|
|
24 |
$this->Package = $package;
|
25 |
}
|
26 |
|
27 |
-
|
28 |
-
* Build the installer script
|
29 |
-
*
|
30 |
-
* @param obj $package A reference to the package that this installer object belongs to
|
31 |
-
*
|
32 |
-
* @return null
|
33 |
-
*/
|
34 |
-
public function build($package)
|
35 |
{
|
|
|
36 |
|
37 |
$this->Package = $package;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
$
|
52 |
-
$
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
"classes/utilities/class.u.php" => "@@CLASS.U.PHP@@",
|
65 |
-
"classes/class.csrf.php" => "@@CLASS.CSRF.PHP@@",
|
66 |
-
"classes/class.server.php" => "@@CLASS.SERVER.PHP@@",
|
67 |
-
"classes/class.db.php" => "@@CLASS.DB.PHP@@",
|
68 |
-
"classes/class.logging.php" => "@@CLASS.LOGGING.PHP@@",
|
69 |
-
"classes/class.engine.php" => "@@CLASS.ENGINE.PHP@@",
|
70 |
-
"classes/class.http.php" => "@@CLASS.HTTP.PHP@@",
|
71 |
-
"classes/config/class.conf.wp.php" => "@@CLASS.CONF.WP.PHP@@",
|
72 |
-
"classes/config/class.conf.srv.php" => "@@CLASS.CONF.SRV.PHP@@",
|
73 |
-
"classes/class.password.php" => "@@CLASS.PASSWORD.PHP@@",
|
74 |
-
"ctrls/ctrl.step1.php" => "@@CTRL.STEP1.PHP@@",
|
75 |
-
"ctrls/ctrl.step2.php" => "@@CTRL.STEP2.PHP@@",
|
76 |
-
"ctrls/ctrl.step3.php" => "@@CTRL.STEP3.PHP@@",
|
77 |
-
"view.init1.php" => "@@VIEW.INIT1.PHP@@",
|
78 |
-
"view.step1.php" => "@@VIEW.STEP1.PHP@@",
|
79 |
-
"view.step2.php" => "@@VIEW.STEP2.PHP@@",
|
80 |
-
"view.step3.php" => "@@VIEW.STEP3.PHP@@",
|
81 |
-
"view.step4.php" => "@@VIEW.STEP4.PHP@@",
|
82 |
-
"view.help.php" => "@@VIEW.HELP.PHP@@",);
|
83 |
-
|
84 |
-
foreach ($embeded_files as $name => $token) {
|
85 |
-
$file_path = DUPLICATOR_PLUGIN_PATH."installer/build/{$name}";
|
86 |
-
@chmod($file_path, 0777);
|
87 |
-
|
88 |
-
$search_data = @file_get_contents($template_path);
|
89 |
-
$insert_data = @file_get_contents($file_path);
|
90 |
-
file_put_contents($template_path, str_replace("${token}", "{$insert_data}", $search_data));
|
91 |
-
if ($search_data === false || $insert_data == false) {
|
92 |
-
DUP_Log::Error("Installer generation failed at {$token}.", '');
|
93 |
}
|
94 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
}
|
96 |
|
97 |
-
|
98 |
-
|
|
|
|
|
|
|
|
|
99 |
|
100 |
-
|
101 |
-
$this->createFromTemplate($template_path);
|
102 |
-
$storePath = "{$this->Package->StorePath}/{$this->File}";
|
103 |
-
$this->Size = @filesize($storePath);
|
104 |
-
$this->addBackup();
|
105 |
}
|
106 |
|
107 |
/**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
* Puts an installer zip file in the archive for backup purposes.
|
109 |
-
*
|
110 |
-
* @return null
|
111 |
*/
|
112 |
-
private function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
{
|
|
|
|
|
|
|
114 |
|
115 |
-
$
|
116 |
-
$installer = DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP)."/{$this->Package->NameHash}_installer.php";
|
117 |
|
118 |
$zipArchive = new ZipArchive();
|
119 |
-
|
120 |
-
|
121 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
} else {
|
123 |
-
DUP_Log::
|
|
|
|
|
|
|
|
|
|
|
124 |
}
|
125 |
-
|
|
|
126 |
}
|
|
|
|
|
127 |
}
|
128 |
|
129 |
-
|
130 |
-
|
131 |
-
*
|
132 |
-
* @param string $template The path to the installer template which is originally copied from main.installer.php
|
133 |
-
*
|
134 |
-
* @return null
|
135 |
-
*/
|
136 |
-
private function createFromTemplate($template)
|
137 |
{
|
|
|
|
|
|
|
|
|
|
|
138 |
|
139 |
-
|
140 |
|
141 |
-
|
142 |
-
$
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
$pass_hash = $hasher->HashPassword($this->Package->Installer->OptsSecurePass);
|
151 |
-
|
152 |
-
$replace_items = Array(
|
153 |
-
//COMPARE VALUES
|
154 |
-
"fwrite_created" => $this->Package->Created,
|
155 |
-
"fwrite_version_dup" => DUPLICATOR_VERSION,
|
156 |
-
"fwrite_version_wp" => $this->Package->VersionWP,
|
157 |
-
"fwrite_version_db" => $this->Package->VersionDB,
|
158 |
-
"fwrite_version_php" => $this->Package->VersionPHP,
|
159 |
-
"fwrite_version_os" => $this->Package->VersionOS,
|
160 |
-
//GENERAL
|
161 |
-
"fwrite_url_old" => get_option('siteurl'),
|
162 |
-
"fwrite_archive_name" => "{$this->Package->NameHash}_archive.zip",
|
163 |
-
"fwrite_archive_onlydb" => $this->Package->Archive->ExportOnlyDB,
|
164 |
-
"fwrite_package_notes" => $this->Package->Notes,
|
165 |
-
"fwrite_package_size" => $this->Package->Archive->Size,
|
166 |
-
"fwrite_secure_name" => $this->Package->NameHash,
|
167 |
-
"fwrite_dbhost" => $this->Package->Installer->OptsDBHost,
|
168 |
-
"fwrite_dbport" => $this->Package->Installer->OptsDBPort,
|
169 |
-
"fwrite_dbname" => $this->Package->Installer->OptsDBName,
|
170 |
-
"fwrite_dbuser" => $this->Package->Installer->OptsDBUser,
|
171 |
-
"fwrite_secureon" => $this->Package->Installer->OptsSecureOn,
|
172 |
-
"fwrite_securepass" => $pass_hash,
|
173 |
-
"fwrite_dbpass" => '',
|
174 |
-
"fwrite_wp_tableprefix" => $wpdb->prefix,
|
175 |
-
"fwrite_opts_delete" => json_encode($deleteOpts),
|
176 |
-
"fwrite_blogname" => esc_html(get_option('blogname')),
|
177 |
-
"fwrite_wproot" => DUPLICATOR_WPROOTPATH,
|
178 |
-
"fwrite_wplogin_url" => wp_login_url(),
|
179 |
-
"package_hash" => $this->Package->getPackageHash(),
|
180 |
-
"fwrite_duplicator_version" => DUPLICATOR_VERSION
|
181 |
-
);
|
182 |
-
|
183 |
-
if (file_exists($template) && is_readable($template)) {
|
184 |
-
$err_msg = "ERROR: Unable to read/write installer. \nERROR INFO: Check permission/owner on file and parent folder.\nInstaller File = <{$installer}>";
|
185 |
-
$install_str = $this->parseTemplate($template, $replace_items);
|
186 |
-
(empty($install_str)) ? DUP_Log::Error("{$err_msg}", "DUP_Installer::createFromTemplate => file-empty-read") : DUP_Log::Info("Template parsed with new data");
|
187 |
-
|
188 |
-
//INSTALLER FILE
|
189 |
-
$fp = (!file_exists($installer)) ? fopen($installer, 'x+') : fopen($installer, 'w');
|
190 |
-
if (!$fp || !fwrite($fp, $install_str, strlen($install_str))) {
|
191 |
-
DUP_Log::Error("{$err_msg}", "DUP_Installer::createFromTemplate => file-write-error");
|
192 |
-
}
|
193 |
|
194 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
195 |
} else {
|
196 |
-
DUP_Log::
|
197 |
}
|
198 |
-
|
199 |
-
|
200 |
}
|
201 |
|
202 |
/**
|
203 |
-
*
|
204 |
-
*
|
205 |
-
* @param string $filename The filename to tokenize
|
206 |
-
* @param array $data The array of key value items to tokenize
|
207 |
*/
|
208 |
-
private function
|
209 |
{
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
}
|
|
|
225 |
}
|
226 |
-
?>
|
1 |
<?php
|
2 |
+
// Exit if accessed directly
|
3 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
4 |
+
|
5 |
+
require_once(DUPLICATOR_PLUGIN_PATH . '/classes/class.archive.config.php');
|
6 |
+
require_once(DUPLICATOR_PLUGIN_PATH . '/classes/utilities/class.u.zip.php');
|
7 |
+
require_once(DUPLICATOR_PLUGIN_PATH . '/classes/utilities/class.u.multisite.php');
|
8 |
require_once(DUPLICATOR_PLUGIN_PATH . '/classes/class.password.php');
|
9 |
|
10 |
class DUP_Installer
|
18 |
public $OptsDBUser;
|
19 |
public $OptsSecureOn = 0;
|
20 |
public $OptsSecurePass;
|
21 |
+
public $numFilesAdded = 0;
|
22 |
+
public $numDirsAdded = 0;
|
23 |
+
|
24 |
+
//PROTECTED
|
25 |
protected $Package;
|
26 |
|
27 |
/**
|
32 |
$this->Package = $package;
|
33 |
}
|
34 |
|
35 |
+
public function build($package, $error_behavior = Dup_ErrorBehavior::Quit)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
{
|
37 |
+
DUP_Log::Info("building installer");
|
38 |
|
39 |
$this->Package = $package;
|
40 |
+
$success = false;
|
41 |
+
|
42 |
+
if ($this->create_enhanced_installer_files()) {
|
43 |
+
$success = $this->add_extra_files($package);
|
44 |
+
} else {
|
45 |
+
DUP_Log::Info("error creating enhanced installer files");
|
46 |
+
}
|
47 |
+
|
48 |
+
|
49 |
+
if ($success) {
|
50 |
+
$package->BuildProgress->installer_built = true;
|
51 |
+
} else {
|
52 |
+
$error_message = 'Error adding installer';
|
53 |
+
|
54 |
+
$package->BuildProgress->set_failed($error_message);
|
55 |
+
$package->Update();
|
56 |
+
|
57 |
+
DUP_Log::error($error_message, "Marking build progress as failed because couldn't add installer files", $error_behavior);
|
58 |
+
//$package->BuildProgress->failed = true;
|
59 |
+
//$package->setStatus(DUP_PackageStatus::ERROR);
|
60 |
+
}
|
61 |
+
|
62 |
+
return $success;
|
63 |
+
}
|
64 |
+
|
65 |
+
private function create_enhanced_installer_files()
|
66 |
+
{
|
67 |
+
$success = false;
|
68 |
|
69 |
+
if ($this->create_enhanced_installer()) {
|
70 |
+
$success = $this->create_archive_config_file();
|
71 |
+
}
|
72 |
+
|
73 |
+
return $success;
|
74 |
+
}
|
75 |
+
|
76 |
+
private function create_enhanced_installer()
|
77 |
+
{
|
78 |
+
$success = true;
|
79 |
+
|
80 |
+
$archive_filepath = DUP_Util::safePath("{$this->Package->StorePath}/{$this->Package->Archive->File}");
|
81 |
+
$installer_filepath = DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP)."/{$this->Package->NameHash}_installer.php";
|
82 |
+
$template_filepath = DUPLICATOR_PLUGIN_PATH.'/installer/installer.tpl';
|
83 |
+
$mini_expander_filepath = DUPLICATOR_PLUGIN_PATH.'/lib/dup_archive/classes/class.duparchive.mini.expander.php';
|
84 |
+
|
85 |
+
// Replace the @@ARCHIVE@@ token
|
86 |
+
$installer_contents = file_get_contents($template_filepath);
|
87 |
+
|
88 |
+
if (DUP_Settings::Get('archive_build_mode') == DUP_Archive_Build_Mode::DupArchive) {
|
89 |
+
$mini_expander_string = file_get_contents($mini_expander_filepath);
|
90 |
+
|
91 |
+
if ($mini_expander_string === false) {
|
92 |
+
DUP_Log::error(DUP_U::__('Error reading DupArchive mini expander'), DUP_U::__('Error reading DupArchive mini expander'), Dup_ErrorBehavior::LogOnly);
|
93 |
+
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
}
|
95 |
+
} else {
|
96 |
+
$mini_expander_string = '';
|
97 |
+
}
|
98 |
+
|
99 |
+
$search_array = array('@@ARCHIVE@@', '@@VERSION@@', '@@ARCHIVE_SIZE@@', '@@PACKAGE_HASH@@', '@@DUPARCHIVE_MINI_EXPANDER@@');
|
100 |
+
$package_hash = $this->Package->getPackageHash();
|
101 |
+
$replace_array = array($this->Package->Archive->File, DUPLICATOR_VERSION, @filesize($archive_filepath), $package_hash, $mini_expander_string);
|
102 |
+
|
103 |
+
$installer_contents = str_replace($search_array, $replace_array, $installer_contents);
|
104 |
+
|
105 |
+
if (@file_put_contents($installer_filepath, $installer_contents) === false) {
|
106 |
+
DUP_Log::error(esc_html__('Error writing installer contents', 'duplicator'), esc_html__("Couldn't write to $installer_filepath", 'duplicator'));
|
107 |
+
$success = false;
|
108 |
}
|
109 |
|
110 |
+
$yn = file_exists($installer_filepath) ? 'yes' : 'no';
|
111 |
+
|
112 |
+
if ($success) {
|
113 |
+
$storePath = "{$this->Package->StorePath}/{$this->File}";
|
114 |
+
$this->Size = @filesize($storePath);
|
115 |
+
}
|
116 |
|
117 |
+
return $success;
|
|
|
|
|
|
|
|
|
118 |
}
|
119 |
|
120 |
/**
|
121 |
+
* Create archive.txt file */
|
122 |
+
private function create_archive_config_file()
|
123 |
+
{
|
124 |
+
global $wpdb;
|
125 |
+
|
126 |
+
$success = true;
|
127 |
+
$archive_config_filepath = DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP)."/{$this->Package->NameHash}_archive.txt";
|
128 |
+
$ac = new DUP_Archive_Config();
|
129 |
+
$extension = strtolower($this->Package->Archive->Format);
|
130 |
+
|
131 |
+
$hasher = new DUP_PasswordHash(8, FALSE);
|
132 |
+
$pass_hash = $hasher->HashPassword($this->Package->Installer->OptsSecurePass);
|
133 |
+
|
134 |
+
//READ-ONLY: COMPARE VALUES
|
135 |
+
$ac->created = $this->Package->Created;
|
136 |
+
$ac->version_dup = DUPLICATOR_VERSION;
|
137 |
+
$ac->version_wp = $this->Package->VersionWP;
|
138 |
+
$ac->version_db = $this->Package->VersionDB;
|
139 |
+
$ac->version_php = $this->Package->VersionPHP;
|
140 |
+
$ac->version_os = $this->Package->VersionOS;
|
141 |
+
$ac->dbInfo = $this->Package->Database->info;
|
142 |
+
|
143 |
+
//READ-ONLY: GENERAL
|
144 |
+
// $ac->installer_base_name = $global->installer_base_name;
|
145 |
+
$ac->installer_base_name = 'installer.php';
|
146 |
+
$ac->package_name = "{$this->Package->NameHash}_archive.{$extension}";
|
147 |
+
$ac->package_hash = $this->Package->getPackageHash();
|
148 |
+
$ac->package_notes = $this->Package->Notes;
|
149 |
+
$ac->url_old = get_option('siteurl');
|
150 |
+
$ac->opts_delete = json_encode($GLOBALS['DUPLICATOR_OPTS_DELETE']);
|
151 |
+
$ac->blogname = esc_html(get_option('blogname'));
|
152 |
+
$ac->wproot = DUPLICATOR_WPROOTPATH;
|
153 |
+
$ac->relative_content_dir = str_replace(ABSPATH, '', WP_CONTENT_DIR);
|
154 |
+
$ac->exportOnlyDB = $this->Package->Archive->ExportOnlyDB;
|
155 |
+
$ac->installSiteOverwriteOn = DUPLICATOR_INSTALL_SITE_OVERWRITE_ON;
|
156 |
+
$ac->wplogin_url = wp_login_url();
|
157 |
+
|
158 |
+
//PRE-FILLED: GENERAL
|
159 |
+
$ac->secure_on = $this->Package->Installer->OptsSecureOn;
|
160 |
+
$ac->secure_pass = $pass_hash;
|
161 |
+
$ac->skipscan = false;
|
162 |
+
$ac->dbhost = $this->Package->Installer->OptsDBHost;
|
163 |
+
$ac->dbname = $this->Package->Installer->OptsDBName;
|
164 |
+
$ac->dbuser = $this->Package->Installer->OptsDBUser;
|
165 |
+
$ac->dbpass = '';
|
166 |
+
$ac->wp_tableprefix = $wpdb->base_prefix;
|
167 |
+
|
168 |
+
$ac->mu_mode = DUP_MU::getMode();
|
169 |
+
|
170 |
+
$json = json_encode($ac);
|
171 |
+
|
172 |
+
DUP_Log::TraceObject('json', $json);
|
173 |
+
|
174 |
+
if (file_put_contents($archive_config_filepath, $json) === false) {
|
175 |
+
DUP_Log::error("Error writing archive config", "Couldn't write archive config at $archive_config_filepath", Dup_ErrorBehavior::LogOnly);
|
176 |
+
$success = false;
|
177 |
+
}
|
178 |
+
|
179 |
+
return $success;
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
* Puts an installer zip file in the archive for backup purposes.
|
|
|
|
|
184 |
*/
|
185 |
+
private function add_extra_files($package)
|
186 |
+
{
|
187 |
+
$success = false;
|
188 |
+
$installer_filepath = DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP)."/{$this->Package->NameHash}_installer.php";
|
189 |
+
$scan_filepath = DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP)."/{$this->Package->NameHash}_scan.json";
|
190 |
+
$sql_filepath = DUP_Util::safePath("{$this->Package->StorePath}/{$this->Package->Database->File}");
|
191 |
+
$archive_filepath = DUP_Util::safePath("{$this->Package->StorePath}/{$this->Package->Archive->File}");
|
192 |
+
$archive_config_filepath = DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP)."/{$this->Package->NameHash}_archive.txt";
|
193 |
+
|
194 |
+
DUP_Log::Info("add_extra_files1");
|
195 |
+
|
196 |
+
if (file_exists($installer_filepath) == false) {
|
197 |
+
DUP_Log::error("Installer $installer_filepath not present", '', Dup_ErrorBehavior::LogOnly);
|
198 |
+
return false;
|
199 |
+
}
|
200 |
+
|
201 |
+
DUP_Log::Info("add_extra_files2");
|
202 |
+
if (file_exists($sql_filepath) == false) {
|
203 |
+
DUP_Log::error("Database SQL file $sql_filepath not present", '', Dup_ErrorBehavior::LogOnly);
|
204 |
+
return false;
|
205 |
+
}
|
206 |
+
|
207 |
+
DUP_Log::Info("add_extra_files3");
|
208 |
+
if (file_exists($archive_config_filepath) == false) {
|
209 |
+
DUP_Log::error("Archive configuration file $archive_config_filepath not present", '', Dup_ErrorBehavior::LogOnly);
|
210 |
+
return false;
|
211 |
+
}
|
212 |
+
|
213 |
+
DUP_Log::Info("add_extra_files4");
|
214 |
+
if ($package->Archive->file_count != 2) {
|
215 |
+
DUP_Log::Info("Doing archive file check");
|
216 |
+
// Only way it's 2 is if the root was part of the filter in which case the archive won't be there
|
217 |
+
DUP_Log::Info("add_extra_files5");
|
218 |
+
if (file_exists($archive_filepath) == false) {
|
219 |
+
|
220 |
+
DUP_Log::error("$error_text. **RECOMMENDATION: $fix_text", '', Dup_ErrorBehavior::LogOnly);
|
221 |
+
|
222 |
+
return false;
|
223 |
+
}
|
224 |
+
DUP_Log::Info("add_extra_files6");
|
225 |
+
}
|
226 |
+
|
227 |
+
if($package->Archive->Format == 'DAF') {
|
228 |
+
DUP_Log::Info("add_extra_files7");
|
229 |
+
$success = $this->add_extra_files_using_duparchive($installer_filepath, $scan_filepath, $sql_filepath, $archive_filepath, $archive_config_filepath);
|
230 |
+
} else {
|
231 |
+
DUP_Log::Info("add_extra_files8");
|
232 |
+
$success = $this->add_extra_files_using_ziparchive($installer_filepath, $scan_filepath, $sql_filepath, $archive_filepath, $archive_config_filepath);
|
233 |
+
}
|
234 |
+
|
235 |
+
// No sense keeping the archive config around
|
236 |
+
@unlink($archive_config_filepath);
|
237 |
+
|
238 |
+
$package->Archive->Size = @filesize($archive_filepath);
|
239 |
+
|
240 |
+
return $success;
|
241 |
+
}
|
242 |
+
|
243 |
+
private function add_extra_files_using_duparchive($installer_filepath, $scan_filepath, $sql_filepath, $archive_filepath, $archive_config_filepath)
|
244 |
+
{
|
245 |
+
$success = false;
|
246 |
+
|
247 |
+
try {
|
248 |
+
DUP_Log::Info("add_extra_files_using_da1");
|
249 |
+
$htaccess_filepath = DUPLICATOR_WPROOTPATH . '.htaccess';
|
250 |
+
$webconf_filepath = DUPLICATOR_WPROOTPATH . 'web.config';
|
251 |
+
$wpconfig_filepath = DUPLICATOR_WPROOTPATH . 'wp-config.php';
|
252 |
+
|
253 |
+
$logger = new DUP_DupArchive_Logger();
|
254 |
+
|
255 |
+
DupArchiveEngine::init($logger, 'DUP_Log::profile');
|
256 |
+
|
257 |
+
$embedded_scan_ark_file_path = $this->getEmbeddedScanFilePath();
|
258 |
+
DupArchiveEngine::addRelativeFileToArchiveST($archive_filepath, $scan_filepath, $embedded_scan_ark_file_path);
|
259 |
+
$this->numFilesAdded++;
|
260 |
+
|
261 |
+
if(file_exists($htaccess_filepath)) {
|
262 |
+
try {
|
263 |
+
DupArchiveEngine::addRelativeFileToArchiveST($archive_filepath, $htaccess_filepath, DUPLICATOR_HTACCESS_ORIG_FILENAME);
|
264 |
+
$this->numFilesAdded++;
|
265 |
+
} catch (Exception $ex) {
|
266 |
+
// Non critical so bury exception
|
267 |
+
}
|
268 |
+
}
|
269 |
+
|
270 |
+
if(file_exists($webconf_filepath)) {
|
271 |
+
try {
|
272 |
+
DupArchiveEngine::addRelativeFileToArchiveST($archive_filepath, $webconf_filepath, DUPLICATOR_WEBCONFIG_ORIG_FILENAME);
|
273 |
+
$this->numFilesAdded++;
|
274 |
+
} catch (Exception $ex) {
|
275 |
+
// Non critical so bury exception
|
276 |
+
}
|
277 |
+
}
|
278 |
+
|
279 |
+
if(file_exists($wpconfig_filepath)) {
|
280 |
+
$conf_ark_file_path = $this->getWPConfArkFilePath();
|
281 |
+
DupArchiveEngine::addRelativeFileToArchiveST($archive_filepath, $wpconfig_filepath, $conf_ark_file_path);
|
282 |
+
$this->numFilesAdded++;
|
283 |
+
}
|
284 |
+
|
285 |
+
$this->add_installer_files_using_duparchive($archive_filepath, $installer_filepath, $archive_config_filepath);
|
286 |
+
|
287 |
+
$success = true;
|
288 |
+
} catch (Exception $ex) {
|
289 |
+
DUP_Log::Error("Error adding installer files to archive. ", $ex->getMessage(), Dup_ErrorBehavior::ThrowException);
|
290 |
+
}
|
291 |
+
|
292 |
+
return $success;
|
293 |
+
}
|
294 |
+
|
295 |
+
private function add_installer_files_using_duparchive($archive_filepath, $installer_filepath, $archive_config_filepath)
|
296 |
+
{
|
297 |
+
/* @var $global DUP_Global_Entity */
|
298 |
+
// $global = DUP_Global_Entity::get_instance();
|
299 |
+
// $installer_backup_filename = $global->get_installer_backup_filename();
|
300 |
+
$installer_backup_filename = 'installer-backup.php';
|
301 |
+
|
302 |
+
$installer_backup_filepath = dirname($installer_filepath) . "/{$installer_backup_filename}";
|
303 |
+
|
304 |
+
DUP_Log::Info('Adding enhanced installer files to archive using DupArchive');
|
305 |
+
|
306 |
+
SnapLibIOU::copy($installer_filepath, $installer_backup_filepath);
|
307 |
+
|
308 |
+
DupArchiveEngine::addFileToArchiveUsingBaseDirST($archive_filepath, dirname($installer_backup_filepath), $installer_backup_filepath);
|
309 |
+
|
310 |
+
SnapLibIOU::rm($installer_backup_filepath);
|
311 |
+
|
312 |
+
$this->numFilesAdded++;
|
313 |
+
|
314 |
+
$base_installer_directory = DUPLICATOR_PLUGIN_PATH.'installer';
|
315 |
+
$installer_directory = "$base_installer_directory/dup-installer";
|
316 |
+
|
317 |
+
$counts = DupArchiveEngine::addDirectoryToArchiveST($archive_filepath, $installer_directory, $base_installer_directory, true);
|
318 |
+
$this->numFilesAdded += $counts->numFilesAdded;
|
319 |
+
$this->numDirsAdded += $counts->numDirsAdded;
|
320 |
+
|
321 |
+
$archive_config_relative_path = $this->getArchiveTxtFilePath();
|
322 |
+
|
323 |
+
DupArchiveEngine::addRelativeFileToArchiveST($archive_filepath, $archive_config_filepath, $archive_config_relative_path);
|
324 |
+
$this->numFilesAdded++;
|
325 |
+
|
326 |
+
// Include dup archive
|
327 |
+
$duparchive_lib_directory = DUPLICATOR_PLUGIN_PATH.'lib/dup_archive';
|
328 |
+
$duparchive_lib_counts = DupArchiveEngine::addDirectoryToArchiveST($archive_filepath, $duparchive_lib_directory, DUPLICATOR_PLUGIN_PATH, true, 'dup-installer/');
|
329 |
+
$this->numFilesAdded += $duparchive_lib_counts->numFilesAdded;
|
330 |
+
$this->numDirsAdded += $duparchive_lib_counts->numDirsAdded;
|
331 |
+
|
332 |
+
// Include snaplib
|
333 |
+
$snaplib_directory = DUPLICATOR_PLUGIN_PATH.'lib/snaplib';
|
334 |
+
$snaplib_counts = DupArchiveEngine::addDirectoryToArchiveST($archive_filepath, $snaplib_directory, DUPLICATOR_PLUGIN_PATH, true, 'dup-installer/');
|
335 |
+
$this->numFilesAdded += $snaplib_counts->numFilesAdded;
|
336 |
+
$this->numDirsAdded += $snaplib_counts->numDirsAdded;
|
337 |
+
|
338 |
+
// Include fileops
|
339 |
+
$fileops_directory = DUPLICATOR_PLUGIN_PATH.'lib/fileops';
|
340 |
+
$fileops_counts = DupArchiveEngine::addDirectoryToArchiveST($archive_filepath, $fileops_directory, DUPLICATOR_PLUGIN_PATH, true, 'dup-installer/');
|
341 |
+
$this->numFilesAdded += $fileops_counts->numFilesAdded;
|
342 |
+
$this->numDirsAdded += $fileops_counts->numDirsAdded;
|
343 |
+
}
|
344 |
+
|
345 |
+
private function add_extra_files_using_ziparchive($installer_filepath, $scan_filepath, $sql_filepath, $zip_filepath, $archive_config_filepath)
|
346 |
{
|
347 |
+
$htaccess_filepath = DUPLICATOR_WPROOTPATH . '.htaccess';
|
348 |
+
$webconfig_filepath = DUPLICATOR_WPROOTPATH . 'web.config';
|
349 |
+
$wpconfig_filepath = DUPLICATOR_WPROOTPATH . 'wp-config.php';
|
350 |
|
351 |
+
$success = false;
|
|
|
352 |
|
353 |
$zipArchive = new ZipArchive();
|
354 |
+
|
355 |
+
if ($zipArchive->open($zip_filepath, ZIPARCHIVE::CREATE) === TRUE) {
|
356 |
+
DUP_Log::Info("Successfully opened zip $zip_filepath");
|
357 |
+
|
358 |
+
if(file_exists($htaccess_filepath)) {
|
359 |
+
DUP_Zip_U::addFileToZipArchive($zipArchive, $htaccess_filepath, DUPLICATOR_HTACCESS_ORIG_FILENAME, true);
|
360 |
+
}
|
361 |
+
|
362 |
+
if(file_exists($webconfig_filepath)) {
|
363 |
+
DUP_Zip_U::addFileToZipArchive($zipArchive, $webconfig_filepath, DUPLICATOR_WEBCONFIG_ORIG_FILENAME, true);
|
364 |
+
}
|
365 |
+
|
366 |
+
if(file_exists($wpconfig_filepath)) {
|
367 |
+
$conf_ark_file_path = $this->getWPConfArkFilePath();
|
368 |
+
DUP_Zip_U::addFileToZipArchive($zipArchive, $wpconfig_filepath, $conf_ark_file_path, true);
|
369 |
+
}
|
370 |
+
|
371 |
+
$embedded_scan_file_path = $this->getEmbeddedScanFilePath();
|
372 |
+
if (DUP_Zip_U::addFileToZipArchive($zipArchive, $scan_filepath, $embedded_scan_file_path, true)) {
|
373 |
+
if ($this->add_installer_files_using_zip_archive($zipArchive, $installer_filepath, $archive_config_filepath, true)) {
|
374 |
+
DUP_Log::info("Installer files added to archive");
|
375 |
+
DUP_Log::info("Added to archive");
|
376 |
+
|
377 |
+
$success = true;
|
378 |
+
} else {
|
379 |
+
DUP_Log::error("Unable to add enhanced enhanced installer files to archive.", '', Dup_ErrorBehavior::LogOnly);
|
380 |
+
}
|
381 |
} else {
|
382 |
+
DUP_Log::error("Unable to add scan file to archive.", '', Dup_ErrorBehavior::LogOnly);
|
383 |
+
}
|
384 |
+
|
385 |
+
if ($zipArchive->close() === false) {
|
386 |
+
DUP_Log::error("Couldn't close archive when adding extra files.", '');
|
387 |
+
$success = false;
|
388 |
}
|
389 |
+
|
390 |
+
DUP_Log::Info('After ziparchive close when adding installer');
|
391 |
}
|
392 |
+
|
393 |
+
return $success;
|
394 |
}
|
395 |
|
396 |
+
// Add installer directory to the archive and the archive.cfg
|
397 |
+
private function add_installer_files_using_zip_archive(&$zip_archive, $installer_filepath, $archive_config_filepath, $is_compressed)
|
|
|
|
|
|
|
|
|
|
|
|
|
398 |
{
|
399 |
+
$success = false;
|
400 |
+
/* @var $global DUP_Global_Entity */
|
401 |
+
// $global = DUP_Global_Entity::get_instance();
|
402 |
+
// $installer_backup_filename = $global->get_installer_backup_filename();
|
403 |
+
$installer_backup_filename = 'installer-backup.php';
|
404 |
|
405 |
+
DUP_Log::Info('Adding enhanced installer files to archive using ZipArchive');
|
406 |
|
407 |
+
// if ($zip_archive->addFile($installer_filepath, $installer_backup_filename)) {
|
408 |
+
if (DUP_Zip_U::addFileToZipArchive($zip_archive, $installer_filepath, $installer_backup_filename, true)) {
|
409 |
+
DUPLICATOR_PLUGIN_PATH.'installer/';
|
410 |
+
|
411 |
+
$installer_directory = DUPLICATOR_PLUGIN_PATH.'installer/dup-installer';
|
412 |
+
|
413 |
+
|
414 |
+
if (DUP_Zip_U::addDirWithZipArchive($zip_archive, $installer_directory, true, '', $is_compressed)) {
|
415 |
+
$archive_config_local_name = $this->getArchiveTxtFilePath();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
416 |
|
417 |
+
// if ($zip_archive->addFile($archive_config_filepath, $archive_config_local_name)) {
|
418 |
+
if (DUP_Zip_U::addFileToZipArchive($zip_archive, $archive_config_filepath, $archive_config_local_name, true)) {
|
419 |
+
|
420 |
+
$snaplib_directory = DUPLICATOR_PLUGIN_PATH . 'lib/snaplib';
|
421 |
+
// $fileops_directory = DUPLICATOR_PLUGIN_PATH . 'lib/fileops';
|
422 |
+
|
423 |
+
//DupArchiveEngine::addDirectoryToArchiveST($archive_filepath, $snaplib_directory, DUPLICATOR_PLUGIN_PATH, true, 'dup-installer/');
|
424 |
+
if (DUP_Zip_U::addDirWithZipArchive($zip_archive, $snaplib_directory, true, 'dup-installer/lib/', $is_compressed))// &&
|
425 |
+
// DUP_Zip_U::addDirWithZipArchive($zip_archive, $fileops_directory, true, 'dup-installer/lib/', $is_compressed)) {
|
426 |
+
{
|
427 |
+
$success = true;
|
428 |
+
} else {
|
429 |
+
// DUP_Log::error("Error adding directory {$snaplib_directory} or {$fileops_directory} to zipArchive", '', false);
|
430 |
+
DUP_Log::error("Error adding directory {$snaplib_directory} to zipArchive", '', Dup_ErrorBehavior::LogOnly);
|
431 |
+
}
|
432 |
+
} else {
|
433 |
+
DUP_Log::error("Error adding $archive_config_filepath to zipArchive", '', Dup_ErrorBehavior::LogOnly);
|
434 |
+
}
|
435 |
+
} else {
|
436 |
+
DUP_Log::error("Error adding directory $installer_directory to zipArchive", '', Dup_ErrorBehavior::LogOnly);
|
437 |
+
}
|
438 |
} else {
|
439 |
+
DUP_Log::error("Error adding backup installer file to zipArchive", '', Dup_ErrorBehavior::LogOnly);
|
440 |
}
|
441 |
+
|
442 |
+
return $success;
|
443 |
}
|
444 |
|
445 |
/**
|
446 |
+
* Get wp-config.php file path along with name in archive file
|
|
|
|
|
|
|
447 |
*/
|
448 |
+
private function getWPConfArkFilePath()
|
449 |
{
|
450 |
+
if (DUPLICATOR_INSTALL_SITE_OVERWRITE_ON) {
|
451 |
+
$package_hash = $this->Package->getPackageHash();
|
452 |
+
$conf_ark_file_path = 'dup-wp-config-arc__'.$package_hash.'.txt';
|
453 |
+
} else {
|
454 |
+
$conf_ark_file_path = 'wp-config.php';
|
455 |
+
}
|
456 |
+
return $conf_ark_file_path;
|
457 |
+
}
|
458 |
+
|
459 |
+
/**
|
460 |
+
* Get scan.json file path along with name in archive file
|
461 |
+
*/
|
462 |
+
private function getEmbeddedScanFilePath() {
|
463 |
+
$package_hash = $this->Package->getPackageHash();
|
464 |
+
$embedded_scan_ark_file_path = 'dup-installer/dup-scan__'.$package_hash.'.json';
|
465 |
+
return $embedded_scan_ark_file_path;
|
466 |
+
}
|
467 |
+
|
468 |
+
/**
|
469 |
+
* Get archive.txt file path along with name in archive file
|
470 |
+
*/
|
471 |
+
private function getArchiveTxtFilePath() {
|
472 |
+
$package_hash = $this->Package->getPackageHash();
|
473 |
+
$archive_txt_file_path = 'dup-installer/dup-archive__'.$package_hash.'.txt';
|
474 |
+
return $archive_txt_file_path;
|
475 |
}
|
476 |
+
|
477 |
}
|
|
classes/package/class.pack.php
CHANGED
@@ -1,37 +1,145 @@
|
|
1 |
<?php
|
2 |
-
|
|
|
3 |
|
4 |
require_once (DUPLICATOR_PLUGIN_PATH.'classes/utilities/class.u.php');
|
5 |
require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.archive.php');
|
6 |
require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.installer.php');
|
7 |
require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.database.php');
|
8 |
|
9 |
-
|
|
|
|
|
|
|
|
|
|
|
10 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
}
|
|
|
|
|
|
|
16 |
const START = 10;
|
17 |
const DBSTART = 20;
|
18 |
const DBDONE = 30;
|
19 |
const ARCSTART = 40;
|
20 |
-
const
|
|
|
21 |
const COMPLETE = 100;
|
22 |
-
|
23 |
}
|
24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
final class DUP_PackageType
|
26 |
{
|
27 |
const MANUAL = 0;
|
28 |
const SCHEDULED = 1;
|
|
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
}
|
31 |
|
32 |
/**
|
33 |
* Class used to store and process all Package logic
|
34 |
*
|
|
|
|
|
|
|
35 |
* @package Duplicator\classes
|
36 |
*/
|
37 |
class DUP_Package
|
@@ -49,11 +157,13 @@ class DUP_Package
|
|
49 |
public $Name;
|
50 |
public $Hash;
|
51 |
public $NameHash;
|
|
|
52 |
public $Type;
|
53 |
public $Notes;
|
54 |
public $StorePath;
|
55 |
public $StoreURL;
|
56 |
public $ScanFile;
|
|
|
57 |
public $Runtime;
|
58 |
public $ExeSize;
|
59 |
public $ZipSize;
|
@@ -64,15 +174,15 @@ class DUP_Package
|
|
64 |
public $Installer;
|
65 |
public $Database;
|
66 |
|
|
|
|
|
67 |
/**
|
68 |
* Manages the Package Process
|
69 |
*/
|
70 |
function __construct()
|
71 |
{
|
72 |
-
|
73 |
$this->ID = null;
|
74 |
$this->Version = DUPLICATOR_VERSION;
|
75 |
-
|
76 |
$this->Type = DUP_PackageType::MANUAL;
|
77 |
$this->Name = self::getDefaultName();
|
78 |
$this->Notes = null;
|
@@ -81,10 +191,12 @@ class DUP_Package
|
|
81 |
$this->Database = new DUP_Database($this);
|
82 |
$this->Archive = new DUP_Archive($this);
|
83 |
$this->Installer = new DUP_Installer($this);
|
|
|
|
|
84 |
}
|
85 |
|
86 |
/**
|
87 |
-
* Generates a
|
88 |
*
|
89 |
* @return array of scan results
|
90 |
*
|
@@ -127,20 +239,24 @@ class DUP_Package
|
|
127 |
$report['ARC']['Dirs'] = $this->Archive->Dirs;
|
128 |
$report['ARC']['Files'] = $this->Archive->Files;
|
129 |
$report['ARC']['Status']['AddonSites'] = count($this->Archive->FilterInfo->Dirs->AddonSites) ? 'Warn' : 'Good';
|
130 |
-
|
131 |
-
|
132 |
|
133 |
//DATABASE
|
134 |
$db = $this->Database->getScannerData();
|
135 |
$report['DB'] = $db;
|
136 |
|
|
|
|
|
|
|
|
|
|
|
137 |
$warnings = array(
|
138 |
$report['SRV']['PHP']['ALL'],
|
139 |
$report['SRV']['WP']['ALL'],
|
140 |
$report['ARC']['Status']['Size'],
|
141 |
$report['ARC']['Status']['Names'],
|
142 |
$db['Status']['DB_Size'],
|
143 |
-
$db['Status']['DB_Rows']
|
|
|
144 |
|
145 |
//array_count_values will throw a warning message if it has null values,
|
146 |
//so lets replace all nulls with empty string
|
@@ -149,7 +265,7 @@ class DUP_Package
|
|
149 |
$warnings[$i] = '';
|
150 |
}
|
151 |
}
|
152 |
-
|
153 |
$warn_counts = is_array($warnings) ? array_count_values($warnings) : 0;
|
154 |
$report['RPT']['Warnings'] = is_null($warn_counts['Warn']) ? 0 : $warn_counts['Warn'];
|
155 |
$report['RPT']['Success'] = is_null($warn_counts['Good']) ? 0 : $warn_counts['Good'];
|
@@ -164,72 +280,653 @@ class DUP_Package
|
|
164 |
}
|
165 |
|
166 |
/**
|
167 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
*
|
169 |
-
* @return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
*/
|
171 |
-
public function
|
172 |
{
|
173 |
-
global $wp_version;
|
174 |
global $wpdb;
|
175 |
-
global $current_user;
|
176 |
|
177 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
|
184 |
-
|
185 |
-
|
186 |
-
$
|
187 |
-
$php_max_memory = @ini_set('memory_limit', DUPLICATOR_PHP_MAX_MEMORY);
|
188 |
-
$php_max_time = ($php_max_time == 0) ? "(0) no time limit imposed" : "[{$php_max_time}] not allowed";
|
189 |
-
$php_max_memory = ($php_max_memory === false) ? "Unabled to set php memory_limit" : DUPLICATOR_PHP_MAX_MEMORY." ({$php_max_memory} default)";
|
190 |
|
191 |
-
$
|
192 |
-
$info .= "DUPLICATOR-LITE PACKAGE-LOG: ".@date(get_option('date_format')." ".get_option('time_format'))."\n";
|
193 |
-
$info .= "NOTICE: Do NOT post to public sites or forums \n";
|
194 |
-
$info .= "********************************************************************************\n";
|
195 |
-
$info .= "VERSION:\t".DUPLICATOR_VERSION."\n";
|
196 |
-
$info .= "WORDPRESS:\t{$wp_version}\n";
|
197 |
-
$info .= "PHP INFO:\t".phpversion().' | '.'SAPI: '.php_sapi_name()."\n";
|
198 |
-
$info .= "SERVER:\t\t{$_SERVER['SERVER_SOFTWARE']} \n";
|
199 |
-
$info .= "PHP TIME LIMIT: {$php_max_time} \n";
|
200 |
-
$info .= "PHP MAX MEMORY: {$php_max_memory} \n";
|
201 |
-
$info .= "MEMORY STACK: ".DUP_Server::getPHPMemory();
|
202 |
-
DUP_Log::Info($info);
|
203 |
-
$info = null;
|
204 |
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
209 |
}
|
210 |
|
211 |
-
$
|
|
|
212 |
|
213 |
-
if ($
|
214 |
-
$
|
215 |
} else {
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
226 |
|
227 |
-
|
228 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
229 |
}
|
230 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
231 |
}
|
232 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
233 |
//START BUILD
|
234 |
//PHPs serialze method will return the object, but the ID above is not passed
|
235 |
//for one reason or another so passing the object back in seems to do the trick
|
@@ -289,7 +986,7 @@ class DUP_Package
|
|
289 |
* @see DUP_Package::getActive
|
290 |
*
|
291 |
* @param $_POST $post The Post server object
|
292 |
-
*
|
293 |
* @return null
|
294 |
*/
|
295 |
public function saveActive($post = null)
|
@@ -299,20 +996,49 @@ class DUP_Package
|
|
299 |
if (isset($post)) {
|
300 |
$post = stripslashes_deep($post);
|
301 |
|
302 |
-
$name
|
303 |
-
$name
|
304 |
-
$name
|
|
|
|
|
305 |
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
315 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
316 |
|
317 |
//PACKAGE
|
318 |
$this->Created = date("Y-m-d H:i:s");
|
@@ -323,7 +1049,7 @@ class DUP_Package
|
|
323 |
$this->VersionDB = sanitize_text_field($dbversion);
|
324 |
$this->Name = sanitize_text_field($name);
|
325 |
$this->Hash = $this->makeHash();
|
326 |
-
$this->NameHash = "{$this->Name}_{$this->Hash}";
|
327 |
|
328 |
$this->Notes = sanitize_textarea_field($post['package-notes']);
|
329 |
//ARCHIVE
|
@@ -332,16 +1058,16 @@ class DUP_Package
|
|
332 |
$this->Archive->FilterOn = isset($post['filter-on']) ? 1 : 0;
|
333 |
$this->Archive->ExportOnlyDB = isset($post['export-onlydb']) ? 1 : 0;
|
334 |
$this->Archive->FilterDirs = sanitize_textarea_field($filter_dirs);
|
335 |
-
|
336 |
-
$this->Archive->FilterExts = str_replace(array('.', ' '), '',
|
337 |
//INSTALLER
|
338 |
$this->Installer->OptsDBHost = sanitize_text_field($post['dbhost']);
|
339 |
$this->Installer->OptsDBPort = sanitize_text_field($post['dbport']);
|
340 |
$this->Installer->OptsDBName = sanitize_text_field($post['dbname']);
|
341 |
$this->Installer->OptsDBUser = sanitize_text_field($post['dbuser']);
|
342 |
$this->Installer->OptsSecureOn = isset($post['secure-on']) ? 1 : 0;
|
343 |
-
$post_secure_pass
|
344 |
-
$this->Installer->OptsSecurePass
|
345 |
//DATABASE
|
346 |
$this->Database->FilterOn = isset($post['dbfilter-on']) ? 1 : 0;
|
347 |
$this->Database->FilterTables = sanitize_text_field($tablelist);
|
@@ -352,6 +1078,37 @@ class DUP_Package
|
|
352 |
}
|
353 |
}
|
354 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
355 |
/**
|
356 |
* Save any property of this class through reflection
|
357 |
*
|
@@ -378,26 +1135,17 @@ class DUP_Package
|
|
378 |
*/
|
379 |
public function setStatus($status)
|
380 |
{
|
381 |
-
global $wpdb;
|
382 |
-
|
383 |
-
$packageObj = serialize($this);
|
384 |
-
|
385 |
if (!isset($status)) {
|
386 |
DUP_Log::Error("Package SetStatus did not receive a proper code.");
|
387 |
}
|
388 |
|
389 |
-
|
390 |
-
DUP_Log::Error("Package SetStatus was unable to serialize package object while updating record.");
|
391 |
-
}
|
392 |
|
393 |
-
$
|
394 |
-
$table = $wpdb->prefix."duplicator_packages";
|
395 |
-
$sql = "UPDATE `{$table}` SET status = ".intval($status).", package = '".esc_sql($packageObj)."' WHERE ID = ".intval($this->ID);
|
396 |
-
$wpdb->query($sql);
|
397 |
}
|
398 |
|
399 |
/**
|
400 |
-
* Does a hash already
|
401 |
*
|
402 |
* @param string $hash An existing hash value
|
403 |
*
|
@@ -407,9 +1155,10 @@ class DUP_Package
|
|
407 |
{
|
408 |
global $wpdb;
|
409 |
|
410 |
-
$
|
|
|
411 |
$qry = $wpdb->get_row("SELECT ID, hash FROM `{$table}` WHERE hash = '{$hash}'");
|
412 |
-
if (strlen($qry->hash) == 0) {
|
413 |
return 0;
|
414 |
} else {
|
415 |
return $qry->ID;
|
@@ -417,14 +1166,12 @@ class DUP_Package
|
|
417 |
}
|
418 |
|
419 |
/**
|
420 |
-
*
|
421 |
-
* Rare cases will need to fall back to GUID
|
422 |
*
|
423 |
-
*
|
424 |
*/
|
425 |
public function makeHash()
|
426 |
{
|
427 |
-
// IMPORTANT! Be VERY careful in changing this format - the FTP delete logic requires 3 segments with the last segment to be the date in YmdHis format.
|
428 |
try {
|
429 |
if (function_exists('random_bytes') && DUP_Util::PHP53()) {
|
430 |
return bin2hex(random_bytes(8)) . mt_rand(1000, 9999) . '_' . date("YmdHis");
|
@@ -455,24 +1202,24 @@ class DUP_Package
|
|
455 |
}
|
456 |
//Incase unserilaize fails
|
457 |
$obj = (is_object($obj)) ? $obj : new DUP_Package();
|
458 |
-
|
459 |
return $obj;
|
460 |
}
|
461 |
|
462 |
/**
|
463 |
* Gets the Package by ID
|
464 |
-
*
|
465 |
* @param int $id A valid package id form the duplicator_packages table
|
466 |
*
|
467 |
* @return obj A copy of the DUP_Package object
|
468 |
*/
|
469 |
public static function getByID($id)
|
470 |
{
|
471 |
-
|
472 |
global $wpdb;
|
473 |
$obj = new DUP_Package();
|
474 |
-
|
475 |
-
$
|
|
|
476 |
if (is_object($row)) {
|
477 |
$obj = @unserialize($row->package);
|
478 |
$obj->Status = $row->status;
|
@@ -491,7 +1238,7 @@ class DUP_Package
|
|
491 |
{
|
492 |
//Remove specail_chars from final result
|
493 |
$special_chars = array(".", "-");
|
494 |
-
$name = ($preDate)
|
495 |
? date('Ymd') . '_' . sanitize_title(get_bloginfo('name', 'display'))
|
496 |
: sanitize_title(get_bloginfo('name', 'display')) . '_' . date('Ymd');
|
497 |
$name = substr(sanitize_file_name($name), 0, 40);
|
@@ -528,10 +1275,10 @@ class DUP_Package
|
|
528 |
|
529 |
/**
|
530 |
* Provides various date formats
|
531 |
-
*
|
532 |
* @param $date The date to format
|
533 |
* @param $format Various date formats to apply
|
534 |
-
*
|
535 |
* @return a formated date based on the $format
|
536 |
*/
|
537 |
public static function getCreatedDateFormat($date, $format = 1)
|
@@ -573,9 +1320,8 @@ class DUP_Package
|
|
573 |
/**
|
574 |
* Cleans up all the tmp files as part of the package build process
|
575 |
*/
|
576 |
-
|
577 |
{
|
578 |
-
|
579 |
$files = DUP_Util::listFiles(DUPLICATOR_SSDIR_PATH_TMP);
|
580 |
$newPath = DUPLICATOR_SSDIR_PATH;
|
581 |
|
@@ -597,17 +1343,19 @@ class DUP_Package
|
|
597 |
}
|
598 |
}
|
599 |
|
|
|
|
|
600 |
/**
|
601 |
* Get package hash
|
602 |
-
*
|
603 |
* @return string package hash
|
604 |
*/
|
605 |
public function getPackageHash() {
|
606 |
$hashParts = explode('_', $this->Hash);
|
607 |
$firstPart = substr($hashParts[0], 0, 7);
|
608 |
$secondPart = substr($hashParts[1], -8);
|
609 |
-
$
|
610 |
-
return $
|
611 |
}
|
612 |
|
613 |
/**
|
@@ -617,9 +1365,31 @@ class DUP_Package
|
|
617 |
*/
|
618 |
public function getSqlArkFilePath()
|
619 |
{
|
620 |
-
$
|
621 |
-
$
|
622 |
-
return $
|
623 |
}
|
624 |
-
|
625 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<?php
|
2 |
+
// Exit if accessed directly
|
3 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
4 |
|
5 |
require_once (DUPLICATOR_PLUGIN_PATH.'classes/utilities/class.u.php');
|
6 |
require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.archive.php');
|
7 |
require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.installer.php');
|
8 |
require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.database.php');
|
9 |
|
10 |
+
/**
|
11 |
+
* Class used to keep track of the build progress
|
12 |
+
*
|
13 |
+
* @package Duplicator\classes
|
14 |
+
*/
|
15 |
+
class DUP_Build_Progress
|
16 |
{
|
17 |
+
public $thread_start_time;
|
18 |
+
public $initialized = false;
|
19 |
+
public $installer_built = false;
|
20 |
+
public $archive_started = false;
|
21 |
+
public $archive_has_database = false;
|
22 |
+
public $archive_built = false;
|
23 |
+
public $database_script_built = false;
|
24 |
+
public $failed = false;
|
25 |
+
public $retries = 0;
|
26 |
+
public $build_failures = array();
|
27 |
+
public $validation_failures = array();
|
28 |
+
|
29 |
+
private $package;
|
30 |
+
|
31 |
+
public function __construct($package)
|
32 |
+
{
|
33 |
+
$this->package = $package;
|
34 |
+
}
|
35 |
|
36 |
+
public function has_completed()
|
37 |
+
{
|
38 |
+
return $this->failed || ($this->installer_built && $this->archive_built && $this->database_script_built);
|
39 |
+
}
|
40 |
+
|
41 |
+
public function timed_out($max_time)
|
42 |
+
{
|
43 |
+
if ($max_time > 0) {
|
44 |
+
$time_diff = time() - $this->thread_start_time;
|
45 |
+
return ($time_diff >= $max_time);
|
46 |
+
} else {
|
47 |
+
return false;
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
public function start_timer()
|
52 |
+
{
|
53 |
+
$this->thread_start_time = time();
|
54 |
+
}
|
55 |
+
|
56 |
+
public function set_validation_failures($failures)
|
57 |
+
{
|
58 |
+
$this->validation_failures = array();
|
59 |
+
|
60 |
+
foreach ($failures as $failure) {
|
61 |
+
$this->validation_failures[] = $failure;
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
public function set_build_failures($failures)
|
66 |
+
{
|
67 |
+
$this->build_failures = array();
|
68 |
+
|
69 |
+
foreach ($failures as $failure) {
|
70 |
+
$this->build_failures[] = $failure->description;
|
71 |
+
}
|
72 |
+
}
|
73 |
+
|
74 |
+
public function set_failed($failure_message = null)
|
75 |
{
|
76 |
+
if($failure_message !== null) {
|
77 |
+
$failure = new StdClass();
|
78 |
+
$failure->type = 0;
|
79 |
+
$failure->subject = '';
|
80 |
+
$failure->description = $failure_message;
|
81 |
+
$failure->isCritical = true;
|
82 |
+
$this->build_failures[] = $failure;
|
83 |
+
}
|
84 |
+
|
85 |
+
$this->failed = true;
|
86 |
+
$this->package->Status = DUP_PackageStatus::ERROR;
|
87 |
+
}
|
88 |
+
}
|
89 |
|
90 |
+
/**
|
91 |
+
* Class used to emulate and ENUM to give the status of a package from 0 to 100%
|
92 |
+
*
|
93 |
+
* @package Duplicator\classes
|
94 |
+
*/
|
95 |
+
final class DUP_PackageStatus
|
96 |
+
{
|
97 |
+
private function __construct()
|
98 |
+
{
|
99 |
}
|
100 |
+
|
101 |
+
const ERROR = -1;
|
102 |
+
const CREATED = 0;
|
103 |
const START = 10;
|
104 |
const DBSTART = 20;
|
105 |
const DBDONE = 30;
|
106 |
const ARCSTART = 40;
|
107 |
+
const ARCVALIDATION = 60;
|
108 |
+
const ARCDONE = 65;
|
109 |
const COMPLETE = 100;
|
|
|
110 |
}
|
111 |
|
112 |
+
/**
|
113 |
+
* Class used to emulate and ENUM to determine how the package was made.
|
114 |
+
* For lite only the MANUAL type is used.
|
115 |
+
*
|
116 |
+
* @package Duplicator\classes
|
117 |
+
*/
|
118 |
final class DUP_PackageType
|
119 |
{
|
120 |
const MANUAL = 0;
|
121 |
const SCHEDULED = 1;
|
122 |
+
}
|
123 |
|
124 |
+
/**
|
125 |
+
* Class used to emulate and ENUM to determine the various file types used in a package
|
126 |
+
*
|
127 |
+
* @package Duplicator\classes
|
128 |
+
*/
|
129 |
+
abstract class DUP_PackageFileType
|
130 |
+
{
|
131 |
+
const Installer = 0;
|
132 |
+
const Archive = 1;
|
133 |
+
const SQL = 2;
|
134 |
+
const Log = 3;
|
135 |
}
|
136 |
|
137 |
/**
|
138 |
* Class used to store and process all Package logic
|
139 |
*
|
140 |
+
* Standard: PSR-2
|
141 |
+
* @link http://www.php-fig.org/psr/psr-2
|
142 |
+
*
|
143 |
* @package Duplicator\classes
|
144 |
*/
|
145 |
class DUP_Package
|
157 |
public $Name;
|
158 |
public $Hash;
|
159 |
public $NameHash;
|
160 |
+
//Set to DUP_PackageType
|
161 |
public $Type;
|
162 |
public $Notes;
|
163 |
public $StorePath;
|
164 |
public $StoreURL;
|
165 |
public $ScanFile;
|
166 |
+
public $TimerStart = -1;
|
167 |
public $Runtime;
|
168 |
public $ExeSize;
|
169 |
public $ZipSize;
|
174 |
public $Installer;
|
175 |
public $Database;
|
176 |
|
177 |
+
public $BuildProgress;
|
178 |
+
|
179 |
/**
|
180 |
* Manages the Package Process
|
181 |
*/
|
182 |
function __construct()
|
183 |
{
|
|
|
184 |
$this->ID = null;
|
185 |
$this->Version = DUPLICATOR_VERSION;
|
|
|
186 |
$this->Type = DUP_PackageType::MANUAL;
|
187 |
$this->Name = self::getDefaultName();
|
188 |
$this->Notes = null;
|
191 |
$this->Database = new DUP_Database($this);
|
192 |
$this->Archive = new DUP_Archive($this);
|
193 |
$this->Installer = new DUP_Installer($this);
|
194 |
+
$this->BuildProgress = new DUP_Build_Progress($this);
|
195 |
+
$this->Status = DUP_PackageStatus::CREATED;
|
196 |
}
|
197 |
|
198 |
/**
|
199 |
+
* Generates a JSON scan report
|
200 |
*
|
201 |
* @return array of scan results
|
202 |
*
|
239 |
$report['ARC']['Dirs'] = $this->Archive->Dirs;
|
240 |
$report['ARC']['Files'] = $this->Archive->Files;
|
241 |
$report['ARC']['Status']['AddonSites'] = count($this->Archive->FilterInfo->Dirs->AddonSites) ? 'Warn' : 'Good';
|
|
|
|
|
242 |
|
243 |
//DATABASE
|
244 |
$db = $this->Database->getScannerData();
|
245 |
$report['DB'] = $db;
|
246 |
|
247 |
+
//Lite Limits
|
248 |
+
$rawTotalSize = $this->Archive->Size + $report['DB']['RawSize'];
|
249 |
+
$report['LL']['TotalSize'] = DUP_Util::byteSize($rawTotalSize);
|
250 |
+
$report['LL']['Status']['TotalSize'] = ($rawTotalSize > DUPLICATOR_MAX_DUPARCHIVE_SIZE) ? 'Fail' : 'Good';
|
251 |
+
|
252 |
$warnings = array(
|
253 |
$report['SRV']['PHP']['ALL'],
|
254 |
$report['SRV']['WP']['ALL'],
|
255 |
$report['ARC']['Status']['Size'],
|
256 |
$report['ARC']['Status']['Names'],
|
257 |
$db['Status']['DB_Size'],
|
258 |
+
$db['Status']['DB_Rows']
|
259 |
+
);
|
260 |
|
261 |
//array_count_values will throw a warning message if it has null values,
|
262 |
//so lets replace all nulls with empty string
|
265 |
$warnings[$i] = '';
|
266 |
}
|
267 |
}
|
268 |
+
|
269 |
$warn_counts = is_array($warnings) ? array_count_values($warnings) : 0;
|
270 |
$report['RPT']['Warnings'] = is_null($warn_counts['Warn']) ? 0 : $warn_counts['Warn'];
|
271 |
$report['RPT']['Success'] = is_null($warn_counts['Good']) ? 0 : $warn_counts['Good'];
|
280 |
}
|
281 |
|
282 |
/**
|
283 |
+
* Validates the inputs from the UI for correct data input
|
284 |
+
*
|
285 |
+
* @return DUP_Validator
|
286 |
+
*/
|
287 |
+
public function validateInputs()
|
288 |
+
{
|
289 |
+
$validator = new DUP_Validator();
|
290 |
+
|
291 |
+
$validator->filter_custom($this->Name , DUP_Validator::FILTER_VALIDATE_NOT_EMPTY ,
|
292 |
+
array( 'valkey' => 'Name' ,
|
293 |
+
'errmsg' => __('Package name can\'t be empty', 'duplicator'),
|
294 |
+
)
|
295 |
+
);
|
296 |
+
|
297 |
+
$validator->explode_filter_custom($this->Archive->FilterDirs, ';' , DUP_Validator::FILTER_VALIDATE_FOLDER ,
|
298 |
+
array( 'valkey' => 'FilterDirs' ,
|
299 |
+
'errmsg' => __('Directories: <b>%1$s</b> isn\'t a valid path', 'duplicator'),
|
300 |
+
)
|
301 |
+
);
|
302 |
+
|
303 |
+
$validator->explode_filter_custom($this->Archive->FilterExts, ';' , DUP_Validator::FILTER_VALIDATE_FILE_EXT ,
|
304 |
+
array( 'valkey' => 'FilterExts' ,
|
305 |
+
'errmsg' => __('File extension: <b>%1$s</b> isn\'t a valid extension', 'duplicator'),
|
306 |
+
)
|
307 |
+
);
|
308 |
+
|
309 |
+
$validator->explode_filter_custom($this->Archive->FilterFiles, ';' , DUP_Validator::FILTER_VALIDATE_FILE ,
|
310 |
+
array( 'valkey' => 'FilterFiles' ,
|
311 |
+
'errmsg' => __('Files: <b>%1$s</b> isn\'t a valid file name', 'duplicator'),
|
312 |
+
)
|
313 |
+
);
|
314 |
+
|
315 |
+
$validator->filter_var($this->Installer->OptsDBHost, FILTER_VALIDATE_URL , array(
|
316 |
+
'valkey' => 'OptsDBHost' ,
|
317 |
+
'errmsg' => __('MySQL Server Host: <b>%1$s</b> isn\'t a valid host', 'duplicator'),
|
318 |
+
'acc_vals' => array(
|
319 |
+
'' ,
|
320 |
+
'localhost'
|
321 |
+
)
|
322 |
+
)
|
323 |
+
);
|
324 |
+
|
325 |
+
$validator->filter_var($this->Installer->OptsDBPort, FILTER_VALIDATE_INT , array(
|
326 |
+
'valkey' => 'OptsDBPort' ,
|
327 |
+
'errmsg' => __('MySQL Server Port: <b>%1$s</b> isn\'t a valid port', 'duplicator'),
|
328 |
+
'acc_vals' => array(
|
329 |
+
''
|
330 |
+
),
|
331 |
+
'options' => array(
|
332 |
+
'min_range' => 0
|
333 |
+
)
|
334 |
+
)
|
335 |
+
);
|
336 |
+
|
337 |
+
return $validator;
|
338 |
+
}
|
339 |
+
|
340 |
+
/**
|
341 |
+
* Saves the active package to the package table
|
342 |
*
|
343 |
+
* @return void
|
344 |
+
*/
|
345 |
+
public function save($extension)
|
346 |
+
{
|
347 |
+
global $wpdb;
|
348 |
+
|
349 |
+
$this->Archive->Format = strtoupper($extension);
|
350 |
+
$this->Archive->File = "{$this->NameHash}_archive.{$extension}";
|
351 |
+
$this->Installer->File = "{$this->NameHash}_installer.php";
|
352 |
+
$this->Database->File = "{$this->NameHash}_database.sql";
|
353 |
+
$this->WPUser = isset($current_user->user_login) ? $current_user->user_login : 'unknown';
|
354 |
+
|
355 |
+
//START LOGGING
|
356 |
+
DUP_Log::Open($this->NameHash);
|
357 |
+
|
358 |
+
do_action('duplicator_lite_build_before_start' , $this);
|
359 |
+
|
360 |
+
$this->writeLogHeader();
|
361 |
+
|
362 |
+
//CREATE DB RECORD
|
363 |
+
$packageObj = serialize($this);
|
364 |
+
if (!$packageObj) {
|
365 |
+
DUP_Log::Error("Unable to serialize package object while building record.");
|
366 |
+
}
|
367 |
+
|
368 |
+
$this->ID = $this->getHashKey($this->Hash);
|
369 |
+
|
370 |
+
if ($this->ID != 0) {
|
371 |
+
DUP_LOG::Trace("ID non zero so setting to start");
|
372 |
+
$this->setStatus(DUP_PackageStatus::START);
|
373 |
+
} else {
|
374 |
+
DUP_LOG::Trace("ID IS zero so creating another package");
|
375 |
+
$tablePrefix = DUP_Util::getTablePrefix();
|
376 |
+
$results = $wpdb->insert($tablePrefix . "duplicator_packages", array(
|
377 |
+
'name' => $this->Name,
|
378 |
+
'hash' => $this->Hash,
|
379 |
+
'status' => DUP_PackageStatus::START,
|
380 |
+
'created' => current_time('mysql', get_option('gmt_offset', 1)),
|
381 |
+
'owner' => isset($current_user->user_login) ? $current_user->user_login : 'unknown',
|
382 |
+
'package' => $packageObj)
|
383 |
+
);
|
384 |
+
if ($results === false) {
|
385 |
+
$wpdb->print_error();
|
386 |
+
DUP_LOG::Trace("Problem inserting package: {$wpdb->last_error}");
|
387 |
+
|
388 |
+
DUP_Log::Error("Duplicator is unable to insert a package record into the database table.", "'{$wpdb->last_error}'");
|
389 |
+
}
|
390 |
+
$this->ID = $wpdb->insert_id;
|
391 |
+
}
|
392 |
+
|
393 |
+
do_action('duplicator_lite_build_start' , $this);
|
394 |
+
}
|
395 |
+
|
396 |
+
/**
|
397 |
+
* Delete all files associated with this package ID
|
398 |
+
*
|
399 |
+
* @return void
|
400 |
*/
|
401 |
+
public function delete()
|
402 |
{
|
|
|
403 |
global $wpdb;
|
|
|
404 |
|
405 |
+
$tablePrefix = DUP_Util::getTablePrefix();
|
406 |
+
$tblName = $tablePrefix.'duplicator_packages';
|
407 |
+
$getResult = $wpdb->get_results($wpdb->prepare("SELECT name, hash FROM `{$tblName}` WHERE id = %d", $this->ID), ARRAY_A);
|
408 |
+
|
409 |
+
if ($getResult) {
|
410 |
+
$row = $getResult[0];
|
411 |
+
$nameHash = "{$row['name']}_{$row['hash']}";
|
412 |
+
$delResult = $wpdb->query($wpdb->prepare("DELETE FROM `{$tblName}` WHERE id = %d", $this->ID));
|
413 |
+
|
414 |
+
if ($delResult != 0) {
|
415 |
+
//Perms
|
416 |
+
@chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}_archive.zip"), 0644);
|
417 |
+
@chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}_database.sql"), 0644);
|
418 |
+
@chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}_installer.php"), 0644);
|
419 |
+
@chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}_scan.json"), 0644);
|
420 |
+
@chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}.log"), 0644);
|
421 |
+
|
422 |
+
@chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_archive.zip"), 0644);
|
423 |
+
@chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_database.sql"), 0644);
|
424 |
+
@chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_installer.php"), 0644);
|
425 |
+
@chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_scan.json"), 0644);
|
426 |
+
@chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}.log"), 0644);
|
427 |
+
//Remove
|
428 |
+
@unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}_archive.zip"));
|
429 |
+
@unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}_database.sql"));
|
430 |
+
@unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}_installer.php"));
|
431 |
+
@unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}_scan.json"));
|
432 |
+
@unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}.log"));
|
433 |
+
|
434 |
+
@unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_archive.zip"));
|
435 |
+
@unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_database.sql"));
|
436 |
+
@unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_installer.php"));
|
437 |
+
@unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_scan.json"));
|
438 |
+
@unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}.log"));
|
439 |
+
}
|
440 |
+
}
|
441 |
+
}
|
442 |
|
443 |
+
/**
|
444 |
+
* Get all packages with status conditions
|
445 |
+
* @global wpdb $wpdb
|
446 |
+
* @param array $conditions es. [
|
447 |
+
* relation = 'AND',
|
448 |
+
* [ 'op' => '>=' ,
|
449 |
+
* 'status' => DUP_PackageStatus::START ]
|
450 |
+
* [ 'op' => '<' ,
|
451 |
+
* 'status' => DUP_PackageStatus::COMPLETED ]
|
452 |
+
* ]
|
453 |
+
* @return DUP_Package[]
|
454 |
+
*/
|
455 |
+
public static function get_all_by_status($conditions = array())
|
456 |
+
{
|
457 |
+
global $wpdb;
|
458 |
+
$tablePrefix = DUP_Util::getTablePrefix();
|
459 |
+
$table = $tablePrefix . "duplicator_packages";
|
460 |
|
461 |
+
$accepted_op = array('<', '>', '=', '<>', '>=', '<=');
|
462 |
+
$relation = (isset($conditions['relation']) && strtoupper($conditions['relation']) == 'OR') ? ' OR ' : ' AND ';
|
463 |
+
unset($conditions['relation']);
|
|
|
|
|
|
|
464 |
|
465 |
+
$where = '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
466 |
|
467 |
+
if (!empty($conditions)) {
|
468 |
+
$str_conds = array();
|
469 |
+
|
470 |
+
foreach ($conditions as $cond) {
|
471 |
+
$op = (isset($cond['op']) && in_array($cond['op'], $accepted_op)) ? $cond['op'] : '=';
|
472 |
+
$status = isset($cond['status']) ? (int) $cond['status'] : 0;
|
473 |
+
$str_conds[] = 'status '.$op.' '.$status;
|
474 |
+
}
|
475 |
+
$where = ' WHERE '.implode($relation, $str_conds).' ';
|
476 |
+
}
|
477 |
+
|
478 |
+
$packages = array();
|
479 |
+
$rows = $wpdb->get_results("SELECT * FROM `{$table}` {$where} ORDER BY id DESC", ARRAY_A);
|
480 |
+
|
481 |
+
if ($rows != null) {
|
482 |
+
foreach ($rows as $row) {
|
483 |
+
$Package = unserialize($row['package']);
|
484 |
+
if ($Package) {
|
485 |
+
// We was not storing Status in Lite 1.2.52, so it is for backward compatibility
|
486 |
+
if (!isset($Package->Status)) {
|
487 |
+
$Package->Status = $row['status'];
|
488 |
+
}
|
489 |
+
|
490 |
+
$packages[] = $Package;
|
491 |
+
}
|
492 |
+
}
|
493 |
+
}
|
494 |
+
return $packages;
|
495 |
+
}
|
496 |
+
|
497 |
+
/**
|
498 |
+
*
|
499 |
+
* @global wpdb $wpdb
|
500 |
+
* @return DUP_Package[]
|
501 |
+
*/
|
502 |
+
public static function get_all()
|
503 |
+
{
|
504 |
+
global $wpdb;
|
505 |
+
$tablePrefix = DUP_Util::getTablePrefix();
|
506 |
+
$table = $tablePrefix."duplicator_packages";
|
507 |
+
|
508 |
+
$packages = array();
|
509 |
+
$rows = $wpdb->get_results("SELECT * FROM `{$table}` ORDER BY id DESC", ARRAY_A);
|
510 |
+
if ($rows != null) {
|
511 |
+
foreach ($rows as $row) {
|
512 |
+
$Package = unserialize($row['package']);
|
513 |
+
if ($Package) {
|
514 |
+
// We was not storing Status in Lite 1.2.52, so it is for backward compatibility
|
515 |
+
if (!isset($Package->Status)) {
|
516 |
+
$Package->Status = $row['status'];
|
517 |
+
}
|
518 |
+
|
519 |
+
$packages[] = $Package;
|
520 |
+
}
|
521 |
+
}
|
522 |
+
}
|
523 |
+
return $packages;
|
524 |
+
}
|
525 |
+
|
526 |
+
/**
|
527 |
+
* Check the DupArchive build to make sure it is good
|
528 |
+
*
|
529 |
+
* @return void
|
530 |
+
*/
|
531 |
+
public function runDupArchiveBuildIntegrityCheck()
|
532 |
+
{
|
533 |
+
//INTEGRITY CHECKS
|
534 |
+
//We should not rely on data set in the serlized object, we need to manually check each value
|
535 |
+
//indepentantly to have a true integrity check.
|
536 |
+
DUP_Log::info("\n********************************************************************************");
|
537 |
+
DUP_Log::info("INTEGRITY CHECKS:");
|
538 |
+
DUP_Log::info("********************************************************************************");
|
539 |
+
|
540 |
+
//------------------------
|
541 |
+
//SQL CHECK: File should be at minimum 5K. A base WP install with only Create tables is about 9K
|
542 |
+
$sql_temp_path = DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP . '/' . $this->Database->File);
|
543 |
+
$sql_temp_size = @filesize($sql_temp_path);
|
544 |
+
$sql_easy_size = DUP_Util::byteSize($sql_temp_size);
|
545 |
+
$sql_done_txt = DUP_Util::tailFile($sql_temp_path, 3);
|
546 |
+
DUP_Log::Trace('rundupa1');
|
547 |
+
|
548 |
+
// Note: Had to add extra size check of 800 since observed bad sql when filter was on
|
549 |
+
if (!strstr($sql_done_txt, 'DUPLICATOR_MYSQLDUMP_EOF') || (!$this->Database->FilterOn && $sql_temp_size < 5120) || ($this->Database->FilterOn && $this->Database->info->tablesFinalCount > 0 && $sql_temp_size < 800)) {
|
550 |
+
DUP_Log::Trace('rundupa2');
|
551 |
+
|
552 |
+
$error_text = "ERROR: SQL file not complete. The file {$sql_temp_path} looks too small ($sql_temp_size bytes) or the end of file marker was not found.";
|
553 |
+
$this->BuildProgress->set_failed($error_text);
|
554 |
+
$this->update();
|
555 |
+
//$this->setStatus(DUP_PackageStatus::ERROR);
|
556 |
+
DUP_Log::Error("$error_text", '', Dup_ErrorBehavior::LogOnly);
|
557 |
+
|
558 |
+
return;
|
559 |
+
}
|
560 |
+
|
561 |
+
DUP_Log::Trace('rundupa3');
|
562 |
+
DUP_Log::Info("SQL FILE: {$sql_easy_size}");
|
563 |
+
|
564 |
+
//------------------------
|
565 |
+
//INSTALLER CHECK:
|
566 |
+
$exe_temp_path = DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP . '/' . $this->Installer->File);
|
567 |
+
|
568 |
+
$exe_temp_size = @filesize($exe_temp_path);
|
569 |
+
$exe_easy_size = DUP_Util::byteSize($exe_temp_size);
|
570 |
+
$exe_done_txt = DUP_Util::tailFile($exe_temp_path, 10);
|
571 |
+
|
572 |
+
if (!strstr($exe_done_txt, 'DUPLICATOR_INSTALLER_EOF') && !$this->BuildProgress->failed) {
|
573 |
+
//$this->BuildProgress->failed = true;
|
574 |
+
$error_message = 'ERROR: Installer file not complete. The end of file marker was not found. Please try to re-create the package.';
|
575 |
+
|
576 |
+
$this->BuildProgress->set_failed($error_message);
|
577 |
+
$this->update();
|
578 |
+
//$this->setStatus(DUP_PackageStatus::ERROR);
|
579 |
+
DUP_Log::error($error_message, '', Dup_ErrorBehavior::LogOnly);
|
580 |
+
return;
|
581 |
+
}
|
582 |
+
DUP_Log::info("INSTALLER FILE: {$exe_easy_size}");
|
583 |
+
|
584 |
+
//------------------------
|
585 |
+
//ARCHIVE CHECK:
|
586 |
+
DUP_LOG::trace("Archive file count is " . $this->Archive->file_count);
|
587 |
+
|
588 |
+
if ($this->Archive->file_count != -1) {
|
589 |
+
$zip_easy_size = DUP_Util::byteSize($this->Archive->Size);
|
590 |
+
if (!($this->Archive->Size)) {
|
591 |
+
//$this->BuildProgress->failed = true;
|
592 |
+
$error_message = "ERROR: The archive file contains no size.";
|
593 |
+
|
594 |
+
$this->BuildProgress->set_failed($error_message);
|
595 |
+
$this->update();
|
596 |
+
//$this->setStatus(DUP_PackageStatus::ERROR);
|
597 |
+
DUP_Log::error($error_message, "Archive Size: {$zip_easy_size}", Dup_ErrorBehavior::LogOnly);
|
598 |
+
return;
|
599 |
+
}
|
600 |
+
|
601 |
+
$scan_filepath = DUPLICATOR_SSDIR_PATH_TMP . "/{$this->NameHash}_scan.json";
|
602 |
+
$json = '';
|
603 |
+
|
604 |
+
DUP_LOG::Trace("***********Does $scan_filepath exist?");
|
605 |
+
if (file_exists($scan_filepath)) {
|
606 |
+
$json = file_get_contents($scan_filepath);
|
607 |
+
} else {
|
608 |
+
$error_message = sprintf(__("Can't find Scanfile %s. Please ensure there no non-English characters in the package or schedule name.", 'duplicator'), $scan_filepath);
|
609 |
+
|
610 |
+
//$this->BuildProgress->failed = true;
|
611 |
+
$this->setStatus(DUP_PackageStatus::ERROR);
|
612 |
+
$this->BuildProgress->set_failed($error_message);
|
613 |
+
$this->update();
|
614 |
+
|
615 |
+
DUP_Log::Error($error_message, '', Dup_ErrorBehavior::LogOnly);
|
616 |
+
return;
|
617 |
+
}
|
618 |
+
|
619 |
+
$scanReport = json_decode($json);
|
620 |
+
|
621 |
+
//RSR TODO: rework/simplify the validateion of duparchive
|
622 |
+
$dirCount = count($scanReport->ARC->Dirs);
|
623 |
+
$numInstallerDirs = $this->Installer->numDirsAdded;
|
624 |
+
$fileCount = count($scanReport->ARC->Files);
|
625 |
+
$numInstallerFiles = $this->Installer->numFilesAdded;
|
626 |
+
|
627 |
+
$expected_filecount = $dirCount + $numInstallerDirs + $fileCount + $numInstallerFiles + 1 -1; // Adding database.sql but subtracting the root dir
|
628 |
+
//Dup_Log::trace("#### a:{$dirCount} b:{$numInstallerDirs} c:{$fileCount} d:{$numInstallerFiles} = {$expected_filecount}");
|
629 |
+
|
630 |
+
DUP_Log::info("ARCHIVE FILE: {$zip_easy_size} ");
|
631 |
+
DUP_Log::info(sprintf(__('EXPECTED FILE/DIRECTORY COUNT: %1$s', 'duplicator'), number_format($expected_filecount)));
|
632 |
+
DUP_Log::info(sprintf(__('ACTUAL FILE/DIRECTORY COUNT: %1$s', 'duplicator'), number_format($this->Archive->file_count)));
|
633 |
+
|
634 |
+
$this->ExeSize = $exe_easy_size;
|
635 |
+
$this->ZipSize = $zip_easy_size;
|
636 |
+
|
637 |
+
/* ------- ZIP Filecount Check -------- */
|
638 |
+
// Any zip of over 500 files should be within 2% - this is probably too loose but it will catch gross errors
|
639 |
+
DUP_LOG::trace("Expected filecount = $expected_filecount and archive filecount=" . $this->Archive->file_count);
|
640 |
+
|
641 |
+
if ($expected_filecount > 500) {
|
642 |
+
$straight_ratio = (float) $expected_filecount / (float) $this->Archive->file_count;
|
643 |
+
|
644 |
+
$warning_count = $scanReport->ARC->WarnFileCount + $scanReport->ARC->WarnDirCount + $scanReport->ARC->UnreadableFileCount + $scanReport->ARC->UnreadableDirCount;
|
645 |
+
DUP_LOG::trace("Warn/unread counts) warnfile:{$scanReport->ARC->WarnFileCount} warndir:{$scanReport->ARC->WarnDirCount} unreadfile:{$scanReport->ARC->UnreadableFileCount} unreaddir:{$scanReport->ARC->UnreadableDirCount}");
|
646 |
+
|
647 |
+
$warning_ratio = ((float) ($expected_filecount + $warning_count)) / (float) $this->Archive->file_count;
|
648 |
+
DUP_LOG::trace("Straight ratio is $straight_ratio and warning ratio is $warning_ratio. # Expected=$expected_filecount # Warning=$warning_count and #Archive File {$this->Archive->file_count}");
|
649 |
+
|
650 |
+
// Allow the real file count to exceed the expected by 10% but only allow 1% the other way
|
651 |
+
if (($straight_ratio < 0.90) || ($straight_ratio > 1.01)) {
|
652 |
+
// Has to exceed both the straight as well as the warning ratios
|
653 |
+
if (($warning_ratio < 0.90) || ($warning_ratio > 1.01)) {
|
654 |
+
|
655 |
+
$error_message = sprintf('ERROR: File count in archive vs expected suggests a bad archive (%1$d vs %2$d).', $archive_file_count, $expected_filecount);
|
656 |
+
$this->BuildProgress->set_failed($error_message);
|
657 |
+
$this->update();
|
658 |
+
$archive_file_count = $this->Archive->file_count;
|
659 |
+
DUP_Log::error($error_message, '', Dup_ErrorBehavior::LogOnly);
|
660 |
+
return;
|
661 |
+
}
|
662 |
+
}
|
663 |
+
}
|
664 |
+
}
|
665 |
+
}
|
666 |
+
|
667 |
+
public function getLocalPackageFile($file_type)
|
668 |
+
{
|
669 |
+
$file_path = null;
|
670 |
+
|
671 |
+
if ($file_type == DUP_PackageFileType::Installer) {
|
672 |
+
DUP_Log::Trace("Installer requested");
|
673 |
+
$file_name = $this->getInstallerFilename();
|
674 |
+
} else if ($file_type == DUP_PackageFileType::Archive) {
|
675 |
+
DUP_Log::Trace("Archive requested");
|
676 |
+
$file_name = $this->getArchiveFilename();
|
677 |
+
} else if ($file_type == DUP_PackageFileType::SQL) {
|
678 |
+
DUP_Log::Trace("SQL requested");
|
679 |
+
$file_name = $this->getDatabaseFilename();
|
680 |
+
} else {
|
681 |
+
DUP_Log::Trace("Log requested");
|
682 |
+
$file_name = $this->getLogFilename();
|
683 |
}
|
684 |
|
685 |
+
$file_path = Dup_Util::safePath(DUPLICATOR_SSDIR_PATH) . "/$file_name";
|
686 |
+
DUP_Log::Trace("File path $file_path");
|
687 |
|
688 |
+
if (file_exists($file_path)) {
|
689 |
+
return $file_path;
|
690 |
} else {
|
691 |
+
return null;
|
692 |
+
}
|
693 |
+
}
|
694 |
+
|
695 |
+
public function getScanFilename()
|
696 |
+
{
|
697 |
+
return $this->NameHash . '_scan.json';
|
698 |
+
}
|
699 |
+
|
700 |
+
public function getLogFilename()
|
701 |
+
{
|
702 |
+
return $this->NameHash . '.log';
|
703 |
+
}
|
704 |
+
|
705 |
+
public function getArchiveFilename()
|
706 |
+
{
|
707 |
+
$extension = strtolower($this->Archive->Format);
|
708 |
+
|
709 |
+
return "{$this->NameHash}_archive.{$extension}";
|
710 |
+
}
|
711 |
+
|
712 |
+
public function getInstallerFilename()
|
713 |
+
{
|
714 |
+
return "{$this->NameHash}_installer.php";
|
715 |
+
}
|
716 |
+
|
717 |
+
public function getDatabaseFilename()
|
718 |
+
{
|
719 |
+
return $this->NameHash . '_database.sql';
|
720 |
+
}
|
721 |
+
|
722 |
+
/**
|
723 |
+
* Removes all files except those of active packages
|
724 |
+
*/
|
725 |
+
public static function not_active_files_tmp_cleanup()
|
726 |
+
{
|
727 |
+
//Check for the 'tmp' folder just for safe measures
|
728 |
+
if (! is_dir(DUPLICATOR_SSDIR_PATH_TMP) && (strpos(DUPLICATOR_SSDIR_PATH_TMP, 'tmp') !== false) ) {
|
729 |
+
return;
|
730 |
+
}
|
731 |
+
|
732 |
+
$iterator = new FilesystemIterator(DUPLICATOR_SSDIR_PATH_TMP);
|
733 |
+
|
734 |
+
// if tmp is empty return
|
735 |
+
if (!$iterator->valid()) {
|
736 |
+
return;
|
737 |
+
}
|
738 |
+
|
739 |
+
// RUNNING PACKAGES
|
740 |
+
$active_pack = self::get_all_by_status(array(
|
741 |
+
'relation' => 'AND',
|
742 |
+
array('op' => '>=' , 'status' => DUP_PackageStatus::CREATED ),
|
743 |
+
array('op' => '<' , 'status' => DUP_PackageStatus::COMPLETE )
|
744 |
+
));
|
745 |
+
$active_files = array();
|
746 |
+
foreach($active_pack as $package) {
|
747 |
+
$active_files[] = $package->NameHash;
|
748 |
+
}
|
749 |
+
|
750 |
+
// ERRORS PACKAGES
|
751 |
+
$err_pack = self::get_all_by_status(array(
|
752 |
+
array('op' => '<' , 'status' => DUP_PackageStatus::CREATED )
|
753 |
+
));
|
754 |
+
$force_del_files = array();
|
755 |
+
foreach($err_pack as $package) {
|
756 |
+
$force_del_files[] = $package->NameHash;
|
757 |
+
}
|
758 |
+
|
759 |
+
// Don't remove json file;
|
760 |
+
$extension_filter = array('json');
|
761 |
+
|
762 |
+
// Calculate delta time for old files
|
763 |
+
$oldTimeToClean = time() - DUPLICATOR_TEMP_CLEANUP_SECONDS;
|
764 |
+
|
765 |
+
foreach ($iterator as $fileinfo) {
|
766 |
+
// Don't remove sub dir
|
767 |
+
if ($fileinfo->isDir()) {
|
768 |
+
continue;
|
769 |
+
}
|
770 |
+
|
771 |
+
// skip all active packages
|
772 |
+
foreach ($active_files as $c_nameHash) {
|
773 |
+
if (strpos($fileinfo->getFilename(), $c_nameHash) === 0) {
|
774 |
+
continue 2;
|
775 |
+
}
|
776 |
+
}
|
777 |
+
|
778 |
+
// Remove all old files
|
779 |
+
if ($fileinfo->getCTime() <= $oldTimeToClean) {
|
780 |
+
@unlink($fileinfo->getRealPath());
|
781 |
+
continue;
|
782 |
+
}
|
783 |
|
784 |
+
// remove all error packages files
|
785 |
+
foreach ($force_del_files as $c_nameHash) {
|
786 |
+
if (strpos($fileinfo->getFilename(), $c_nameHash) === 0) {
|
787 |
+
@unlink($fileinfo->getRealPath());
|
788 |
+
continue 2;
|
789 |
+
}
|
790 |
+
}
|
791 |
+
|
792 |
+
// skip json file for pre build packages
|
793 |
+
if (in_array($fileinfo->getExtension(),$extension_filter) || in_array($fileinfo->getFilename() , $active_files)) {
|
794 |
+
continue;
|
795 |
+
}
|
796 |
+
|
797 |
+
@unlink($fileinfo->getRealPath());
|
798 |
+
}
|
799 |
+
}
|
800 |
+
|
801 |
+
/**
|
802 |
+
* Cleans up the temp storage folder have a time interval
|
803 |
+
*
|
804 |
+
* @return void
|
805 |
+
*/
|
806 |
+
public static function safeTmpCleanup($purge_temp_archives = false)
|
807 |
+
{
|
808 |
+
if ($purge_temp_archives) {
|
809 |
+
$dir = DUPLICATOR_SSDIR_PATH_TMP . "/*_archive.zip.*";
|
810 |
+
foreach (glob($dir) as $file_path) {
|
811 |
+
unlink($file_path);
|
812 |
+
}
|
813 |
+
$dir = DUPLICATOR_SSDIR_PATH_TMP . "/*_archive.daf.*";
|
814 |
+
foreach (glob($dir) as $file_path) {
|
815 |
+
unlink($file_path);
|
816 |
+
}
|
817 |
+
} else {
|
818 |
+
//Remove all temp files that are 24 hours old
|
819 |
+
$dir = DUPLICATOR_SSDIR_PATH_TMP . "/*";
|
820 |
+
|
821 |
+
$files = glob($dir);
|
822 |
+
|
823 |
+
if ($files !== false) {
|
824 |
+
foreach ($files as $file_path) {
|
825 |
+
// Cut back to keeping things around for just an hour 15 min
|
826 |
+
if (filemtime($file_path) <= time() - DUPLICATOR_TEMP_CLEANUP_SECONDS) {
|
827 |
+
unlink($file_path);
|
828 |
+
}
|
829 |
+
}
|
830 |
}
|
831 |
+
}
|
832 |
+
}
|
833 |
+
|
834 |
+
/**
|
835 |
+
* Starts the package DupArchive progressive build process - always assumed to only run off active package, NOT one in the package table
|
836 |
+
*
|
837 |
+
* @return obj Returns a DUP_Package object
|
838 |
+
*/
|
839 |
+
public function runDupArchiveBuild()
|
840 |
+
{
|
841 |
+
$this->BuildProgress->start_timer();
|
842 |
+
DUP_Log::Trace('Called');
|
843 |
+
|
844 |
+
if ($this->BuildProgress->failed) {
|
845 |
+
|
846 |
+
DUP_LOG::Trace("build progress failed so setting package to failed");
|
847 |
+
$this->setStatus(DUP_PackageStatus::ERROR);
|
848 |
+
$message = "Package creation failed.";
|
849 |
+
DUP_Log::Trace($message);
|
850 |
+
return true;
|
851 |
+
}
|
852 |
+
|
853 |
+
if ($this->BuildProgress->initialized == false) {
|
854 |
+
DUP_Log::Trace('Initializing');
|
855 |
+
$this->BuildProgress->initialized = true;
|
856 |
+
$this->TimerStart = Dup_Util::getMicrotime();
|
857 |
+
$this->update();
|
858 |
}
|
859 |
|
860 |
+
//START BUILD
|
861 |
+
if (!$this->BuildProgress->database_script_built) {
|
862 |
+
DUP_Log::Trace('Building database script');
|
863 |
+
|
864 |
+
$this->Database->build($this, Dup_ErrorBehavior::ThrowException);
|
865 |
+
$this->BuildProgress->database_script_built = true;
|
866 |
+
$this->update();
|
867 |
+
DUP_LOG::Trace("Built database script");
|
868 |
+
} else if (!$this->BuildProgress->archive_built) {
|
869 |
+
DUP_Log::Trace('e');
|
870 |
+
|
871 |
+
$this->Archive->build($this);
|
872 |
+
$this->update();
|
873 |
+
} else if (!$this->BuildProgress->installer_built) {
|
874 |
+
|
875 |
+
DUP_Log::Trace('f');
|
876 |
+
// Installer being built is stuffed into the archive build phase
|
877 |
+
}
|
878 |
+
|
879 |
+
if ($this->BuildProgress->has_completed()) {
|
880 |
+
|
881 |
+
DUP_Log::Trace('c');
|
882 |
+
|
883 |
+
if (!$this->BuildProgress->failed) {
|
884 |
+
DUP_LOG::trace("top of loop build progress not failed");
|
885 |
+
// Only makees sense to perform build integrity check on completed archives
|
886 |
+
$this->runDupArchiveBuildIntegrityCheck();
|
887 |
+
} else {
|
888 |
+
DUP_LOG::trace("top of loop build progress failed");
|
889 |
+
}
|
890 |
+
|
891 |
+
$timerEnd = DUP_Util::getMicrotime();
|
892 |
+
$timerSum = DUP_Util::elapsedTime($timerEnd, $this->TimerStart);
|
893 |
+
$this->Runtime = $timerSum;
|
894 |
+
|
895 |
+
//FINAL REPORT
|
896 |
+
$info = "\n********************************************************************************\n";
|
897 |
+
$info .= "RECORD ID:[{$this->ID}]\n";
|
898 |
+
$info .= "TOTAL PROCESS RUNTIME: {$timerSum}\n";
|
899 |
+
$info .= "PEAK PHP MEMORY USED: " . DUP_Server::getPHPMemory(true) . "\n";
|
900 |
+
$info .= "DONE PROCESSING => {$this->Name} " . @date("Y-m-d H:i:s") . "\n";
|
901 |
+
|
902 |
+
DUP_Log::info($info);
|
903 |
+
DUP_LOG::trace("Done package building");
|
904 |
+
|
905 |
+
if (!$this->BuildProgress->failed) {
|
906 |
+
|
907 |
+
$this->setStatus(DUP_PackageStatus::COMPLETE);
|
908 |
+
DUP_LOG::Trace("Cleaning up duparchive temp files");
|
909 |
+
//File Cleanup
|
910 |
+
$this->buildCleanup();
|
911 |
+
do_action('duplicator_lite_build_completed' , $this);
|
912 |
+
}
|
913 |
+
}
|
914 |
+
|
915 |
+
DUP_Log::Close();
|
916 |
+
|
917 |
+
return $this->BuildProgress->has_completed();
|
918 |
+
}
|
919 |
+
|
920 |
+
/**
|
921 |
+
* Starts the package build process
|
922 |
+
*
|
923 |
+
* @return obj Returns a DUP_Package object
|
924 |
+
*/
|
925 |
+
public function runZipBuild()
|
926 |
+
{
|
927 |
+
$timerStart = DUP_Util::getMicrotime();
|
928 |
+
|
929 |
+
DUP_Log::Trace('#### start of zip build');
|
930 |
//START BUILD
|
931 |
//PHPs serialze method will return the object, but the ID above is not passed
|
932 |
//for one reason or another so passing the object back in seems to do the trick
|
986 |
* @see DUP_Package::getActive
|
987 |
*
|
988 |
* @param $_POST $post The Post server object
|
989 |
+
*
|
990 |
* @return null
|
991 |
*/
|
992 |
public function saveActive($post = null)
|
996 |
if (isset($post)) {
|
997 |
$post = stripslashes_deep($post);
|
998 |
|
999 |
+
$name = isset($post['package-name']) ? trim($post['package-name']) : self::getDefaultName();
|
1000 |
+
$name = str_replace(array(' ', '-'), '_', $name);
|
1001 |
+
$name = str_replace(array('.', ';', ':', "'", '"'), '', $name);
|
1002 |
+
$name = sanitize_file_name($name);
|
1003 |
+
$name = substr(trim($name), 0, 40);
|
1004 |
|
1005 |
+
if (isset($post['filter-dirs'])) {
|
1006 |
+
$post_filter_dirs = sanitize_text_field($post['filter-dirs']);
|
1007 |
+
$filter_dirs = $this->Archive->parseDirectoryFilter($post_filter_dirs);
|
1008 |
+
} else {
|
1009 |
+
$filter_dirs = '';
|
1010 |
+
}
|
1011 |
+
|
1012 |
+
if (isset($post['filter-files'])) {
|
1013 |
+
$post_filter_files = sanitize_text_field($post['filter-files']);
|
1014 |
+
$filter_files = $this->Archive->parseFileFilter($post_filter_files);
|
1015 |
+
} else {
|
1016 |
+
$filter_files = '';
|
1017 |
+
}
|
1018 |
+
|
1019 |
+
if (isset($post['filter-exts'])) {
|
1020 |
+
$post_filter_exts = sanitize_text_field($post['filter-exts']);
|
1021 |
+
$filter_exts = $this->Archive->parseExtensionFilter($post_filter_exts);
|
1022 |
+
} else {
|
1023 |
+
$filter_exts = '';
|
1024 |
+
}
|
1025 |
+
|
1026 |
+
$tablelist = '';
|
1027 |
+
if (isset($post['dbtables'])) {
|
1028 |
+
$tablelist = implode(',', $post['dbtables']);
|
1029 |
+
}
|
1030 |
|
1031 |
+
if (isset($post['dbcompat'])) {
|
1032 |
+
$post_dbcompat = sanitize_text_field($post['dbcompat']);
|
1033 |
+
$compatlist = isset($post['dbcompat']) ? implode(',', $post_dbcompat) : '';
|
1034 |
+
} else {
|
1035 |
+
$compatlist = '';
|
1036 |
+
}
|
1037 |
+
|
1038 |
+
$dbversion = DUP_DB::getVersion();
|
1039 |
+
$dbversion = is_null($dbversion) ? '- unknown -' : sanitize_text_field($dbversion);
|
1040 |
+
$dbcomments = sanitize_text_field(DUP_DB::getVariable('version_comment'));
|
1041 |
+
$dbcomments = is_null($dbcomments) ? '- unknown -' : sanitize_text_field($dbcomments);
|
1042 |
|
1043 |
//PACKAGE
|
1044 |
$this->Created = date("Y-m-d H:i:s");
|
1049 |
$this->VersionDB = sanitize_text_field($dbversion);
|
1050 |
$this->Name = sanitize_text_field($name);
|
1051 |
$this->Hash = $this->makeHash();
|
1052 |
+
$this->NameHash = sanitize_text_field("{$this->Name}_{$this->Hash}");
|
1053 |
|
1054 |
$this->Notes = sanitize_textarea_field($post['package-notes']);
|
1055 |
//ARCHIVE
|
1058 |
$this->Archive->FilterOn = isset($post['filter-on']) ? 1 : 0;
|
1059 |
$this->Archive->ExportOnlyDB = isset($post['export-onlydb']) ? 1 : 0;
|
1060 |
$this->Archive->FilterDirs = sanitize_textarea_field($filter_dirs);
|
1061 |
+
$this->Archive->FilterFiles = sanitize_textarea_field($filter_files);
|
1062 |
+
$this->Archive->FilterExts = str_replace(array('.', ' '), '', $filter_exts);
|
1063 |
//INSTALLER
|
1064 |
$this->Installer->OptsDBHost = sanitize_text_field($post['dbhost']);
|
1065 |
$this->Installer->OptsDBPort = sanitize_text_field($post['dbport']);
|
1066 |
$this->Installer->OptsDBName = sanitize_text_field($post['dbname']);
|
1067 |
$this->Installer->OptsDBUser = sanitize_text_field($post['dbuser']);
|
1068 |
$this->Installer->OptsSecureOn = isset($post['secure-on']) ? 1 : 0;
|
1069 |
+
$post_secure_pass = sanitize_text_field($post['secure-pass']);
|
1070 |
+
$this->Installer->OptsSecurePass = DUP_Util::installerScramble($post_secure_pass);
|
1071 |
//DATABASE
|
1072 |
$this->Database->FilterOn = isset($post['dbfilter-on']) ? 1 : 0;
|
1073 |
$this->Database->FilterTables = sanitize_text_field($tablelist);
|
1078 |
}
|
1079 |
}
|
1080 |
|
1081 |
+
/**
|
1082 |
+
* Update the serialized package and status in the database
|
1083 |
+
*
|
1084 |
+
* @return void
|
1085 |
+
*/
|
1086 |
+
public function update()
|
1087 |
+
{
|
1088 |
+
global $wpdb;
|
1089 |
+
|
1090 |
+
$packageObj = serialize($this);
|
1091 |
+
|
1092 |
+
if (!$packageObj) {
|
1093 |
+
DUP_Log::Error("Package SetStatus was unable to serialize package object while updating record.");
|
1094 |
+
}
|
1095 |
+
|
1096 |
+
$wpdb->flush();
|
1097 |
+
$tablePrefix = DUP_Util::getTablePrefix();
|
1098 |
+
$table = $tablePrefix."duplicator_packages";
|
1099 |
+
$sql = "UPDATE `{$table}` SET status = {$this->Status},";
|
1100 |
+
$sql .= "package = '" . esc_sql($packageObj) . "'";
|
1101 |
+
$sql .= "WHERE ID = {$this->ID}";
|
1102 |
+
|
1103 |
+
DUP_Log::Trace('-------------------------');
|
1104 |
+
DUP_Log::Trace("status = {$this->Status}");
|
1105 |
+
DUP_Log::Trace("ID = {$this->ID}");
|
1106 |
+
DUP_Log::Trace('-------------------------');
|
1107 |
+
|
1108 |
+
//DUP_Log::Trace('####Executing SQL' . $sql . '-----------');
|
1109 |
+
$wpdb->query($sql);
|
1110 |
+
}
|
1111 |
+
|
1112 |
/**
|
1113 |
* Save any property of this class through reflection
|
1114 |
*
|
1135 |
*/
|
1136 |
public function setStatus($status)
|
1137 |
{
|
|
|
|
|
|
|
|
|
1138 |
if (!isset($status)) {
|
1139 |
DUP_Log::Error("Package SetStatus did not receive a proper code.");
|
1140 |
}
|
1141 |
|
1142 |
+
$this->Status = $status;
|
|
|
|
|
1143 |
|
1144 |
+
$this->update();
|
|
|
|
|
|
|
1145 |
}
|
1146 |
|
1147 |
/**
|
1148 |
+
* Does a hash already exists
|
1149 |
*
|
1150 |
* @param string $hash An existing hash value
|
1151 |
*
|
1155 |
{
|
1156 |
global $wpdb;
|
1157 |
|
1158 |
+
$tablePrefix = DUP_Util::getTablePrefix();
|
1159 |
+
$table = $tablePrefix."duplicator_packages";
|
1160 |
$qry = $wpdb->get_row("SELECT ID, hash FROM `{$table}` WHERE hash = '{$hash}'");
|
1161 |
+
if (is_null($qry) || strlen($qry->hash) == 0) {
|
1162 |
return 0;
|
1163 |
} else {
|
1164 |
return $qry->ID;
|
1166 |
}
|
1167 |
|
1168 |
/**
|
1169 |
+
* Makes the hashkey for the package files
|
|
|
1170 |
*
|
1171 |
+
* @return string A unique hashkey
|
1172 |
*/
|
1173 |
public function makeHash()
|
1174 |
{
|
|
|
1175 |
try {
|
1176 |
if (function_exists('random_bytes') && DUP_Util::PHP53()) {
|
1177 |
return bin2hex(random_bytes(8)) . mt_rand(1000, 9999) . '_' . date("YmdHis");
|
1202 |
}
|
1203 |
//Incase unserilaize fails
|
1204 |
$obj = (is_object($obj)) ? $obj : new DUP_Package();
|
1205 |
+
|
1206 |
return $obj;
|
1207 |
}
|
1208 |
|
1209 |
/**
|
1210 |
* Gets the Package by ID
|
1211 |
+
*
|
1212 |
* @param int $id A valid package id form the duplicator_packages table
|
1213 |
*
|
1214 |
* @return obj A copy of the DUP_Package object
|
1215 |
*/
|
1216 |
public static function getByID($id)
|
1217 |
{
|
|
|
1218 |
global $wpdb;
|
1219 |
$obj = new DUP_Package();
|
1220 |
+
$tablePrefix = DUP_Util::getTablePrefix();
|
1221 |
+
$sql = $wpdb->prepare("SELECT * FROM `{$tablePrefix}duplicator_packages` WHERE ID = %d", $id);
|
1222 |
+
$row = $wpdb->get_row($sql);
|
1223 |
if (is_object($row)) {
|
1224 |
$obj = @unserialize($row->package);
|
1225 |
$obj->Status = $row->status;
|
1238 |
{
|
1239 |
//Remove specail_chars from final result
|
1240 |
$special_chars = array(".", "-");
|
1241 |
+
$name = ($preDate)
|
1242 |
? date('Ymd') . '_' . sanitize_title(get_bloginfo('name', 'display'))
|
1243 |
: sanitize_title(get_bloginfo('name', 'display')) . '_' . date('Ymd');
|
1244 |
$name = substr(sanitize_file_name($name), 0, 40);
|
1275 |
|
1276 |
/**
|
1277 |
* Provides various date formats
|
1278 |
+
*
|
1279 |
* @param $date The date to format
|
1280 |
* @param $format Various date formats to apply
|
1281 |
+
*
|
1282 |
* @return a formated date based on the $format
|
1283 |
*/
|
1284 |
public static function getCreatedDateFormat($date, $format = 1)
|
1320 |
/**
|
1321 |
* Cleans up all the tmp files as part of the package build process
|
1322 |
*/
|
1323 |
+
public function buildCleanup()
|
1324 |
{
|
|
|
1325 |
$files = DUP_Util::listFiles(DUPLICATOR_SSDIR_PATH_TMP);
|
1326 |
$newPath = DUPLICATOR_SSDIR_PATH;
|
1327 |
|
1343 |
}
|
1344 |
}
|
1345 |
|
1346 |
+
|
1347 |
+
|
1348 |
/**
|
1349 |
* Get package hash
|
1350 |
+
*
|
1351 |
* @return string package hash
|
1352 |
*/
|
1353 |
public function getPackageHash() {
|
1354 |
$hashParts = explode('_', $this->Hash);
|
1355 |
$firstPart = substr($hashParts[0], 0, 7);
|
1356 |
$secondPart = substr($hashParts[1], -8);
|
1357 |
+
$package_hash = $firstPart.'-'.$secondPart;
|
1358 |
+
return $package_hash;
|
1359 |
}
|
1360 |
|
1361 |
/**
|
1365 |
*/
|
1366 |
public function getSqlArkFilePath()
|
1367 |
{
|
1368 |
+
$package_hash = $this->getPackageHash();
|
1369 |
+
$sql_ark_file_Path = 'dup-installer/dup-database__'.$package_hash.'.sql';
|
1370 |
+
return $sql_ark_file_Path;
|
1371 |
}
|
1372 |
+
|
1373 |
+
private function writeLogHeader()
|
1374 |
+
{
|
1375 |
+
$php_max_time = @ini_get("max_execution_time");
|
1376 |
+
$php_max_memory = @ini_set('memory_limit', DUPLICATOR_PHP_MAX_MEMORY);
|
1377 |
+
$php_max_time = ($php_max_time == 0) ? "(0) no time limit imposed" : "[{$php_max_time}] not allowed";
|
1378 |
+
$php_max_memory = ($php_max_memory === false) ? "Unabled to set php memory_limit" : DUPLICATOR_PHP_MAX_MEMORY." ({$php_max_memory} default)";
|
1379 |
+
|
1380 |
+
$info = "********************************************************************************\n";
|
1381 |
+
$info .= "DUPLICATOR-LITE PACKAGE-LOG: ".@date(get_option('date_format')." ".get_option('time_format'))."\n";
|
1382 |
+
$info .= "NOTICE: Do NOT post to public sites or forums \n";
|
1383 |
+
$info .= "********************************************************************************\n";
|
1384 |
+
$info .= "VERSION:\t".DUPLICATOR_VERSION."\n";
|
1385 |
+
$info .= "WORDPRESS:\t{$GLOBALS['wp_version']}\n";
|
1386 |
+
$info .= "PHP INFO:\t".phpversion().' | '.'SAPI: '.php_sapi_name()."\n";
|
1387 |
+
$info .= "SERVER:\t\t{$_SERVER['SERVER_SOFTWARE']} \n";
|
1388 |
+
$info .= "PHP TIME LIMIT: {$php_max_time} \n";
|
1389 |
+
$info .= "PHP MAX MEMORY: {$php_max_memory} \n";
|
1390 |
+
$info .= "MEMORY STACK: ".DUP_Server::getPHPMemory();
|
1391 |
+
DUP_Log::Info($info);
|
1392 |
+
|
1393 |
+
$info = null;
|
1394 |
+
}
|
1395 |
+
}
|
classes/package/duparchive/class.pack.archive.duparchive.php
ADDED
@@ -0,0 +1,368 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
defined("ABSPATH") or die("");
|
3 |
+
if (!defined('DUPLICATOR_VERSION')) exit; // Exit if accessed directly
|
4 |
+
|
5 |
+
//?require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.archive.php');
|
6 |
+
//require_once (DUPLICATOR_PLUGIN_PATH.'classes/utilities/class.u.php');
|
7 |
+
require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/duparchive/class.pack.archive.duparchive.state.expand.php');
|
8 |
+
require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/duparchive/class.pack.archive.duparchive.state.create.php');
|
9 |
+
require_once (DUPLICATOR_PLUGIN_PATH.'lib/dup_archive/classes/class.duparchive.loggerbase.php');
|
10 |
+
require_once (DUPLICATOR_PLUGIN_PATH.'lib/dup_archive/classes/class.duparchive.engine.php');
|
11 |
+
require_once (DUPLICATOR_PLUGIN_PATH.'lib/dup_archive/classes/states/class.duparchive.state.create.php');
|
12 |
+
require_once (DUPLICATOR_PLUGIN_PATH.'lib/dup_archive/classes/states/class.duparchive.state.expand.php');
|
13 |
+
|
14 |
+
class DUP_DupArchive_Logger extends DupArchiveLoggerBase
|
15 |
+
{
|
16 |
+
|
17 |
+
public function log($s, $flush = false, $callingFunctionOverride = null)
|
18 |
+
{
|
19 |
+
DUP_Log::Trace($s, true, $callingFunctionOverride);
|
20 |
+
}
|
21 |
+
}
|
22 |
+
|
23 |
+
class DUP_DupArchive
|
24 |
+
{
|
25 |
+
// Using a worker time override since evidence shorter time works much
|
26 |
+
const WorkerTimeInSec = 10;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* CREATE
|
30 |
+
* Creates the zip file and adds the SQL file to the archive
|
31 |
+
*/
|
32 |
+
public static function create($archive, $buildProgress, $package)
|
33 |
+
{
|
34 |
+
/* @var $buildProgress DUP_Build_Progress */
|
35 |
+
|
36 |
+
DUP_LOG::trace("start");
|
37 |
+
try {
|
38 |
+
if(DUP_Log::$logFileHandle == null) {
|
39 |
+
DUP_Log::Open($package->NameHash);
|
40 |
+
}
|
41 |
+
|
42 |
+
DUP_LOG::trace("c2");
|
43 |
+
|
44 |
+
if ($buildProgress->retries > DUPLICATOR_MAX_BUILD_RETRIES) {
|
45 |
+
DUP_LOG::trace("c3");
|
46 |
+
$error_msg = __('Package build appears stuck so marking package as failed. Is the Max Worker Time set too high?.', 'duplicator');
|
47 |
+
DUP_Log::error(esc_html__('Build Failure', 'duplicator'), esc_html($error_msg), Dup_ErrorBehavior::LogOnly);
|
48 |
+
//$buildProgress->failed = true;
|
49 |
+
$buildProgress->set_failed($error_msg);
|
50 |
+
return true;
|
51 |
+
} else {
|
52 |
+
DUP_LOG::trace("c4");
|
53 |
+
// If all goes well retries will be reset to 0 at the end of this function.
|
54 |
+
$buildProgress->retries++;
|
55 |
+
$package->update();
|
56 |
+
}
|
57 |
+
|
58 |
+
$done = false;
|
59 |
+
|
60 |
+
DUP_LOG::trace("c5");
|
61 |
+
DupArchiveEngine::init(new DUP_DupArchive_Logger());
|
62 |
+
|
63 |
+
DUP_LOG::trace("c6");
|
64 |
+
DUP_Package::safeTmpCleanup(true);
|
65 |
+
|
66 |
+
$compressDir = rtrim(DUP_Util::safePath($archive->PackDir), '/');
|
67 |
+
$sqlPath = DUP_Util::safePath("{$package->StorePath}/{$package->Database->File}");
|
68 |
+
$archivePath = DUP_Util::safePath("{$package->StorePath}/{$archive->File}");
|
69 |
+
|
70 |
+
$scanFilepath = DUPLICATOR_SSDIR_PATH_TMP."/{$package->NameHash}_scan.json";
|
71 |
+
|
72 |
+
DUP_LOG::trace("c7");
|
73 |
+
$skipArchiveFinalization = false;
|
74 |
+
$json = '';
|
75 |
+
|
76 |
+
DUP_LOG::trace("c8");
|
77 |
+
if (file_exists($scanFilepath)) {
|
78 |
+
|
79 |
+
DUP_LOG::trace("c9");
|
80 |
+
$json = file_get_contents($scanFilepath);
|
81 |
+
|
82 |
+
if (empty($json)) {
|
83 |
+
DUP_LOG::trace("c10");
|
84 |
+
$errorText = __("Scan file $scanFilepath is empty!", 'duplicator');
|
85 |
+
$fixText = __("Click on \"Resolve This\" button to fix the JSON settings.", 'duplicator');
|
86 |
+
|
87 |
+
DUP_Log::Trace($errorText);
|
88 |
+
DUP_Log::error(esc_html($errorText)." **RECOMMENDATION: ".esc_html($fixText).".", '', Dup_ErrorBehavior::LogOnly);
|
89 |
+
|
90 |
+
//$buildProgress->failed = true;
|
91 |
+
$buildProgress->set_failed($errorText);
|
92 |
+
return true;
|
93 |
+
}
|
94 |
+
} else {
|
95 |
+
DUP_LOG::trace("c11");
|
96 |
+
DUP_Log::trace("**** scan file $scanFilepath doesn't exist!!");
|
97 |
+
$errorMessage = sprintf(__("ERROR: Can't find Scanfile %s. Please ensure there no non-English characters in the package or schedule name.", 'duplicator'), $scanFilepath);
|
98 |
+
|
99 |
+
DUP_Log::error($errorMessage, '', Dup_ErrorBehavior::LogOnly);
|
100 |
+
|
101 |
+
//$buildProgress->failed = true;
|
102 |
+
$buildProgress->set_failed($errorMessage);
|
103 |
+
return true;
|
104 |
+
}
|
105 |
+
|
106 |
+
DUP_LOG::trace("c12");
|
107 |
+
Dup_Log::TraceObject("buildprogress object", $buildProgress, false);
|
108 |
+
|
109 |
+
$scanReport = json_decode($json);
|
110 |
+
|
111 |
+
if ($buildProgress->archive_started == false) {
|
112 |
+
|
113 |
+
$filterDirs = empty($archive->FilterDirs) ? 'not set' : $archive->FilterDirs;
|
114 |
+
$filterExts = empty($archive->FilterExts) ? 'not set' : $archive->FilterExts;
|
115 |
+
$filterFiles = empty($archive->FilterFiles) ? 'not set' : $archive->FilterFiles;
|
116 |
+
$filterOn = ($archive->FilterOn) ? 'ON' : 'OFF';
|
117 |
+
$filterDirsFormat = rtrim(str_replace(';', "\n\t", $filterDirs));
|
118 |
+
$filterFilesFormat = rtrim(str_replace(';', "\n\t", $filterFiles));
|
119 |
+
|
120 |
+
DUP_LOG::trace("c13");
|
121 |
+
DUP_Log::info("\n********************************************************************************");
|
122 |
+
DUP_Log::info("ARCHIVE Type=DUP Mode=DupArchive");
|
123 |
+
DUP_Log::info("********************************************************************************");
|
124 |
+
DUP_Log::info("ARCHIVE DIR: ".$compressDir);
|
125 |
+
DUP_Log::info("ARCHIVE FILE: ".basename($archivePath));
|
126 |
+
DUP_Log::info("FILTERS: *{$filterOn}*");
|
127 |
+
DUP_Log::Info("DIRS:\n\t{$filterDirsFormat}");
|
128 |
+
DUP_Log::Info("FILES:\n\t{$filterFilesFormat}");
|
129 |
+
DUP_Log::info("EXTS: {$filterExts}");
|
130 |
+
|
131 |
+
DUP_Log::info("----------------------------------------");
|
132 |
+
DUP_Log::info("COMPRESSING");
|
133 |
+
DUP_Log::info("SIZE:\t".$scanReport->ARC->Size);
|
134 |
+
DUP_Log::info("STATS:\tDirs ".$scanReport->ARC->DirCount." | Files ".$scanReport->ARC->FileCount." | Total ".$scanReport->ARC->FullCount);
|
135 |
+
|
136 |
+
if (($scanReport->ARC->DirCount == '') || ($scanReport->ARC->FileCount == '') || ($scanReport->ARC->FullCount == '')) {
|
137 |
+
$error_message = 'Invalid Scan Report Detected';
|
138 |
+
|
139 |
+
DUP_Log::error($error_message, 'Invalid Scan Report Detected', Dup_ErrorBehavior::LogOnly);
|
140 |
+
//$buildProgress->failed = true;
|
141 |
+
$buildProgress->set_failed($error_message);
|
142 |
+
return true;
|
143 |
+
}
|
144 |
+
|
145 |
+
try {
|
146 |
+
DupArchiveEngine::createArchive($archivePath, true);
|
147 |
+
$sql_ark_file_path = $package->getSqlArkFilePath();
|
148 |
+
DupArchiveEngine::addRelativeFileToArchiveST($archivePath, $sqlPath, $sql_ark_file_path);
|
149 |
+
} catch (Exception $ex) {
|
150 |
+
$error_message = 'Error adding database.sql to archive';
|
151 |
+
|
152 |
+
DUP_Log::error($error_message, $ex->getMessage(), Dup_ErrorBehavior::LogOnly);
|
153 |
+
//$buildProgress->failed = true;
|
154 |
+
$buildProgress->set_failed($error_message);
|
155 |
+
return true;
|
156 |
+
}
|
157 |
+
|
158 |
+
$buildProgress->archive_started = true;
|
159 |
+
|
160 |
+
$buildProgress->retries = 0;
|
161 |
+
|
162 |
+
$createState = DUP_DupArchive_Create_State::createNew($archivePath, $compressDir, self::WorkerTimeInSec, true, true);
|
163 |
+
$createState->throttleDelayInUs = 0;
|
164 |
+
|
165 |
+
$createState->save();
|
166 |
+
|
167 |
+
$package->Update();
|
168 |
+
}
|
169 |
+
|
170 |
+
try {
|
171 |
+
|
172 |
+
DUP_LOG::trace("c14");
|
173 |
+
$createState = DUP_DupArchive_Create_State::get_instance();
|
174 |
+
|
175 |
+
if($buildProgress->retries > 1) {
|
176 |
+
// Indicates it had problems before so move into robustness mode
|
177 |
+
$createState->isRobust = true;
|
178 |
+
|
179 |
+
$createState->save();
|
180 |
+
}
|
181 |
+
|
182 |
+
if ($createState->working) {
|
183 |
+
DUP_LOG::Trace("Create state is working");
|
184 |
+
//die(0);//rsr
|
185 |
+
|
186 |
+
DupArchiveEngine::addItemsToArchive($createState, $scanReport->ARC);
|
187 |
+
|
188 |
+
$buildProgress->set_build_failures($createState->failures);
|
189 |
+
|
190 |
+
if($createState->isCriticalFailurePresent()) {
|
191 |
+
|
192 |
+
throw new Exception($createState->getFailureSummary());
|
193 |
+
}
|
194 |
+
|
195 |
+
$totalFileCount = count($scanReport->ARC->Files);
|
196 |
+
|
197 |
+
$package->Status = SnapLibUtil::getWorkPercent(DUP_PackageStatus::ARCSTART, DUP_PackageStatus::ARCVALIDATION, $totalFileCount, $createState->currentFileIndex);
|
198 |
+
|
199 |
+
$buildProgress->retries = 0;
|
200 |
+
|
201 |
+
$createState->save();
|
202 |
+
|
203 |
+
DUP_LOG::TraceObject("Stored Create State", $createState);
|
204 |
+
DUP_LOG::TraceObject('Stored build_progress', $package->BuildProgress);
|
205 |
+
|
206 |
+
if ($createState->working == false) {
|
207 |
+
// Want it to do the final cleanup work in an entirely new thread so return immediately
|
208 |
+
$skipArchiveFinalization = true;
|
209 |
+
DUP_LOG::TraceObject("Done build phase. Create State=", $createState);
|
210 |
+
}
|
211 |
+
}
|
212 |
+
}
|
213 |
+
catch (Exception $ex) {
|
214 |
+
DUP_LOG::trace("c15");
|
215 |
+
$message = __('Problem adding items to archive.', 'duplicator').' '.$ex->getMessage();
|
216 |
+
|
217 |
+
DUP_Log::Error(__('Problems adding items to archive.', 'duplicator'), $message, Dup_ErrorBehavior::LogOnly);
|
218 |
+
DUP_Log::TraceObject($message." EXCEPTION:", $ex);
|
219 |
+
//$buildProgress->failed = true;
|
220 |
+
$buildProgress->set_failed($message);
|
221 |
+
return true;
|
222 |
+
}
|
223 |
+
|
224 |
+
DUP_LOG::trace("c16");
|
225 |
+
|
226 |
+
//-- Final Wrapup of the Archive
|
227 |
+
if ((!$skipArchiveFinalization) && ($createState->working == false)) {
|
228 |
+
|
229 |
+
DUP_LOG::Trace("Create state is not working and not skip archive finalization");
|
230 |
+
|
231 |
+
DUP_LOG::trace("c17");
|
232 |
+
|
233 |
+
if(!$buildProgress->installer_built) {
|
234 |
+
|
235 |
+
if($package->Installer->build($package, false))
|
236 |
+
{
|
237 |
+
$package->Runtime = -1;
|
238 |
+
$package->ExeSize = DUP_Util::byteSize($package->Installer->Size);
|
239 |
+
$package->ZipSize = DUP_Util::byteSize($package->Archive->Size);
|
240 |
+
$package->update();
|
241 |
+
}
|
242 |
+
else
|
243 |
+
{
|
244 |
+
$package->update();
|
245 |
+
return;
|
246 |
+
}
|
247 |
+
|
248 |
+
|
249 |
+
|
250 |
+
//rsr todo need this somewhere $package->buildCleanup();
|
251 |
+
|
252 |
+
DUP_Log::Trace("Installer has been built so running expand now");
|
253 |
+
|
254 |
+
$expandState = DUP_DupArchive_Expand_State::getInstance(true);
|
255 |
+
|
256 |
+
$expandState->archivePath = $archivePath;
|
257 |
+
$expandState->working = true;
|
258 |
+
$expandState->timeSliceInSecs = self::WorkerTimeInSec;
|
259 |
+
$expandState->basePath = DUPLICATOR_SSDIR_PATH_TMP.'/validate';
|
260 |
+
$expandState->throttleDelayInUs = 0; // RSR TODO
|
261 |
+
$expandState->validateOnly = true;
|
262 |
+
$expandState->validationType = DupArchiveValidationTypes::Standard;
|
263 |
+
$expandState->working = true;
|
264 |
+
$expandState->expectedDirectoryCount = count($scanReport->ARC->Dirs) - $createState->skippedDirectoryCount + $package->Installer->numDirsAdded;
|
265 |
+
$expandState->expectedFileCount = count($scanReport->ARC->Files) + 1 - $createState->skippedFileCount + $package->Installer->numFilesAdded; // database.sql will be in there
|
266 |
+
|
267 |
+
$expandState->save();
|
268 |
+
|
269 |
+
$sfc = count($scanReport->ARC->Files);
|
270 |
+
$nfa = $package->Installer->numFilesAdded;
|
271 |
+
Dup_Log::trace("####scan files {$sfc} skipped files {$createState->skippedFileCount} num files added {$nfa}");
|
272 |
+
DUP_LOG::traceObject("EXPAND STATE AFTER SAVE", $expandState);
|
273 |
+
}
|
274 |
+
else {
|
275 |
+
|
276 |
+
DUP_LOG::trace("c18");
|
277 |
+
try {
|
278 |
+
|
279 |
+
$expandState = DUP_DupArchive_Expand_State::getInstance();
|
280 |
+
|
281 |
+
if($buildProgress->retries > 1) {
|
282 |
+
|
283 |
+
// Indicates it had problems before so move into robustness mode
|
284 |
+
$expandState->isRobust = true;
|
285 |
+
|
286 |
+
$expandState->save();
|
287 |
+
}
|
288 |
+
|
289 |
+
DUP_Log::traceObject('Resumed validation expand state', $expandState);
|
290 |
+
|
291 |
+
DupArchiveEngine::expandArchive($expandState);
|
292 |
+
|
293 |
+
$buildProgress->set_validation_failures($expandState->failures);
|
294 |
+
|
295 |
+
$totalFileCount = count($scanReport->ARC->Files);
|
296 |
+
$archiveSize = @filesize($expandState->archivePath);
|
297 |
+
|
298 |
+
$package->Status = SnapLibUtil::getWorkPercent(DUP_PackageStatus::ARCVALIDATION, DUP_PackageStatus::COMPLETE, $archiveSize,
|
299 |
+
$expandState->archiveOffset);
|
300 |
+
DUP_LOG::TraceObject("package status after expand=", $package->Status);
|
301 |
+
DUP_LOG::Trace("archive size:{$archiveSize} expand offset:{$expandState->archiveOffset}");
|
302 |
+
|
303 |
+
} catch (Exception $ex) {
|
304 |
+
DUP_Log::Trace('Exception:'.$ex->getMessage().':'.$ex->getTraceAsString());
|
305 |
+
//$buildProgress->failed = true;
|
306 |
+
$buildProgress->set_failed('Error validating archive');
|
307 |
+
return true;
|
308 |
+
}
|
309 |
+
|
310 |
+
if($expandState->isCriticalFailurePresent())
|
311 |
+
{
|
312 |
+
DUP_LOG::trace("c20");
|
313 |
+
// Fail immediately if critical failure present - even if havent completed processing the entire archive.
|
314 |
+
|
315 |
+
$error_message = __('Critical failure present in validation', 'duplicator');
|
316 |
+
|
317 |
+
DUP_Log::Error($error_message, $expandState->getFailureSummary(), Dup_ErrorBehavior::LogOnly);
|
318 |
+
|
319 |
+
//$buildProgress->failed = true;
|
320 |
+
$buildProgress->set_failed($error_message);
|
321 |
+
return true;
|
322 |
+
} else if (!$expandState->working) {
|
323 |
+
DUP_LOG::trace("c21");
|
324 |
+
|
325 |
+
$buildProgress->archive_built = true;
|
326 |
+
$buildProgress->retries = 0;
|
327 |
+
|
328 |
+
// rsr todo is this required?
|
329 |
+
$package->update();
|
330 |
+
|
331 |
+
$timerAllEnd = DUP_Util::getMicrotime();
|
332 |
+
$timerAllSum = DUP_Util::elapsedTime($timerAllEnd, $package->TimerStart);
|
333 |
+
|
334 |
+
DUP_LOG::traceObject("create state", $createState);
|
335 |
+
|
336 |
+
$archiveFileSize = @filesize($archivePath);
|
337 |
+
DUP_Log::info("COMPRESSED SIZE: ".DUP_Util::byteSize($archiveFileSize));
|
338 |
+
DUP_Log::info("ARCHIVE RUNTIME: {$timerAllSum}");
|
339 |
+
DUP_Log::info("MEMORY STACK: ".DUP_Server::getPHPMemory());
|
340 |
+
DUP_Log::info("CREATE WARNINGS: ".$createState->getFailureSummary(false, true));
|
341 |
+
DUP_Log::info("VALIDATION WARNINGS: ".$expandState->getFailureSummary(false, true));
|
342 |
+
|
343 |
+
$archive->file_count = $expandState->fileWriteCount + $expandState->directoryWriteCount;
|
344 |
+
|
345 |
+
$package->update();
|
346 |
+
|
347 |
+
DUP_LOG::trace("c22");
|
348 |
+
$done = true;
|
349 |
+
} else {
|
350 |
+
DUP_LOG::trace("c23");
|
351 |
+
$expandState->save();
|
352 |
+
DUP_LOG::trace("c24");
|
353 |
+
}
|
354 |
+
}
|
355 |
+
}
|
356 |
+
} catch (Exception $ex) {
|
357 |
+
// Have to have a catchall since the main system that calls this function is not prepared to handle exceptions
|
358 |
+
DUP_Log::trace('Top level create Exception:'.$ex->getMessage().':'.$ex->getTraceAsString());
|
359 |
+
//$buildProgress->failed = true;
|
360 |
+
$buildProgress->set_failed('Error encoundtered creating archive. See package log');
|
361 |
+
return true;
|
362 |
+
}
|
363 |
+
|
364 |
+
$buildProgress->retries = 0;
|
365 |
+
|
366 |
+
return $done;
|
367 |
+
}
|
368 |
+
}
|
classes/package/duparchive/class.pack.archive.duparchive.state.create.php
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
defined("ABSPATH") or die("");
|
3 |
+
/*
|
4 |
+
* To change this license header, choose License Headers in Project Properties.
|
5 |
+
* To change this template file, choose Tools | Templates
|
6 |
+
* and open the template in the editor.
|
7 |
+
*/
|
8 |
+
|
9 |
+
require_once (DUPLICATOR_PLUGIN_PATH.'lib/dup_archive/classes/states/class.duparchive.state.create.php');
|
10 |
+
|
11 |
+
class DUP_DupArchive_Create_State extends DupArchiveCreateState
|
12 |
+
{
|
13 |
+
/* @var $package DUP_Package */
|
14 |
+
// private $package;
|
15 |
+
|
16 |
+
// public function setPackage(&$package)
|
17 |
+
public function setPackage(&$package)
|
18 |
+
{
|
19 |
+
// $this->package = &$package;
|
20 |
+
}
|
21 |
+
|
22 |
+
// Only one active package so straightforward
|
23 |
+
// public static function createFromPackage(&$package)
|
24 |
+
public static function get_instance()
|
25 |
+
{
|
26 |
+
$instance = new DUP_DupArchive_Create_State();
|
27 |
+
|
28 |
+
$data = DUP_Settings::Get('duparchive_create_state');
|
29 |
+
|
30 |
+
DUP_Util::objectCopy($data, $instance);
|
31 |
+
|
32 |
+
$instance->startTimestamp = time();
|
33 |
+
|
34 |
+
DUP_Log::TraceObject("retrieving create state", $instance);
|
35 |
+
|
36 |
+
return $instance;
|
37 |
+
}
|
38 |
+
|
39 |
+
public static function createNew($archivePath, $basePath, $timeSliceInSecs, $isCompressed, $setArchiveOffsetToEndOfArchive)
|
40 |
+
{
|
41 |
+
$instance = new DUP_DupArchive_Create_State();
|
42 |
+
|
43 |
+
/* @var $buildProgress DUP_Build_Progress */
|
44 |
+
$buildProgress = &$package->BuildProgress;
|
45 |
+
|
46 |
+
if ($setArchiveOffsetToEndOfArchive) {
|
47 |
+
$instance->archiveOffset = filesize($archivePath);
|
48 |
+
} else {
|
49 |
+
$instance->archiveOffset = 0;
|
50 |
+
}
|
51 |
+
|
52 |
+
$instance->archivePath = $archivePath;
|
53 |
+
$instance->basePath = $basePath;
|
54 |
+
$instance->currentDirectoryIndex = 0;
|
55 |
+
$instance->currentFileOffset = 0;
|
56 |
+
$instance->currentFileIndex = 0;
|
57 |
+
$instance->failures = array();
|
58 |
+
$instance->globSize = DupArchiveCreateState::DEFAULT_GLOB_SIZE;
|
59 |
+
$instance->isCompressed = $isCompressed;
|
60 |
+
$instance->timeSliceInSecs = $timeSliceInSecs;
|
61 |
+
$instance->working = true;
|
62 |
+
$instance->skippedDirectoryCount = 0;
|
63 |
+
$instance->skippedFileCount = 0;
|
64 |
+
|
65 |
+
$instance->startTimestamp = time();
|
66 |
+
|
67 |
+
return $instance;
|
68 |
+
}
|
69 |
+
|
70 |
+
public function addFailure($type, $subject, $description, $isCritical = false)
|
71 |
+
{
|
72 |
+
$failure = parent::addFailure($type, $subject, $description, $isCritical);
|
73 |
+
}
|
74 |
+
|
75 |
+
public function save()
|
76 |
+
{
|
77 |
+
DUP_Log::TraceObject("Saving create state", $this);
|
78 |
+
DUP_Settings::Set('duparchive_create_state', $this);
|
79 |
+
|
80 |
+
DUP_Settings::Save();
|
81 |
+
}
|
82 |
+
}
|
classes/package/duparchive/class.pack.archive.duparchive.state.expand.php
ADDED
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* To change this license header, choose License Headers in Project Properties.
|
4 |
+
* To change this template file, choose Tools | Templates
|
5 |
+
* and open the template in the editor.
|
6 |
+
*/
|
7 |
+
|
8 |
+
require_once (DUPLICATOR_PLUGIN_PATH.'lib/dup_archive/classes/states/class.duparchive.state.expand.php');
|
9 |
+
|
10 |
+
class DUP_DupArchive_Expand_State extends DupArchiveExpandState
|
11 |
+
{
|
12 |
+
public static function getInstance($reset = false)
|
13 |
+
{
|
14 |
+
$instance = new DUP_DupArchive_Expand_State();
|
15 |
+
|
16 |
+
if ($reset) {
|
17 |
+
$instance->initMembers();
|
18 |
+
} else {
|
19 |
+
$instance->loadMembers();
|
20 |
+
}
|
21 |
+
|
22 |
+
return $instance;
|
23 |
+
}
|
24 |
+
|
25 |
+
private function loadMembers()
|
26 |
+
{
|
27 |
+
$data = DUP_Settings::Get('duparchive_expand_state');
|
28 |
+
|
29 |
+
DUP_LOG::traceObject("****RAW EXPAND STATE LOADED****", $data);
|
30 |
+
|
31 |
+
if($data->currentFileHeaderString != null) {
|
32 |
+
$this->currentFileHeader = DUP_JSON::decode($data->currentFileHeaderString);
|
33 |
+
} else {
|
34 |
+
$this->currentFileHeader = null;
|
35 |
+
}
|
36 |
+
|
37 |
+
if($data->archiveHeaderString != null) {
|
38 |
+
$this->archiveHeader = DUP_JSON::decode($data->archiveHeaderString);
|
39 |
+
} else {
|
40 |
+
$this->archiveHeader = null;
|
41 |
+
}
|
42 |
+
|
43 |
+
if($data->failuresString)
|
44 |
+
{
|
45 |
+
$this->failures = DUP_JSON::decode($data->failuresString);
|
46 |
+
}
|
47 |
+
else
|
48 |
+
{
|
49 |
+
$this->failures = array();
|
50 |
+
}
|
51 |
+
|
52 |
+
DUP_Util::objectCopy($data, $this, array('archiveHeaderString', 'currentFileHeaderString', 'failuresString'));
|
53 |
+
|
54 |
+
//
|
55 |
+
// $this->archiveOffset = $data->archiveOffset;
|
56 |
+
// $this->archivePath = $data->archivePath;
|
57 |
+
// $this->basePath = $data->basePath;
|
58 |
+
// $this->currentFileOffset = $data->currentFileOffset;
|
59 |
+
// $this->failures = $data->failures;
|
60 |
+
// $this->isCompressed = $data->isCompressed;
|
61 |
+
// $this->startTimestamp = $data->startTimestamp;
|
62 |
+
// $this->timeSliceInSecs = $data->timeSliceInSecs;
|
63 |
+
// $this->fileWriteCount = $data->fileWriteCount;
|
64 |
+
// $this->directoryWriteCount = $data->directoryWriteCount;
|
65 |
+
// $this->working = $data->working;
|
66 |
+
// $this->directoryModeOverride = $data->directoryModeOverride;
|
67 |
+
// $this->fileModeOverride = $data->fileModeOverride;
|
68 |
+
// $this->throttleDelayInUs = $data->throttleDelayInUs;
|
69 |
+
// $this->validateOnly = $data->validateOnly;
|
70 |
+
// $this->validationType = $data->validationType;
|
71 |
+
}
|
72 |
+
|
73 |
+
public function save()
|
74 |
+
{
|
75 |
+
$data = new stdClass();
|
76 |
+
|
77 |
+
if($this->currentFileHeader != null) {
|
78 |
+
$data->currentFileHeaderString = json_encode($this->currentFileHeader);
|
79 |
+
} else {
|
80 |
+
$data->currentFileHeaderString = null;
|
81 |
+
}
|
82 |
+
|
83 |
+
if($this->archiveHeader != null) {
|
84 |
+
$data->archiveHeaderString = json_encode($this->archiveHeader);
|
85 |
+
} else {
|
86 |
+
$data->archiveHeaderString = null;
|
87 |
+
}
|
88 |
+
|
89 |
+
$data->failuresString = json_encode($this->failures, JSON_FORCE_OBJECT);
|
90 |
+
|
91 |
+
// Object members auto skipped
|
92 |
+
DUP_Util::objectCopy($this, $data);
|
93 |
+
|
94 |
+
// $data->archiveOffset = $this->archiveOffset;
|
95 |
+
// $data->archivePath = $this->archivePath;
|
96 |
+
// $data->basePath = $this->basePath;
|
97 |
+
// $data->currentFileOffset = $this->currentFileOffset;
|
98 |
+
// $data->failures = $this->failures;
|
99 |
+
// $data->isCompressed = $this->isCompressed;
|
100 |
+
// $data->startTimestamp = $this->startTimestamp;
|
101 |
+
// $data->timeSliceInSecs = $this->timeSliceInSecs;
|
102 |
+
// $data->fileWriteCount = $this->fileWriteCount;
|
103 |
+
// $data->directoryWriteCount = $this->directoryWriteCount;
|
104 |
+
// $data->working = $this->working;
|
105 |
+
// $data->directoryModeOverride = $this->directoryModeOverride;
|
106 |
+
// $data->fileModeOverride = $this->fileModeOverride;
|
107 |
+
// $data->throttleDelayInUs = $this->throttleDelayInUs;
|
108 |
+
// $data->validateOnly = $this->validateOnly;
|
109 |
+
// $data->validationType = $this->validationType;
|
110 |
+
|
111 |
+
DUP_LOG::traceObject("****SAVING EXPAND STATE****", $this);
|
112 |
+
DUP_LOG::traceObject("****SERIALIZED STATE****", $data);
|
113 |
+
DUP_Settings::Set('duparchive_expand_state', $data);
|
114 |
+
DUP_Settings::Save();
|
115 |
+
}
|
116 |
+
|
117 |
+
private function initMembers()
|
118 |
+
{
|
119 |
+
$this->currentFileHeader = null;
|
120 |
+
$this->archiveOffset = 0;
|
121 |
+
$this->archiveHeader = null;
|
122 |
+
$this->archivePath = null;
|
123 |
+
$this->basePath = null;
|
124 |
+
$this->currentFileOffset = 0;
|
125 |
+
$this->failures = array();
|
126 |
+
$this->isCompressed = false;
|
127 |
+
$this->startTimestamp = time();
|
128 |
+
$this->timeSliceInSecs = -1;
|
129 |
+
$this->working = false;
|
130 |
+
$this->validateOnly = false;
|
131 |
+
$this->directoryModeOverride = -1;
|
132 |
+
$this->fileModeOverride = -1;
|
133 |
+
$this->throttleDelayInUs = 0;
|
134 |
+
}
|
135 |
+
}
|
classes/package/duparchive/index.php
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
<?php
|
2 |
+
//silent
|
classes/ui/class.ui.dialog.php
CHANGED
@@ -1,202 +1,198 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Used to generate a
|
4 |
-
*
|
5 |
-
* Standard: PSR-2
|
6 |
-
* @link http://www.php-fig.org/psr/psr-2
|
7 |
-
*
|
8 |
-
* @package Duplicator
|
9 |
-
* @subpackage classes/ui
|
10 |
-
* @copyright (c) 2017, Snapcreek LLC
|
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 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
*
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
$
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
*
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
$
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
$
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
<
|
176 |
-
'
|
177 |
-
</div>
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
"jQuery('#TB_window').attr('style', styleData);";
|
199 |
-
|
200 |
-
echo $html;
|
201 |
-
}
|
202 |
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Used to generate a thick-box inline dialog such as an alert or confirm pop-up
|
4 |
+
*
|
5 |
+
* Standard: PSR-2
|
6 |
+
* @link http://www.php-fig.org/psr/psr-2
|
7 |
+
*
|
8 |
+
* @package Duplicator
|
9 |
+
* @subpackage classes/ui
|
10 |
+
* @copyright (c) 2017, Snapcreek LLC
|
11 |
+
*
|
12 |
+
*/
|
13 |
+
|
14 |
+
// Exit if accessed directly
|
15 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
16 |
+
|
17 |
+
class DUP_UI_Dialog
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* The title that shows up in the dialog
|
21 |
+
*/
|
22 |
+
public $title;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* The message displayed in the body of the dialog
|
26 |
+
*/
|
27 |
+
public $message;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* The width of the dialog the default is used if not set
|
31 |
+
* Alert = 475px (default) | Confirm = 500px (default)
|
32 |
+
*/
|
33 |
+
public $width;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* The height of the dialog the default is used if not set
|
37 |
+
* Alert = 125px (default) | Confirm = 150px (default)
|
38 |
+
*/
|
39 |
+
public $height;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* When the progress meter is running show this text
|
43 |
+
* Available only on confirm dialogs
|
44 |
+
*/
|
45 |
+
public $progressText;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* When true a progress meter will run until page is reloaded
|
49 |
+
* Available only on confirm dialogs
|
50 |
+
*/
|
51 |
+
public $progressOn = true;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* The javascript call back method to call when the 'Yes' button is clicked
|
55 |
+
* Available only on confirm dialogs
|
56 |
+
*/
|
57 |
+
public $jscallback;
|
58 |
+
|
59 |
+
/**
|
60 |
+
* The id given to the full dialog
|
61 |
+
*/
|
62 |
+
private $id;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* A unique id that is added to all id elements
|
66 |
+
*/
|
67 |
+
private $uniqid;
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Init this object when created
|
71 |
+
*/
|
72 |
+
public function __construct()
|
73 |
+
{
|
74 |
+
add_thickbox();
|
75 |
+
$this->progressText = __('Processing please wait...', 'duplicator');
|
76 |
+
$this->uniqid = substr(uniqid('',true),0,14) . rand();
|
77 |
+
$this->id = 'dup-dlg-'.$this->uniqid;
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Gets the unique id that is assigned to each instance of a dialog
|
82 |
+
*
|
83 |
+
* @return int The unique ID of this dialog
|
84 |
+
*/
|
85 |
+
public function getID()
|
86 |
+
{
|
87 |
+
return $this->id;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Gets the unique id that is assigned to each instance of a dialogs message text
|
92 |
+
*
|
93 |
+
* @return int The unique ID of the message
|
94 |
+
*/
|
95 |
+
public function getMessageID()
|
96 |
+
{
|
97 |
+
return "{$this->id}_message";
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Initialize the alert base html code used to display when needed
|
102 |
+
*
|
103 |
+
* @return string The html content used for the alert dialog
|
104 |
+
*/
|
105 |
+
public function initAlert()
|
106 |
+
{
|
107 |
+
$ok = __('OK', 'duplicator');
|
108 |
+
|
109 |
+
$html = '
|
110 |
+
<div id="'.esc_attr($this->id).'" style="display:none">
|
111 |
+
<div class="dup-dlg-alert-txt">
|
112 |
+
'.$this->message.'
|
113 |
+
<br/><br/>
|
114 |
+
</div>
|
115 |
+
<div class="dup-dlg-alert-btns">
|
116 |
+
<input type="button" class="button button-large" value="'.esc_attr($ok).'" onclick="tb_remove()" />
|
117 |
+
</div>
|
118 |
+
</div>';
|
119 |
+
|
120 |
+
echo $html;
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Shows the alert base JS code used to display when needed
|
125 |
+
*
|
126 |
+
* @return string The javascript content used for the alert dialog
|
127 |
+
*/
|
128 |
+
public function showAlert()
|
129 |
+
{
|
130 |
+
$this->width = is_numeric($this->width) ? $this->width : 500;
|
131 |
+
$this->height = is_numeric($this->height) ? $this->height : 175;
|
132 |
+
|
133 |
+
$html = "tb_show('".esc_js($this->title)."', '#TB_inline?width=".esc_js($this->width)."&height=".esc_js($this->height)."&inlineId=".esc_js($this->id)."');\n" .
|
134 |
+
"var styleData = jQuery('#TB_window').attr('style') + 'height: ".esc_js($this->height)."px !important';\n" .
|
135 |
+
"jQuery('#TB_window').attr('style', styleData);";
|
136 |
+
|
137 |
+
echo $html;
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Shows the confirm base JS code used to display when needed
|
142 |
+
*
|
143 |
+
* @return string The javascript content used for the confirm dialog
|
144 |
+
*/
|
145 |
+
public function initConfirm()
|
146 |
+
{
|
147 |
+
$ok = __('OK', 'duplicator');
|
148 |
+
$cancel = __('Cancel', 'duplicator');
|
149 |
+
|
150 |
+
$progress_data = '';
|
151 |
+
$progress_func2 = '';
|
152 |
+
|
153 |
+
//Enable the progress spinner
|
154 |
+
if ($this->progressOn) {
|
155 |
+
$progress_func1 = "__DUP_UI_Dialog_".$this->uniqid;
|
156 |
+
$progress_func2 = ";{$progress_func1}(this)";
|
157 |
+
$progress_data = "<div class='dup-dlg-confirm-progress'><i class='fa fa-circle-o-notch fa-spin fa-lg fa-fw'></i> ".esc_js($this->progressText)."</div>
|
158 |
+
<script>
|
159 |
+
function {$progress_func1}(obj)
|
160 |
+
{
|
161 |
+
jQuery(obj).parent().parent().find('.dup-dlg-confirm-progress').show();
|
162 |
+
jQuery(obj).closest('.dup-dlg-confirm-btns').find('input').attr('disabled', 'true');
|
163 |
+
}
|
164 |
+
</script>";
|
165 |
+
}
|
166 |
+
|
167 |
+
$html =
|
168 |
+
'<div id="'.esc_attr($this->id).'" style="display:none">
|
169 |
+
<div class="dup-dlg-confirm-txt">
|
170 |
+
<span id="'.esc_attr($this->id).'_message">'.esc_html($this->message).'</span>
|
171 |
+
<br/><br/>
|
172 |
+
'.$progress_data.'
|
173 |
+
</div>
|
174 |
+
<div class="dup-dlg-confirm-btns">
|
175 |
+
<input type="button" class="button button-large" value="'.esc_attr($ok).'" onclick="'.$this->jscallback.$progress_func2.'" />
|
176 |
+
<input type="button" class="button button-large" value="'.esc_attr($cancel).'" onclick="tb_remove()" />
|
177 |
+
</div>
|
178 |
+
</div>';
|
179 |
+
|
180 |
+
echo $html;
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Shows the confirm base JS code used to display when needed
|
185 |
+
*
|
186 |
+
* @return string The javascript content used for the confirm dialog
|
187 |
+
*/
|
188 |
+
public function showConfirm()
|
189 |
+
{
|
190 |
+
$this->width = is_numeric($this->width) ? $this->width : 500;
|
191 |
+
$this->height = is_numeric($this->height) ? $this->height : 225;
|
192 |
+
$html = "tb_show('".esc_js($this->title)."', '#TB_inline?width=".esc_js($this->width)."&height=".esc_js($this->height)."&inlineId=".esc_js($this->id)."');\n" .
|
193 |
+
"var styleData = jQuery('#TB_window').attr('style') + 'height: ".esc_js($this->height)."px !important';\n" .
|
194 |
+
"jQuery('#TB_window').attr('style', styleData);";
|
195 |
+
|
196 |
+
echo $html;
|
197 |
+
}
|
|
|
|
|
|
|
|
|
198 |
}
|
classes/ui/class.ui.notice.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
* Used to display notices in the WordPress Admin area
|
4 |
-
* This class takes
|
5 |
*
|
6 |
* Standard: PSR-2
|
7 |
* @link http://www.php-fig.org/psr/psr-2
|
@@ -9,14 +9,11 @@
|
|
9 |
* @package Duplicator
|
10 |
* @subpackage classes/ui
|
11 |
* @copyright (c) 2017, Snapcreek LLC
|
12 |
-
* @since 1.1.0
|
13 |
*
|
14 |
*/
|
15 |
|
16 |
// Exit if accessed directly
|
17 |
-
if (!defined('DUPLICATOR_VERSION'))
|
18 |
-
exit;
|
19 |
-
}
|
20 |
|
21 |
class DUP_UI_Notice
|
22 |
{
|
@@ -41,30 +38,29 @@ class DUP_UI_Notice
|
|
41 |
if (DUP_Server::hasInstallerFiles() && !$is_installer_cleanup_req) {
|
42 |
|
43 |
$on_active_tab = isset($_GET['section'])? $_GET['section']: '';
|
44 |
-
echo '<div class="updated notice-success" id="dup-global-error-reserved-files"><p>';
|
45 |
|
46 |
//Safe Mode Notice
|
47 |
$safe_html = '';
|
48 |
if(get_option("duplicator_exe_safe_mode", 0) > 0 ){
|
49 |
$safe_msg1 = __('Safe Mode:', 'duplicator');
|
50 |
$safe_msg2 = __('During the install safe mode was enabled deactivating all plugins.<br/> Please be sure to ', 'duplicator');
|
51 |
-
$safe_msg3 = __('
|
52 |
$safe_html = "<div class='notice-safemode'><b>{$safe_msg1}</b><br/>{$safe_msg2} <a href='plugins.php'>{$safe_msg3}</a>!</div><br/>";
|
53 |
}
|
54 |
|
55 |
//On Tools > Cleanup Page
|
56 |
-
|
57 |
if ($screen->id == 'duplicator_page_duplicator-tools' && ($on_active_tab == "info" || $on_active_tab == '') ) {
|
58 |
|
59 |
$title = __('This site has been successfully migrated!', 'duplicator');
|
60 |
$msg1 = __('Final step(s):', 'duplicator');
|
61 |
-
$msg2 = __('This message will be removed after all installer files are removed. Installer files must be removed to maintain a secure site
|
62 |
. 'Click the link above or button below to remove all installer files and complete the migration.', 'duplicator');
|
63 |
|
64 |
echo "<b class='pass-msg'><i class='fa fa-check-circle'></i> ".esc_html($title)."</b> <br/> {$safe_html} <b>".esc_html($msg1)."</b> <br/>";
|
65 |
printf("1. <a href='javascript:void(0)' onclick='jQuery(\"#dup-remove-installer-files-btn\").click()'>%s</a><br/>", esc_html__('Remove Installation Files Now!', 'duplicator'));
|
66 |
-
|
67 |
-
|
68 |
|
69 |
//All other Pages
|
70 |
} else {
|
@@ -91,9 +87,9 @@ class DUP_UI_Notice
|
|
91 |
public static function redirect($location)
|
92 |
{
|
93 |
echo '<div class="dup-redirect"><i class="fa fa-circle-o-notch fa-spin fa-fw"></i>';
|
94 |
-
|
95 |
echo '</div>';
|
96 |
echo "<script>window.location = '{$location}';</script>";
|
97 |
-
die(
|
98 |
}
|
99 |
-
}
|
1 |
<?php
|
2 |
/**
|
3 |
* Used to display notices in the WordPress Admin area
|
4 |
+
* This class takes advantage of the admin_notice action.
|
5 |
*
|
6 |
* Standard: PSR-2
|
7 |
* @link http://www.php-fig.org/psr/psr-2
|
9 |
* @package Duplicator
|
10 |
* @subpackage classes/ui
|
11 |
* @copyright (c) 2017, Snapcreek LLC
|
|
|
12 |
*
|
13 |
*/
|
14 |
|
15 |
// Exit if accessed directly
|
16 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
|
|
|
|
17 |
|
18 |
class DUP_UI_Notice
|
19 |
{
|
38 |
if (DUP_Server::hasInstallerFiles() && !$is_installer_cleanup_req) {
|
39 |
|
40 |
$on_active_tab = isset($_GET['section'])? $_GET['section']: '';
|
41 |
+
echo '<div class="dup-updated notice-success" id="dup-global-error-reserved-files"><p>';
|
42 |
|
43 |
//Safe Mode Notice
|
44 |
$safe_html = '';
|
45 |
if(get_option("duplicator_exe_safe_mode", 0) > 0 ){
|
46 |
$safe_msg1 = __('Safe Mode:', 'duplicator');
|
47 |
$safe_msg2 = __('During the install safe mode was enabled deactivating all plugins.<br/> Please be sure to ', 'duplicator');
|
48 |
+
$safe_msg3 = __('re-activate the plugins', 'duplicator');
|
49 |
$safe_html = "<div class='notice-safemode'><b>{$safe_msg1}</b><br/>{$safe_msg2} <a href='plugins.php'>{$safe_msg3}</a>!</div><br/>";
|
50 |
}
|
51 |
|
52 |
//On Tools > Cleanup Page
|
|
|
53 |
if ($screen->id == 'duplicator_page_duplicator-tools' && ($on_active_tab == "info" || $on_active_tab == '') ) {
|
54 |
|
55 |
$title = __('This site has been successfully migrated!', 'duplicator');
|
56 |
$msg1 = __('Final step(s):', 'duplicator');
|
57 |
+
$msg2 = __('This message will be removed after all installer files are removed. Installer files must be removed to maintain a secure site. '
|
58 |
. 'Click the link above or button below to remove all installer files and complete the migration.', 'duplicator');
|
59 |
|
60 |
echo "<b class='pass-msg'><i class='fa fa-check-circle'></i> ".esc_html($title)."</b> <br/> {$safe_html} <b>".esc_html($msg1)."</b> <br/>";
|
61 |
printf("1. <a href='javascript:void(0)' onclick='jQuery(\"#dup-remove-installer-files-btn\").click()'>%s</a><br/>", esc_html__('Remove Installation Files Now!', 'duplicator'));
|
62 |
+
printf("2. <a href='https://wordpress.org/support/plugin/duplicator/reviews/?filter=5' target='wporg'>%s</a> <br/> ", esc_html__('Optionally, Review Duplicator at WordPress.org...', 'duplicator'));
|
63 |
+
echo "<div class='pass-msg'>".esc_html($msg2)."</div>";
|
64 |
|
65 |
//All other Pages
|
66 |
} else {
|
87 |
public static function redirect($location)
|
88 |
{
|
89 |
echo '<div class="dup-redirect"><i class="fa fa-circle-o-notch fa-spin fa-fw"></i>';
|
90 |
+
esc_html__('Redirecting Please Wait...', 'duplicator');
|
91 |
echo '</div>';
|
92 |
echo "<script>window.location = '{$location}';</script>";
|
93 |
+
die(esc_html__('Invalid token permissions to perform this request.', 'duplicator'));
|
94 |
}
|
95 |
+
}
|
classes/ui/class.ui.screen.base.php
CHANGED
@@ -1,77 +1,78 @@
|
|
1 |
-
<?php
|
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 |
-
* @param string $
|
38 |
-
*
|
39 |
-
*
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
."<
|
46 |
-
."<li><a href='https://snapcreek.com/duplicator/docs/
|
47 |
-
."
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
'
|
52 |
-
'
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
*
|
60 |
-
*
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
$
|
66 |
-
$
|
67 |
-
$
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
."<i class='fa fa-
|
73 |
-
."<i class='fa fa-
|
74 |
-
|
75 |
-
|
76 |
-
|
|
|
77 |
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* The base class for all screen.php files. This class is used to control items that are common
|
4 |
+
* among all screens, namely the Help tab and Screen Options drop down items. When creating a
|
5 |
+
* screen object please extent this class.
|
6 |
+
*
|
7 |
+
* Standard: PSR-2
|
8 |
+
* @link http://www.php-fig.org/psr/psr-2
|
9 |
+
*
|
10 |
+
* @package Duplicator
|
11 |
+
* @subpackage classes/ui
|
12 |
+
* @copyright (c) 2017, Snapcreek LLC
|
13 |
+
*
|
14 |
+
*/
|
15 |
+
|
16 |
+
// Exit if accessed directly
|
17 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
18 |
+
|
19 |
+
class DUP_UI_Screen
|
20 |
+
{
|
21 |
+
/**
|
22 |
+
* Used as a placeholder for the current screen object
|
23 |
+
*/
|
24 |
+
public $screen;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Init this object when created
|
28 |
+
*/
|
29 |
+
public function __construct()
|
30 |
+
{
|
31 |
+
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Get the help support tab view content shown in the help system
|
36 |
+
*
|
37 |
+
* @param string $guide The target URL to navigate to on the online user guide
|
38 |
+
* @param string $faq The target URL to navigate to on the online user tech FAQ
|
39 |
+
*
|
40 |
+
* @return null
|
41 |
+
*/
|
42 |
+
public function getSupportTab($guide, $faq)
|
43 |
+
{
|
44 |
+
$content = __("<b>Need Help?</b> Please check out these resources first:"
|
45 |
+
."<ul>"
|
46 |
+
."<li><a href='https://snapcreek.com/duplicator/docs/guide{$guide}' target='_sc-faq'>Full Online User Guide</a></li>"
|
47 |
+
."<li><a href='https://snapcreek.com/duplicator/docs/faqs-tech{$faq}' target='_sc-faq'>Frequently Asked Questions</a></li>"
|
48 |
+
."</ul>", 'duplicator');
|
49 |
+
|
50 |
+
$this->screen->add_help_tab(array(
|
51 |
+
'id' => 'dup_help_tab_callback',
|
52 |
+
'title' => esc_html__('Support', 'duplicator'),
|
53 |
+
'content' => "<p>{$content}</p>"
|
54 |
+
)
|
55 |
+
);
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Get the help support side bar found in the right most part of the help system
|
60 |
+
*
|
61 |
+
* @return null
|
62 |
+
*/
|
63 |
+
public function getHelpSidbar()
|
64 |
+
{
|
65 |
+
$txt_title = __("Resources", 'duplicator');
|
66 |
+
$txt_home = __("Knowledge Base", 'duplicator');
|
67 |
+
$txt_guide = __("Full User Guide", 'duplicator');
|
68 |
+
$txt_faq = __("Technical FAQs", 'duplicator');
|
69 |
+
$txt_sets = __("Package Settings", 'duplicator');
|
70 |
+
$this->screen->set_help_sidebar(
|
71 |
+
"<div class='dup-screen-hlp-info'><b>".esc_html($txt_title).":</b> <br/>"
|
72 |
+
."<i class='fa fa-home'></i> <a href='https://snapcreek.com/duplicator/docs/' target='_sc-home'>".esc_html($txt_home)."</a> <br/>"
|
73 |
+
."<i class='fa fa-book'></i> <a href='https://snapcreek.com/duplicator/docs/guide/' target='_sc-guide'>".esc_html($txt_guide)."</a> <br/>"
|
74 |
+
."<i class='fa fa-file-code-o'></i> <a href='https://snapcreek.com/duplicator/docs/faqs-tech/' target='_sc-faq'>".esc_html($txt_faq)."</a> <br/>"
|
75 |
+
."<i class='fa fa-gear'></i> <a href='admin.php?page=duplicator-settings&tab=package'>".esc_html($txt_sets)."</a></div>"
|
76 |
+
);
|
77 |
+
}
|
78 |
}
|
classes/ui/class.ui.viewstate.php
CHANGED
@@ -1,74 +1,71 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Gets the view state of UI elements to remember its viewable state
|
4 |
-
*
|
5 |
-
* Standard: PSR-2
|
6 |
-
* @link http://www.php-fig.org/psr/psr-2
|
7 |
-
*
|
8 |
-
* @package Duplicator
|
9 |
-
* @subpackage classes/ui
|
10 |
-
* @copyright (c) 2017, Snapcreek LLC
|
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 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
*
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
}
|
72 |
-
return null;
|
73 |
-
}
|
74 |
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Gets the view state of UI elements to remember its viewable state
|
4 |
+
*
|
5 |
+
* Standard: PSR-2
|
6 |
+
* @link http://www.php-fig.org/psr/psr-2
|
7 |
+
*
|
8 |
+
* @package Duplicator
|
9 |
+
* @subpackage classes/ui
|
10 |
+
* @copyright (c) 2017, Snapcreek LLC
|
11 |
+
*
|
12 |
+
*/
|
13 |
+
|
14 |
+
// Exit if accessed directly
|
15 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
16 |
+
|
17 |
+
class DUP_UI_ViewState
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* The key used in the wp_options table
|
21 |
+
*
|
22 |
+
* @var string
|
23 |
+
*/
|
24 |
+
private static $optionsViewStateKey = 'duplicator_ui_view_state';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Save the view state of UI elements
|
28 |
+
*
|
29 |
+
* @param string $key A unique key to define the UI element
|
30 |
+
* @param string $value A generic value to use for the view state
|
31 |
+
*
|
32 |
+
* @return bool Returns true if the value was successfully saved
|
33 |
+
*/
|
34 |
+
public static function save($key, $value)
|
35 |
+
{
|
36 |
+
$view_state = array();
|
37 |
+
$view_state = get_option(self::$optionsViewStateKey);
|
38 |
+
$view_state[$key] = $value;
|
39 |
+
$success = update_option(self::$optionsViewStateKey, $view_state);
|
40 |
+
return $success;
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Gets all the values from the settings array
|
45 |
+
*
|
46 |
+
* @return array Returns and array of all the values stored in the settings array
|
47 |
+
*/
|
48 |
+
public static function getArray()
|
49 |
+
{
|
50 |
+
return get_option(self::$optionsViewStateKey);
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Return the value of the of view state item
|
55 |
+
*
|
56 |
+
* @param type $searchKey The key to search on
|
57 |
+
* @return string Returns the value of the key searched or null if key is not found
|
58 |
+
*/
|
59 |
+
public static function getValue($searchKey)
|
60 |
+
{
|
61 |
+
$view_state = get_option(self::$optionsViewStateKey);
|
62 |
+
if (is_array($view_state)) {
|
63 |
+
foreach ($view_state as $key => $value) {
|
64 |
+
if ($key == $searchKey) {
|
65 |
+
return $value;
|
66 |
+
}
|
67 |
+
}
|
68 |
+
}
|
69 |
+
return null;
|
70 |
+
}
|
|
|
|
|
|
|
71 |
}
|
classes/utilities/class.u.json.php
CHANGED
@@ -1,153 +1,193 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class
|
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 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
$
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
153 |
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Utility class for working with JSON data
|
4 |
+
*
|
5 |
+
* Standard: PSR-2
|
6 |
+
* @link http://www.php-fig.org/psr/psr-2
|
7 |
+
*
|
8 |
+
* @subpackage classes/utilities
|
9 |
+
* @copyright (c) 2017, Snapcreek LLC
|
10 |
+
* @license https://opensource.org/licenses/GPL-3.0 GNU Public License
|
11 |
+
*/
|
12 |
+
|
13 |
+
// Exit if accessed directly
|
14 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
15 |
+
|
16 |
+
class DUP_JSON
|
17 |
+
{
|
18 |
+
protected static $_messages = array(
|
19 |
+
JSON_ERROR_NONE => 'No error has occurred',
|
20 |
+
JSON_ERROR_DEPTH => 'The maximum stack depth has been exceeded',
|
21 |
+
JSON_ERROR_STATE_MISMATCH => 'Invalid or malformed JSON',
|
22 |
+
JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
|
23 |
+
JSON_ERROR_SYNTAX => 'Syntax error',
|
24 |
+
JSON_ERROR_UTF8 => 'Malformed UTF-8 characters. To resolve see https://snapcreek.com/duplicator/docs/faqs-tech/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=malformed_utf8#faq-package-170-q'
|
25 |
+
);
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Used on PHP 5.3+ to better handle calling the json_encode method
|
29 |
+
*
|
30 |
+
* Returns a string containing the JSON representation of the supplied value
|
31 |
+
*
|
32 |
+
* @return string
|
33 |
+
*/
|
34 |
+
public static function customEncode($value, $iteration = 1)
|
35 |
+
{
|
36 |
+
if (DUP_Util::$on_php_53_plus) {
|
37 |
+
|
38 |
+
$encoded = json_encode($value);
|
39 |
+
|
40 |
+
switch (json_last_error()) {
|
41 |
+
case JSON_ERROR_NONE:
|
42 |
+
return $encoded;
|
43 |
+
case JSON_ERROR_DEPTH:
|
44 |
+
throw new RuntimeException('Maximum stack depth exceeded');
|
45 |
+
case JSON_ERROR_STATE_MISMATCH:
|
46 |
+
throw new RuntimeException('Underflow or the modes mismatch');
|
47 |
+
case JSON_ERROR_CTRL_CHAR:
|
48 |
+
throw new RuntimeException('Unexpected control character found');
|
49 |
+
case JSON_ERROR_SYNTAX:
|
50 |
+
throw new RuntimeException('Syntax error, malformed JSON');
|
51 |
+
case JSON_ERROR_UTF8:
|
52 |
+
if ($iteration == 1) {
|
53 |
+
$clean = self::makeUTF8($value);
|
54 |
+
return self::customEncode($clean, $iteration + 1);
|
55 |
+
} else {
|
56 |
+
throw new RuntimeException('UTF-8 error loop');
|
57 |
+
}
|
58 |
+
default:
|
59 |
+
throw new RuntimeException('Unknown error');
|
60 |
+
}
|
61 |
+
} else {
|
62 |
+
return self::oldCustomEncode($value);
|
63 |
+
}
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Attempts to only call the json_encode method directly
|
68 |
+
*
|
69 |
+
* Returns a string containing the JSON representation of the supplied value
|
70 |
+
*
|
71 |
+
* @return string
|
72 |
+
*/
|
73 |
+
public static function encode($value, $options = 0)
|
74 |
+
{
|
75 |
+
$result = json_encode($value, $options);
|
76 |
+
|
77 |
+
if ($result !== FALSE) {
|
78 |
+
return $result;
|
79 |
+
}
|
80 |
+
|
81 |
+
if (function_exists('json_last_error')) {
|
82 |
+
$message = self::$_messages[json_last_error()];
|
83 |
+
} else {
|
84 |
+
$message = esc_html__("One or more filenames isn't compatible with JSON encoding", 'duplicator');
|
85 |
+
}
|
86 |
+
|
87 |
+
throw new RuntimeException($message);
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Attempts to call json_encode upon error DUP_JSON::customEncode is called
|
92 |
+
*
|
93 |
+
* Returns a string containing the JSON representation of the supplied value
|
94 |
+
*
|
95 |
+
* @return string
|
96 |
+
*/
|
97 |
+
public static function safeEncode($value)
|
98 |
+
{
|
99 |
+
$jsonString = json_encode($value);
|
100 |
+
if (($jsonString === false) || trim($jsonString) == '') {
|
101 |
+
$jsonString = self::customEncode($value);
|
102 |
+
|
103 |
+
if (($jsonString === false) || trim($jsonString) == '') {
|
104 |
+
throw new Exception('Unable to generate JSON from object');
|
105 |
+
}
|
106 |
+
}
|
107 |
+
return $jsonString;
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Attempts to only call the json_decode method directly
|
112 |
+
*
|
113 |
+
* Returns the value encoded in json in appropriate PHP type. Values true, false and null are returned as TRUE, FALSE and NULL respectively.
|
114 |
+
* NULL is returned if the json cannot be decoded or if the encoded data is deeper than the recursion limit.
|
115 |
+
*
|
116 |
+
* @return object
|
117 |
+
*/
|
118 |
+
public static function decode($json, $assoc = false)
|
119 |
+
{
|
120 |
+
$result = json_decode($json, $assoc);
|
121 |
+
|
122 |
+
if ($result) {
|
123 |
+
return $result;
|
124 |
+
}
|
125 |
+
|
126 |
+
if (function_exists('json_last_error')) {
|
127 |
+
throw new RuntimeException(self::$_messages[json_last_error()]);
|
128 |
+
} else {
|
129 |
+
throw new RuntimeException("DUP_JSON decode error");
|
130 |
+
}
|
131 |
+
|
132 |
+
}
|
133 |
+
|
134 |
+
private static function makeUTF8($mixed)
|
135 |
+
{
|
136 |
+
if (is_array($mixed)) {
|
137 |
+
foreach ($mixed as $key => $value) {
|
138 |
+
$mixed[$key] = self::makeUTF8($value);
|
139 |
+
}
|
140 |
+
} else if (is_string($mixed)) {
|
141 |
+
return utf8_encode($mixed);
|
142 |
+
}
|
143 |
+
return $mixed;
|
144 |
+
}
|
145 |
+
|
146 |
+
private static function escapeString($str)
|
147 |
+
{
|
148 |
+
return addcslashes($str, "\v\t\n\r\f\"\\/");
|
149 |
+
}
|
150 |
+
|
151 |
+
private static function oldCustomEncode($in)
|
152 |
+
{
|
153 |
+
$out = "";
|
154 |
+
|
155 |
+
if (is_object($in)) {
|
156 |
+
$arr[$key] = "\"".self::escapeString($key)."\":\"{$val}\"";
|
157 |
+
$in = get_object_vars($in);
|
158 |
+
}
|
159 |
+
|
160 |
+
if (is_array($in)) {
|
161 |
+
$obj = false;
|
162 |
+
$arr = array();
|
163 |
+
|
164 |
+
foreach ($in AS $key => $val) {
|
165 |
+
if (!is_numeric($key)) {
|
166 |
+
$obj = true;
|
167 |
+
}
|
168 |
+
$arr[$key] = self::oldCustomEncode($val);
|
169 |
+
}
|
170 |
+
|
171 |
+
if ($obj) {
|
172 |
+
foreach ($arr AS $key => $val) {
|
173 |
+
$arr[$key] = "\"".self::escapeString($key)."\":{$val}";
|
174 |
+
}
|
175 |
+
$val = implode(',', $arr);
|
176 |
+
$out .= "{{$val}}";
|
177 |
+
} else {
|
178 |
+
$val = implode(',', $arr);
|
179 |
+
$out .= "[{$val}]";
|
180 |
+
}
|
181 |
+
} elseif (is_bool($in)) {
|
182 |
+
$out .= $in ? 'true' : 'false';
|
183 |
+
} elseif (is_null($in)) {
|
184 |
+
$out .= 'null';
|
185 |
+
} elseif (is_string($in)) {
|
186 |
+
$out .= "\"".self::escapeString($in)."\"";
|
187 |
+
} else {
|
188 |
+
$out .= $in;
|
189 |
+
}
|
190 |
+
|
191 |
+
return "{$out}";
|
192 |
+
}
|
193 |
}
|
classes/utilities/class.u.multisite.php
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Methods used to work with WordPress MU sites
|
4 |
+
*
|
5 |
+
* Standard: PSR-2
|
6 |
+
* @link http://www.php-fig.org/psr/psr-2
|
7 |
+
*
|
8 |
+
* @package Duplicator
|
9 |
+
* @subpackage classes/utilities
|
10 |
+
* @copyright (c) 2017, Snapcreek LLC
|
11 |
+
*
|
12 |
+
* @todo Refactor out IO methods into class.io.php file
|
13 |
+
*/
|
14 |
+
|
15 |
+
// Exit if accessed directly
|
16 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
17 |
+
|
18 |
+
class DUP_MU
|
19 |
+
{
|
20 |
+
public static function isMultisite()
|
21 |
+
{
|
22 |
+
return self::getMode() > 0;
|
23 |
+
}
|
24 |
+
|
25 |
+
// 0 = single site; 1 = multisite subdomain; 2 = multisite subdirectory
|
26 |
+
public static function getMode()
|
27 |
+
{
|
28 |
+
if(is_multisite()) {
|
29 |
+
if (defined('SUBDOMAIN_INSTALL') && SUBDOMAIN_INSTALL) {
|
30 |
+
return 1;
|
31 |
+
} else {
|
32 |
+
return 2;
|
33 |
+
}
|
34 |
+
} else {
|
35 |
+
return 0;
|
36 |
+
}
|
37 |
+
}
|
38 |
+
|
39 |
+
public static function getGeneration()
|
40 |
+
{
|
41 |
+
if (self::getMode() == 0) {
|
42 |
+
return DUP_PRO_MU_Generations::NotMultisite;
|
43 |
+
} else {
|
44 |
+
$sitesDir = WP_CONTENT_DIR.'/uploads/sites';
|
45 |
+
|
46 |
+
if (file_exists($sitesDir)) {
|
47 |
+
return DUP_PRO_MU_Generations::ThreeFivePlus;
|
48 |
+
} else {
|
49 |
+
return DUP_PRO_MU_Generations::PreThreeFive;
|
50 |
+
}
|
51 |
+
}
|
52 |
+
}
|
53 |
+
}
|
classes/utilities/class.u.php
CHANGED
@@ -8,17 +8,12 @@
|
|
8 |
* @package Duplicator
|
9 |
* @subpackage classes/utilities
|
10 |
* @copyright (c) 2017, Snapcreek LLC
|
11 |
-
* @since 1.1.0
|
12 |
*
|
13 |
* @todo Refactor out IO methods into class.io.php file
|
14 |
*/
|
15 |
|
16 |
// Exit if accessed directly
|
17 |
-
if (!defined('DUPLICATOR_VERSION'))
|
18 |
-
exit;
|
19 |
-
}
|
20 |
-
|
21 |
-
//require_once (DUPLICATOR_PLUGIN_PATH.'classes/class.crypt.php');
|
22 |
|
23 |
class DUP_Util
|
24 |
{
|
@@ -53,6 +48,15 @@ class DUP_Util
|
|
53 |
self::$PHP7_plus = version_compare(PHP_VERSION, '7.0.0', '>=');
|
54 |
}
|
55 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
|
57 |
public static function getWPCoreDirs()
|
58 |
{
|
@@ -69,10 +73,10 @@ class DUP_Util
|
|
69 |
$wp_core_dirs[] = $wp_path.'/plugins';
|
70 |
$wp_core_dirs[] = $wp_path.'/themes';
|
71 |
|
72 |
-
|
73 |
return $wp_core_dirs;
|
74 |
}
|
75 |
-
|
|
|
76 |
* return absolute path for the files that are core directories
|
77 |
* @return string array
|
78 |
*/
|
@@ -92,7 +96,7 @@ class DUP_Util
|
|
92 |
* @param mixed $key,... The key to group or split by. Can be a _string_, an _integer_, a _float_, or a _callable_.
|
93 |
* - If the key is a callback, it must return a valid key from the array.
|
94 |
* - If the key is _NULL_, the iterated element is skipped.
|
95 |
-
* - string|
|
96 |
*
|
97 |
* @return array|null Returns a multidimensional array or `null` if `$key` is invalid.
|
98 |
*/
|
@@ -133,7 +137,7 @@ class DUP_Util
|
|
133 |
}
|
134 |
|
135 |
/**
|
136 |
-
* PHP_SAPI for
|
137 |
* bytes every 40 seconds or else it forces a script halt
|
138 |
*
|
139 |
* @return string A series of 256 space characters
|
@@ -146,9 +150,9 @@ class DUP_Util
|
|
146 |
}
|
147 |
|
148 |
/**
|
149 |
-
* Returns the wp-snapshot
|
150 |
*
|
151 |
-
* @return string The full
|
152 |
*/
|
153 |
public static function snapshotURL()
|
154 |
{
|
@@ -156,7 +160,7 @@ class DUP_Util
|
|
156 |
}
|
157 |
|
158 |
/**
|
159 |
-
* Returns the last N lines of a file.
|
160 |
*
|
161 |
* @param string $filepath The full path to the file to be tailed
|
162 |
* @param int $lines The number of lines to return with each tail call
|
@@ -165,7 +169,6 @@ class DUP_Util
|
|
165 |
*/
|
166 |
public static function tailFile($filepath, $lines = 2)
|
167 |
{
|
168 |
-
|
169 |
// Open file
|
170 |
$f = @fopen($filepath, "rb");
|
171 |
if ($f === false) return false;
|
@@ -208,21 +211,6 @@ class DUP_Util
|
|
208 |
return trim($output);
|
209 |
}
|
210 |
|
211 |
-
/**
|
212 |
-
* Runs the APC cache to pre-cache the php files
|
213 |
-
*
|
214 |
-
* @returns bool True if all files where cached
|
215 |
-
*/
|
216 |
-
public static function runAPC()
|
217 |
-
{
|
218 |
-
if (function_exists('apc_compile_file')) {
|
219 |
-
$file01 = @apc_compile_file(DUPLICATOR_PLUGIN_PATH."duplicator.php");
|
220 |
-
return ($file01);
|
221 |
-
} else {
|
222 |
-
return false;
|
223 |
-
}
|
224 |
-
}
|
225 |
-
|
226 |
/**
|
227 |
* Display human readable byte sizes
|
228 |
*
|
@@ -246,7 +234,7 @@ class DUP_Util
|
|
246 |
/**
|
247 |
* Makes path safe for any OS
|
248 |
* Paths should ALWAYS READ be "/"
|
249 |
-
* uni: /home/path/file.
|
250 |
* win: D:/home/path/file.txt
|
251 |
*
|
252 |
* @param string $path The path to make safe
|
@@ -304,7 +292,7 @@ class DUP_Util
|
|
304 |
* @param string $path The full path to a system directory
|
305 |
*
|
306 |
* @return array of all files in that path
|
307 |
-
*
|
308 |
* Notes:
|
309 |
* - Avoid using glob() as GLOB_BRACE is not an option on some operating systems
|
310 |
* - Pre PHP 5.3 DirectoryIterator will crash on unreadable files
|
@@ -320,7 +308,6 @@ class DUP_Util
|
|
320 |
return $files;
|
321 |
|
322 |
} catch (Exception $exc) {
|
323 |
-
|
324 |
$result = array();
|
325 |
$files = @scandir($path);
|
326 |
if (is_array($files)) {
|
@@ -426,6 +413,32 @@ class DUP_Util
|
|
426 |
return false;
|
427 |
}
|
428 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
429 |
/**
|
430 |
* Does the current user have the capability
|
431 |
*
|
@@ -482,32 +495,6 @@ class DUP_Util
|
|
482 |
}
|
483 |
}
|
484 |
|
485 |
-
/**
|
486 |
-
* Wrap to prevent malware scanners from reporting false/positive
|
487 |
-
* Switched from our old method to avoid WordFence reporting a false positive
|
488 |
-
*
|
489 |
-
* @param string $string The string to decrypt i.e. base64_decode
|
490 |
-
*
|
491 |
-
* @return string Returns the string base64 decoded
|
492 |
-
*/
|
493 |
-
public static function installerUnscramble($string)
|
494 |
-
{
|
495 |
-
return base64_decode($string);
|
496 |
-
}
|
497 |
-
|
498 |
-
/**
|
499 |
-
* Wrap to prevent malware scanners from reporting false/positive
|
500 |
-
* Switched from our old method to avoid WordFence reporting a false positive
|
501 |
-
*
|
502 |
-
* @param string $string The string to decrypt i.e. base64_encode
|
503 |
-
*
|
504 |
-
* @return string Returns the string base64 encode
|
505 |
-
*/
|
506 |
-
public static function installerScramble($string)
|
507 |
-
{
|
508 |
-
return base64_encode($string);
|
509 |
-
}
|
510 |
-
|
511 |
/**
|
512 |
* Creates the snapshot directory if it doesn't already exist
|
513 |
*
|
@@ -604,6 +591,16 @@ class DUP_Util
|
|
604 |
return $filepath;
|
605 |
}
|
606 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
607 |
/**
|
608 |
* Returns an array of the WordPress core tables.
|
609 |
*
|
@@ -626,13 +623,14 @@ class DUP_Util
|
|
626 |
"{$wpdb->prefix}usermeta",
|
627 |
"{$wpdb->prefix}users");
|
628 |
}
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
|
|
636 |
public static function isExecutable($cmd)
|
637 |
{
|
638 |
if (strlen($cmd) < 1) return false;
|
@@ -654,14 +652,29 @@ class DUP_Util
|
|
654 |
return false;
|
655 |
}
|
656 |
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
665 |
}
|
666 |
}
|
667 |
-
DUP_Util::init();
|
8 |
* @package Duplicator
|
9 |
* @subpackage classes/utilities
|
10 |
* @copyright (c) 2017, Snapcreek LLC
|
|
|
11 |
*
|
12 |
* @todo Refactor out IO methods into class.io.php file
|
13 |
*/
|
14 |
|
15 |
// Exit if accessed directly
|
16 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
|
|
|
|
|
|
|
|
17 |
|
18 |
class DUP_Util
|
19 |
{
|
48 |
self::$PHP7_plus = version_compare(PHP_VERSION, '7.0.0', '>=');
|
49 |
}
|
50 |
|
51 |
+
public static function objectCopy($srcObject, $destObject, $skipMemberArray = null)
|
52 |
+
{
|
53 |
+
foreach ($srcObject as $member_name => $member_value) {
|
54 |
+
if (!is_object($member_value) && (($skipMemberArray == null) || !in_array($member_name, $skipMemberArray))) {
|
55 |
+
// Skipping all object members
|
56 |
+
$destObject->$member_name = $member_value;
|
57 |
+
}
|
58 |
+
}
|
59 |
+
}
|
60 |
|
61 |
public static function getWPCoreDirs()
|
62 |
{
|
73 |
$wp_core_dirs[] = $wp_path.'/plugins';
|
74 |
$wp_core_dirs[] = $wp_path.'/themes';
|
75 |
|
|
|
76 |
return $wp_core_dirs;
|
77 |
}
|
78 |
+
|
79 |
+
/**
|
80 |
* return absolute path for the files that are core directories
|
81 |
* @return string array
|
82 |
*/
|
96 |
* @param mixed $key,... The key to group or split by. Can be a _string_, an _integer_, a _float_, or a _callable_.
|
97 |
* - If the key is a callback, it must return a valid key from the array.
|
98 |
* - If the key is _NULL_, the iterated element is skipped.
|
99 |
+
* - string|oink callback ( mixed $item )
|
100 |
*
|
101 |
* @return array|null Returns a multidimensional array or `null` if `$key` is invalid.
|
102 |
*/
|
137 |
}
|
138 |
|
139 |
/**
|
140 |
+
* PHP_SAPI for FCGI requires a data flush of at least 256
|
141 |
* bytes every 40 seconds or else it forces a script halt
|
142 |
*
|
143 |
* @return string A series of 256 space characters
|
150 |
}
|
151 |
|
152 |
/**
|
153 |
+
* Returns the wp-snapshot URL
|
154 |
*
|
155 |
+
* @return string The full URL of the duplicators snapshot storage directory
|
156 |
*/
|
157 |
public static function snapshotURL()
|
158 |
{
|
160 |
}
|
161 |
|
162 |
/**
|
163 |
+
* Returns the last N lines of a file. Equivalent to tail command
|
164 |
*
|
165 |
* @param string $filepath The full path to the file to be tailed
|
166 |
* @param int $lines The number of lines to return with each tail call
|
169 |
*/
|
170 |
public static function tailFile($filepath, $lines = 2)
|
171 |
{
|
|
|
172 |
// Open file
|
173 |
$f = @fopen($filepath, "rb");
|
174 |
if ($f === false) return false;
|
211 |
return trim($output);
|
212 |
}
|
213 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
214 |
/**
|
215 |
* Display human readable byte sizes
|
216 |
*
|
234 |
/**
|
235 |
* Makes path safe for any OS
|
236 |
* Paths should ALWAYS READ be "/"
|
237 |
+
* uni: /home/path/file.txt
|
238 |
* win: D:/home/path/file.txt
|
239 |
*
|
240 |
* @param string $path The path to make safe
|
292 |
* @param string $path The full path to a system directory
|
293 |
*
|
294 |
* @return array of all files in that path
|
295 |
+
*
|
296 |
* Notes:
|
297 |
* - Avoid using glob() as GLOB_BRACE is not an option on some operating systems
|
298 |
* - Pre PHP 5.3 DirectoryIterator will crash on unreadable files
|
308 |
return $files;
|
309 |
|
310 |
} catch (Exception $exc) {
|
|
|
311 |
$result = array();
|
312 |
$files = @scandir($path);
|
313 |
if (is_array($files)) {
|
413 |
return false;
|
414 |
}
|
415 |
|
416 |
+
/**
|
417 |
+
* Wrap to prevent malware scanners from reporting false/positive
|
418 |
+
* Switched from our old method to avoid WordFence reporting a false positive
|
419 |
+
*
|
420 |
+
* @param string $string The string to decrypt i.e. base64_decode
|
421 |
+
*
|
422 |
+
* @return string Returns the string base64 decoded
|
423 |
+
*/
|
424 |
+
public static function installerUnscramble($string)
|
425 |
+
{
|
426 |
+
return base64_decode($string);
|
427 |
+
}
|
428 |
+
|
429 |
+
/**
|
430 |
+
* Wrap to prevent malware scanners from reporting false/positive
|
431 |
+
* Switched from our old method to avoid WordFence reporting a false positive
|
432 |
+
*
|
433 |
+
* @param string $string The string to decrypt i.e. base64_encode
|
434 |
+
*
|
435 |
+
* @return string Returns the string base64 encode
|
436 |
+
*/
|
437 |
+
public static function installerScramble($string)
|
438 |
+
{
|
439 |
+
return base64_encode($string);
|
440 |
+
}
|
441 |
+
|
442 |
/**
|
443 |
* Does the current user have the capability
|
444 |
*
|
495 |
}
|
496 |
}
|
497 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
498 |
/**
|
499 |
* Creates the snapshot directory if it doesn't already exist
|
500 |
*
|
591 |
return $filepath;
|
592 |
}
|
593 |
|
594 |
+
/**
|
595 |
+
* Is the server PHP 5.3 or better
|
596 |
+
*
|
597 |
+
* @return bool Returns true if the server PHP 5.3 or better
|
598 |
+
*/
|
599 |
+
public static function PHP53()
|
600 |
+
{
|
601 |
+
return version_compare(PHP_VERSION, '5.3.2', '>=');
|
602 |
+
}
|
603 |
+
|
604 |
/**
|
605 |
* Returns an array of the WordPress core tables.
|
606 |
*
|
623 |
"{$wpdb->prefix}usermeta",
|
624 |
"{$wpdb->prefix}users");
|
625 |
}
|
626 |
+
|
627 |
+
/**
|
628 |
+
* Finds if its a valid executable or not
|
629 |
+
*
|
630 |
+
* @param type $exe A non zero length executable path to find if that is executable or not.
|
631 |
+
* @param type $expectedValue expected value for the result
|
632 |
+
* @return boolean
|
633 |
+
*/
|
634 |
public static function isExecutable($cmd)
|
635 |
{
|
636 |
if (strlen($cmd) < 1) return false;
|
652 |
return false;
|
653 |
}
|
654 |
|
655 |
+
/**
|
656 |
+
* Display human readable byte sizes
|
657 |
+
*
|
658 |
+
* @param string $size The size in bytes
|
659 |
+
*
|
660 |
+
* @return string Human readable bytes such as 50MB, 1GB
|
661 |
+
*/
|
662 |
+
public static function readableByteSize($size)
|
663 |
+
{
|
664 |
+
try {
|
665 |
+
$units = array('B', 'KB', 'MB', 'GB', 'TB');
|
666 |
+
for ($i = 0; $size >= 1024 && $i < 4; $i++)
|
667 |
+
$size /= 1024;
|
668 |
+
return round($size, 2).$units[$i];
|
669 |
+
} catch (Exception $e) {
|
670 |
+
return "n/a";
|
671 |
+
}
|
672 |
+
}
|
673 |
+
|
674 |
+
public static function getTablePrefix() {
|
675 |
+
global $wpdb;
|
676 |
+
$tablePrefix = (is_multisite() && is_plugin_active_for_network('duplicator/duplicator.php')) ? $wpdb->base_prefix : $wpdb->prefix;
|
677 |
+
return $tablePrefix;
|
678 |
}
|
679 |
}
|
680 |
+
DUP_Util::init();
|
classes/utilities/class.u.scancheck.php
CHANGED
@@ -6,16 +6,13 @@
|
|
6 |
* @link http://www.php-fig.org/psr/psr-2
|
7 |
*
|
8 |
* @package Duplicator
|
9 |
-
* @subpackage classes/
|
10 |
* @copyright (c) 2017, Snapcreek LLC
|
11 |
-
* @since 1.1.26
|
12 |
*
|
13 |
*/
|
14 |
|
15 |
// Exit if accessed directly
|
16 |
-
if (!defined('DUPLICATOR_VERSION'))
|
17 |
-
exit;
|
18 |
-
}
|
19 |
|
20 |
class DUP_ScanCheck
|
21 |
{
|
@@ -154,7 +151,7 @@ class DUP_ScanCheck
|
|
154 |
}
|
155 |
}
|
156 |
}
|
157 |
-
|
158 |
$this->dirCount++;
|
159 |
}
|
160 |
}
|
@@ -164,9 +161,9 @@ class DUP_ScanCheck
|
|
164 |
}
|
165 |
|
166 |
/**
|
167 |
-
*
|
168 |
*
|
169 |
-
* @param string $target A valid file path
|
170 |
*
|
171 |
* @return bool Is the target a sym link
|
172 |
*/
|
6 |
* @link http://www.php-fig.org/psr/psr-2
|
7 |
*
|
8 |
* @package Duplicator
|
9 |
+
* @subpackage classes/utilities
|
10 |
* @copyright (c) 2017, Snapcreek LLC
|
|
|
11 |
*
|
12 |
*/
|
13 |
|
14 |
// Exit if accessed directly
|
15 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
|
|
|
|
16 |
|
17 |
class DUP_ScanCheck
|
18 |
{
|
151 |
}
|
152 |
}
|
153 |
}
|
154 |
+
|
155 |
$this->dirCount++;
|
156 |
}
|
157 |
}
|
161 |
}
|
162 |
|
163 |
/**
|
164 |
+
* Separation logic for supporting how different operating systems work
|
165 |
*
|
166 |
+
* @param string $target A valid file path
|
167 |
*
|
168 |
* @return bool Is the target a sym link
|
169 |
*/
|
classes/utilities/class.u.shell.php
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
defined("ABSPATH") or die("");
|
3 |
+
|
4 |
+
// Exit if accessed directly
|
5 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
6 |
+
|
7 |
+
class DUP_Shell_U
|
8 |
+
{
|
9 |
+
/**
|
10 |
+
* Escape a string to be used as a shell argument with bypass support for Windows
|
11 |
+
*
|
12 |
+
* NOTES:
|
13 |
+
* Provides a way to support shell args on Windows OS and allows %,! on Windows command line
|
14 |
+
* Safe if input is know such as a defined constant and not from user input escape shellarg
|
15 |
+
* on Windows with turn %,! into spaces
|
16 |
+
*
|
17 |
+
* @return string
|
18 |
+
*/
|
19 |
+
public static function escapeshellargWindowsSupport($string)
|
20 |
+
{
|
21 |
+
if (strncasecmp(PHP_OS, 'WIN', 3) == 0) {
|
22 |
+
if (strstr($string, '%') || strstr($string, '!')) {
|
23 |
+
$result = '"'.str_replace('"', '', $string).'"';
|
24 |
+
return $result;
|
25 |
+
}
|
26 |
+
}
|
27 |
+
return escapeshellarg($string);
|
28 |
+
}
|
29 |
+
|
30 |
+
public static function isPopenEnabled() {
|
31 |
+
if (!function_exists('popen') || !function_exists('proc_open')) {
|
32 |
+
$ret = false;
|
33 |
+
} else {
|
34 |
+
$ret = true;
|
35 |
+
}
|
36 |
+
$ret = apply_filters('duplicator_pro_is_popen_enabled', $ret);
|
37 |
+
return $ret;
|
38 |
+
}
|
39 |
+
}
|
classes/utilities/class.u.string.php
ADDED
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Utility class working with strings
|
4 |
+
*
|
5 |
+
* Standard: PSR-2
|
6 |
+
* @link http://www.php-fig.org/psr/psr-2
|
7 |
+
*
|
8 |
+
* @package DUP
|
9 |
+
* @subpackage classes/utilities
|
10 |
+
* @copyright (c) 2017, Snapcreek LLC
|
11 |
+
* @license https://opensource.org/licenses/GPL-3.0 GNU Public License
|
12 |
+
*
|
13 |
+
*/
|
14 |
+
class DUP_STR
|
15 |
+
{
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Append the value to the string if it doesn't already exist
|
19 |
+
*
|
20 |
+
* @param string $string The string to append to
|
21 |
+
* @param string $value The string to append to the $string
|
22 |
+
*
|
23 |
+
* @return string Returns the string with the $value appended once
|
24 |
+
*/
|
25 |
+
public static function appendOnce($string, $value)
|
26 |
+
{
|
27 |
+
return $string.(substr($string, -1) == $value ? '' : $value);
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Returns true if the string contains UTF8 characters
|
32 |
+
* @see http://php.net/manual/en/function.mb-detect-encoding.php
|
33 |
+
*
|
34 |
+
* @param string $string The class name where the $destArray exists
|
35 |
+
*
|
36 |
+
* @return null
|
37 |
+
*/
|
38 |
+
public static function hasUTF8($string)
|
39 |
+
{
|
40 |
+
return preg_match('%(?:
|
41 |
+
[\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
|
42 |
+
|\xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
|
43 |
+
|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
|
44 |
+
|\xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
|
45 |
+
|\xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
|
46 |
+
|[\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
|
47 |
+
|\xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
|
48 |
+
)+%xs', $string);
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Returns true if the $needle is found in the $haystack
|
53 |
+
*
|
54 |
+
* @param string $haystack The full string to search in
|
55 |
+
* @param string $needle The string to for
|
56 |
+
*
|
57 |
+
* @return bool
|
58 |
+
*/
|
59 |
+
public static function contains($haystack, $needle)
|
60 |
+
{
|
61 |
+
$pos = strpos($haystack, $needle);
|
62 |
+
return ($pos !== false);
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Returns true if the $haystack string starts with the $needle
|
67 |
+
*
|
68 |
+
* @param string $haystack The full string to search in
|
69 |
+
* @param string $needle The string to for
|
70 |
+
*
|
71 |
+
* @return bool Returns true if the $haystack string starts with the $needle
|
72 |
+
*/
|
73 |
+
public static function startsWith($haystack, $needle)
|
74 |
+
{
|
75 |
+
$length = strlen($needle);
|
76 |
+
return (substr($haystack, 0, $length) === $needle);
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Returns true if the $haystack string ends with the $needle
|
81 |
+
*
|
82 |
+
* @param string $haystack The full string to search in
|
83 |
+
* @param string $needle The string to for
|
84 |
+
*
|
85 |
+
* @return bool Returns true if the $haystack string ends with the $needle
|
86 |
+
*/
|
87 |
+
public static function endsWith($haystack, $needle)
|
88 |
+
{
|
89 |
+
$length = strlen($needle);
|
90 |
+
if ($length == 0) {
|
91 |
+
return true;
|
92 |
+
}
|
93 |
+
return (substr($haystack, -$length) === $needle);
|
94 |
+
}
|
95 |
+
|
96 |
+
|
97 |
+
}
|
98 |
+
|
classes/utilities/class.u.validator.php
ADDED
@@ -0,0 +1,228 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Validate variables
|
4 |
+
*
|
5 |
+
* Standard: PSR-2
|
6 |
+
* @link http://www.php-fig.org/psr/psr-2
|
7 |
+
*
|
8 |
+
* @package Duplicator
|
9 |
+
* @subpackage classes/utilities
|
10 |
+
* @copyright (c) 2017, Snapcreek LLC
|
11 |
+
*
|
12 |
+
*/
|
13 |
+
|
14 |
+
// Exit if accessed directly
|
15 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
16 |
+
|
17 |
+
class DUP_Validator
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* @var array $patterns
|
21 |
+
*/
|
22 |
+
private static $patterns = array(
|
23 |
+
'fdir' => '/^([a-zA-Z]:|\/|\\\\\\\\)[\p{L}\s0-9-_!%&()=\[\]#@,.;+\\\\\/]+$/',
|
24 |
+
'ffile' => '/^([a-zA-Z]:|\/|\\\\\\\\)[\p{L}\s0-9-_!%&()=\[\]#@,.;+\\\\\/]+\.[A-Za-z0-9]{2,4}$/',
|
25 |
+
'fext' => '/^\.?[A-Za-z0-9]{2,4}$/',
|
26 |
+
'email' => '[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+',
|
27 |
+
'empty' => '/^$/',
|
28 |
+
'nempty' => '/^.+$/',
|
29 |
+
);
|
30 |
+
|
31 |
+
const FILTER_VALIDATE_IS_EMPTY = 'empty';
|
32 |
+
const FILTER_VALIDATE_NOT_EMPTY = 'nempty';
|
33 |
+
const FILTER_VALIDATE_FILE = 'ffile';
|
34 |
+
const FILTER_VALIDATE_FOLDER = 'fdir';
|
35 |
+
const FILTER_VALIDATE_FILE_EXT = 'fext';
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @var array $errors [ ['key' => string field key,
|
39 |
+
* 'msg' => error message ] , [] ]
|
40 |
+
*/
|
41 |
+
private $errors = array();
|
42 |
+
|
43 |
+
/**
|
44 |
+
*
|
45 |
+
*/
|
46 |
+
public function __construct()
|
47 |
+
{
|
48 |
+
$this->errors = array();
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
*
|
53 |
+
*/
|
54 |
+
public function reset()
|
55 |
+
{
|
56 |
+
$this->errors = array();
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
*
|
61 |
+
* @return bool
|
62 |
+
*/
|
63 |
+
public function isSuccess()
|
64 |
+
{
|
65 |
+
return empty($this->errors);
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
*
|
70 |
+
* @return array
|
71 |
+
*/
|
72 |
+
public function getErrors()
|
73 |
+
{
|
74 |
+
return $this->errors;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
*
|
79 |
+
* @return array return errors messages
|
80 |
+
*/
|
81 |
+
public function getErrorsMsg()
|
82 |
+
{
|
83 |
+
$result = array();
|
84 |
+
foreach ($this->errors as $err) {
|
85 |
+
$result[] = $err['msg'];
|
86 |
+
}
|
87 |
+
return $result;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
*
|
92 |
+
* @param string $format printf format message where %s is the variable content default "%s\n"
|
93 |
+
* @param bool $echo if false return string
|
94 |
+
* @return void|string
|
95 |
+
*/
|
96 |
+
public function getErrorsFormat($format = "%s\n", $echo = true)
|
97 |
+
{
|
98 |
+
$msgs = $this->getErrorsMsg();
|
99 |
+
|
100 |
+
ob_start();
|
101 |
+
foreach ($msgs as $msg) {
|
102 |
+
printf($format, $msg);
|
103 |
+
}
|
104 |
+
|
105 |
+
if ($echo) {
|
106 |
+
ob_end_flush();
|
107 |
+
} else {
|
108 |
+
return ob_get_clean();
|
109 |
+
}
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
*
|
114 |
+
* @param string $key
|
115 |
+
* @param string $msg
|
116 |
+
*/
|
117 |
+
protected function addError($key, $msg)
|
118 |
+
{
|
119 |
+
$this->errors[] = array(
|
120 |
+
'key' => $key,
|
121 |
+
'msg' => $msg
|
122 |
+
);
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* filter_var function wrapper see http://php.net/manual/en/function.filter-var.php
|
127 |
+
*
|
128 |
+
* additional options
|
129 |
+
* valkey => key of field
|
130 |
+
* errmsg => error message; % s will be replaced with the contents of the variable es. "<b>%s</b> isn't a valid field"
|
131 |
+
* acc_vals => array of accepted values that skip validation
|
132 |
+
*
|
133 |
+
* @param mixed $variable
|
134 |
+
* @param int $filter
|
135 |
+
* @param array $options
|
136 |
+
* @return mixed
|
137 |
+
*/
|
138 |
+
public function filter_var($variable, $filter = FILTER_DEFAULT, $options = array())
|
139 |
+
{
|
140 |
+
$success = true;
|
141 |
+
$result = null;
|
142 |
+
|
143 |
+
if (isset($options['acc_vals']) && in_array($variable , $options['acc_vals'])) {
|
144 |
+
return $variable;
|
145 |
+
}
|
146 |
+
|
147 |
+
if ($filter === FILTER_VALIDATE_BOOLEAN) {
|
148 |
+
$options['flags'] = FILTER_NULL_ON_FAILURE;
|
149 |
+
|
150 |
+
$result = filter_var($variable, $filter, $options);
|
151 |
+
|
152 |
+
if (is_null($result)) {
|
153 |
+
$success = false;
|
154 |
+
}
|
155 |
+
} else {
|
156 |
+
$result = filter_var($variable, $filter, $options);
|
157 |
+
|
158 |
+
if ($result === false) {
|
159 |
+
$success = false;
|
160 |
+
}
|
161 |
+
}
|
162 |
+
|
163 |
+
if (!$success) {
|
164 |
+
$key = isset($options['valkey']) ? $options['valkey'] : '';
|
165 |
+
|
166 |
+
if (isset($options['errmsg'])) {
|
167 |
+
$msg = sprintf($options['errmsg'], $variable);
|
168 |
+
} else {
|
169 |
+
$msg = sprintf('%1$s isn\'t a valid value', $variable);
|
170 |
+
}
|
171 |
+
|
172 |
+
$this->addError($key, $msg);
|
173 |
+
}
|
174 |
+
|
175 |
+
return $result;
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* validation of predefined regular expressions
|
180 |
+
*
|
181 |
+
* @param mixed $variable
|
182 |
+
* @param string $filter
|
183 |
+
* @param array $options
|
184 |
+
* @return type
|
185 |
+
* @throws Exception
|
186 |
+
*/
|
187 |
+
public function filter_custom($variable, $filter, $options = array())
|
188 |
+
{
|
189 |
+
|
190 |
+
if (!isset(self::$patterns[$filter])) {
|
191 |
+
throw new Exception('Filter not valid');
|
192 |
+
}
|
193 |
+
|
194 |
+
$options = array_merge($options, array(
|
195 |
+
'options' => array(
|
196 |
+
'regexp' => self::$patterns[$filter])
|
197 |
+
)
|
198 |
+
);
|
199 |
+
|
200 |
+
//$options['regexp'] = self::$patterns[$filter];
|
201 |
+
|
202 |
+
return $this->filter_var($variable, FILTER_VALIDATE_REGEXP, $options);
|
203 |
+
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* it explodes a string with a delimiter and validates every element of the array
|
207 |
+
*
|
208 |
+
* @param string $variable
|
209 |
+
* @param string $delimiter
|
210 |
+
* @param string $filter
|
211 |
+
* @param array $options
|
212 |
+
*/
|
213 |
+
public function explode_filter_custom($variable, $delimiter , $filter, $options = array()) {
|
214 |
+
if (empty($variable)) {
|
215 |
+
return array();
|
216 |
+
}
|
217 |
+
|
218 |
+
$vals = explode($delimiter, trim($variable, $delimiter));
|
219 |
+
$res = array();
|
220 |
+
|
221 |
+
foreach ($vals as $val) {
|
222 |
+
$res[] = $this->filter_custom($val, $filter, $options);
|
223 |
+
}
|
224 |
+
|
225 |
+
return $res;
|
226 |
+
}
|
227 |
+
|
228 |
+
}
|
classes/utilities/class.u.zip.php
ADDED
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
defined("ABSPATH") or die("");
|
3 |
+
/**
|
4 |
+
* Utility class for zipping up content
|
5 |
+
*
|
6 |
+
* Standard: PSR-2
|
7 |
+
* @link http://www.php-fig.org/psr/psr-2
|
8 |
+
*
|
9 |
+
* @subpackage classes/utilities
|
10 |
+
* @copyright (c) 2017, Snapcreek LLC
|
11 |
+
* @license https://opensource.org/licenses/GPL-3.0 GNU Public License
|
12 |
+
*/
|
13 |
+
|
14 |
+
// Exit if accessed directly
|
15 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
16 |
+
|
17 |
+
class DUP_Zip_U
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* Add a directory to an existing ZipArchive object
|
21 |
+
*
|
22 |
+
* @param ZipArchive $zipArchive An existing ZipArchive object
|
23 |
+
* @param string $directoryPath The full directory path to add to the ZipArchive
|
24 |
+
* @param bool $retainDirectory Should the full directory path be retained in the archive
|
25 |
+
*
|
26 |
+
* @return bool Returns true if the directory was added to the object
|
27 |
+
*/
|
28 |
+
public static function addDirWithZipArchive(&$zipArchive, $directoryPath, $retainDirectory, $localPrefix, $isCompressed)
|
29 |
+
{
|
30 |
+
$success = true;
|
31 |
+
|
32 |
+
$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directoryPath), RecursiveIteratorIterator::SELF_FIRST);
|
33 |
+
|
34 |
+
foreach ($objects as $path => $object) {
|
35 |
+
$path = DUP_Util::safePath($path);
|
36 |
+
$local_name = ltrim(str_replace($directoryPath, '', $path), '/');
|
37 |
+
|
38 |
+
if ($retainDirectory) {
|
39 |
+
$local_name = basename($directoryPath)."/$local_name";
|
40 |
+
}
|
41 |
+
|
42 |
+
$local_name = $localPrefix . $local_name;
|
43 |
+
|
44 |
+
if (!is_dir($path)) {
|
45 |
+
if (is_readable($path)) {
|
46 |
+
$added = DUP_Zip_U::addFileToZipArchive($zipArchive, $path, $local_name, $isCompressed);
|
47 |
+
} else {
|
48 |
+
$added = false;
|
49 |
+
}
|
50 |
+
} else {
|
51 |
+
$added = true;
|
52 |
+
}
|
53 |
+
|
54 |
+
if (!$added) {
|
55 |
+
DUP_Log::error("Couldn't add file $path to archive", '', Dup_ErrorBehavior::LogOnly);
|
56 |
+
$success = false;
|
57 |
+
break;
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
return $success;
|
62 |
+
}
|
63 |
+
|
64 |
+
|
65 |
+
public static function extractFiles($archiveFilepath, $relativeFilesToExtract, $destinationDirectory, $useShellUnZip)
|
66 |
+
{
|
67 |
+
// TODO: Unzip using either shell unzip or ziparchive
|
68 |
+
if($useShellUnZip) {
|
69 |
+
$shellExecPath = DUPX_Server::get_unzip_filepath();
|
70 |
+
|
71 |
+
$filenameString = implode(' ', $relativeFilesToExtract);
|
72 |
+
|
73 |
+
$command = "{$shellExecPath} -o -qq \"{$archiveFilepath}\" {$filenameString} -d {$destinationDirectory} 2>&1";
|
74 |
+
|
75 |
+
$stderr = shell_exec($command);
|
76 |
+
|
77 |
+
if ($stderr != '') {
|
78 |
+
$errorMessage = DUP_U::__("Error extracting {$archiveFilepath}): {$stderr}");
|
79 |
+
|
80 |
+
throw new Exception($errorMessage);
|
81 |
+
}
|
82 |
+
} else {
|
83 |
+
$zipArchive = new ZipArchive();
|
84 |
+
|
85 |
+
$result = $zipArchive->open($archiveFilepath);
|
86 |
+
|
87 |
+
if($result !== true) {
|
88 |
+
throw new Exception("Error opening {$archiveFilepath} when extracting. Error code: {$retVal}");
|
89 |
+
}
|
90 |
+
|
91 |
+
$result = $zipArchive->extractTo($destinationDirectory, $relativeFilesToExtract);
|
92 |
+
|
93 |
+
if($result === false) {
|
94 |
+
throw new Exception("Error extracting {$archiveFilepath}.");
|
95 |
+
}
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Add a directory to an existing ZipArchive object
|
101 |
+
*
|
102 |
+
* @param string $sourceFilePath The file to add to the zip file
|
103 |
+
* @param string $zipFilePath The zip file to be added to
|
104 |
+
* @param bool $deleteOld Delete the zip file before adding a file
|
105 |
+
* @param string $newName Rename the $sourceFile if needed
|
106 |
+
*
|
107 |
+
* @return bool Returns true if the file was added to the zip file
|
108 |
+
*/
|
109 |
+
public static function zipFile($sourceFilePath, $zipFilePath, $deleteOld, $newName, $isCompressed)
|
110 |
+
{
|
111 |
+
if ($deleteOld && file_exists($zipFilePath)) {
|
112 |
+
DUP_IO::deleteFile($zipFilePath);
|
113 |
+
}
|
114 |
+
|
115 |
+
if (file_exists($sourceFilePath)) {
|
116 |
+
$zip_archive = new ZipArchive();
|
117 |
+
|
118 |
+
$is_zip_open = ($zip_archive->open($zipFilePath, ZIPARCHIVE::CREATE) === TRUE);
|
119 |
+
|
120 |
+
if ($is_zip_open === false) {
|
121 |
+
DUP_Log::error("Cannot create zip archive {$zipFilePath}");
|
122 |
+
} else {
|
123 |
+
//ADD SQL
|
124 |
+
if ($newName == null) {
|
125 |
+
$source_filename = basename($sourceFilePath);
|
126 |
+
DUP_Log::Info("adding {$source_filename}");
|
127 |
+
} else {
|
128 |
+
$source_filename = $newName;
|
129 |
+
DUP_Log::Info("new name added {$newName}");
|
130 |
+
}
|
131 |
+
|
132 |
+
$in_zip = DUP_Zip_U::addFileToZipArchive($zip_archive, $sourceFilePath, $source_filename, $isCompressed);
|
133 |
+
|
134 |
+
if ($in_zip === false) {
|
135 |
+
DUP_Log::error("Unable to add {$sourceFilePath} to $zipFilePath");
|
136 |
+
}
|
137 |
+
|
138 |
+
$zip_archive->close();
|
139 |
+
|
140 |
+
return true;
|
141 |
+
}
|
142 |
+
} else {
|
143 |
+
DUP_Log::error("Trying to add {$sourceFilePath} to a zip but it doesn't exist!");
|
144 |
+
}
|
145 |
+
|
146 |
+
return false;
|
147 |
+
}
|
148 |
+
|
149 |
+
public static function addFileToZipArchive(&$zipArchive, $filepath, $localName, $isCompressed)
|
150 |
+
{
|
151 |
+
$added = $zipArchive->addFile($filepath, $localName);
|
152 |
+
|
153 |
+
return $added;
|
154 |
+
}
|
155 |
+
}
|
ctrls/ctrl.base.php
CHANGED
@@ -1,4 +1,7 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
2 |
require_once(DUPLICATOR_PLUGIN_PATH.'/classes/utilities/class.u.php');
|
3 |
|
4 |
//Enum used to define the various test statues
|
@@ -37,6 +40,13 @@ class DUP_CTRL_Base
|
|
37 |
$post = is_array($post) ? $post : array();
|
38 |
return array_merge($_POST, $post);
|
39 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
}
|
41 |
|
42 |
/**
|
1 |
<?php
|
2 |
+
// Exit if accessed directly
|
3 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
4 |
+
|
5 |
require_once(DUPLICATOR_PLUGIN_PATH.'/classes/utilities/class.u.php');
|
6 |
|
7 |
//Enum used to define the various test statues
|
40 |
$post = is_array($post) ? $post : array();
|
41 |
return array_merge($_POST, $post);
|
42 |
}
|
43 |
+
|
44 |
+
//Merges $_GET params with custom parameters.
|
45 |
+
public function getParamMerge($params)
|
46 |
+
{
|
47 |
+
$params = is_array($params) ? $params : array();
|
48 |
+
return array_merge($_GET, $params);
|
49 |
+
}
|
50 |
}
|
51 |
|
52 |
/**
|
ctrls/ctrl.package.php
CHANGED
@@ -1,9 +1,13 @@
|
|
1 |
<?php
|
|
|
|
|
2 |
|
3 |
-
require_once(DUPLICATOR_PLUGIN_PATH
|
4 |
-
require_once(DUPLICATOR_PLUGIN_PATH
|
5 |
-
require_once(DUPLICATOR_PLUGIN_PATH
|
6 |
-
require_once(DUPLICATOR_PLUGIN_PATH
|
|
|
|
|
7 |
|
8 |
/**
|
9 |
* DUPLICATOR_PACKAGE_SCAN
|
@@ -12,28 +16,29 @@ require_once(DUPLICATOR_PLUGIN_PATH . '/classes/package/class.pack.php');
|
|
12 |
* @return json JSON report object
|
13 |
* @example to test: /wp-admin/admin-ajax.php?action=duplicator_package_scan
|
14 |
*/
|
15 |
-
function duplicator_package_scan()
|
|
|
16 |
$nonce = sanitize_text_field($_REQUEST['nonce']);
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
die($json_response);
|
38 |
}
|
39 |
|
@@ -43,41 +48,146 @@ function duplicator_package_scan() {
|
|
43 |
*
|
44 |
* @return json JSON object of package results
|
45 |
*/
|
46 |
-
function duplicator_package_build()
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
check_ajax_referer( 'dup_package_build', 'nonce');
|
51 |
-
|
52 |
-
header('Content-Type: application/json');
|
53 |
-
|
54 |
-
@set_time_limit(0);
|
55 |
-
$errLevel = error_reporting();
|
56 |
-
error_reporting(E_ERROR);
|
57 |
-
DUP_Util::initSnapshotDirectory();
|
58 |
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
//die(0);
|
79 |
|
80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
die($json_response);
|
82 |
}
|
83 |
|
@@ -86,73 +196,79 @@ function duplicator_package_build() {
|
|
86 |
* Deletes the files and database record entries
|
87 |
*
|
88 |
* @return json A JSON message about the action.
|
89 |
-
*
|
90 |
*/
|
91 |
-
function duplicator_package_delete()
|
92 |
-
|
93 |
-
DUP_Util::hasCapability('export');
|
94 |
-
check_ajax_referer(
|
95 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
try {
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
|
|
105 |
if ($postIDs != null) {
|
106 |
-
|
107 |
foreach ($list as $id) {
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
$delCount++;
|
140 |
-
}
|
141 |
-
}
|
142 |
}
|
143 |
}
|
144 |
-
|
145 |
} catch (Exception $e) {
|
146 |
-
|
147 |
die(json_encode($json));
|
148 |
}
|
149 |
-
|
150 |
-
$json['ids'] = "{$postIDs}";
|
151 |
-
$json['removed'] = $delCount;
|
152 |
-
die(json_encode($json));
|
153 |
-
}
|
154 |
-
|
155 |
|
|
|
|
|
|
|
|
|
|
|
156 |
|
157 |
/**
|
158 |
* Controller for Tools
|
@@ -160,59 +276,211 @@ function duplicator_package_delete() {
|
|
160 |
*/
|
161 |
class DUP_CTRL_Package extends DUP_CTRL_Base
|
162 |
{
|
163 |
-
|
|
|
164 |
* Init this instance of the object
|
165 |
*/
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
|
|
171 |
|
172 |
-
|
173 |
* Removed all reserved installer files names
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
*/
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
|
|
184 |
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
|
|
|
|
193 |
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
|
|
|
|
198 |
|
199 |
-
|
200 |
-
|
|
|
201 |
|
202 |
-
|
203 |
-
$package = DUP_Package::getActive();
|
204 |
-
$payload['dirs-in'] = $post['dir_paths'];
|
205 |
-
$payload['dir-out'] = $package->Archive->FilterDirs;
|
206 |
-
$payload['files-in'] = $post['file_paths'];
|
207 |
-
$payload['files-out'] = $package->Archive->FilterFiles;
|
208 |
|
209 |
-
|
210 |
-
|
211 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
212 |
|
213 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
214 |
$result->processError($exc);
|
215 |
}
|
216 |
-
|
217 |
-
|
218 |
}
|
1 |
<?php
|
2 |
+
// Exit if accessed directly
|
3 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
4 |
|
5 |
+
require_once(DUPLICATOR_PLUGIN_PATH.'/ctrls/ctrl.base.php');
|
6 |
+
require_once(DUPLICATOR_PLUGIN_PATH.'/classes/utilities/class.u.scancheck.php');
|
7 |
+
require_once(DUPLICATOR_PLUGIN_PATH.'/classes/utilities/class.u.json.php');
|
8 |
+
require_once(DUPLICATOR_PLUGIN_PATH.'/classes/package/class.pack.php');
|
9 |
+
require_once(DUPLICATOR_PLUGIN_PATH.'/classes/package/duparchive/class.pack.archive.duparchive.state.create.php');
|
10 |
+
/* @var $package DUP_Package */
|
11 |
|
12 |
/**
|
13 |
* DUPLICATOR_PACKAGE_SCAN
|
16 |
* @return json JSON report object
|
17 |
* @example to test: /wp-admin/admin-ajax.php?action=duplicator_package_scan
|
18 |
*/
|
19 |
+
function duplicator_package_scan()
|
20 |
+
{
|
21 |
$nonce = sanitize_text_field($_REQUEST['nonce']);
|
22 |
+
if (!wp_verify_nonce($nonce, 'duplicator_package_scan')) {
|
23 |
+
die('An unathorized security request was made to this page. Please try again!');
|
24 |
+
}
|
25 |
+
|
26 |
+
header('Content-Type: application/json;');
|
27 |
+
DUP_Util::hasCapability('export');
|
28 |
+
|
29 |
+
@set_time_limit(0);
|
30 |
+
$errLevel = error_reporting();
|
31 |
+
error_reporting(E_ERROR);
|
32 |
+
DUP_Util::initSnapshotDirectory();
|
33 |
+
|
34 |
+
$package = DUP_Package::getActive();
|
35 |
+
$report = $package->runScanner();
|
36 |
+
|
37 |
+
$package->saveActiveItem('ScanFile', $package->ScanFile);
|
38 |
+
$json_response = DUP_JSON::safeEncode($report);
|
39 |
+
|
40 |
+
DUP_Package::tempFileCleanup();
|
41 |
+
error_reporting($errLevel);
|
42 |
die($json_response);
|
43 |
}
|
44 |
|
48 |
*
|
49 |
* @return json JSON object of package results
|
50 |
*/
|
51 |
+
function duplicator_package_build()
|
52 |
+
{
|
53 |
+
DUP_Util::hasCapability('export');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
|
55 |
+
check_ajax_referer('duplicator_package_build', 'nonce');
|
56 |
+
header('Content-Type: application/json');
|
57 |
+
|
58 |
+
@set_time_limit(0);
|
59 |
+
$errLevel = error_reporting();
|
60 |
+
error_reporting(E_ERROR);
|
61 |
+
DUP_Util::initSnapshotDirectory();
|
62 |
+
|
63 |
+
$Package = DUP_Package::getActive();
|
64 |
+
$Package->save('zip');
|
65 |
+
|
66 |
+
DUP_Settings::Set('active_package_id', $Package->ID);
|
67 |
+
DUP_Settings::Save();
|
68 |
+
|
69 |
+
if (!is_readable(DUPLICATOR_SSDIR_PATH_TMP."/{$Package->ScanFile}")) {
|
70 |
+
die("The scan result file was not found. Please run the scan step before building the package.");
|
71 |
+
}
|
72 |
+
|
73 |
+
$Package->runZipBuild();
|
74 |
+
|
75 |
+
//JSON:Debug Response
|
76 |
+
//Pass = 1, Warn = 2, Fail = 3
|
77 |
+
$json = array();
|
78 |
+
$json['status'] = 1;
|
79 |
+
$json['package'] = $Package;
|
80 |
+
$json['runtime'] = $Package->Runtime;
|
81 |
+
$json['exeSize'] = $Package->ExeSize;
|
82 |
+
$json['archiveSize'] = $Package->ZipSize;
|
83 |
+
$json_response = json_encode($json);
|
84 |
+
|
85 |
+
//Simulate a Host Build Interrupt
|
86 |
//die(0);
|
87 |
|
88 |
+
error_reporting($errLevel);
|
89 |
+
die($json_response);
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Returns the package result status
|
94 |
+
*
|
95 |
+
* @return json JSON object of package results
|
96 |
+
*/
|
97 |
+
function duplicator_duparchive_package_build()
|
98 |
+
{
|
99 |
+
DUP_LOG::Trace("call to duplicator_duparchive_package_build");
|
100 |
+
|
101 |
+
DUP_Util::hasCapability('export');
|
102 |
+
check_ajax_referer('duplicator_duparchive_package_build', 'nonce');
|
103 |
+
header('Content-Type: application/json');
|
104 |
+
|
105 |
+
@set_time_limit(0);
|
106 |
+
$errLevel = error_reporting();
|
107 |
+
error_reporting(E_ERROR);
|
108 |
+
|
109 |
+
// The DupArchive build process always works on a saved package so the first time through save the active package to the package table.
|
110 |
+
// After that, just retrieve it.
|
111 |
+
$active_package_id = DUP_Settings::Get('active_package_id');
|
112 |
+
|
113 |
+
if ($active_package_id == -1) {
|
114 |
+
|
115 |
+
$package = DUP_Package::getActive();
|
116 |
+
$package->save('daf');
|
117 |
+
DUP_Log::TraceObject("saving active package as new id={$package->ID}", package);
|
118 |
+
DUP_Settings::Set('active_package_id', $package->ID);
|
119 |
+
DUP_Settings::Save();
|
120 |
+
} else {
|
121 |
+
|
122 |
+
DUP_Log::TraceObject("getting active package by id {$active_package_id}", package);
|
123 |
+
$package = DUP_Package::getByID($active_package_id);
|
124 |
+
}
|
125 |
+
|
126 |
+
if (!is_readable(DUPLICATOR_SSDIR_PATH_TMP."/{$package->ScanFile}")) {
|
127 |
+
die("The scan result file was not found. Please run the scan step before building the package.");
|
128 |
+
}
|
129 |
+
|
130 |
+
if ($package === null) {
|
131 |
+
die("There is no active package.");
|
132 |
+
}
|
133 |
+
|
134 |
+
if($package->Status == DUP_PackageStatus::ERROR) {
|
135 |
+
$hasCompleted = true;
|
136 |
+
} else {
|
137 |
+
try {
|
138 |
+
$hasCompleted = $package->runDupArchiveBuild();
|
139 |
+
}
|
140 |
+
catch(Exception $ex) {
|
141 |
+
Dup_Log::Trace('#### caught exception');
|
142 |
+
Dup_Log::Error('Caught exception', $ex->getMessage(), Dup_ErrorBehavior::LogOnly);
|
143 |
+
Dup_Log::Trace('#### after log');
|
144 |
+
$package->setStatus(DUP_PackageStatus::ERROR);
|
145 |
+
$hasCompleted = true;
|
146 |
+
}
|
147 |
+
}
|
148 |
+
|
149 |
+
$json = array();
|
150 |
+
$json['failures'] = array_merge($package->BuildProgress->build_failures, $package->BuildProgress->validation_failures);
|
151 |
+
DUP_LOG::traceObject("#### failures", $json['failures']);
|
152 |
+
|
153 |
+
//JSON:Debug Response
|
154 |
+
//Pass = 1, Warn = 2, 3 = Failure, 4 = Not Done
|
155 |
+
if ($hasCompleted) {
|
156 |
+
|
157 |
+
Dup_Log::Trace('#### completed');
|
158 |
+
|
159 |
+
if($package->Status == DUP_PackageStatus::ERROR) {
|
160 |
+
|
161 |
+
Dup_Log::Trace('#### error');
|
162 |
+
$error_message = __('Error building DupArchive package') . '<br/>';
|
163 |
+
|
164 |
+
foreach($json['failures'] as $failure) {
|
165 |
+
$error_message .= implode(',', $failure->description);
|
166 |
+
}
|
167 |
+
|
168 |
+
Dup_Log::Error("Build failed so sending back error", esc_html($error_message), Dup_ErrorBehavior::LogOnly);
|
169 |
+
Dup_Log::Trace('#### after log 2');
|
170 |
+
|
171 |
+
$json['status'] = 3;
|
172 |
+
} else {
|
173 |
+
Dup_Log::Info("sending back success status");
|
174 |
+
$json['status'] = 1;
|
175 |
+
}
|
176 |
+
|
177 |
+
Dup_Log::Trace('#### json package');
|
178 |
+
$json['package'] = $package;
|
179 |
+
$json['runtime'] = $package->Runtime;
|
180 |
+
$json['exeSize'] = $package->ExeSize;
|
181 |
+
$json['archiveSize'] = $package->ZipSize;
|
182 |
+
} else {
|
183 |
+
Dup_Log::Info("sending back continue status");
|
184 |
+
$json['status'] = 4;
|
185 |
+
}
|
186 |
+
|
187 |
+
$json_response = json_encode($json);
|
188 |
+
|
189 |
+
Dup_Log::TraceObject('json response', $json_response);
|
190 |
+
error_reporting($errLevel);
|
191 |
die($json_response);
|
192 |
}
|
193 |
|
196 |
* Deletes the files and database record entries
|
197 |
*
|
198 |
* @return json A JSON message about the action.
|
199 |
+
* Use console.log to debug from client
|
200 |
*/
|
201 |
+
function duplicator_package_delete()
|
202 |
+
{
|
203 |
+
DUP_Util::hasCapability('export');
|
204 |
+
check_ajax_referer('package_list', 'nonce');
|
205 |
+
|
206 |
+
function _unlinkFile($file) {
|
207 |
+
if (! file_exists($file)) {
|
208 |
+
return;
|
209 |
+
}
|
210 |
+
if (! @unlink($file)) {
|
211 |
+
@chmod($file, 0644);
|
212 |
+
@unlink($file);
|
213 |
+
}
|
214 |
+
}
|
215 |
+
|
216 |
try {
|
217 |
+
global $wpdb;
|
218 |
+
$json = array();
|
219 |
+
$post = stripslashes_deep($_POST);
|
220 |
+
$tablePrefix = DUP_Util::getTablePrefix();
|
221 |
+
$tblName = $tablePrefix.'duplicator_packages';
|
222 |
+
$postIDs = isset($post['duplicator_delid']) ? sanitize_text_field($post['duplicator_delid']) : null;
|
223 |
+
$list = explode(",", $postIDs);
|
224 |
+
$delCount = 0;
|
225 |
+
|
226 |
if ($postIDs != null) {
|
227 |
+
|
228 |
foreach ($list as $id) {
|
229 |
+
|
230 |
+
$getResult = $wpdb->get_results($wpdb->prepare("SELECT name, hash FROM `{$tblName}` WHERE id = %d", $id), ARRAY_A);
|
231 |
+
|
232 |
+
if ($getResult) {
|
233 |
+
$row = $getResult[0];
|
234 |
+
$nameHash = "{$row['name']}_{$row['hash']}";
|
235 |
+
$delResult = $wpdb->query($wpdb->prepare("DELETE FROM `{$tblName}` WHERE id = %d", $id));
|
236 |
+
if ($delResult != 0) {
|
237 |
+
|
238 |
+
//TMP FILES
|
239 |
+
_unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}_archive.daf"));
|
240 |
+
_unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}_archive.zip"));
|
241 |
+
_unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}_database.sql"));
|
242 |
+
_unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}_installer.php"));
|
243 |
+
|
244 |
+
//WP-SNAPSHOT FILES
|
245 |
+
_unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_archive.daf"));
|
246 |
+
_unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_archive.zip"));
|
247 |
+
_unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_database.sql"));
|
248 |
+
_unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_installer.php"));
|
249 |
+
_unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_scan.json"));
|
250 |
+
_unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}.log"));
|
251 |
+
|
252 |
+
//Unfinished Zip files
|
253 |
+
$tmpZip = DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}_archive.zip.*";
|
254 |
+
if ($tmpZip !== false) {
|
255 |
+
array_map('unlink', glob($tmpZip));
|
256 |
+
}
|
257 |
+
$delCount++;
|
258 |
+
}
|
259 |
+
}
|
|
|
|
|
|
|
260 |
}
|
261 |
}
|
|
|
262 |
} catch (Exception $e) {
|
263 |
+
$json['error'] = "{$e}";
|
264 |
die(json_encode($json));
|
265 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
266 |
|
267 |
+
$json['ids'] = "{$postIDs}";
|
268 |
+
$json['removed'] = $delCount;
|
269 |
+
echo json_encode($json);
|
270 |
+
die();
|
271 |
+
}
|
272 |
|
273 |
/**
|
274 |
* Controller for Tools
|
276 |
*/
|
277 |
class DUP_CTRL_Package extends DUP_CTRL_Base
|
278 |
{
|
279 |
+
|
280 |
+
/**
|
281 |
* Init this instance of the object
|
282 |
*/
|
283 |
+
function __construct()
|
284 |
+
{
|
285 |
+
add_action('wp_ajax_DUP_CTRL_Package_addQuickFilters', array($this, 'addQuickFilters'));
|
286 |
+
add_action('wp_ajax_DUP_CTRL_Package_getPackageFile', array($this, 'getPackageFile'));
|
287 |
+
add_action('wp_ajax_DUP_CTRL_Package_getActivePackageStatus', array($this, 'getActivePackageStatus'));
|
288 |
+
}
|
289 |
|
290 |
+
/**
|
291 |
* Removed all reserved installer files names
|
292 |
+
*
|
293 |
+
* @param string $_POST['dir_paths'] A semi-colon separated list of directory paths
|
294 |
+
*
|
295 |
+
* @return string Returns all of the active directory filters as a ";" separated string
|
296 |
*/
|
297 |
+
public function addQuickFilters($post)
|
298 |
+
{
|
299 |
+
$post = $this->postParamMerge($post);
|
300 |
+
$action = sanitize_text_field($post['action']);
|
301 |
+
check_ajax_referer($action, 'nonce');
|
302 |
+
$result = new DUP_CTRL_Result($this);
|
303 |
|
304 |
+
try {
|
305 |
+
//CONTROLLER LOGIC
|
306 |
+
$package = DUP_Package::getActive();
|
307 |
|
308 |
+
//DIRS
|
309 |
+
$dir_filters = ($package->Archive->FilterOn)
|
310 |
+
? $package->Archive->FilterDirs.';'.sanitize_text_field($post['dir_paths'])
|
311 |
+
: sanitize_text_field($post['dir_paths']);
|
312 |
+
$dir_filters = $package->Archive->parseDirectoryFilter($dir_filters);
|
313 |
+
$changed = $package->Archive->saveActiveItem($package, 'FilterDirs', $dir_filters);
|
314 |
|
315 |
+
//FILES
|
316 |
+
$file_filters = ($package->Archive->FilterOn)
|
317 |
+
? $package->Archive->FilterFiles.';'.sanitize_text_field($post['file_paths'])
|
318 |
+
: sanitize_text_field($post['file_paths']);
|
319 |
+
$file_filters = $package->Archive->parseFileFilter($file_filters);
|
320 |
+
$changed = $package->Archive->saveActiveItem($package, 'FilterFiles', $file_filters);
|
321 |
|
322 |
+
if (!$package->Archive->FilterOn && !empty($package->Archive->FilterExts)) {
|
323 |
+
$changed = $package->Archive->saveActiveItem($package, 'FilterExts', '');
|
324 |
+
}
|
325 |
|
326 |
+
$changed = $package->Archive->saveActiveItem($package, 'FilterOn', 1);
|
|
|
|
|
|
|
|
|
|
|
327 |
|
328 |
+
//Result
|
329 |
+
$package = DUP_Package::getActive();
|
330 |
+
$payload['dirs-in'] = esc_html(sanitize_text_field($post['dir_paths']));
|
331 |
+
$payload['dir-out'] = esc_html($package->Archive->FilterDirs);
|
332 |
+
$payload['files-in'] = esc_html(sanitize_text_field($post['file_paths']));
|
333 |
+
$payload['files-out'] = esc_html($package->Archive->FilterFiles);
|
334 |
+
|
335 |
+
//RETURN RESULT
|
336 |
+
$test = ($changed) ? DUP_CTRL_Status::SUCCESS : DUP_CTRL_Status::FAILED;
|
337 |
+
$result->process($payload, $test);
|
338 |
+
} catch (Exception $exc) {
|
339 |
+
$result->processError($exc);
|
340 |
+
}
|
341 |
+
}
|
342 |
+
|
343 |
+
/**
|
344 |
+
* Download the requested package file
|
345 |
+
*
|
346 |
+
* @param string $_POST['which']
|
347 |
+
* @param string $_POST['package_id']
|
348 |
+
*
|
349 |
+
* @return downloadable file
|
350 |
+
*/
|
351 |
+
function getPackageFile($post)
|
352 |
+
{
|
353 |
+
$params = $this->postParamMerge($post);
|
354 |
|
355 |
+
$nonce = sanitize_text_field($_GET['nonce']);
|
356 |
+
if (!wp_verify_nonce($nonce, 'DUP_CTRL_Package_getPackageFile')) {
|
357 |
+
die('An unathorized security request was made to this page. Please try again!');
|
358 |
+
}
|
359 |
+
|
360 |
+
$params = $this->getParamMerge($params);
|
361 |
+
// check_ajax_referer($post['action'], 'nonce');
|
362 |
+
|
363 |
+
$result = new DUP_CTRL_Result($this);
|
364 |
+
|
365 |
+
try {
|
366 |
+
//CONTROLLER LOGIC
|
367 |
+
|
368 |
+
DUP_Util::hasCapability('export');
|
369 |
+
|
370 |
+
$request = stripslashes_deep($_REQUEST);
|
371 |
+
$which = (int) $request['which'];
|
372 |
+
$packageId = (int) $request['package_id'];
|
373 |
+
$package = DUP_Package::getByID($packageId);
|
374 |
+
$isBinary = ($which != DUP_PackageFileType::Log);
|
375 |
+
$filePath = $package->getLocalPackageFile($which);
|
376 |
+
|
377 |
+
//OUTPUT: Installer, Archive, SQL File
|
378 |
+
if ($isBinary) {
|
379 |
+
header("Pragma: public");
|
380 |
+
header("Expires: 0");
|
381 |
+
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
|
382 |
+
header("Cache-Control: private", false);
|
383 |
+
header("Content-Transfer-Encoding: binary");
|
384 |
+
|
385 |
+
if ($filePath != null) {
|
386 |
+
$fp = fopen($filePath, 'rb');
|
387 |
+
if ($fp !== false) {
|
388 |
+
|
389 |
+
if ($which == DUP_PackageFileType::Installer) {
|
390 |
+
$fileName = 'installer.php';
|
391 |
+
} else {
|
392 |
+
$fileName = basename($filePath);
|
393 |
+
}
|
394 |
+
|
395 |
+
header("Content-Type: application/octet-stream");
|
396 |
+
header("Content-Disposition: attachment; filename=\"{$fileName}\";");
|
397 |
+
|
398 |
+
@ob_end_clean(); // required or large files wont work
|
399 |
+
DUP_Log::Trace("streaming $filePath");
|
400 |
+
|
401 |
+
if (fpassthru($fp) === false) {
|
402 |
+
DUP_Log::Trace("Error with fpassthru for {$filePath}");
|
403 |
+
}
|
404 |
+
fclose($fp);
|
405 |
+
die(); //Supress additional ouput
|
406 |
+
} else {
|
407 |
+
header("Content-Type: text/plain");
|
408 |
+
header("Content-Disposition: attachment; filename=\"error.txt\";");
|
409 |
+
$message = "Couldn't open $filePath.";
|
410 |
+
DUP_Log::Trace($message);
|
411 |
+
echo esc_html($message);
|
412 |
+
}
|
413 |
+
} else {
|
414 |
+
$message = __("Couldn't find a local copy of the file requested.", 'duplicator');
|
415 |
+
|
416 |
+
header("Content-Type: text/plain");
|
417 |
+
header("Content-Disposition: attachment; filename=\"error.txt\";");
|
418 |
+
|
419 |
+
// Report that we couldn't find the file
|
420 |
+
DUP_Log::Trace($message);
|
421 |
+
echo esc_html($message);
|
422 |
+
}
|
423 |
+
|
424 |
+
//OUTPUT: Log File
|
425 |
+
} else {
|
426 |
+
if ($filePath != null) {
|
427 |
+
header("Content-Type: text/plain");
|
428 |
+
$text = file_get_contents($filePath);
|
429 |
+
|
430 |
+
die($text);
|
431 |
+
} else {
|
432 |
+
$message = __("Couldn't find a local copy of the file requested.", 'duplicator');
|
433 |
+
echo esc_html($message);
|
434 |
+
}
|
435 |
+
}
|
436 |
+
} catch (Exception $exc) {
|
437 |
+
$result->processError($exc);
|
438 |
+
}
|
439 |
+
}
|
440 |
+
|
441 |
+
/**
|
442 |
+
* Get active package status
|
443 |
+
*
|
444 |
+
* <code>
|
445 |
+
* //JavaScript Ajax Request
|
446 |
+
* Duplicator.Package.getActivePackageStatus()
|
447 |
+
* </code>
|
448 |
+
*/
|
449 |
+
public function getActivePackageStatus($post)
|
450 |
+
{
|
451 |
+
$post = $this->postParamMerge($post);
|
452 |
+
$nonce = sanitize_text_field($post['nonce']);
|
453 |
+
if (!wp_verify_nonce($nonce, 'DUP_CTRL_Package_getActivePackageStatus')) {
|
454 |
+
die('An unathorized security request was made to this page. Please try again!');
|
455 |
+
}
|
456 |
+
$result = new DUP_CTRL_Result($this);
|
457 |
+
|
458 |
+
try
|
459 |
+
{
|
460 |
+
//CONTROLLER LOGIC
|
461 |
+
$post = stripslashes_deep($_POST);
|
462 |
+
|
463 |
+
$active_package_id = DUP_Settings::Get('active_package_id');
|
464 |
+
|
465 |
+
$package = DUP_Package::getByID($active_package_id);
|
466 |
+
|
467 |
+
$payload = array();
|
468 |
+
|
469 |
+
if($package != null) {
|
470 |
+
$test = DUP_CTRL_Status::SUCCESS;
|
471 |
+
|
472 |
+
$payload['status'] = $package->Status;
|
473 |
+
} else {
|
474 |
+
$test = DUP_CTRL_Status::FAILED;
|
475 |
+
}
|
476 |
+
|
477 |
+
//RETURN RESULT
|
478 |
+
return $result->process($payload, $test);
|
479 |
+
}
|
480 |
+
catch (Exception $exc)
|
481 |
+
{
|
482 |
$result->processError($exc);
|
483 |
}
|
484 |
+
}
|
485 |
+
|
486 |
}
|
ctrls/ctrl.tools.php
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
<?php
|
2 |
-
|
|
|
3 |
|
4 |
require_once(DUPLICATOR_PLUGIN_PATH . '/ctrls/ctrl.base.php');
|
5 |
require_once(DUPLICATOR_PLUGIN_PATH . '/classes/utilities/class.u.scancheck.php');
|
@@ -16,6 +17,7 @@ class DUP_CTRL_Tools extends DUP_CTRL_Base
|
|
16 |
function __construct()
|
17 |
{
|
18 |
add_action('wp_ajax_DUP_CTRL_Tools_runScanValidator', array($this, 'runScanValidator'));
|
|
|
19 |
}
|
20 |
|
21 |
/**
|
@@ -29,20 +31,26 @@ class DUP_CTRL_Tools extends DUP_CTRL_Base
|
|
29 |
public function runScanValidator($post)
|
30 |
{
|
31 |
@set_time_limit(0);
|
32 |
-
|
33 |
-
|
|
|
34 |
|
35 |
$result = new DUP_CTRL_Result($this);
|
36 |
|
37 |
try
|
38 |
{
|
39 |
//CONTROLLER LOGIC
|
40 |
-
$path = isset($post['scan-path']) ? sanitize_text_field($post['scan-path']) :
|
41 |
if (!is_dir($path)) {
|
42 |
throw new Exception("Invalid directory provided '{$path}'!");
|
43 |
}
|
44 |
-
|
45 |
-
|
|
|
|
|
|
|
|
|
|
|
46 |
$payload = $scanner->run($path);
|
47 |
|
48 |
//RETURN RESULT
|
@@ -56,4 +64,67 @@ class DUP_CTRL_Tools extends DUP_CTRL_Base
|
|
56 |
$result->processError($exc);
|
57 |
}
|
58 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
}
|
1 |
<?php
|
2 |
+
// Exit if accessed directly
|
3 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
4 |
|
5 |
require_once(DUPLICATOR_PLUGIN_PATH . '/ctrls/ctrl.base.php');
|
6 |
require_once(DUPLICATOR_PLUGIN_PATH . '/classes/utilities/class.u.scancheck.php');
|
17 |
function __construct()
|
18 |
{
|
19 |
add_action('wp_ajax_DUP_CTRL_Tools_runScanValidator', array($this, 'runScanValidator'));
|
20 |
+
add_action('wp_ajax_DUP_CTRL_Tools_getTraceLog', array($this, 'getTraceLog'));
|
21 |
}
|
22 |
|
23 |
/**
|
31 |
public function runScanValidator($post)
|
32 |
{
|
33 |
@set_time_limit(0);
|
34 |
+
$post = $this->postParamMerge($post);
|
35 |
+
$action = sanitize_text_field($post['action']);
|
36 |
+
check_ajax_referer($action, 'nonce');
|
37 |
|
38 |
$result = new DUP_CTRL_Result($this);
|
39 |
|
40 |
try
|
41 |
{
|
42 |
//CONTROLLER LOGIC
|
43 |
+
$path = isset($post['scan-path']) ? sanitize_text_field($post['scan-path']) : DUPLICATOR_WPROOTPATH;
|
44 |
if (!is_dir($path)) {
|
45 |
throw new Exception("Invalid directory provided '{$path}'!");
|
46 |
}
|
47 |
+
$scanner = new DUP_ScanCheck();
|
48 |
+
if (isset($post['scan-recursive'])) {
|
49 |
+
$scan_recursive_val = sanitize_text_field($post['scan-recursive']);
|
50 |
+
$scan_recursive = ($scan_recursive_val != 'false');
|
51 |
+
}
|
52 |
+
|
53 |
+
$scanner->recursion = $scan_recursive ? true : false;
|
54 |
$payload = $scanner->run($path);
|
55 |
|
56 |
//RETURN RESULT
|
64 |
$result->processError($exc);
|
65 |
}
|
66 |
}
|
67 |
+
|
68 |
+
public function getTraceLog()
|
69 |
+
{
|
70 |
+
DUP_Log::Trace("enter");
|
71 |
+
|
72 |
+
$nonce = sanitize_text_field($_GET['nonce']);
|
73 |
+
if (!wp_verify_nonce($nonce, 'DUP_CTRL_Tools_getTraceLog')) {
|
74 |
+
die('An unathorized security request was made to this page. Please try again!');
|
75 |
+
}
|
76 |
+
|
77 |
+
Dup_Util::hasCapability('export');
|
78 |
+
|
79 |
+
$request = stripslashes_deep($_REQUEST);
|
80 |
+
$file_path = DUP_Log::GetTraceFilepath();
|
81 |
+
$backup_path = DUP_Log::GetBackupTraceFilepath();
|
82 |
+
$zip_path = DUPLICATOR_SSDIR_PATH."/".DUPLICATOR_ZIPPED_LOG_FILENAME;
|
83 |
+
$zipped = DUP_Zip_U::zipFile($file_path, $zip_path, true, null, true);
|
84 |
+
|
85 |
+
if ($zipped && file_exists($backup_path)) {
|
86 |
+
$zipped = DUP_Zip_U::zipFile($backup_path, $zip_path, false, null, true);
|
87 |
+
}
|
88 |
+
|
89 |
+
header("Pragma: public");
|
90 |
+
header("Expires: 0");
|
91 |
+
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
|
92 |
+
header("Cache-Control: private", false);
|
93 |
+
header("Content-Transfer-Encoding: binary");
|
94 |
+
|
95 |
+
$fp = fopen($zip_path, 'rb');
|
96 |
+
|
97 |
+
if (($fp !== false) && $zipped) {
|
98 |
+
$zip_filename = basename($zip_path);
|
99 |
+
|
100 |
+
header("Content-Type: application/octet-stream");
|
101 |
+
header("Content-Disposition: attachment; filename=\"$zip_filename\";");
|
102 |
+
|
103 |
+
// required or large files wont work
|
104 |
+
if (ob_get_length()) {
|
105 |
+
ob_end_clean();
|
106 |
+
}
|
107 |
+
|
108 |
+
DUP_Log::trace("streaming $zip_path");
|
109 |
+
if (fpassthru($fp) === false) {
|
110 |
+
DUP_Log::trace("Error with fpassthru for $zip_path");
|
111 |
+
}
|
112 |
+
|
113 |
+
fclose($fp);
|
114 |
+
@unlink($zip_path);
|
115 |
+
} else {
|
116 |
+
header("Content-Type: text/plain");
|
117 |
+
header("Content-Disposition: attachment; filename=\"error.txt\";");
|
118 |
+
if ($zipped === false) {
|
119 |
+
$message = "Couldn't create zip file.";
|
120 |
+
} else {
|
121 |
+
$message = "Couldn't open $file_path.";
|
122 |
+
}
|
123 |
+
DUP_Log::trace($message);
|
124 |
+
echo esc_html($message);
|
125 |
+
}
|
126 |
+
|
127 |
+
exit;
|
128 |
+
}
|
129 |
+
|
130 |
}
|
ctrls/ctrl.ui.php
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
<?php
|
2 |
-
|
|
|
3 |
|
4 |
require_once(DUPLICATOR_PLUGIN_PATH . '/ctrls/ctrl.base.php');
|
5 |
require_once(DUPLICATOR_PLUGIN_PATH . '/classes/ui/class.ui.viewstate.php');
|
@@ -42,9 +43,10 @@ class DUP_CTRL_UI extends DUP_CTRL_Base
|
|
42 |
|
43 |
$nonce = sanitize_text_field($post['nonce']);
|
44 |
if (!wp_verify_nonce($nonce, 'DUP_CTRL_UI_SaveViewState')) {
|
45 |
-
die('
|
46 |
}
|
47 |
|
|
|
48 |
$result = new DUP_CTRL_Result($this);
|
49 |
|
50 |
try
|
@@ -84,13 +86,6 @@ class DUP_CTRL_UI extends DUP_CTRL_Base
|
|
84 |
*/
|
85 |
public function GetViewStateList()
|
86 |
{
|
87 |
-
if (isset($_REQUEST['nonce'])) {
|
88 |
-
$nonce = sanitize_text_field($_REQUEST['nonce']);
|
89 |
-
if (!wp_verify_nonce($nonce, 'DUP_CTRL_UI_GetViewStateList')) {
|
90 |
-
die('Security check disrupted, please return to packages screen.');
|
91 |
-
}
|
92 |
-
}
|
93 |
-
|
94 |
$result = new DUP_CTRL_Result($this);
|
95 |
|
96 |
try
|
1 |
<?php
|
2 |
+
// Exit if accessed directly
|
3 |
+
if (! defined('DUPLICATOR_VERSION')) exit;
|
4 |
|
5 |
require_once(DUPLICATOR_PLUGIN_PATH . '/ctrls/ctrl.base.php');
|
6 |
require_once(DUPLICATOR_PLUGIN_PATH . '/classes/ui/class.ui.viewstate.php');
|
43 |
|
44 |
$nonce = sanitize_text_field($post['nonce']);
|
45 |
if (!wp_verify_nonce($nonce, 'DUP_CTRL_UI_SaveViewState')) {
|
46 |
+
die('An unathorized security request was made to this page. Please try again!');
|
47 |
}
|
48 |
|
49 |
+
|
50 |
$result = new DUP_CTRL_Result($this);
|
51 |
|
52 |
try
|
86 |
*/
|
87 |
public function GetViewStateList()
|
88 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
$result = new DUP_CTRL_Result($this);
|
90 |
|
91 |
try
|
debug/main.php
DELETED
@@ -1,191 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
DUP_Util::hasCapability('read');
|
3 |
-
|
4 |
-
require_once(DUPLICATOR_PLUGIN_PATH . '/assets/js/javascript.php');
|
5 |
-
require_once(DUPLICATOR_PLUGIN_PATH . '/views/inc.header.php');
|
6 |
-
|
7 |
-
|
8 |
-
function DUP_DEBUG_TestSetup($CTRL)
|
9 |
-
{
|
10 |
-
$title = $CTRL['Title'];
|
11 |
-
$action = $CTRL['Action'];
|
12 |
-
$testable = $CTRL['Test'] ? 1 : 0;
|
13 |
-
$test_css = $testable ? '' : 'style="display:none"';
|
14 |
-
$nonce = wp_create_nonce($action);
|
15 |
-
|
16 |
-
$html = '
|
17 |
-
<div class="keys">
|
18 |
-
<input type="hidden" name="testable" value="'.esc_attr($testable).'" />
|
19 |
-
<input type="hidden" name="action" value="'.esc_attr($action).'" />
|
20 |
-
<input type="hidden" name="nonce" value="'.esc_attr($nonce).'" />
|
21 |
-
<span class="result"><i class="fa fa-cube fa-lg"></i></span>
|
22 |
-
<input type="checkbox" id="'.esc_attr($action).'" name="'.esc_attr($action).'" '.$test_css.' />
|
23 |
-
<label for="'.esc_attr($action).'">'.esc_html($title).'</label>
|
24 |
-
<a href="javascript:void(0)" onclick=\'jQuery(this).closest("form").find("div.params").toggle()\'>Params</a> |
|
25 |
-
<a href="javascript:void(0)" onclick="jQuery(this).closest("form").submit()">Test</a>
|
26 |
-
</div>';
|
27 |
-
echo $html;
|
28 |
-
}
|
29 |
-
|
30 |
-
?>
|
31 |
-
<style>
|
32 |
-
div.debug-area {line-height: 26px}
|
33 |
-
table.debug-toolbar {width:100%; margin: 3px 0 -10px -5px; }
|
34 |
-
table.debug-toolbar td {padding:3px; white-space: nowrap}
|
35 |
-
table.debug-toolbar td:last-child {width: 100%}
|
36 |
-
|
37 |
-
div.debug-area form {margin: 15px 0 0 0; border-top: 1px solid #dfdfdf; padding-top: 5px}
|
38 |
-
div.debug-area div.keys label {font-weight: bold; font-size: 14px; padding-right: 5px }
|
39 |
-
div.debug-area div.params label {width:150px; display:inline-block}
|
40 |
-
div.debug-area input[type=text] {width:400px}
|
41 |
-
|
42 |
-
div.section-hdr {margin:35px 0 0 0; font-size: 16px; font-weight: bold; border:1px solid silver; border-radius: 3px; padding:1px 5px 1px 5px; background: #dfdfdf;}
|
43 |
-
div.params {display:none}
|
44 |
-
i.result-pass {color:green}
|
45 |
-
i.result-fail {color:red}
|
46 |
-
</style>
|
47 |
-
|
48 |
-
<script>
|
49 |
-
var UNIT_TEST_FORMS;
|
50 |
-
var UNIT_TEST_CHKBOXES;
|
51 |
-
var UNIT_TEST_PASSED;
|
52 |
-
var UNIT_TEST_COUNTER;
|
53 |
-
var UNIT_TEST_RUNNING = false;
|
54 |
-
</script>
|
55 |
-
|
56 |
-
<div class="wrap dup-wrap dup-support-all">
|
57 |
-
<h1><?php esc_html_e('Testing Interface', 'duplicator'); ?></h1>
|
58 |
-
<hr size="1" />
|
59 |
-
|
60 |
-
<table class="debug-toolbar">
|
61 |
-
<tr>
|
62 |
-
<td>
|
63 |
-
<span id="results-all"><i class="fa fa-cube fa-lg"></i></span>
|
64 |
-
<input id="test-checkall" type="checkbox" onclick="Duplicator.Debug.CheckAllTests()">
|
65 |
-
</td>
|
66 |
-
<td>
|
67 |
-
<input type="button" class="button button-small" value="<?php esc_attr_e('Run Tests', 'duplicator'); ?>" onclick="Duplicator.Debug.RunTests()" />
|
68 |
-
<input type="button" class="button button-small" value="<?php esc_html_e('Refresh Page', 'duplicator'); ?>" onclick="window.location.reload();" />
|
69 |
-
</td>
|
70 |
-
<td> <input type="checkbox" id="test-openwindow" onchange="Duplicator.Debug.TestNewWindow()" /> <label for="test-openwindow">Tests in new window</label> </td>
|
71 |
-
</tr>
|
72 |
-
</table>
|
73 |
-
|
74 |
-
<div class="debug-area">
|
75 |
-
<?php
|
76 |
-
include_once 'tst.tools.php';
|
77 |
-
include_once 'tst.ui.php';
|
78 |
-
include_once 'tst.packages.php';
|
79 |
-
?>
|
80 |
-
</div>
|
81 |
-
</div>
|
82 |
-
|
83 |
-
<script>
|
84 |
-
jQuery(document).ready(function($)
|
85 |
-
{
|
86 |
-
//Run test on all checked options
|
87 |
-
Duplicator.Debug.RunTests = function()
|
88 |
-
{
|
89 |
-
try
|
90 |
-
{
|
91 |
-
UNIT_TEST_RUNNING = true;
|
92 |
-
UNIT_TEST_PASSED = true;
|
93 |
-
UNIT_TEST_COUNTER = 0;
|
94 |
-
UNIT_TEST_CHKBOXES = $("div.keys input[type='checkbox']:checked").length;
|
95 |
-
UNIT_TEST_FORMS = $("div.keys input[name='testable'][value='1']").closest('form');
|
96 |
-
|
97 |
-
$(UNIT_TEST_FORMS).each(function(index)
|
98 |
-
{
|
99 |
-
var $form = $(this);
|
100 |
-
var $result = $form.find('span.result');
|
101 |
-
var $check = $form.find('div.keys input[type="checkbox"]');
|
102 |
-
var input;
|
103 |
-
|
104 |
-
if ($check.is(':checked'))
|
105 |
-
{
|
106 |
-
$('#results-all').html('<i class="fa fa-cog fa-spin fa-fw fa-lg"></i>');
|
107 |
-
$result.html('<i class="fa fa-circle-o-notch fa-spin fa-fw fa-lg"></i>');
|
108 |
-
|
109 |
-
//Run any callbacks if defined
|
110 |
-
if ($form.attr("onsubmit") != undefined) {
|
111 |
-
$form.submit();
|
112 |
-
}
|
113 |
-
input = $form.serialize();
|
114 |
-
|
115 |
-
$.ajax({
|
116 |
-
type: "POST",
|
117 |
-
url: ajaxurl,
|
118 |
-
dataType: "json",
|
119 |
-
data: input,
|
120 |
-
success: function(data) { Duplicator.Debug.ProcessResult(data, $result) },
|
121 |
-
error: function(data) {},
|
122 |
-
done: function(data) {}
|
123 |
-
});
|
124 |
-
}
|
125 |
-
});
|
126 |
-
}
|
127 |
-
catch (e) {
|
128 |
-
console.log(e);
|
129 |
-
} finally {
|
130 |
-
UNIT_TEST_RUNNING = false;
|
131 |
-
}
|
132 |
-
}
|
133 |
-
|
134 |
-
//Call back used to test the status of a result
|
135 |
-
Duplicator.Debug.ProcessResult = function(data, result)
|
136 |
-
{
|
137 |
-
UNIT_TEST_COUNTER++;
|
138 |
-
var status = data.report.status || 0;
|
139 |
-
//console.log(data);
|
140 |
-
|
141 |
-
if (status > 0) {
|
142 |
-
result.html('<i class="fa fa-check-circle fa-lg result-pass"></i>');
|
143 |
-
} else {
|
144 |
-
UNIT_TEST_PASSED = false;
|
145 |
-
result.html('<i class="fa fa-check-circle fa-lg result-fail"></i>');
|
146 |
-
}
|
147 |
-
|
148 |
-
//Set after all tests have ran
|
149 |
-
if (UNIT_TEST_COUNTER >= UNIT_TEST_CHKBOXES) {
|
150 |
-
(UNIT_TEST_PASSED)
|
151 |
-
? $('#results-all').html('<i class="fa fa-check-circle fa-lg result-pass"></i>')
|
152 |
-
: $('#results-all').html('<i class="fa fa-check-circle fa-lg result-fail"></i>');
|
153 |
-
}
|
154 |
-
}
|
155 |
-
|
156 |
-
//Check all of the check boxes
|
157 |
-
Duplicator.Debug.CheckAllTests = function()
|
158 |
-
{
|
159 |
-
var checkAll = $('#test-checkall').is(':checked');
|
160 |
-
$("div.keys input[type='checkbox']:visible").each(function() {
|
161 |
-
(checkAll)
|
162 |
-
? $(this).attr('checked', '1')
|
163 |
-
: $(this).removeAttr('checked');
|
164 |
-
});
|
165 |
-
}
|
166 |
-
|
167 |
-
//Test links will open in seperate window if checked
|
168 |
-
Duplicator.Debug.TestNewWindow = function()
|
169 |
-
{
|
170 |
-
var check = $('#test-openwindow').is(':checked');
|
171 |
-
var count = 0;
|
172 |
-
$("form").each(function(index)
|
173 |
-
{
|
174 |
-
count++;
|
175 |
-
(check)
|
176 |
-
? $(this).attr('target', 'dup_debug' + count)
|
177 |
-
: $(this).attr('target', 'dup_debug');
|
178 |
-
});
|
179 |
-
}
|
180 |
-
|
181 |
-
//INIT
|
182 |
-
$("form").each(function(index)
|
183 |
-
{
|
184 |
-
var $form = $(this);
|
185 |
-
$form.attr('action', 'admin-ajax.php');
|
186 |
-
$form.attr('target', 'dup_debug');
|
187 |
-
$form.attr('method', 'post');
|
188 |
-
});
|
189 |
-
|
190 |
-
});
|
191 |
-
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
debug/tst.packages.php
DELETED
@@ -1,31 +0,0 @@
|
|
1 |
-
<div class="section-hdr">PACKAGE CTRLS</div>
|
2 |
-
|
3 |
-
<form>
|
4 |
-
<?php
|
5 |
-
$CTRL['Title'] = 'duplicator_package_scan';
|
6 |
-
$CTRL['Action'] = 'duplicator_package_scan';
|
7 |
-
$CTRL['Test'] = false;
|
8 |
-
DUP_DEBUG_TestSetup($CTRL);
|
9 |
-
?>
|
10 |
-
<div class="params">
|
11 |
-
No Params
|
12 |
-
</div>
|
13 |
-
</form>
|
14 |
-
|
15 |
-
<form>
|
16 |
-
<?php
|
17 |
-
$CTRL['Title'] = 'DUP_CTRL_Package_addQuickFilters';
|
18 |
-
$CTRL['Action'] = 'DUP_CTRL_Package_addQuickFilters';
|
19 |
-
$CTRL['Test'] = true;
|
20 |
-
DUP_DEBUG_TestSetup($CTRL);
|
21 |
-
?>
|
22 |
-
<div class="params">
|
23 |
-
<textarea style="width:200px; height: 50px" name="dir_paths">D:/path1/;
|
24 |
-
D:/path2/path/;
|
25 |
-
</textarea>
|
26 |
-
<textarea style="width:200px; height: 50px" name="file_paths">D:/path1/test.txt;
|
27 |
-
D:/path2/path/test2.txt;
|
28 |
-
</textarea>
|
29 |
-
</div>
|
30 |
-
</form>
|
31 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
debug/tst.tools.php
DELETED
@@ -1,38 +0,0 @@
|
|
1 |
-
|
2 |
-
<div class="section-tests">
|
3 |
-
<div class="section-hdr">TOOLS CTRLS</div>
|
4 |
-
|
5 |
-
<!-- METHOD TEST -->
|
6 |
-
<form>
|
7 |
-
<?php
|
8 |
-
$CTRL['Title'] = 'DUP_CTRL_Tools_runScanValidator';
|
9 |
-
$CTRL['Action'] = 'DUP_CTRL_Tools_runScanValidator';
|
10 |
-
$CTRL['Test'] = true;
|
11 |
-
DUP_DEBUG_TestSetup($CTRL);
|
12 |
-
?>
|
13 |
-
<div class="params">
|
14 |
-
<label>Allow Recursion:</label>
|
15 |
-
<input type="checkbox" name="scan-recursive" /><br/>
|
16 |
-
<label>Search Path:</label>
|
17 |
-
<input type="text" name="scan-path" value="<?php echo DUPLICATOR_WPROOTPATH ?>" /> <br/>
|
18 |
-
</div>
|
19 |
-
</form>
|
20 |
-
|
21 |
-
<!-- METHOD TEST -->
|
22 |
-
<form>
|
23 |
-
<?php
|
24 |
-
$CTRL['Title'] = 'DUP_CTRL_Tools_runScanValidatorFull';
|
25 |
-
$CTRL['Action'] = 'DUP_CTRL_Tools_runScanValidator';
|
26 |
-
$CTRL['Test'] = true;
|
27 |
-
DUP_DEBUG_TestSetup($CTRL);
|
28 |
-
?>
|
29 |
-
<div class="params">
|
30 |
-
<label>Recursion:</label> True
|
31 |
-
<input type="hidden" name="scan-recursive" value="true" /><br/>
|
32 |
-
<label>Search Path:</label>
|
33 |
-
<input type="text" name="scan-path" value="<?php echo DUPLICATOR_WPROOTPATH ?>" /> <br/>
|
34 |
-
</div>
|
35 |
-
</form>
|
36 |
-
|
37 |
-
|
38 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
debug/tst.ui.php
DELETED
@@ -1,45 +0,0 @@
|
|
1 |
-
|
2 |
-
<div class="section-tests">
|
3 |
-
<div class="section-hdr">UI CTRLS</div>
|
4 |
-
|
5 |
-
<!-- METHOD TEST -->
|
6 |
-
<script>
|
7 |
-
function JS_DUP_CTRL_UI_SaveViewState(form)
|
8 |
-
{
|
9 |
-
//value param must be dynamic with each submit or else
|
10 |
-
//wp update_option method will return false
|
11 |
-
jQuery(form).find('input[name="value"]').val(new Date(jQuery.now()));
|
12 |
-
return ! UNIT_TEST_RUNNING;
|
13 |
-
}
|
14 |
-
</script>
|
15 |
-
<form onsubmit="return JS_DUP_CTRL_UI_SaveViewState(this);">
|
16 |
-
<?php
|
17 |
-
$CTRL['Title'] = 'DUP_CTRL_UI_SaveViewState';
|
18 |
-
$CTRL['Action'] = 'DUP_CTRL_UI_SaveViewState';
|
19 |
-
$CTRL['Test'] = true;
|
20 |
-
DUP_DEBUG_TestSetup($CTRL);
|
21 |
-
?>
|
22 |
-
|
23 |
-
<div class="params">
|
24 |
-
<label>Key:</label>
|
25 |
-
<input type="text" name="key" value="dup_ctrl_test" /><br/>
|
26 |
-
<label>Value:</label>
|
27 |
-
<input type="text" name="value" /> <br/>
|
28 |
-
</div>
|
29 |
-
</form>
|
30 |
-
|
31 |
-
|
32 |
-
<!-- METHOD TEST -->
|
33 |
-
<form>
|
34 |
-
<?php
|
35 |
-
$CTRL['Title'] = 'DUP_CTRL_UI_GetViewStateList';
|
36 |
-
$CTRL['Action'] = 'DUP_CTRL_UI_GetViewStateList';
|
37 |
-
$CTRL['Test'] = true;
|
38 |
-
DUP_DEBUG_TestSetup($CTRL);
|
39 |
-
?>
|
40 |
-
|
41 |
-
<div class="params">No Params</div>
|
42 |
-
</form>
|
43 |
-
|
44 |
-
|
45 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
define.php
CHANGED
@@ -2,8 +2,7 @@
|
|
2 |
//Prevent directly browsing to the file
|
3 |
if (function_exists('plugin_dir_url'))
|
4 |
{
|
5 |
-
define('DUPLICATOR_VERSION', '1.
|
6 |
-
define('DUPLICATOR_HOMEPAGE', 'https://snapcreek.com/duplicator/duplicator-free/');
|
7 |
define('DUPLICATOR_PLUGIN_URL', plugin_dir_url(__FILE__));
|
8 |
define('DUPLICATOR_SITE_URL', get_site_url());
|
9 |
|
@@ -19,13 +18,18 @@ if (function_exists('plugin_dir_url'))
|
|
19 |
if (! defined('DUPLICATOR_WPROOTPATH')) {
|
20 |
define('DUPLICATOR_WPROOTPATH', str_replace('\\', '/', ABSPATH));
|
21 |
}
|
22 |
-
|
23 |
-
define('DUPLICATOR_PLUGIN_PATH',
|
24 |
-
|
25 |
-
define('
|
26 |
-
|
27 |
-
define(
|
28 |
-
define('
|
|
|
|
|
|
|
|
|
|
|
29 |
|
30 |
//GENERAL CONSTRAINTS
|
31 |
define('DUPLICATOR_PHP_MAX_MEMORY', '2048M');
|
@@ -41,9 +45,29 @@ if (function_exists('plugin_dir_url'))
|
|
41 |
define('DUPLICATOR_SCAN_DB_TBL_SIZE', 10485760); //10MB Table
|
42 |
define('DUPLICATOR_SCAN_TIMEOUT', 150); //Seconds
|
43 |
define('DUPLICATOR_SCAN_MIN_WP', '4.7.0');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
|
45 |
$GLOBALS['DUPLICATOR_SERVER_LIST'] = array('Apache','LiteSpeed', 'Nginx', 'Lighttpd', 'IIS', 'WebServerX', 'uWSGI');
|
46 |
$GLOBALS['DUPLICATOR_OPTS_DELETE'] = array('duplicator_ui_view_state', 'duplicator_package_active', 'duplicator_settings');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
/* Used to flush a response every N items.
|
49 |
* Note: This value will cause the Zip file to double in size durning the creation process only*/
|
@@ -63,7 +87,6 @@ if (function_exists('plugin_dir_url'))
|
|
63 |
if(!defined('PHP_MAJOR_VERSION')) define('PHP_MAJOR_VERSION', $version[0]);
|
64 |
if(!defined('PHP_MINOR_VERSION')) define('PHP_MINOR_VERSION', $version[1]);
|
65 |
if(!defined('PHP_RELEASE_VERSION')) define('PHP_RELEASE_VERSION', $version[2]);
|
66 |
-
|
67 |
}
|
68 |
|
69 |
} else {
|
2 |
//Prevent directly browsing to the file
|
3 |
if (function_exists('plugin_dir_url'))
|
4 |
{
|
5 |
+
define('DUPLICATOR_VERSION', '1.3.0');
|
|
|
6 |
define('DUPLICATOR_PLUGIN_URL', plugin_dir_url(__FILE__));
|
7 |
define('DUPLICATOR_SITE_URL', get_site_url());
|
8 |
|
18 |
if (! defined('DUPLICATOR_WPROOTPATH')) {
|
19 |
define('DUPLICATOR_WPROOTPATH', str_replace('\\', '/', ABSPATH));
|
20 |
}
|
21 |
+
|
22 |
+
define('DUPLICATOR_PLUGIN_PATH', str_replace("\\", "/", plugin_dir_path(__FILE__)));
|
23 |
+
define('DUPLICATOR_SSDIR_NAME', 'wp-snapshots');
|
24 |
+
define('DUPLICATOR_SSDIR_PATH', str_replace("\\", "/", DUPLICATOR_WPROOTPATH . DUPLICATOR_SSDIR_NAME));
|
25 |
+
define('DUPLICATOR_SSDIR_PATH_TMP', DUPLICATOR_SSDIR_PATH . '/tmp');
|
26 |
+
define("DUPLICATOR_SSDIR_PATH_INSTALLER", DUPLICATOR_SSDIR_PATH . '/installer');
|
27 |
+
define('DUPLICATOR_SSDIR_URL', DUPLICATOR_SITE_URL . "/" . DUPLICATOR_SSDIR_NAME);
|
28 |
+
define('DUPLICATOR_ZIPPED_LOG_FILENAME', 'duplicator_lite_log.zip');
|
29 |
+
define('DUPLICATOR_INSTALL_PHP', 'installer.php');
|
30 |
+
define('DUPLICATOR_INSTALL_BAK', 'installer-backup.php');
|
31 |
+
define('DUPLICATOR_INSTALLER_HASH_PATTERN', '[a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]');
|
32 |
+
define('DUPLICATOR_INSTALL_SITE_OVERWRITE_ON', false);
|
33 |
|
34 |
//GENERAL CONSTRAINTS
|
35 |
define('DUPLICATOR_PHP_MAX_MEMORY', '2048M');
|
45 |
define('DUPLICATOR_SCAN_DB_TBL_SIZE', 10485760); //10MB Table
|
46 |
define('DUPLICATOR_SCAN_TIMEOUT', 150); //Seconds
|
47 |
define('DUPLICATOR_SCAN_MIN_WP', '4.7.0');
|
48 |
+
define('DUPLICATOR_MAX_DUPARCHIVE_SIZE', 524288000); // 500 GB
|
49 |
+
|
50 |
+
define('DUPLICATOR_TEMP_CLEANUP_SECONDS', 900); // 15 min = How many seconds to keep temp files around when delete is requested
|
51 |
+
define('DUPLICATOR_MAX_BUILD_RETRIES', 10); // Max times to try a part of progressive build work
|
52 |
+
define('DUPLICATOR_HTACCESS_ORIG_FILENAME', 'htaccess.orig');
|
53 |
+
define('DUPLICATOR_WEBCONFIG_ORIG_FILENAME', 'web.config.orig');
|
54 |
+
define("DUPLICATOR_INSTALLER_DIRECTORY", DUPLICATOR_WPROOTPATH . 'dup-installer');
|
55 |
+
define('DUPLICATOR_MAX_LOG_SIZE', 400000); // The higher this is the more overhead
|
56 |
|
57 |
$GLOBALS['DUPLICATOR_SERVER_LIST'] = array('Apache','LiteSpeed', 'Nginx', 'Lighttpd', 'IIS', 'WebServerX', 'uWSGI');
|
58 |
$GLOBALS['DUPLICATOR_OPTS_DELETE'] = array('duplicator_ui_view_state', 'duplicator_package_active', 'duplicator_settings');
|
59 |
+
$GLOBALS['DUPLICATOR_GLOBAL_FILE_FILTERS_ON'] = true;
|
60 |
+
$GLOBALS['DUPLICATOR_GLOBAL_FILE_FILTERS'] = array(
|
61 |
+
'error_log',
|
62 |
+
'error.log',
|
63 |
+
'debug_log',
|
64 |
+
'ws_ftp.log',
|
65 |
+
'dbcache',
|
66 |
+
'pgcache',
|
67 |
+
'objectcache',
|
68 |
+
'.DS_Store'
|
69 |
+
);
|
70 |
+
|
71 |
|
72 |
/* Used to flush a response every N items.
|
73 |
* Note: This value will cause the Zip file to double in size durning the creation process only*/
|
87 |
if(!defined('PHP_MAJOR_VERSION')) define('PHP_MAJOR_VERSION', $version[0]);
|
88 |
if(!defined('PHP_MINOR_VERSION')) define('PHP_MINOR_VERSION', $version[1]);
|
89 |
if(!defined('PHP_RELEASE_VERSION')) define('PHP_RELEASE_VERSION', $version[2]);
|
|
|
90 |
}
|
91 |
|
92 |
} else {
|
duplicator.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: Duplicator
|
4 |
Plugin URI: https://snapcreek.com/duplicator/duplicator-free/
|
5 |
Description: Migrate and backup a copy of your WordPress files and database. Duplicate and move a site from one location to another quickly.
|
6 |
-
Version: 1.
|
7 |
Author: Snap Creek
|
8 |
Author URI: http://www.snapcreek.com/duplicator/
|
9 |
Text Domain: duplicator
|
@@ -25,6 +25,7 @@
|
|
25 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
26 |
|
27 |
SOURCE CONTRIBUTORS:
|
|
|
28 |
https://github.com/interconnectit/Search-Replace-DB/
|
29 |
================================================================================ */
|
30 |
|
@@ -109,9 +110,11 @@ if (!function_exists('_sanitize_text_fields')) {
|
|
109 |
if (is_admin() == true)
|
110 |
{
|
111 |
//Classes
|
112 |
-
require_once 'classes/class.logging.php';
|
113 |
require_once 'classes/class.settings.php';
|
|
|
114 |
require_once 'classes/utilities/class.u.php';
|
|
|
|
|
115 |
require_once 'classes/class.db.php';
|
116 |
require_once 'classes/class.server.php';
|
117 |
require_once 'classes/ui/class.ui.viewstate.php';
|
@@ -200,14 +203,19 @@ if (is_admin() == true)
|
|
200 |
* ===================================================== */
|
201 |
add_action('plugins_loaded', 'duplicator_update');
|
202 |
add_action('plugins_loaded', 'duplicator_wpfront_integrate');
|
203 |
-
|
204 |
add_action('admin_menu', 'duplicator_menu');
|
|
|
205 |
add_action('admin_notices', array('DUP_UI_Notice', 'showReservedFilesNotice'));
|
206 |
|
207 |
//CTRL ACTIONS
|
208 |
-
add_action('wp_ajax_duplicator_package_scan',
|
209 |
-
add_action('wp_ajax_duplicator_package_build',
|
210 |
-
add_action('wp_ajax_duplicator_package_delete',
|
|
|
|
|
|
|
|
|
211 |
$GLOBALS['CTRLS_DUP_CTRL_UI'] = new DUP_CTRL_UI();
|
212 |
$GLOBALS['CTRLS_DUP_CTRL_Tools'] = new DUP_CTRL_Tools();
|
213 |
$GLOBALS['CTRLS_DUP_CTRL_Package'] = new DUP_CTRL_Package();
|
@@ -236,13 +244,29 @@ if (is_admin() == true)
|
|
236 |
/* CSS */
|
237 |
wp_register_style('dup-jquery-ui', DUPLICATOR_PLUGIN_URL . 'assets/css/jquery-ui.css', null, "1.11.2");
|
238 |
wp_register_style('dup-font-awesome', DUPLICATOR_PLUGIN_URL . 'assets/css/font-awesome.min.css', null, '4.7.0');
|
239 |
-
wp_register_style('dup-plugin-style', DUPLICATOR_PLUGIN_URL . 'assets/css/
|
|
|
|
|
240 |
wp_register_style('dup-jquery-qtip',DUPLICATOR_PLUGIN_URL . 'assets/js/jquery.qtip/jquery.qtip.min.css', null, '2.2.1');
|
241 |
-
wp_register_style('dup-parsley-style', DUPLICATOR_PLUGIN_URL . 'assets/css/
|
242 |
/* JS */
|
243 |
wp_register_script('dup-handlebars', DUPLICATOR_PLUGIN_URL . 'assets/js/handlebars.min.js', array('jquery'), '4.0.10');
|
244 |
-
wp_register_script('dup-parsley', DUPLICATOR_PLUGIN_URL . 'assets/js/parsley.min.js', array('jquery'), '
|
245 |
wp_register_script('dup-jquery-qtip', DUPLICATOR_PLUGIN_URL . 'assets/js/jquery.qtip/jquery.qtip.min.js', array('jquery'), '2.2.1');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
}
|
247 |
|
248 |
/**
|
@@ -260,7 +284,7 @@ if (is_admin() == true)
|
|
260 |
case 'duplicator-settings': include('views/settings/controller.php'); break;
|
261 |
case 'duplicator-tools': include('views/tools/controller.php'); break;
|
262 |
case 'duplicator-debug': include('debug/main.php'); break;
|
263 |
-
case 'duplicator-gopro': include('views/
|
264 |
}
|
265 |
}
|
266 |
|
@@ -302,17 +326,6 @@ if (is_admin() == true)
|
|
302 |
$go_pro_link = '<span style="color:#f18500">' . $lang_txt . '</span>';
|
303 |
$perms = apply_filters($wpfront_caps_translator, $perms);
|
304 |
$page_gopro = add_submenu_page('duplicator', $go_pro_link, $go_pro_link, $perms, 'duplicator-gopro', 'duplicator_get_menu');
|
305 |
-
|
306 |
-
$package_debug = DUP_Settings::Get('package_debug');
|
307 |
-
if ($package_debug != null && $package_debug == true)
|
308 |
-
{
|
309 |
-
$perms = 'manage_options';
|
310 |
-
$perms = apply_filters($wpfront_caps_translator, $perms);
|
311 |
-
$lang_txt = esc_html__('Debug', 'duplicator');
|
312 |
-
$page_debug = add_submenu_page('duplicator', $lang_txt, $lang_txt, $perms, 'duplicator-debug', 'duplicator_get_menu');
|
313 |
-
add_action('admin_print_scripts-' . $page_debug, 'duplicator_scripts');
|
314 |
-
add_action('admin_print_styles-' . $page_debug, 'duplicator_styles');
|
315 |
-
}
|
316 |
|
317 |
//Apply Scripts
|
318 |
add_action('admin_print_scripts-' . $page_packages, 'duplicator_scripts');
|
@@ -325,7 +338,6 @@ if (is_admin() == true)
|
|
325 |
add_action('admin_print_styles-' . $page_settings, 'duplicator_styles');
|
326 |
add_action('admin_print_styles-' . $page_tools, 'duplicator_styles');
|
327 |
add_action('admin_print_styles-' . $page_gopro, 'duplicator_styles');
|
328 |
-
|
329 |
}
|
330 |
|
331 |
/**
|
@@ -341,6 +353,7 @@ if (is_admin() == true)
|
|
341 |
wp_enqueue_script('jquery-ui-progressbar');
|
342 |
wp_enqueue_script('dup-parsley');
|
343 |
wp_enqueue_script('dup-jquery-qtip');
|
|
|
344 |
}
|
345 |
|
346 |
/**
|
@@ -355,7 +368,6 @@ if (is_admin() == true)
|
|
355 |
wp_enqueue_style('dup-font-awesome');
|
356 |
wp_enqueue_style('dup-plugin-style');
|
357 |
wp_enqueue_style('dup-jquery-qtip');
|
358 |
-
wp_enqueue_style('dup-parsley-style');
|
359 |
}
|
360 |
|
361 |
|
@@ -378,7 +390,7 @@ if (is_admin() == true)
|
|
378 |
$this_plugin = plugin_basename(__FILE__);
|
379 |
|
380 |
if ($file == $this_plugin) {
|
381 |
-
$settings_link = '<a href="admin.php?page=duplicator">' .
|
382 |
array_unshift($links, $settings_link);
|
383 |
}
|
384 |
return $links;
|
@@ -395,7 +407,7 @@ if (is_admin() == true)
|
|
395 |
$plugin = plugin_basename(__FILE__);
|
396 |
// create link
|
397 |
if ($file == $plugin) {
|
398 |
-
$links[] = '<a href="admin.php?page=duplicator-gopro" title="' .
|
399 |
return $links;
|
400 |
}
|
401 |
return $links;
|
3 |
Plugin Name: Duplicator
|
4 |
Plugin URI: https://snapcreek.com/duplicator/duplicator-free/
|
5 |
Description: Migrate and backup a copy of your WordPress files and database. Duplicate and move a site from one location to another quickly.
|
6 |
+
Version: 1.3.0
|
7 |
Author: Snap Creek
|
8 |
Author URI: http://www.snapcreek.com/duplicator/
|
9 |
Text Domain: duplicator
|
25 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
26 |
|
27 |
SOURCE CONTRIBUTORS:
|
28 |
+
David Coveney of Interconnect IT Ltd
|
29 |
https://github.com/interconnectit/Search-Replace-DB/
|
30 |
================================================================================ */
|
31 |
|
110 |
if (is_admin() == true)
|
111 |
{
|
112 |
//Classes
|
|
|
113 |
require_once 'classes/class.settings.php';
|
114 |
+
require_once 'classes/class.logging.php';
|
115 |
require_once 'classes/utilities/class.u.php';
|
116 |
+
require_once 'classes/utilities/class.u.string.php';
|
117 |
+
require_once 'classes/utilities/class.u.validator.php';
|
118 |
require_once 'classes/class.db.php';
|
119 |
require_once 'classes/class.server.php';
|
120 |
require_once 'classes/ui/class.ui.viewstate.php';
|
203 |
* ===================================================== */
|
204 |
add_action('plugins_loaded', 'duplicator_update');
|
205 |
add_action('plugins_loaded', 'duplicator_wpfront_integrate');
|
206 |
+
add_action('admin_init', 'duplicator_init');
|
207 |
add_action('admin_menu', 'duplicator_menu');
|
208 |
+
add_action('admin_enqueue_scripts', 'duplicator_admin_enqueue_scripts' );
|
209 |
add_action('admin_notices', array('DUP_UI_Notice', 'showReservedFilesNotice'));
|
210 |
|
211 |
//CTRL ACTIONS
|
212 |
+
add_action('wp_ajax_duplicator_package_scan', 'duplicator_package_scan');
|
213 |
+
add_action('wp_ajax_duplicator_package_build', 'duplicator_package_build');
|
214 |
+
add_action('wp_ajax_duplicator_package_delete', 'duplicator_package_delete');
|
215 |
+
add_action('wp_ajax_duplicator_duparchive_package_build', 'duplicator_duparchive_package_build');
|
216 |
+
add_action('wp_ajax_nopriv_duplicator_duparchive_package_build', 'duplicator_duparchive_package_build');
|
217 |
+
|
218 |
+
|
219 |
$GLOBALS['CTRLS_DUP_CTRL_UI'] = new DUP_CTRL_UI();
|
220 |
$GLOBALS['CTRLS_DUP_CTRL_Tools'] = new DUP_CTRL_Tools();
|
221 |
$GLOBALS['CTRLS_DUP_CTRL_Package'] = new DUP_CTRL_Package();
|
244 |
/* CSS */
|
245 |
wp_register_style('dup-jquery-ui', DUPLICATOR_PLUGIN_URL . 'assets/css/jquery-ui.css', null, "1.11.2");
|
246 |
wp_register_style('dup-font-awesome', DUPLICATOR_PLUGIN_URL . 'assets/css/font-awesome.min.css', null, '4.7.0');
|
247 |
+
wp_register_style('dup-plugin-global-style', DUPLICATOR_PLUGIN_URL . 'assets/css/global_admin_style.css', null , DUPLICATOR_VERSION);
|
248 |
+
wp_register_style('dup-plugin-style', DUPLICATOR_PLUGIN_URL . 'assets/css/style.css', array('dup-plugin-global-style') , DUPLICATOR_VERSION);
|
249 |
+
|
250 |
wp_register_style('dup-jquery-qtip',DUPLICATOR_PLUGIN_URL . 'assets/js/jquery.qtip/jquery.qtip.min.css', null, '2.2.1');
|
251 |
+
wp_register_style('dup-parsley-style', DUPLICATOR_PLUGIN_URL . 'assets/css/parsley.css', null, '2.3.5');
|
252 |
/* JS */
|
253 |
wp_register_script('dup-handlebars', DUPLICATOR_PLUGIN_URL . 'assets/js/handlebars.min.js', array('jquery'), '4.0.10');
|
254 |
+
wp_register_script('dup-parsley', DUPLICATOR_PLUGIN_URL . 'assets/js/parsley.min.js', array('jquery'), '1.1.18');
|
255 |
wp_register_script('dup-jquery-qtip', DUPLICATOR_PLUGIN_URL . 'assets/js/jquery.qtip/jquery.qtip.min.js', array('jquery'), '2.2.1');
|
256 |
+
|
257 |
+
|
258 |
+
// Clean tmp folder
|
259 |
+
DUP_Package::not_active_files_tmp_cleanup();
|
260 |
+
}
|
261 |
+
|
262 |
+
/**
|
263 |
+
* Hooked into `admin_enqueue_scripts`. Init routines for all admin pages
|
264 |
+
*
|
265 |
+
* @access global
|
266 |
+
* @return null
|
267 |
+
*/
|
268 |
+
function duplicator_admin_enqueue_scripts() {
|
269 |
+
wp_enqueue_style('dup-plugin-global-style');
|
270 |
}
|
271 |
|
272 |
/**
|
284 |
case 'duplicator-settings': include('views/settings/controller.php'); break;
|
285 |
case 'duplicator-tools': include('views/tools/controller.php'); break;
|
286 |
case 'duplicator-debug': include('debug/main.php'); break;
|
287 |
+
case 'duplicator-gopro': include('views/settings/gopro.php'); break;
|
288 |
}
|
289 |
}
|
290 |
|
326 |
$go_pro_link = '<span style="color:#f18500">' . $lang_txt . '</span>';
|
327 |
$perms = apply_filters($wpfront_caps_translator, $perms);
|
328 |
$page_gopro = add_submenu_page('duplicator', $go_pro_link, $go_pro_link, $perms, 'duplicator-gopro', 'duplicator_get_menu');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
329 |
|
330 |
//Apply Scripts
|
331 |
add_action('admin_print_scripts-' . $page_packages, 'duplicator_scripts');
|
338 |
add_action('admin_print_styles-' . $page_settings, 'duplicator_styles');
|
339 |
add_action('admin_print_styles-' . $page_tools, 'duplicator_styles');
|
340 |
add_action('admin_print_styles-' . $page_gopro, 'duplicator_styles');
|
|
|
341 |
}
|
342 |
|
343 |
/**
|
353 |
wp_enqueue_script('jquery-ui-progressbar');
|
354 |
wp_enqueue_script('dup-parsley');
|
355 |
wp_enqueue_script('dup-jquery-qtip');
|
356 |
+
|
357 |
}
|
358 |
|
359 |
/**
|
368 |
wp_enqueue_style('dup-font-awesome');
|
369 |
wp_enqueue_style('dup-plugin-style');
|
370 |
wp_enqueue_style('dup-jquery-qtip');
|
|
|
371 |
}
|
372 |
|
373 |
|
390 |
$this_plugin = plugin_basename(__FILE__);
|
391 |
|
392 |
if ($file == $this_plugin) {
|
393 |
+
$settings_link = '<a href="admin.php?page=duplicator">' . esc_html__("Manage", 'duplicator') . '</a>';
|
394 |
array_unshift($links, $settings_link);
|
395 |
}
|
396 |
return $links;
|
407 |
$plugin = plugin_basename(__FILE__);
|
408 |
// create link
|
409 |
if ($file == $plugin) {
|
410 |
+
$links[] = '<a href="admin.php?page=duplicator-gopro" title="' . esc_attr__('Get Help', 'duplicator') . '" style="">' . esc_html__('Go Pro', 'duplicator') . '</a>';
|
411 |
return $links;
|
412 |
}
|
413 |
return $links;
|
installer/build/assets/inc.css.php
DELETED
@@ -1,246 +0,0 @@
|
|
1 |
-
<style>
|
2 |
-
body {font-family:Verdana,Arial,sans-serif; font-size:13px;}
|
3 |
-
fieldset {border:1px solid silver; border-radius:5px; padding:10px}
|
4 |
-
h3 {margin:1px; padding:1px; font-size:13px;}
|
5 |
-
a {color:#222}
|
6 |
-
a:hover{color:gray}
|
7 |
-
input[type=text], input[type=password], select {width:97%; border-radius:2px; border:1px solid silver; padding:4px; font-family:Verdana,Arial,sans-serif;}
|
8 |
-
select {padding-left:0; width:99%}
|
9 |
-
select:disabled {background:#EBEBE4}
|
10 |
-
input.readonly {background-color:#efefef;}
|
11 |
-
|
12 |
-
/* ============================
|
13 |
-
COMMON VIEWS
|
14 |
-
============================ */
|
15 |
-
div#content {border:1px solid #CDCDCD; width:750px; min-height:550px; margin:auto; margin-top:18px; border-radius:5px; box-shadow:0 8px 6px -6px #333; font-size:13px}
|
16 |
-
div#content-inner {padding:10px 25px; min-height:550px}
|
17 |
-
form.content-form {min-height:550px; position:relative; line-height:17px}
|
18 |
-
div.status-badge-pass {border-radius:4px; color:#fff; padding:0 4px 0 4px; font-size:12px; min-width:30px; text-align:center; background-color:#418446;display:inline-block }
|
19 |
-
div.status-badge-fail {border-radius:4px; color:#fff; padding:0 4px 0 4px; font-size:12px; min-width:30px; text-align:center; background-color:maroon; display:inline-block}
|
20 |
-
|
21 |
-
/* WIZARD STEPS */
|
22 |
-
table.dupx-header {border-top-left-radius:5px; border-top-right-radius:5px; width:100%; box-shadow:0 5px 3px -3px #999; background-color:#F1F1F1; font-weight:bold;}
|
23 |
-
.dupx-header-version {white-space:nowrap; color:#777; font-size:11px; font-style:italic; text-align:right; padding:0 15px 5px 0; line-height:14px; font-weight:normal;}
|
24 |
-
.dupx-header-version a {color:#555;}
|
25 |
-
div.dupx-logfile-link {float:right; font-weight:normal; font-size:11px; font-style:italic}
|
26 |
-
div#progress-area {padding:5px; margin:150px 0 0 0px; text-align:center;}
|
27 |
-
div#ajaxerr-data {padding:5px; height:350px; width:99%; border:1px solid silver; border-radius:5px; background-color:#efefef; font-size:13px; overflow-y:scroll; line-height:24px}
|
28 |
-
|
29 |
-
/*TITLE HEADERS */
|
30 |
-
div.hdr-main {font-size:22px; padding:0 0 5px 0; border-bottom:1px solid #D3D3D3; font-weight:bold; margin:15px 0 20px 0;}
|
31 |
-
div.hdr-main span.step {color:#DB4B38}
|
32 |
-
div.hdr-sub1 {font-size:18px; margin-bottom:5px;border:1px solid #D3D3D3;padding:7px; background-color:#f9f9f9; font-weight:bold; border-radius:4px}
|
33 |
-
div.hdr-sub1 a {cursor:pointer; text-decoration: none !important}
|
34 |
-
div.hdr-sub1:hover {cursor:pointer; background-color:#f1f1f1; border:1px solid #dcdcdc; }
|
35 |
-
div.hdr-sub1:hover a{color:#000}
|
36 |
-
div.hdr-sub2 {font-size:15px; padding:2px 2px 2px 0; border-bottom:1px solid #D3D3D3; font-weight:bold; margin-bottom:5px; border:none}
|
37 |
-
div.hdr-sub3 {font-size:15px; padding:2px 2px 2px 0; border-bottom:1px solid #D3D3D3; font-weight:bold; margin-bottom:5px;}
|
38 |
-
div.hdr-sub4 {font-size:15px; padding:7px; border:1px solid #D3D3D3;; font-weight:bold; background-color:#e9e9e9;}
|
39 |
-
div.hdr-sub4:hover {background-color:#dfdfdf; cursor:pointer}
|
40 |
-
|
41 |
-
/* BUTTONS */
|
42 |
-
div.dupx-footer-buttons {position:absolute; bottom:10px; padding:10px; right:0}
|
43 |
-
div.dupx-footer-buttons input:hover, button:hover {border:1px solid #000}
|
44 |
-
div.dupx-footer-buttons input[disabled=disabled]{background-color:#F4F4F4; color:silver; border:1px solid silver;}
|
45 |
-
div.dupx-footer-buttons button[disabled]{background-color:#F4F4F4; color:silver; border:1px solid silver;}
|
46 |
-
button.default-btn, input.default-btn {
|
47 |
-
cursor:pointer; color:#fff; font-size:16px; border-radius:5px; padding:8px 25px 6px 25px;
|
48 |
-
background-color:#13659C; border:1px solid gray;
|
49 |
-
}
|
50 |
-
table.dupx-opts {width:100%; border:0px;}
|
51 |
-
table.dupx-opts td{white-space:nowrap; padding:3px;}
|
52 |
-
table.dupx-opts td:first-child{width:125px; font-weight: bold}
|
53 |
-
table.dupx-advopts td:first-child{width:125px; font-weight:bold}
|
54 |
-
table.dupx-advopts td label{min-width:60px; display:inline-block; cursor:pointer}
|
55 |
-
|
56 |
-
.dupx-pass {display:inline-block; color:green;}
|
57 |
-
.dupx-fail {display:inline-block; color:#AF0000;}
|
58 |
-
.dupx-notice {display:inline-block; color:#000;}
|
59 |
-
div.dupx-ui-error {padding-top:2px; font-size:13px; line-height: 20px}
|
60 |
-
|
61 |
-
/*Dialog Info */
|
62 |
-
div.dlg-serv-info {line-height:22px; font-size:12px; margin:0}
|
63 |
-
div.dlg-serv-info div.info-txt {text-align: center; font-size:11px; font-style:italic}
|
64 |
-
div.dlg-serv-info label {display:inline-block; width:175px; font-weight: bold}
|
65 |
-
div.dlg-serv-info div.hdr {background-color: #dfdfdf; font-weight: bold; margin-top:5px; border-radius: 4px; padding:2px 5px 2px 5px; border: 1px solid silver; font-size: 16px}
|
66 |
-
div#modal-window div.modal-title {background-color:#D0D0D0}
|
67 |
-
div#modal-window div.modal-text {padding-top:10px !important}
|
68 |
-
div.installer-mode {font-weight:normal; position:absolute; top:5px; right:20px; font-style:italic; font-size:11px}
|
69 |
-
i.secure-unlocked {color:maroon;}
|
70 |
-
|
71 |
-
|
72 |
-
/* ============================
|
73 |
-
INIT 1:SECURE PASSWORD
|
74 |
-
============================ */
|
75 |
-
button.pass-toggle {height:26px; width:26px; position:absolute; top:0px; right:0px; border:1px solid silver; border-radius:0 4px 4px 0;}
|
76 |
-
button.pass-toggle i { padding:0; display:block; margin:-4px 0 0 -5px}
|
77 |
-
div.i1-pass-area {width:100%; text-align:center}
|
78 |
-
div.i1-pass-data {padding:30px; margin:auto; text-align:center; width:300px}
|
79 |
-
div.i1-pass-data table {width:100%; border-collapse:collapse; padding:0}
|
80 |
-
div.i1-pass-data label {font-weight:bold}
|
81 |
-
div.i1-pass-errmsg {color:maroon; font-weight:bold}
|
82 |
-
div#i1-pass-input {position:relative; margin:2px 0 15px 0}
|
83 |
-
input#secure-pass {border-radius:4px 0 0 4px; width:250px}
|
84 |
-
div.error-pane {border:1px solid #efefef; border-left:4px solid #D54E21; padding:0 0 0 10px; margin:2px 0 10px 0}
|
85 |
-
div.dupx-ui-error {padding-top:2px; font-size:13px; line-height: 20px}
|
86 |
-
label.secure-lock {cursor:pointer}
|
87 |
-
|
88 |
-
/* ======================================
|
89 |
-
STEP 1 VIEW
|
90 |
-
====================================== */
|
91 |
-
table.s1-archive-local {width:100%}
|
92 |
-
table.s1-archive-local tr {vertical-align:top}
|
93 |
-
table.s1-archive-local td {padding:4px 4px 4px 4px}
|
94 |
-
table.s1-archive-local td:first-child {font-weight:bold; width:55px}
|
95 |
-
div#s1-area-sys-setup {padding:5px 0 0 10px}
|
96 |
-
div#s1-area-sys-setup div.info-top {text-align:center; font-style:italic; font-size:11px; padding:0 5px 5px 5px}
|
97 |
-
table.s1-checks-area {width:100%; margin:0; padding:0}
|
98 |
-
table.s1-checks-area td.title {font-size:16px; width:100%}
|
99 |
-
table.s1-checks-area td.title small {font-size:11px; font-weight:normal}
|
100 |
-
table.s1-checks-area td.toggle {font-size:11px; margin-right:7px; font-weight:normal}
|
101 |
-
|
102 |
-
div.s1-reqs {background-color:#efefef; border:1px solid silver; border-radius:5px; margin-top:-5px}
|
103 |
-
div.s1-reqs div.header {background-color:#E0E0E0; color:#000; border-bottom: 1px solid silver; padding:2px; font-weight:bold }
|
104 |
-
div.s1-reqs div.notice {background-color:#E0E0E0; color:#000; text-align:center; font-size:12px; border-bottom: 1px solid silver; padding:2px; font-style:italic}
|
105 |
-
div.s1-reqs div.status {float:right; border-radius:4px; color:#fff; padding:0 4px 0 4px; margin:4px 5px 0 0; font-size:12px; min-width:30px; text-align:center; font-weight:bold}
|
106 |
-
div.s1-reqs div.pass {background-color:green;}
|
107 |
-
div.s1-reqs div.fail {background-color:maroon;}
|
108 |
-
div.s1-reqs div.title {padding:4px; font-size:13px;}
|
109 |
-
div.s1-reqs div.title:hover {background-color:#dfdfdf; cursor:pointer}
|
110 |
-
div.s1-reqs div.info {padding:8px 8px 20px 8px; background-color:#fff; display:none; line-height:18px; font-size: 12px}
|
111 |
-
div.s1-reqs div.info a {color:#485AA3;}
|
112 |
-
div.s1-archive-failed-msg {padding:15px; border:1px dashed maroon; font-size: 12px; border-radius:5px;}
|
113 |
-
div.s1-err-msg {padding:8px; border:1px dashed #999; margin:20px 0 20px 0px; border-radius:5px; color:maroon}
|
114 |
-
|
115 |
-
/*Terms and Notices*/
|
116 |
-
div#s1-warning-check label{cursor:pointer;}
|
117 |
-
div#s1-warning-msg {padding:5px;font-size:12px; color:#333; line-height:14px;font-style:italic; overflow-y:scroll; height:250px; border:1px solid #dfdfdf; background:#fff; border-radius:3px}
|
118 |
-
div#s1-warning-check {padding:3px; font-size:14px; font-weight:normal;}
|
119 |
-
input#accept-warnings {height: 17px; width:17px}
|
120 |
-
|
121 |
-
/* ======================================
|
122 |
-
STEP 2 VIEW
|
123 |
-
====================================== */
|
124 |
-
/*Toggle Buttons */
|
125 |
-
div.s2-btngrp {text-align:center; margin:0 auto 10px auto}
|
126 |
-
div.s2-btngrp input[type=button] {font-size:14px; padding:6px; width:120px; border:1px solid silver; cursor:pointer}
|
127 |
-
div.s2-btngrp input[type=button]:first-child {border-radius:5px 0 0 5px; margin-right:-2px}
|
128 |
-
div.s2-btngrp input[type=button]:last-child {border-radius:0 5px 5px 0; margin-left:-4px}
|
129 |
-
div.s2-btngrp input[type=button].active {background-color:#13659C; color:#fff;}
|
130 |
-
div.s2-btngrp input[type=button].in-active {background-color:#E4E4E4; }
|
131 |
-
div.s2-btngrp input[type=button]:hover {border:1px solid #999}
|
132 |
-
|
133 |
-
div.s2-modes {padding:0px 15px 0 0px;}
|
134 |
-
div#s2-dbconn {margin:auto; text-align:center; margin:15px 0 10px 0px}
|
135 |
-
input.s2-small-btn {height:25px; border:1px solid gray; border-radius:3px; cursor:pointer}
|
136 |
-
table.s2-opts-dbhost td {padding:0; margin:0}
|
137 |
-
input#s2-dbport-btn { width:80px}
|
138 |
-
div.s2-db-test small{display:block; font-style:italic; color:#333; padding:3px 2px 5px 2px; border-bottom:1px dashed silver; margin-bottom:10px; text-align: center }
|
139 |
-
table.s2-db-test-dtls {text-align: left; margin: auto}
|
140 |
-
table.s2-db-test-dtls td:first-child {font-weight: bold}
|
141 |
-
div#s2-dbconn-test-msg {font-size:12px}
|
142 |
-
div#s2-dbconn-status {border:1px solid silver; border-radius:3px; background-color:#f9f9f9; padding:2px 5px; margin-top:10px; height:200px; overflow-y: scroll}
|
143 |
-
div#s2-dbconn-status div.warn-msg {text-align: left; padding:5px; margin:10px 0 10px 0}
|
144 |
-
div#s2-dbconn-status div.warn-msg b{color:maroon}
|
145 |
-
|
146 |
-
/*cPanel Tab */
|
147 |
-
div#s2-cpnl-pane {display: none; min-height: 190px;}
|
148 |
-
div.s2-gopro {color: black; margin-top:10px; padding:0 20px 10px 20px; border: 1px solid silver; background-color:#F6F6F6; border-radius: 4px}
|
149 |
-
div.s2-gopro h2 {text-align: center; margin:10px}
|
150 |
-
div.s2-gopro small {font-style: italic}
|
151 |
-
div.s2-cpanel-login {padding:15px; color:#fff; text-align:center; margin:15px 5px 15px 5px; border:1px solid silver; border-radius:5px; background-color:#13659C; font-size:14px; line-height:22px}
|
152 |
-
div.s2-cpanel-off {padding:15px; color:#fff; text-align:center; margin:15px 5px 15px 5px; border:1px solid silver; border-radius:5px; background-color:#b54949; font-size:14px; line-height:22px}
|
153 |
-
|
154 |
-
/*Advanced Options & Warning Area*/
|
155 |
-
div#s2-area-adv-opts label {cursor: pointer}
|
156 |
-
div#s2-warning {padding:5px;font-size:12px; color:gray; line-height:12px;font-style:italic; overflow-y:scroll; height:150px; border:1px solid #dfdfdf; background-color:#fff; border-radius:3px}
|
157 |
-
div#s2-warning-check {padding:5px; font-size:12px; font-weight:normal; font-style:italic;}
|
158 |
-
div#s2-warning-check label {cursor: pointer; line-height: 14px}
|
159 |
-
div#s2-warning-emptydb {display:none; color:#AF2222; margin:2px 0 0 0; font-size: 11px}
|
160 |
-
table.s2-advopts label.radio {width:50px; display:inline-block}
|
161 |
-
|
162 |
-
/* ======================================
|
163 |
-
STEP 3 VIEW
|
164 |
-
====================================== */
|
165 |
-
table.s3-table-inputs {width:100%; border:0px;}
|
166 |
-
table.s3-table-inputs td{white-space:nowrap; padding:2px;}
|
167 |
-
table.s3-table-inputs td:first-child{font-weight: bold; width:125px}
|
168 |
-
div#s3-adv-opts {margin-top:5px; }
|
169 |
-
div.s3-allnonelinks {font-size:11px; float:right;}
|
170 |
-
select#plugins {width:330px; height:100px}
|
171 |
-
select#tables {width:330px; height:100px}
|
172 |
-
|
173 |
-
/* password indicator */
|
174 |
-
.top_testresult{font-weight:bold; font-size:11px; color:#222; padding:1px 1px 1px 4px; margin:4px 0 0 0px; width:495px; dislay:inline-block}
|
175 |
-
.top_testresult span{margin:0;}
|
176 |
-
.top_shortPass{background:#edabab; border:1px solid #bc0000;display:block;}
|
177 |
-
.top_badPass{background:#edabab;border:1px solid #bc0000;display:block;}
|
178 |
-
.top_goodPass{background:#ffffe0; border:1px solid #e6db55; display:block;}
|
179 |
-
.top_strongPass{background:#d3edab; border:1px solid #73bc00; display:block;}
|
180 |
-
|
181 |
-
/* ======================================
|
182 |
-
STEP 4 VIEW
|
183 |
-
====================================== */
|
184 |
-
div.s4-final-title {color:#BE2323;font-size:18px}
|
185 |
-
div.s4-connect {font-size:12px; text-align:center; font-style:italic; position:absolute; bottom:10px; padding:10px; width:100%; margin-top:20px}
|
186 |
-
table.s4-report-results,
|
187 |
-
table.s4-report-errs {border-collapse:collapse; border:1px solid #dfdfdf; }
|
188 |
-
table.s4-report-errs td {text-align:center; width:33%}
|
189 |
-
table.s4-report-results th, table.s4-report-errs th {background-color:#efefef; padding:0px; font-size:13px; padding:0px}
|
190 |
-
table.s4-report-results td, table.s4-report-errs td {padding:0px; white-space:nowrap; border:1px solid #dfdfdf; text-align:center; font-size:12px}
|
191 |
-
table.s4-report-results td:first-child {text-align:left; font-weight:bold; padding-left:3px}
|
192 |
-
div.s4-err-title {background-color:#dfdfdf; font-weight: bold; margin:-3px 0 15px 0; padding:5px; border-radius:3px; font-size:13px}
|
193 |
-
|
194 |
-
div.s4-err-msg {padding:8px; display:none; border:1px dashed #999; margin:10px 0 20px 0px; border-radius:5px;}
|
195 |
-
div.s4-err-msg div.content{padding:5px; font-size:11px; line-height:17px; max-height:125px; overflow-y:scroll; border:1px solid silver; margin:3px; }
|
196 |
-
div.s4-err-msg div.info-error{padding:7px; background-color:#f9c9c9; border:1px solid silver; border-radius:2px; font-size:12px; line-height:16px }
|
197 |
-
div.s4-err-msg div.info-notice{padding:7px; background-color:#FCFEC5; border:1px solid silver; border-radius:2px; font-size:12px; line-height:16px;}
|
198 |
-
table.s4-final-step {width:100%;}
|
199 |
-
table.s4-final-step td {padding:5px 15px 5px 5px}
|
200 |
-
table.s4-final-step td:first-child {white-space:nowrap;}
|
201 |
-
div.s4-go-back {border-top:1px dotted #dfdfdf; margin:auto; font-style:italic; font-size:11px; color:#333; padding-top:4px}
|
202 |
-
div.s4-go-back ul {line-height:18px}
|
203 |
-
button.s4-final-btns {cursor:pointer; color:#fff; font-size:16px; border-radius:5px; padding:7px; background-color:#13659C; border:1px solid gray; width:165px;}
|
204 |
-
button.s4-final-btns:hover {background-color: #dfdfdf;}
|
205 |
-
div.s4-gopro-btn {text-align:center; font-size:14px; margin:auto; width:200px; font-style: italic; font-weight:bold}
|
206 |
-
div.s4-gopro-btn a{color:green}
|
207 |
-
|
208 |
-
|
209 |
-
/* PARSLEY:Overrides*/
|
210 |
-
input.parsley-error, textarea.parsley-error, select.parsley-error {
|
211 |
-
color:#B94A48 !important; background-color:#F2DEDE !important; border:1px solid #EED3D7 !important;
|
212 |
-
}
|
213 |
-
ul.parsley-errors-list {margin:1px 0 0 -40px; list-style-type:none; font-size:10px}
|
214 |
-
|
215 |
-
/* ============================
|
216 |
-
STEP 5 HELP
|
217 |
-
============================ */
|
218 |
-
div.help-target {float:right; font-size:11px}
|
219 |
-
div#main-help a.help-target {display:block; margin:5px}
|
220 |
-
div#main-help sup {font-size:11px; font-weight:normal; font-style:italic; color:blue}
|
221 |
-
div.help-online {text-align:center; font-size:18px; padding:10px 0 0 0; line-height:24px}
|
222 |
-
div.help {color:#555; font-style:italic; font-size:11px; padding:4px; border-top:1px solid #dfdfdf}
|
223 |
-
div.help-page {padding:5px 0 0 5px}
|
224 |
-
div.help-page fieldset {margin-bottom:25px}
|
225 |
-
div#main-help {font-size:13px; line-height:17px}
|
226 |
-
div#main-help h2 {background-color:#F1F1F1; border:1px solid silver; border-radius:4px; padding:10px; margin:26px 0 8px 0; font-size:22px; }
|
227 |
-
div#main-help h3 {border-bottom:1px solid silver; padding:8px; margin:4px 0 8px 0; font-size:20px}
|
228 |
-
div#main-help span.step {color:#DB4B38}
|
229 |
-
table.help-opt {width: 100%; border: none; border-collapse: collapse; margin:5px 0 0 0;}
|
230 |
-
table.help-opt td.section {background-color:#dfdfdf;}
|
231 |
-
table.help-opt td, th {padding:7px; border:1px solid silver;}
|
232 |
-
table.help-opt td:first-child {font-weight:bold; padding-right:10px; white-space:nowrap}
|
233 |
-
table.help-opt th {background: #333; color: #fff;border:1px solid #333; padding:3px}
|
234 |
-
|
235 |
-
|
236 |
-
<?php if ($GLOBALS['DUPX_DEBUG']) : ?>
|
237 |
-
.dupx-debug {display:block; margin:4px 0 30px 0; font-size:11px;}
|
238 |
-
.dupx-debug label {font-weight:bold; display:block; margin:6px 0 2px 0}
|
239 |
-
.dupx-debug textarea {width:95%; height:100px; font-size:11px}
|
240 |
-
<?php else : ?>
|
241 |
-
.dupx-debug {display:none}
|
242 |
-
<?php endif; ?>
|
243 |
-
small.s3-warn {color: maroon;font-style: italic;}
|
244 |
-
div.s4-warn {color: maroon;}
|
245 |
-
|
246 |
-
</style>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/build/assets/inc.js.php
DELETED
@@ -1,78 +0,0 @@
|
|
1 |
-
<?php defined("DUPXABSPATH") or die(""); ?>
|
2 |
-
<script>
|
3 |
-
//Unique namespace
|
4 |
-
DUPX = new Object();
|
5 |
-
|
6 |
-
DUPX.showProgressBar = function ()
|
7 |
-
{
|
8 |
-
DUPX.animateProgressBar('progress-bar');
|
9 |
-
$('#ajaxerr-area').hide();
|
10 |
-
$('#progress-area').show();
|
11 |
-
}
|
12 |
-
|
13 |
-
DUPX.hideProgressBar = function ()
|
14 |
-
{
|
15 |
-
$('#progress-area').hide(100);
|
16 |
-
$('#ajaxerr-area').fadeIn(400);
|
17 |
-
}
|
18 |
-
|
19 |
-
DUPX.animateProgressBar = function(id)
|
20 |
-
{
|
21 |
-
//Create Progress Bar
|
22 |
-
var $mainbar = $("#" + id);
|
23 |
-
$mainbar.progressbar({ value: 100 });
|
24 |
-
$mainbar.height(25);
|
25 |
-
runAnimation($mainbar);
|
26 |
-
|
27 |
-
function runAnimation($pb) {
|
28 |
-
$pb.css({ "padding-left": "0%", "padding-right": "90%" });
|
29 |
-
$pb.progressbar("option", "value", 100);
|
30 |
-
$pb.animate({ paddingLeft: "90%", paddingRight: "0%" }, 3500, "linear", function () { runAnimation($pb); });
|
31 |
-
}
|
32 |
-
}
|
33 |
-
|
34 |
-
DUPX.toggleAll = function(id)
|
35 |
-
{
|
36 |
-
$(id + " *[data-type='toggle']").each(function() {
|
37 |
-
$(this).trigger('click');
|
38 |
-
});
|
39 |
-
}
|
40 |
-
|
41 |
-
|
42 |
-
DUPX.toggleClick = function()
|
43 |
-
{
|
44 |
-
var id = $(this).attr('data-target');
|
45 |
-
var text = $(this).text().replace(/\+|\-/, "");
|
46 |
-
var icon = $(this).find('i.dupx-plus-square, i.dupx-minus-square');
|
47 |
-
var target = $(id);
|
48 |
-
$(icon).removeClass('dupx-plus-square dupx-minus-square');
|
49 |
-
|
50 |
-
if (target.is(':hidden') ) {
|
51 |
-
(icon.length)
|
52 |
-
? $(icon).addClass('dupx-minus-square')
|
53 |
-
: $(this).html("- " + text );
|
54 |
-
target.show();
|
55 |
-
} else {
|
56 |
-
(icon.length)
|
57 |
-
? $(icon).addClass('dupx-plus-square')
|
58 |
-
: $(this).html("+ " + text );
|
59 |
-
target.hide();
|
60 |
-
}
|
61 |
-
}
|
62 |
-
|
63 |
-
$(document).ready(function()
|
64 |
-
{
|
65 |
-
<?php if ($GLOBALS['DUPX_DEBUG']) : ?>
|
66 |
-
$("div.dupx-debug input[type=hidden], div.dupx-debug textarea").each(function() {
|
67 |
-
var label = '<label>' + $(this).attr('name') + ':</label>';
|
68 |
-
$(this).before(label);
|
69 |
-
$(this).after('<br/>');
|
70 |
-
});
|
71 |
-
$("div.dupx-debug input[type=hidden]").each(function() {
|
72 |
-
$(this).attr('type', 'text');
|
73 |
-
});
|
74 |
-
|
75 |
-
$("div.dupx-debug").prepend('<h2>Debug View</h2>');
|
76 |
-
<?php endif; ?>
|
77 |
-
});
|
78 |
-
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/build/assets/inc.libs.css.php
DELETED
@@ -1,48 +0,0 @@
|
|
1 |
-
<?php defined("DUPXABSPATH") or die(""); ?>
|
2 |
-
<?php
|
3 |
-
// Exit if accessed directly
|
4 |
-
if (! defined('DUPLICATOR_INIT')) {
|
5 |
-
$_baseURL = "http://" . strlen($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : $_SERVER['HTTP_HOST'];
|
6 |
-
header("HTTP/1.1 301 Moved Permanently");
|
7 |
-
header("Location: $_baseURL");
|
8 |
-
exit;
|
9 |
-
}
|
10 |
-
?>
|
11 |
-
<?php if( DUPX_U::isURLActive("ajax.googleapis.com", 443) ): ?>
|
12 |
-
<link rel='stylesheet' href='//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/themes/smoothness/jquery-ui.css' type='text/css' media='all' />
|
13 |
-
<?php else: ?>
|
14 |
-
<style type="text/css">
|
15 |
-
/*! jQuery UI - v1.11.2 - 2014-12-20
|
16 |
-
* http://jqueryui.com
|
17 |
-
* Includes: core.css, progressbar.css, theme.css
|
18 |
-
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
|
19 |
-
* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
|
20 |
-
|
21 |
-
.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,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");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #aaa;background:#fff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #999;background:#dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#212121;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-state-default .ui-icon{background-image:url("images/ui-icons_888888_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-active .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-highlight .ui-icon{background-image:url("images/ui-icons_2e83ff_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cd0a0a_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px}
|
22 |
-
</style>
|
23 |
-
<?php endif; ?>
|
24 |
-
|
25 |
-
|
26 |
-
<style type="text/css">
|
27 |
-
/*! * CSS Modal
|
28 |
-
* Copyright (c) 2015 CreativeDream
|
29 |
-
* Website https://github.com/CreativeDream/jquery.modal
|
30 |
-
* Version: 1.2.3 (10-04-2015)
|
31 |
-
*/
|
32 |
-
#modal-window{background-color:rgba(0,0,0,.35)}#modal-window>*{margin:0;padding:0;border:0;font:inherit;line-height:normal;vertical-align:baseline}#modal-window .modal-box{position:absolute;margin-bottom:10px;top:40%!important;background-color:#fff;font-family:sans-serif;color:#444;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;-webkit-box-shadow:0 0 7px rgba(0,0,0,.3);-moz-box-shadow:0 0 7px rgba(0,0,0,.3);box-shadow:0 0 7px rgba(0,0,0,.3);outline:0;overflow:hidden}#modal-window .modal-box.modal-size-normal{width:560px}#modal-window .modal-box.modal-size-small{width:350px}#modal-window .modal-box.modal-size-large{width:1000px}@media only screen and (max-width :580px){#modal-window .modal-box.modal-size-normal{width:96%;left:0!important;margin-left:2%!important;margin-right:2%}}@media only screen and (max-width :1020px){#modal-window .modal-box.modal-size-large{width:96%;left:0!important;margin-left:2%!important;margin-right:2%}}@media only screen and (max-width :370px){#modal-window .modal-box.modal-size-small{width:96%;left:0!important;margin-left:2%!important;margin-right:2%}}#modal-window .modal-box .modal-title{position:relative;padding:12px 15px;border-bottom:1px solid #e5e5e5;font-size:20px;overflow:hidden}#modal-window .modal-box .modal-title h3{font-size:20px;font-weight:400;line-height:normal;display:inline-block;margin:0;padding:0}#modal-window .modal-box .modal-title .modal-close-btn{position:absolute;display:block;width:14px;height:14px;right:20px;top:50%;margin-top:-7px;cursor:pointer;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpGNzdGMTE3NDA3MjA2ODExOEMxNDkyODc0N0NBMUEwNCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo3N0ZBOTUxNzNERkIxMUUyQUZGMEFDRjY0RjNFODlDOCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo3N0ZBOTUxNjNERkIxMUUyQUZGMEFDRjY0RjNFODlDOCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkY3N0YxMTc0MDcyMDY4MTE4MDgzRkQyMTE2MTM0QUNBIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkY3N0YxMTc0MDcyMDY4MTE4QzE0OTI4NzQ3Q0ExQTA0Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+5Ke+4QAAAMlJREFUeNqkk90KwyAMha0dvp/ghfthsFcb67YLYe83EBdZlCxL3KCFU0nM+WqjTqUUs+bZ1Nd2d6jDDDqDHqCk1AeQBx1B+Xa9vAFovmNBwFwSzAvIoWKFWJxciNGxmJtp3FeQMDkziCEfcCTObYUUEPE3JAg3xwawZKJBMsm5kZkDNIhqlgC0+J/cFyAIDTOD3fkABKXbeQSxP8xRaWyHNIAfdFvbHU8BJ9JdqdscktDTD9ITtCcnTLpMDRLwMlWPmdZe55cAAwD+1kOdnSr5eQAAAABJRU5ErkJggg==) center no-repeat;background-size:14px,14px;opacity:.5;filter:alpha(opacity=50)}#modal-window .modal-box .modal-title .modal-close-btn:hover{opacity:1;filter:alpha(opacity=100)}#modal-window .modal-box .modal-text{font-size:14px;padding:18px 15px;overflow-y:auto}#modal-window .modal-box img{height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#modal-window .modal-box .modal-text input.modal-prompt-input{width:97%;width:-webkit-calc(100% - 14px);width:-moz-calc(100% - 14px);width:calc(100% - 14px);display:block;outline:0;border:1px solid #ddd;border-top:1px solid #ccc;margin:10px 0;padding:6px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 0 2px #eee;-moz-box-shadow:inset 0 0 2px #eee;box-shadow:inset 0 0 2px #eee;-webkit-transition:all .1s linear;transition:all .1s linear}#modal-window .modal-box .modal-text input.modal-prompt-input:hover{border:1px solid #bbb;border-top:1px solid #aaa}#modal-window .modal-box .modal-text input.modal-prompt-input:active,#modal-window .modal-box .modal-text input.modal-prompt-input:focus{border-color:rgba(82,168,236,.8);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.3);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.3);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.3)}#modal-window .modal-box .modal-buttons{padding:10px 15px;text-align:right;background-color:#f9f9f9;border-top:1px solid #ddd}#modal-window .modal-box .modal-buttons a.modal-btn{display:inline-block;padding:8px 12px;outline:0;border:1px solid transparent;cursor:pointer;text-decoration:none;text-align:center;white-space:nowrap;font-size:12px;font-weight:700;line-height:normal;color:#555;vertical-align:middle}#modal-window .modal-box .modal-buttons a.modal-btn:active,a.modal-btn:focus{outline:0!important}#modal-window .modal-box .modal-buttons a.modal-btn:active,a.modal-btn.active{-webkit-box-shadow:inset 0 0 7px rgba(0,0,0,.2);-moz-box-shadow:inset 0 0 7px rgba(0,0,0,.2);box-shadow:inset 0 0 7px rgba(0,0,0,.2)}#modal-window .modal-box .modal-buttons a.modal-btn+a.modal-btn{margin-left:5px}#modal-window .modal-box .modal-buttons a.modal-btn.btn-disabled{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65)}#modal-window .modal-box .modal-buttons a.modal-btn.btn-large{padding:8px 14px;font-size:16px}#modal-window .modal-box .modal-buttons a.modal-btn.btn-small{padding:6px 8px;font-size:10px}#modal-window .modal-box .modal-buttons a.modal-btn.btn-rounded{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}#modal-window .modal-box .modal-buttons a.modal-btn.btn-circle{-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}#modal-window .modal-box .modal-buttons a.modal-btn.btn-square{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}#modal-window .modal-box .modal-buttons a.modal-btn i,#modal-window .modal-box .modal-buttons a.modal-btn img{vertical-align:middle;display:inline-block;float:left;max-height:16px;margin-right:5px}#modal-window .modal-box .modal-buttons a.modal-btn{background-color:#fcfcfc;border-color:#c9c9c9;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.08);-moz-box-shadow:0 1px 1px rgba(0,0,0,.08);box-shadow:0 1px 1px rgba(0,0,0,.08)}#modal-window .modal-box .modal-buttons a.modal-btn.btn-green{background-color:#5cb85c;border-color:#4cae4c;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-green:hover{background-color:#449d44;border-color:#398439;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-purple{background-color:#8149B4;border-color:#6922AD;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-purple:hover{background-color:#6f32a8;border-color:#5b149e;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-orange{background-color:#f7aa47;border-color:#eea236;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-orange:hover{background-color:#f69f2f;border-color:#d58512;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-pink{background-color:#ff6264;border-color:#eb5b5c;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-pink:hover{background-color:#ff484b;border-color:#e53a3d;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-turquoise{background-color:#00b19d;border-color:#11a594;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-turquoise:hover{background-color:#009886;border-color:#0b8173;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-light-green{background-color:#8dc63f;border-color:#7db432;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-light-green:hover{background-color:#82b838;border-color:#75a336;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-light-blue{background-color:#428bca;border-color:#357ebd;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-light-blue:hover{background-color:#3071a9;border-color:#285e8e;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-blue{background-color:#0e62c7;border-color:#0D54AA;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-blue:hover{background-color:#0c56af;border-color:#0B4992;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-red{background-color:#cc3f44;border-color:#bd1b21;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-red:hover{background-color:#ab2d32;border-color:#96050b;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-light-red{background-color:#d9534f;border-color:#d43f3a;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-light-red:hover{background-color:#c9302c;border-color:#ac2925;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-yellow{background-color:#ffba00;border-color:#e4a703;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-yellow:hover{background-color:#f0bb2e;border-color:#dba71a;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-black{background-color:#444;border-color:#313131;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-black:hover{background-color:#333;border-color:#222;color:#fff}#modal-window .modal-box .modal-buttons a.modal-btn.btn-white{background-color:#fff;color:#555;border:1px solid #ddd}#modal-window .modal-box .modal-buttons a.modal-btn.btn-white:hover{background-color:#f7f7f7;border:1px solid #ccc}#modal-window .modal-box .modal-buttons a.modal-btn.btn-white:active,#modal-window .modal-box .modal-buttons a.modal-btn.btn-white:focus{-webkit-box-shadow:inset 0 0 10px rgba(0,0,0,.1);-moz-box-shadow:inset 0 0 10px rgba(0,0,0,.1);box-shadow:inset 0 0 10px rgba(0,0,0,.1)}#modal-window .modal-box.modal-type-success .modal-title{background-color:#61b832}#modal-window .modal-box.modal-type-warning .modal-title{background-color:#f1b40e}#modal-window .modal-box.modal-type-error .modal-title{background-color:#de4343}#modal-window .modal-box.modal-type-info .modal-title{background-color:#4ea5cd}#modal-window .modal-box.modal-type-inverted .modal-title{background-color:#232B31}#modal-window .modal-box.modal-type-primary .modal-title{background-color:#428bca}#modal-window .modal-box.modal-type-error .modal-title,#modal-window .modal-box.modal-type-info .modal-title,#modal-window .modal-box.modal-type-inverted .modal-title,#modal-window .modal-box.modal-type-primary .modal-title,#modal-window .modal-box.modal-type-success .modal-title,#modal-window .modal-box.modal-type-warning .modal-title{color:#FFF;text-shadow:0 1px 3px rgba(0,0,0,.25);border-bottom-color:transparent}#modal-window .modal-box.modal-type-error .modal-title .modal-close-btn,#modal-window .modal-box.modal-type-info .modal-title .modal-close-btn,#modal-window .modal-box.modal-type-inverted .modal-title .modal-close-btn,#modal-window .modal-box.modal-type-primary .modal-title .modal-close-btn,#modal-window .modal-box.modal-type-success .modal-title .modal-close-btn,#modal-window .modal-box.modal-type-warning .modal-title .modal-close-btn{background:url('data:image/png;base64,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') center no-repeat}#modal-window .modal-box.modal-theme-reseted{background:0 0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}#modal-window .modal-box.modal-theme-reseted .modal-title{border-bottom:0;padding:0}#modal-window .modal-box.modal-theme-reseted .modal-title .modal-close-btn{right:0}#modal-window .modal-box.modal-theme-reseted .modal-text{padding:0}#modal-window .modal-box.modal-theme-reseted .modal-buttons{border-top:0;background:0 0;padding:0}
|
33 |
-
|
34 |
-
/*CSS ICONS
|
35 |
-
http://androidcss.com/css-shape-icon-generator/
|
36 |
-
*/
|
37 |
-
|
38 |
-
.dupx-plus-square{display:inline-block!important;position:relative;width:14px;height:14px;border-radius:25%;background-color:#000000;box-sizing:content-box}
|
39 |
-
.dupx-plus-square:before{position:absolute;content:'';margin:auto;width:calc(14px/8);height:calc(14px/1.5);background-color:#fff;top:0;bottom:0;left:0;right:0}
|
40 |
-
.dupx-plus-square:after{position:absolute;content:'';margin:auto;width:calc(14px/1.5);height:calc(14px/8);background-color:#fff;top:0;bottom:0;left:0;right:0}
|
41 |
-
|
42 |
-
.dupx-minus-square{display:inline-block!important;position:relative;width:14px;height:14px;border-radius:25%;background-color:#000000;box-sizing:content-box}
|
43 |
-
.dupx-minus-square:after{position:absolute;content:'';margin:auto;width:calc(14px/1.5);height:calc(14px/10);background-color:#fff;top:0;bottom:0;left:0;right:0}
|
44 |
-
|
45 |
-
|
46 |
-
</style>
|
47 |
-
|
48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/build/assets/inc.libs.js.php
DELETED
@@ -1,191 +0,0 @@
|
|
1 |
-
<?php defined("DUPXABSPATH") or die(""); ?>
|
2 |
-
<?php
|
3 |
-
// Exit if accessed directly
|
4 |
-
if (! defined('DUPLICATOR_INIT')) {
|
5 |
-
$_baseURL = "http://" . strlen($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : $_SERVER['HTTP_HOST'];
|
6 |
-
header("HTTP/1.1 301 Moved Permanently");
|
7 |
-
header("Location: $_baseURL");
|
8 |
-
exit;
|
9 |
-
}
|
10 |
-
?>
|
11 |
-
<!-- ========================================
|
12 |
-
JQUERY ASSETS -->
|
13 |
-
<?php if(DUPX_U::isURLActive("ajax.googleapis.com", 443) ): ?>
|
14 |
-
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
15 |
-
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
|
16 |
-
<?php else: ?>
|
17 |
-
<script type="text/javascript">
|
18 |
-
/*! jQuery v2.1.3 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
|
19 |
-
!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=hb(),z=hb(),A=hb(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},eb=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fb){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function gb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+rb(o[l]);w=ab.test(a)&&pb(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function hb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ib(a){return a[u]=!0,a}function jb(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function kb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function lb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function nb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function ob(a){return ib(function(b){return b=+b,ib(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pb(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=gb.support={},f=gb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=gb.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",eb,!1):e.attachEvent&&e.attachEvent("onunload",eb)),p=!f(g),c.attributes=jb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=jb(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=jb(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(jb(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\f]' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),jb(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&jb(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return lb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?lb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},gb.matches=function(a,b){return gb(a,null,null,b)},gb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return gb(b,n,null,[a]).length>0},gb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},gb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},gb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},gb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=gb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=gb.selectors={cacheLength:50,createPseudo:ib,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||gb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&gb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=gb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||gb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ib(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ib(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ib(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ib(function(a){return function(b){return gb(a,b).length>0}}),contains:ib(function(a){return a=a.replace(cb,db),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ib(function(a){return W.test(a||"")||gb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:ob(function(){return[0]}),last:ob(function(a,b){return[b-1]}),eq:ob(function(a,b,c){return[0>c?c+b:c]}),even:ob(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:ob(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:ob(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:ob(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=mb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=nb(b);function qb(){}qb.prototype=d.filters=d.pseudos,d.setFilters=new qb,g=gb.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?gb.error(a):z(a,i).slice(0)};function rb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function sb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function tb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ub(a,b,c){for(var d=0,e=b.length;e>d;d++)gb(a,b[d],c);return c}function vb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wb(a,b,c,d,e,f){return d&&!d[u]&&(d=wb(d)),e&&!e[u]&&(e=wb(e,f)),ib(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ub(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:vb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=vb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=vb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sb(function(a){return a===b},h,!0),l=sb(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sb(tb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wb(i>1&&tb(m),i>1&&rb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xb(a.slice(i,e)),f>e&&xb(a=a.slice(e)),f>e&&rb(a))}m.push(c)}return tb(m)}function yb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=vb(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&gb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ib(f):f}return h=gb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,yb(e,d)),f.selector=a}return f},i=gb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&pb(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&rb(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&pb(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=jb(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),jb(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||kb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&jb(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||kb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),jb(function(a){return null==a.getAttribute("disabled")})||kb(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),gb}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c)
|
20 |
-
},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=L.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var Q=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,R=["Top","Right","Bottom","Left"],S=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)},T=/^(?:checkbox|radio)$/i;!function(){var a=l.createDocumentFragment(),b=a.appendChild(l.createElement("div")),c=l.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||l,d=c.documentElement,e=c.body,a.pageX=b.clientX+(d&&d.scrollLeft||e&&e.scrollLeft||0)-(d&&d.clientLeft||e&&e.clientLeft||0),a.pageY=b.clientY+(d&&d.scrollTop||e&&e.scrollTop||0)-(d&&d.clientTop||e&&e.clientTop||0)),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=W.test(e)?this.mouseHooks:V.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new n.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=l),3===a.target.nodeType&&(a.target=a.target.parentNode),g.filter?g.filter(a,f):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==_()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===_()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&n.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=n.extend(new n.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?n.event.trigger(e,null,b):n.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?Z:$):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={isDefaultPrevented:$,isPropagationStopped:$,isImmediatePropagationStopped:$,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=Z,a&&a.preventDefault&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=Z,a&&a.stopPropagation&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=Z,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.focusinBubbles||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a),!0)};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=L.access(d,b);e||d.addEventListener(a,c,!0),L.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=L.access(d,b)-1;e?L.access(d,b,e):(d.removeEventListener(a,c,!0),L.remove(d,b))}}}),n.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(g in a)this.on(g,b,c,a[g],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=$;else if(!d)return this;return 1===e&&(f=d,d=function(a){return n().off(a),f.apply(this,arguments)},d.guid=f.guid||(f.guid=n.guid++)),this.each(function(){n.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=$),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var ab=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,ib={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1></$2>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=qb[0].contentDocument,b.write(),b.close(),c=sb(a,b),qb.detach()),rb[a]=c),c}var ub=/^margin/,vb=new RegExp("^("+Q+")(?!px)[a-z%]+$","i"),wb=function(b){return b.ownerDocument.defaultView.opener?b.ownerDocument.defaultView.getComputedStyle(b,null):a.getComputedStyle(b,null)};function xb(a,b,c){var d,e,f,g,h=a.style;return c=c||wb(a),c&&(g=c.getPropertyValue(b)||c[b]),c&&(""!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),vb.test(g)&&ub.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function yb(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d=l.documentElement,e=l.createElement("div"),f=l.createElement("div");if(f.style){f.style.backgroundClip="content-box",f.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===f.style.backgroundClip,e.style.cssText="border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;position:absolute",e.appendChild(f);function g(){f.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",f.innerHTML="",d.appendChild(e);var g=a.getComputedStyle(f,null);b="1%"!==g.top,c="4px"===g.width,d.removeChild(e)}a.getComputedStyle&&n.extend(k,{pixelPosition:function(){return g(),b},boxSizingReliable:function(){return null==c&&g(),c},reliableMarginRight:function(){var b,c=f.appendChild(l.createElement("div"));return c.style.cssText=f.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",f.style.width="1px",d.appendChild(e),b=!parseFloat(a.getComputedStyle(c,null).marginRight),d.removeChild(e),f.removeChild(c),b}})}}(),n.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var zb=/^(none|table(?!-c[ea]).+)/,Ab=new RegExp("^("+Q+")(.*)$","i"),Bb=new RegExp("^([+-])=("+Q+")","i"),Cb={position:"absolute",visibility:"hidden",display:"block"},Db={letterSpacing:"0",fontWeight:"400"},Eb=["Webkit","O","Moz","ms"];function Fb(a,b){if(b in a)return b;var c=b[0].toUpperCase()+b.slice(1),d=b,e=Eb.length;while(e--)if(b=Eb[e]+c,b in a)return b;return d}function Gb(a,b,c){var d=Ab.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Hb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+R[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+R[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+R[f]+"Width",!0,e))):(g+=n.css(a,"padding"+R[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+R[f]+"Width",!0,e)));return g}function Ib(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=wb(a),g="border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=xb(a,b,f),(0>e||null==e)&&(e=a.style[b]),vb.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Hb(a,b,c||(g?"border":"content"),d,f)+"px"}function Jb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=L.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&S(d)&&(f[g]=L.access(d,"olddisplay",tb(d.nodeName)))):(e=S(d),"none"===c&&e||L.set(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=xb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Fb(i,h)),g=n.cssHooks[b]||n.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=Bb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||n.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Fb(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=xb(a,b,d)),"normal"===e&&b in Db&&(e=Db[b]),""===c||c?(f=parseFloat(e),c===!0||n.isNumeric(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?zb.test(n.css(a,"display"))&&0===a.offsetWidth?n.swap(a,Cb,function(){return Ib(a,b,d)}):Ib(a,b,d):void 0},set:function(a,c,d){var e=d&&wb(a);return Gb(a,c,d?Hb(a,b,d,"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),n.cssHooks.marginRight=yb(k.reliableMarginRight,function(a,b){return b?n.swap(a,{display:"inline-block"},xb,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+R[d]+b]=f[d]||f[d-2]||f[0];return e}},ub.test(a)||(n.cssHooks[a+b].set=Gb)}),n.fn.extend({css:function(a,b){return J(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=wb(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Jb(this,!0)},hide:function(){return Jb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){S(this)?n(this).show():n(this).hide()})}});function Kb(a,b,c,d,e){return new Kb.prototype.init(a,b,c,d,e)}n.Tween=Kb,Kb.prototype={constructor:Kb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Kb.propHooks[this.prop];return a&&a.get?a.get(this):Kb.propHooks._default.get(this)},run:function(a){var b,c=Kb.propHooks[this.prop];return this.pos=b=this.options.duration?n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Kb.propHooks._default.set(this),this}},Kb.prototype.init.prototype=Kb.prototype,Kb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Kb.propHooks.scrollTop=Kb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=Kb.prototype.init,n.fx.step={};var Lb,Mb,Nb=/^(?:toggle|show|hide)$/,Ob=new RegExp("^(?:([+-])=|)("+Q+")([a-z%]*)$","i"),Pb=/queueHooks$/,Qb=[Vb],Rb={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=Ob.exec(b),f=e&&e[3]||(n.cssNumber[a]?"":"px"),g=(n.cssNumber[a]||"px"!==f&&+d)&&Ob.exec(n.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,n.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function Sb(){return setTimeout(function(){Lb=void 0}),Lb=n.now()}function Tb(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=R[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ub(a,b,c){for(var d,e=(Rb[b]||[]).concat(Rb["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Vb(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&S(a),q=L.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?L.get(a,"olddisplay")||tb(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Nb.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?tb(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=L.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;L.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ub(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function Wb(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function Xb(a,b,c){var d,e,f=0,g=Qb.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Lb||Sb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:Lb||Sb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(Wb(k,j.opts.specialEasing);g>f;f++)if(d=Qb[f].call(j,a,k,j.opts))return d;return n.map(k,Ub,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(Xb,{tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],Rb[c]=Rb[c]||[],Rb[c].unshift(b)},prefilter:function(a,b){b?Qb.unshift(a):Qb.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(S).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=Xb(this,n.extend({},a),f);(e||L.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=L.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Pb.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=L.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Tb(b,!0),a,d,e)}}),n.each({slideDown:Tb("show"),slideUp:Tb("hide"),slideToggle:Tb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(Lb=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),Lb=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Mb||(Mb=setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){clearInterval(Mb),Mb=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(a,b){return a=n.fx?n.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a=l.createElement("input"),b=l.createElement("select"),c=b.appendChild(l.createElement("option"));a.type="checkbox",k.checkOn=""!==a.value,k.optSelected=c.selected,b.disabled=!0,k.optDisabled=!c.disabled,a=l.createElement("input"),a.value="t",a.type="radio",k.radioValue="t"===a.value}();var Yb,Zb,$b=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return J(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===U?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?Zb:Yb)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void n.removeAttr(a,b))
|
21 |
-
},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),Zb={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=$b[b]||n.find.attr;$b[b]=function(a,b,d){var e,f;return d||(f=$b[b],$b[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,$b[b]=f),e}});var _b=/^(?:input|select|textarea|button)$/i;n.fn.extend({prop:function(a,b){return J(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){return a.hasAttribute("tabindex")||_b.test(a.nodeName)||a.href?a.tabIndex:-1}}}}),k.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var ac=/[\t\r\n\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h="string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=n.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0===arguments.length||"string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?n.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=n(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===U||"boolean"===c)&&(this.className&&L.set(this,"__className__",this.className),this.className=this.className||a===!1?"":L.get(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(ac," ").indexOf(b)>=0)return!0;return!1}});var bc=/\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(bc,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(d.value,f)>=0)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},k.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var cc=n.now(),dc=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.parseXML=function(a){var b,c;if(!a||"string"!=typeof a)return null;try{c=new DOMParser,b=c.parseFromString(a,"text/xml")}catch(d){b=void 0}return(!b||b.getElementsByTagName("parsererror").length)&&n.error("Invalid XML: "+a),b};var ec=/#.*$/,fc=/([?&])_=[^&]*/,gc=/^(.*?):[ \t]*([^\r\n]*)$/gm,hc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,ic=/^(?:GET|HEAD)$/,jc=/^\/\//,kc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,lc={},mc={},nc="*/".concat("*"),oc=a.location.href,pc=kc.exec(oc.toLowerCase())||[];function qc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(n.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function rc(a,b,c,d){var e={},f=a===mc;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function sc(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function tc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function uc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:oc,type:"GET",isLocal:hc.test(pc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":nc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?sc(sc(a,n.ajaxSettings),b):sc(n.ajaxSettings,a)},ajaxPrefilter:qc(lc),ajaxTransport:qc(mc),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!f){f={};while(b=gc.exec(e))f[b[1].toLowerCase()]=b[2]}b=f[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?e:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return c&&c.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||oc)+"").replace(ec,"").replace(jc,pc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(h=kc.exec(k.url.toLowerCase()),k.crossDomain=!(!h||h[1]===pc[1]&&h[2]===pc[2]&&(h[3]||("http:"===h[1]?"80":"443"))===(pc[3]||("http:"===pc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),rc(lc,k,b,v),2===t)return v;i=n.event&&k.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!ic.test(k.type),d=k.url,k.hasContent||(k.data&&(d=k.url+=(dc.test(d)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=fc.test(d)?d.replace(fc,"$1_="+cc++):d+(dc.test(d)?"&":"?")+"_="+cc++)),k.ifModified&&(n.lastModified[d]&&v.setRequestHeader("If-Modified-Since",n.lastModified[d]),n.etag[d]&&v.setRequestHeader("If-None-Match",n.etag[d])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+nc+"; q=0.01":""):k.accepts["*"]);for(j in k.headers)v.setRequestHeader(j,k.headers[j]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(j in{success:1,error:1,complete:1})v[j](k[j]);if(c=rc(mc,k,b,v)){v.readyState=1,i&&m.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,c.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,f,h){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),c=void 0,e=h||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,f&&(u=tc(k,v,f)),u=uc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(n.lastModified[d]=w),w=v.getResponseHeader("etag"),w&&(n.etag[d]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,i&&m.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),i&&(m.trigger("ajaxComplete",[v,k]),--n.active||n.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var vc=/%20/g,wc=/\[\]$/,xc=/\r?\n/g,yc=/^(?:submit|button|image|reset|file)$/i,zc=/^(?:input|select|textarea|keygen)/i;function Ac(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||wc.test(a)?d(a,e):Ac(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Ac(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Ac(c,a[c],b,e);return d.join("&").replace(vc,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&zc.test(this.nodeName)&&!yc.test(a)&&(this.checked||!T.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(xc,"\r\n")}}):{name:b.name,value:c.replace(xc,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(a){}};var Bc=0,Cc={},Dc={0:200,1223:204},Ec=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in Cc)Cc[a]()}),k.cors=!!Ec&&"withCredentials"in Ec,k.ajax=Ec=!!Ec,n.ajaxTransport(function(a){var b;return k.cors||Ec&&!a.crossDomain?{send:function(c,d){var e,f=a.xhr(),g=++Bc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)f.setRequestHeader(e,c[e]);b=function(a){return function(){b&&(delete Cc[g],b=f.onload=f.onerror=null,"abort"===a?f.abort():"error"===a?d(f.status,f.statusText):d(Dc[f.status]||f.status,f.statusText,"string"==typeof f.responseText?{text:f.responseText}:void 0,f.getAllResponseHeaders()))}},f.onload=b(),f.onerror=b("error"),b=Cc[g]=b("abort");try{f.send(a.hasContent&&a.data||null)}catch(h){if(b)throw h}},abort:function(){b&&b()}}:void 0}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(d,e){b=n("<script>").prop({async:!0,charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&e("error"===a.type?404:200,a.type)}),l.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Fc=[],Gc=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Fc.pop()||n.expando+"_"+cc++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Gc.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Gc.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Gc,"$1"+e):b.jsonp!==!1&&(b.url+=(dc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Fc.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||l;var d=v.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=n.buildFragment([a],b,e),e&&e.length&&n(e).remove(),n.merge([],d.childNodes))};var Hc=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&Hc)return Hc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e,dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,f||[a.responseText,b,a])}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var Ic=a.document.documentElement;function Jc(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(typeof d.getBoundingClientRect!==U&&(e=d.getBoundingClientRect()),c=Jc(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===n.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(d=a.offset()),d.top+=n.css(a[0],"borderTopWidth",!0),d.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-d.top-n.css(c,"marginTop",!0),left:b.left-d.left-n.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||Ic;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Ic})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(b,c){var d="pageYOffset"===c;n.fn[b]=function(e){return J(this,function(b,e,f){var g=Jc(b);return void 0===f?g?g[c]:b[e]:void(g?g.scrollTo(d?a.pageXOffset:f,d?f:a.pageYOffset):b[e]=f)},b,e,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=yb(k.pixelPosition,function(a,c){return c?(c=xb(a,b),vb.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return J(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var Kc=a.jQuery,Lc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Lc),b&&a.jQuery===n&&(a.jQuery=Kc),n},typeof b===U&&(a.jQuery=a.$=n),n});
|
22 |
-
</script>
|
23 |
-
<script type="text/javascript">
|
24 |
-
/*! jQuery UI - v1.11.2 - 2014-12-20
|
25 |
-
* http://jqueryui.com
|
26 |
-
* Includes: core.js, widget.js, progressbar.js
|
27 |
-
* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
|
28 |
-
(function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e(jQuery)})(function(e){function t(t,s){var n,a,o,r=t.nodeName.toLowerCase();return"area"===r?(n=t.parentNode,a=n.name,t.href&&a&&"map"===n.nodeName.toLowerCase()?(o=e("img[usemap='#"+a+"']")[0],!!o&&i(o)):!1):(/input|select|textarea|button|object/.test(r)?!t.disabled:"a"===r?t.href||s:s)&&i(t)}function i(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}e.ui=e.ui||{},e.extend(e.ui,{version:"1.11.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({scrollParent:function(t){var i=this.css("position"),s="absolute"===i,n=t?/(auto|scroll|hidden)/:/(auto|scroll)/,a=this.parents().filter(function(){var t=e(this);return s&&"static"===t.css("position")?!1:n.test(t.css("overflow")+t.css("overflow-y")+t.css("overflow-x"))}).eq(0);return"fixed"!==i&&a.length?a:e(this[0].ownerDocument||document)},uniqueId:function(){var e=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++e)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(i){return t(i,!isNaN(e.attr(i,"tabindex")))},tabbable:function(i){var s=e.attr(i,"tabindex"),n=isNaN(s);return(n||s>=0)&&t(i,!n)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(t,i){function s(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===i?["Left","Right"]:["Top","Bottom"],a=i.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+i]=function(t){return void 0===t?o["inner"+i].call(this):this.each(function(){e(this).css(a,s(this,t)+"px")})},e.fn["outer"+i]=function(t,n){return"number"!=typeof t?o["outer"+i].call(this,t):this.each(function(){e(this).css(a,s(this,t,!0,n)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),disableSelection:function(){var e="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.bind(e+".ui-disableSelection",function(e){e.preventDefault()})}}(),enableSelection:function(){return this.unbind(".ui-disableSelection")},zIndex:function(t){if(void 0!==t)return this.css("zIndex",t);if(this.length)for(var i,s,n=e(this[0]);n.length&&n[0]!==document;){if(i=n.css("position"),("absolute"===i||"relative"===i||"fixed"===i)&&(s=parseInt(n.css("zIndex"),10),!isNaN(s)&&0!==s))return s;n=n.parent()}return 0}}),e.ui.plugin={add:function(t,i,s){var n,a=e.ui[t].prototype;for(n in s)a.plugins[n]=a.plugins[n]||[],a.plugins[n].push([i,s[n]])},call:function(e,t,i,s){var n,a=e.plugins[t];if(a&&(s||e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType))for(n=0;a.length>n;n++)e.options[a[n][0]]&&a[n][1].apply(e.element,i)}};var s=0,n=Array.prototype.slice;e.cleanData=function(t){return function(i){var s,n,a;for(a=0;null!=(n=i[a]);a++)try{s=e._data(n,"events"),s&&s.remove&&e(n).triggerHandler("remove")}catch(o){}t(i)}}(e.cleanData),e.widget=function(t,i,s){var n,a,o,r,h={},l=t.split(".")[0];return t=t.split(".")[1],n=l+"-"+t,s||(s=i,i=e.Widget),e.expr[":"][n.toLowerCase()]=function(t){return!!e.data(t,n)},e[l]=e[l]||{},a=e[l][t],o=e[l][t]=function(e,t){return this._createWidget?(arguments.length&&this._createWidget(e,t),void 0):new o(e,t)},e.extend(o,a,{version:s.version,_proto:e.extend({},s),_childConstructors:[]}),r=new i,r.options=e.widget.extend({},r.options),e.each(s,function(t,s){return e.isFunction(s)?(h[t]=function(){var e=function(){return i.prototype[t].apply(this,arguments)},n=function(e){return i.prototype[t].apply(this,e)};return function(){var t,i=this._super,a=this._superApply;return this._super=e,this._superApply=n,t=s.apply(this,arguments),this._super=i,this._superApply=a,t}}(),void 0):(h[t]=s,void 0)}),o.prototype=e.widget.extend(r,{widgetEventPrefix:a?r.widgetEventPrefix||t:t},h,{constructor:o,namespace:l,widgetName:t,widgetFullName:n}),a?(e.each(a._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete a._childConstructors):i._childConstructors.push(o),e.widget.bridge(t,o),o},e.widget.extend=function(t){for(var i,s,a=n.call(arguments,1),o=0,r=a.length;r>o;o++)for(i in a[o])s=a[o][i],a[o].hasOwnProperty(i)&&void 0!==s&&(t[i]=e.isPlainObject(s)?e.isPlainObject(t[i])?e.widget.extend({},t[i],s):e.widget.extend({},s):s);return t},e.widget.bridge=function(t,i){var s=i.prototype.widgetFullName||t;e.fn[t]=function(a){var o="string"==typeof a,r=n.call(arguments,1),h=this;return a=!o&&r.length?e.widget.extend.apply(null,[a].concat(r)):a,o?this.each(function(){var i,n=e.data(this,s);return"instance"===a?(h=n,!1):n?e.isFunction(n[a])&&"_"!==a.charAt(0)?(i=n[a].apply(n,r),i!==n&&void 0!==i?(h=i&&i.jquery?h.pushStack(i.get()):i,!1):void 0):e.error("no such method '"+a+"' for "+t+" widget instance"):e.error("cannot call methods on "+t+" prior to initialization; "+"attempted to call method '"+a+"'")}):this.each(function(){var t=e.data(this,s);t?(t.option(a||{}),t._init&&t._init()):e.data(this,s,new i(a,this))}),h}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,i){i=e(i||this.defaultElement||this)[0],this.element=e(i),this.uuid=s++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=e(),this.hoverable=e(),this.focusable=e(),i!==this&&(e.data(i,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===i&&this.destroy()}}),this.document=e(i.style?i.ownerDocument:i.document||i),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(t,i){var s,n,a,o=t;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof t)if(o={},s=t.split("."),t=s.shift(),s.length){for(n=o[t]=e.widget.extend({},this.options[t]),a=0;s.length-1>a;a++)n[s[a]]=n[s[a]]||{},n=n[s[a]];if(t=s.pop(),1===arguments.length)return void 0===n[t]?null:n[t];n[t]=i}else{if(1===arguments.length)return void 0===this.options[t]?null:this.options[t];o[t]=i}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!t),t&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(t,i,s){var n,a=this;"boolean"!=typeof t&&(s=i,i=t,t=!1),s?(i=n=e(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),e.each(s,function(s,o){function r(){return t||a.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?a[o]:o).apply(a,arguments):void 0}"string"!=typeof o&&(r.guid=o.guid=o.guid||r.guid||e.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+a.eventNamespace,u=h[2];u?n.delegate(u,l,r):i.bind(l,r)})},_off:function(t,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(i).undelegate(i),this.bindings=e(this.bindings.not(t).get()),this.focusable=e(this.focusable.not(t).get()),this.hoverable=e(this.hoverable.not(t).get())},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,o=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(o)&&o.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var o,r=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),o=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),o&&e.effects&&e.effects.effect[r]?s[t](n):r!==t&&s[r]?s[r](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}}),e.widget,e.widget("ui.progressbar",{version:"1.11.2",options:{max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min}),this.valueDiv=e("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(e){return void 0===e?this.options.value:(this.options.value=this._constrainedValue(e),this._refreshValue(),void 0)},_constrainedValue:function(e){return void 0===e&&(e=this.options.value),this.indeterminate=e===!1,"number"!=typeof e&&(e=0),this.indeterminate?!1:Math.min(this.options.max,Math.max(this.min,e))},_setOptions:function(e){var t=e.value;delete e.value,this._super(e),this.options.value=this._constrainedValue(t),this._refreshValue()},_setOption:function(e,t){"max"===e&&(t=Math.max(this.min,t)),"disabled"===e&&this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this._super(e,t)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var t=this.options.value,i=this._percentage();this.valueDiv.toggle(this.indeterminate||t>this.min).toggleClass("ui-corner-right",t===this.options.max).width(i.toFixed(0)+"%"),this.element.toggleClass("ui-progressbar-indeterminate",this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=e("<div class='ui-progressbar-overlay'></div>").appendTo(this.valueDiv))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":t}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==t&&(this.oldValue=t,this._trigger("change")),t===this.options.max&&this._trigger("complete")}})});
|
29 |
-
</script>
|
30 |
-
<?php endif; ?>
|
31 |
-
|
32 |
-
<!-- ========================================
|
33 |
-
KNOCKOUT ASSETS -->
|
34 |
-
<?php if( DUPX_U::isURLActive("ajax.aspnetcdn.com", 443) ): ?>
|
35 |
-
<script src="//ajax.aspnetcdn.com/ajax/knockout/knockout-2.2.1.js"></script>
|
36 |
-
<?php else: ?>
|
37 |
-
<script type="text/javascript">
|
38 |
-
// Knockout JavaScript library v2.2.1
|
39 |
-
// (c) Steven Sanderson - http://knockoutjs.com/
|
40 |
-
// License: MIT (http://www.opensource.org/licenses/mit-license.php)
|
41 |
-
|
42 |
-
(function() {function j(w){throw w;}var m=!0,p=null,r=!1;function u(w){return function(){return w}};var x=window,y=document,ga=navigator,F=window.jQuery,I=void 0;
|
43 |
-
function L(w){function ha(a,d,c,e,f){var g=[];a=b.j(function(){var a=d(c,f)||[];0<g.length&&(b.a.Ya(M(g),a),e&&b.r.K(e,p,[c,a,f]));g.splice(0,g.length);b.a.P(g,a)},p,{W:a,Ka:function(){return 0==g.length||!b.a.X(g[0])}});return{M:g,j:a.pa()?a:I}}function M(a){for(;a.length&&!b.a.X(a[0]);)a.splice(0,1);if(1<a.length){for(var d=a[0],c=a[a.length-1],e=[d];d!==c;){d=d.nextSibling;if(!d)return;e.push(d)}Array.prototype.splice.apply(a,[0,a.length].concat(e))}return a}function S(a,b,c,e,f){var g=Math.min,
|
44 |
-
h=Math.max,k=[],l,n=a.length,q,s=b.length,v=s-n||1,G=n+s+1,J,A,z;for(l=0;l<=n;l++){A=J;k.push(J=[]);z=g(s,l+v);for(q=h(0,l-1);q<=z;q++)J[q]=q?l?a[l-1]===b[q-1]?A[q-1]:g(A[q]||G,J[q-1]||G)+1:q+1:l+1}g=[];h=[];v=[];l=n;for(q=s;l||q;)s=k[l][q]-1,q&&s===k[l][q-1]?h.push(g[g.length]={status:c,value:b[--q],index:q}):l&&s===k[l-1][q]?v.push(g[g.length]={status:e,value:a[--l],index:l}):(g.push({status:"retained",value:b[--q]}),--l);if(h.length&&v.length){a=10*n;var t;for(b=c=0;(f||b<a)&&(t=h[c]);c++){for(e=
|
45 |
-
0;k=v[e];e++)if(t.value===k.value){t.moved=k.index;k.moved=t.index;v.splice(e,1);b=e=0;break}b+=e}}return g.reverse()}function T(a,d,c,e,f){f=f||{};var g=a&&N(a),g=g&&g.ownerDocument,h=f.templateEngine||O;b.za.vb(c,h,g);c=h.renderTemplate(c,e,f,g);("number"!=typeof c.length||0<c.length&&"number"!=typeof c[0].nodeType)&&j(Error("Template engine must return an array of DOM nodes"));g=r;switch(d){case "replaceChildren":b.e.N(a,c);g=m;break;case "replaceNode":b.a.Ya(a,c);g=m;break;case "ignoreTargetNode":break;
|
46 |
-
default:j(Error("Unknown renderMode: "+d))}g&&(U(c,e),f.afterRender&&b.r.K(f.afterRender,p,[c,e.$data]));return c}function N(a){return a.nodeType?a:0<a.length?a[0]:p}function U(a,d){if(a.length){var c=a[0],e=a[a.length-1];V(c,e,function(a){b.Da(d,a)});V(c,e,function(a){b.s.ib(a,[d])})}}function V(a,d,c){var e;for(d=b.e.nextSibling(d);a&&(e=a)!==d;)a=b.e.nextSibling(e),(1===e.nodeType||8===e.nodeType)&&c(e)}function W(a,d,c){a=b.g.aa(a);for(var e=b.g.Q,f=0;f<a.length;f++){var g=a[f].key;if(e.hasOwnProperty(g)){var h=
|
47 |
-
e[g];"function"===typeof h?(g=h(a[f].value))&&j(Error(g)):h||j(Error("This template engine does not support the '"+g+"' binding within its templates"))}}a="ko.__tr_ambtns(function($context,$element){return(function(){return{ "+b.g.ba(a)+" } })()})";return c.createJavaScriptEvaluatorBlock(a)+d}function X(a,d,c,e){function f(a){return function(){return k[a]}}function g(){return k}var h=0,k,l;b.j(function(){var n=c&&c instanceof b.z?c:new b.z(b.a.d(c)),q=n.$data;e&&b.eb(a,n);if(k=("function"==typeof d?
|
48 |
-
d(n,a):d)||b.J.instance.getBindings(a,n)){if(0===h){h=1;for(var s in k){var v=b.c[s];v&&8===a.nodeType&&!b.e.I[s]&&j(Error("The binding '"+s+"' cannot be used with virtual elements"));if(v&&"function"==typeof v.init&&(v=(0,v.init)(a,f(s),g,q,n))&&v.controlsDescendantBindings)l!==I&&j(Error("Multiple bindings ("+l+" and "+s+") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.")),l=s}h=2}if(2===h)for(s in k)(v=b.c[s])&&"function"==
|
49 |
-
typeof v.update&&(0,v.update)(a,f(s),g,q,n)}},p,{W:a});return{Nb:l===I}}function Y(a,d,c){var e=m,f=1===d.nodeType;f&&b.e.Ta(d);if(f&&c||b.J.instance.nodeHasBindings(d))e=X(d,p,a,c).Nb;e&&Z(a,d,!f)}function Z(a,d,c){for(var e=b.e.firstChild(d);d=e;)e=b.e.nextSibling(d),Y(a,d,c)}function $(a,b){var c=aa(a,b);return c?0<c.length?c[c.length-1].nextSibling:a.nextSibling:p}function aa(a,b){for(var c=a,e=1,f=[];c=c.nextSibling;){if(H(c)&&(e--,0===e))return f;f.push(c);B(c)&&e++}b||j(Error("Cannot find closing comment tag to match: "+
|
50 |
-
a.nodeValue));return p}function H(a){return 8==a.nodeType&&(K?a.text:a.nodeValue).match(ia)}function B(a){return 8==a.nodeType&&(K?a.text:a.nodeValue).match(ja)}function P(a,b){for(var c=p;a!=c;)c=a,a=a.replace(ka,function(a,c){return b[c]});return a}function la(){var a=[],d=[];this.save=function(c,e){var f=b.a.i(a,c);0<=f?d[f]=e:(a.push(c),d.push(e))};this.get=function(c){c=b.a.i(a,c);return 0<=c?d[c]:I}}function ba(a,b,c){function e(e){var g=b(a[e]);switch(typeof g){case "boolean":case "number":case "string":case "function":f[e]=
|
51 |
-
g;break;case "object":case "undefined":var h=c.get(g);f[e]=h!==I?h:ba(g,b,c)}}c=c||new la;a=b(a);if(!("object"==typeof a&&a!==p&&a!==I&&!(a instanceof Date)))return a;var f=a instanceof Array?[]:{};c.save(a,f);var g=a;if(g instanceof Array){for(var h=0;h<g.length;h++)e(h);"function"==typeof g.toJSON&&e("toJSON")}else for(h in g)e(h);return f}function ca(a,d){if(a)if(8==a.nodeType){var c=b.s.Ua(a.nodeValue);c!=p&&d.push({sb:a,Fb:c})}else if(1==a.nodeType)for(var c=0,e=a.childNodes,f=e.length;c<f;c++)ca(e[c],
|
52 |
-
d)}function Q(a,d,c,e){b.c[a]={init:function(a){b.a.f.set(a,da,{});return{controlsDescendantBindings:m}},update:function(a,g,h,k,l){h=b.a.f.get(a,da);g=b.a.d(g());k=!c!==!g;var n=!h.Za;if(n||d||k!==h.qb)n&&(h.Za=b.a.Ia(b.e.childNodes(a),m)),k?(n||b.e.N(a,b.a.Ia(h.Za)),b.Ea(e?e(l,g):l,a)):b.e.Y(a),h.qb=k}};b.g.Q[a]=r;b.e.I[a]=m}function ea(a,d,c){c&&d!==b.k.q(a)&&b.k.T(a,d);d!==b.k.q(a)&&b.r.K(b.a.Ba,p,[a,"change"])}var b="undefined"!==typeof w?w:{};b.b=function(a,d){for(var c=a.split("."),e=b,f=0;f<
|
53 |
-
c.length-1;f++)e=e[c[f]];e[c[c.length-1]]=d};b.p=function(a,b,c){a[b]=c};b.version="2.2.1";b.b("version",b.version);b.a=new function(){function a(a,d){if("input"!==b.a.u(a)||!a.type||"click"!=d.toLowerCase())return r;var c=a.type;return"checkbox"==c||"radio"==c}var d=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,c={},e={};c[/Firefox\/2/i.test(ga.userAgent)?"KeyboardEvent":"UIEvents"]=["keyup","keydown","keypress"];c.MouseEvents="click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave".split(" ");
|
54 |
-
for(var f in c){var g=c[f];if(g.length)for(var h=0,k=g.length;h<k;h++)e[g[h]]=f}var l={propertychange:m},n,c=3;f=y.createElement("div");for(g=f.getElementsByTagName("i");f.innerHTML="\x3c!--[if gt IE "+ ++c+"]><i></i><![endif]--\x3e",g[0];);n=4<c?c:I;return{Na:["authenticity_token",/^__RequestVerificationToken(_.*)?$/],o:function(a,b){for(var d=0,c=a.length;d<c;d++)b(a[d])},i:function(a,b){if("function"==typeof Array.prototype.indexOf)return Array.prototype.indexOf.call(a,b);for(var d=0,c=a.length;d<
|
55 |
-
c;d++)if(a[d]===b)return d;return-1},lb:function(a,b,d){for(var c=0,e=a.length;c<e;c++)if(b.call(d,a[c]))return a[c];return p},ga:function(a,d){var c=b.a.i(a,d);0<=c&&a.splice(c,1)},Ga:function(a){a=a||[];for(var d=[],c=0,e=a.length;c<e;c++)0>b.a.i(d,a[c])&&d.push(a[c]);return d},V:function(a,b){a=a||[];for(var d=[],c=0,e=a.length;c<e;c++)d.push(b(a[c]));return d},fa:function(a,b){a=a||[];for(var d=[],c=0,e=a.length;c<e;c++)b(a[c])&&d.push(a[c]);return d},P:function(a,b){if(b instanceof Array)a.push.apply(a,
|
56 |
-
b);else for(var d=0,c=b.length;d<c;d++)a.push(b[d]);return a},extend:function(a,b){if(b)for(var d in b)b.hasOwnProperty(d)&&(a[d]=b[d]);return a},ka:function(a){for(;a.firstChild;)b.removeNode(a.firstChild)},Hb:function(a){a=b.a.L(a);for(var d=y.createElement("div"),c=0,e=a.length;c<e;c++)d.appendChild(b.A(a[c]));return d},Ia:function(a,d){for(var c=0,e=a.length,g=[];c<e;c++){var f=a[c].cloneNode(m);g.push(d?b.A(f):f)}return g},N:function(a,d){b.a.ka(a);if(d)for(var c=0,e=d.length;c<e;c++)a.appendChild(d[c])},
|
57 |
-
Ya:function(a,d){var c=a.nodeType?[a]:a;if(0<c.length){for(var e=c[0],g=e.parentNode,f=0,h=d.length;f<h;f++)g.insertBefore(d[f],e);f=0;for(h=c.length;f<h;f++)b.removeNode(c[f])}},bb:function(a,b){7>n?a.setAttribute("selected",b):a.selected=b},D:function(a){return(a||"").replace(d,"")},Rb:function(a,d){for(var c=[],e=(a||"").split(d),f=0,g=e.length;f<g;f++){var h=b.a.D(e[f]);""!==h&&c.push(h)}return c},Ob:function(a,b){a=a||"";return b.length>a.length?r:a.substring(0,b.length)===b},tb:function(a,b){if(b.compareDocumentPosition)return 16==
|
58 |
-
(b.compareDocumentPosition(a)&16);for(;a!=p;){if(a==b)return m;a=a.parentNode}return r},X:function(a){return b.a.tb(a,a.ownerDocument)},u:function(a){return a&&a.tagName&&a.tagName.toLowerCase()},n:function(b,d,c){var e=n&&l[d];if(!e&&"undefined"!=typeof F){if(a(b,d)){var f=c;c=function(a,b){var d=this.checked;b&&(this.checked=b.nb!==m);f.call(this,a);this.checked=d}}F(b).bind(d,c)}else!e&&"function"==typeof b.addEventListener?b.addEventListener(d,c,r):"undefined"!=typeof b.attachEvent?b.attachEvent("on"+
|
59 |
-
d,function(a){c.call(b,a)}):j(Error("Browser doesn't support addEventListener or attachEvent"))},Ba:function(b,d){(!b||!b.nodeType)&&j(Error("element must be a DOM node when calling triggerEvent"));if("undefined"!=typeof F){var c=[];a(b,d)&&c.push({nb:b.checked});F(b).trigger(d,c)}else"function"==typeof y.createEvent?"function"==typeof b.dispatchEvent?(c=y.createEvent(e[d]||"HTMLEvents"),c.initEvent(d,m,m,x,0,0,0,0,0,r,r,r,r,0,b),b.dispatchEvent(c)):j(Error("The supplied element doesn't support dispatchEvent")):
|
60 |
-
"undefined"!=typeof b.fireEvent?(a(b,d)&&(b.checked=b.checked!==m),b.fireEvent("on"+d)):j(Error("Browser doesn't support triggering events"))},d:function(a){return b.$(a)?a():a},ua:function(a){return b.$(a)?a.t():a},da:function(a,d,c){if(d){var e=/[\w-]+/g,f=a.className.match(e)||[];b.a.o(d.match(e),function(a){var d=b.a.i(f,a);0<=d?c||f.splice(d,1):c&&f.push(a)});a.className=f.join(" ")}},cb:function(a,d){var c=b.a.d(d);if(c===p||c===I)c="";if(3===a.nodeType)a.data=c;else{var e=b.e.firstChild(a);
|
61 |
-
!e||3!=e.nodeType||b.e.nextSibling(e)?b.e.N(a,[y.createTextNode(c)]):e.data=c;b.a.wb(a)}},ab:function(a,b){a.name=b;if(7>=n)try{a.mergeAttributes(y.createElement("<input name='"+a.name+"'/>"),r)}catch(d){}},wb:function(a){9<=n&&(a=1==a.nodeType?a:a.parentNode,a.style&&(a.style.zoom=a.style.zoom))},ub:function(a){if(9<=n){var b=a.style.width;a.style.width=0;a.style.width=b}},Lb:function(a,d){a=b.a.d(a);d=b.a.d(d);for(var c=[],e=a;e<=d;e++)c.push(e);return c},L:function(a){for(var b=[],d=0,c=a.length;d<
|
62 |
-
c;d++)b.push(a[d]);return b},Pb:6===n,Qb:7===n,Z:n,Oa:function(a,d){for(var c=b.a.L(a.getElementsByTagName("input")).concat(b.a.L(a.getElementsByTagName("textarea"))),e="string"==typeof d?function(a){return a.name===d}:function(a){return d.test(a.name)},f=[],g=c.length-1;0<=g;g--)e(c[g])&&f.push(c[g]);return f},Ib:function(a){return"string"==typeof a&&(a=b.a.D(a))?x.JSON&&x.JSON.parse?x.JSON.parse(a):(new Function("return "+a))():p},xa:function(a,d,c){("undefined"==typeof JSON||"undefined"==typeof JSON.stringify)&&
|
63 |
-
j(Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js"));return JSON.stringify(b.a.d(a),d,c)},Jb:function(a,d,c){c=c||{};var e=c.params||{},f=c.includeFields||this.Na,g=a;if("object"==typeof a&&"form"===b.a.u(a))for(var g=a.action,h=f.length-1;0<=h;h--)for(var k=b.a.Oa(a,f[h]),l=k.length-1;0<=l;l--)e[k[l].name]=k[l].value;d=b.a.d(d);var n=y.createElement("form");
|
64 |
-
n.style.display="none";n.action=g;n.method="post";for(var w in d)a=y.createElement("input"),a.name=w,a.value=b.a.xa(b.a.d(d[w])),n.appendChild(a);for(w in e)a=y.createElement("input"),a.name=w,a.value=e[w],n.appendChild(a);y.body.appendChild(n);c.submitter?c.submitter(n):n.submit();setTimeout(function(){n.parentNode.removeChild(n)},0)}}};b.b("utils",b.a);b.b("utils.arrayForEach",b.a.o);b.b("utils.arrayFirst",b.a.lb);b.b("utils.arrayFilter",b.a.fa);b.b("utils.arrayGetDistinctValues",b.a.Ga);b.b("utils.arrayIndexOf",
|
65 |
-
b.a.i);b.b("utils.arrayMap",b.a.V);b.b("utils.arrayPushAll",b.a.P);b.b("utils.arrayRemoveItem",b.a.ga);b.b("utils.extend",b.a.extend);b.b("utils.fieldsIncludedWithJsonPost",b.a.Na);b.b("utils.getFormFields",b.a.Oa);b.b("utils.peekObservable",b.a.ua);b.b("utils.postJson",b.a.Jb);b.b("utils.parseJson",b.a.Ib);b.b("utils.registerEventHandler",b.a.n);b.b("utils.stringifyJson",b.a.xa);b.b("utils.range",b.a.Lb);b.b("utils.toggleDomNodeCssClass",b.a.da);b.b("utils.triggerEvent",b.a.Ba);b.b("utils.unwrapObservable",
|
66 |
-
b.a.d);Function.prototype.bind||(Function.prototype.bind=function(a){var b=this,c=Array.prototype.slice.call(arguments);a=c.shift();return function(){return b.apply(a,c.concat(Array.prototype.slice.call(arguments)))}});b.a.f=new function(){var a=0,d="__ko__"+(new Date).getTime(),c={};return{get:function(a,d){var c=b.a.f.la(a,r);return c===I?I:c[d]},set:function(a,d,c){c===I&&b.a.f.la(a,r)===I||(b.a.f.la(a,m)[d]=c)},la:function(b,f){var g=b[d];if(!g||!("null"!==g&&c[g])){if(!f)return I;g=b[d]="ko"+
|
67 |
-
a++;c[g]={}}return c[g]},clear:function(a){var b=a[d];return b?(delete c[b],a[d]=p,m):r}}};b.b("utils.domData",b.a.f);b.b("utils.domData.clear",b.a.f.clear);b.a.F=new function(){function a(a,d){var e=b.a.f.get(a,c);e===I&&d&&(e=[],b.a.f.set(a,c,e));return e}function d(c){var e=a(c,r);if(e)for(var e=e.slice(0),k=0;k<e.length;k++)e[k](c);b.a.f.clear(c);"function"==typeof F&&"function"==typeof F.cleanData&&F.cleanData([c]);if(f[c.nodeType])for(e=c.firstChild;c=e;)e=c.nextSibling,8===c.nodeType&&d(c)}
|
68 |
-
var c="__ko_domNodeDisposal__"+(new Date).getTime(),e={1:m,8:m,9:m},f={1:m,9:m};return{Ca:function(b,d){"function"!=typeof d&&j(Error("Callback must be a function"));a(b,m).push(d)},Xa:function(d,e){var f=a(d,r);f&&(b.a.ga(f,e),0==f.length&&b.a.f.set(d,c,I))},A:function(a){if(e[a.nodeType]&&(d(a),f[a.nodeType])){var c=[];b.a.P(c,a.getElementsByTagName("*"));for(var k=0,l=c.length;k<l;k++)d(c[k])}return a},removeNode:function(a){b.A(a);a.parentNode&&a.parentNode.removeChild(a)}}};b.A=b.a.F.A;b.removeNode=
|
69 |
-
b.a.F.removeNode;b.b("cleanNode",b.A);b.b("removeNode",b.removeNode);b.b("utils.domNodeDisposal",b.a.F);b.b("utils.domNodeDisposal.addDisposeCallback",b.a.F.Ca);b.b("utils.domNodeDisposal.removeDisposeCallback",b.a.F.Xa);b.a.ta=function(a){var d;if("undefined"!=typeof F)if(F.parseHTML)d=F.parseHTML(a);else{if((d=F.clean([a]))&&d[0]){for(a=d[0];a.parentNode&&11!==a.parentNode.nodeType;)a=a.parentNode;a.parentNode&&a.parentNode.removeChild(a)}}else{var c=b.a.D(a).toLowerCase();d=y.createElement("div");
|
70 |
-
c=c.match(/^<(thead|tbody|tfoot)/)&&[1,"<table>","</table>"]||!c.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!c.indexOf("<td")||!c.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||[0,"",""];a="ignored<div>"+c[1]+a+c[2]+"</div>";for("function"==typeof x.innerShiv?d.appendChild(x.innerShiv(a)):d.innerHTML=a;c[0]--;)d=d.lastChild;d=b.a.L(d.lastChild.childNodes)}return d};b.a.ca=function(a,d){b.a.ka(a);d=b.a.d(d);if(d!==p&&d!==I)if("string"!=typeof d&&(d=d.toString()),
|
71 |
-
"undefined"!=typeof F)F(a).html(d);else for(var c=b.a.ta(d),e=0;e<c.length;e++)a.appendChild(c[e])};b.b("utils.parseHtmlFragment",b.a.ta);b.b("utils.setHtml",b.a.ca);var R={};b.s={ra:function(a){"function"!=typeof a&&j(Error("You can only pass a function to ko.memoization.memoize()"));var b=(4294967296*(1+Math.random())|0).toString(16).substring(1)+(4294967296*(1+Math.random())|0).toString(16).substring(1);R[b]=a;return"\x3c!--[ko_memo:"+b+"]--\x3e"},hb:function(a,b){var c=R[a];c===I&&j(Error("Couldn't find any memo with ID "+
|
72 |
-
a+". Perhaps it's already been unmemoized."));try{return c.apply(p,b||[]),m}finally{delete R[a]}},ib:function(a,d){var c=[];ca(a,c);for(var e=0,f=c.length;e<f;e++){var g=c[e].sb,h=[g];d&&b.a.P(h,d);b.s.hb(c[e].Fb,h);g.nodeValue="";g.parentNode&&g.parentNode.removeChild(g)}},Ua:function(a){return(a=a.match(/^\[ko_memo\:(.*?)\]$/))?a[1]:p}};b.b("memoization",b.s);b.b("memoization.memoize",b.s.ra);b.b("memoization.unmemoize",b.s.hb);b.b("memoization.parseMemoText",b.s.Ua);b.b("memoization.unmemoizeDomNodeAndDescendants",
|
73 |
-
b.s.ib);b.Ma={throttle:function(a,d){a.throttleEvaluation=d;var c=p;return b.j({read:a,write:function(b){clearTimeout(c);c=setTimeout(function(){a(b)},d)}})},notify:function(a,d){a.equalityComparer="always"==d?u(r):b.m.fn.equalityComparer;return a}};b.b("extenders",b.Ma);b.fb=function(a,d,c){this.target=a;this.ha=d;this.rb=c;b.p(this,"dispose",this.B)};b.fb.prototype.B=function(){this.Cb=m;this.rb()};b.S=function(){this.w={};b.a.extend(this,b.S.fn);b.p(this,"subscribe",this.ya);b.p(this,"extend",
|
74 |
-
this.extend);b.p(this,"getSubscriptionsCount",this.yb)};b.S.fn={ya:function(a,d,c){c=c||"change";var e=new b.fb(this,d?a.bind(d):a,function(){b.a.ga(this.w[c],e)}.bind(this));this.w[c]||(this.w[c]=[]);this.w[c].push(e);return e},notifySubscribers:function(a,d){d=d||"change";this.w[d]&&b.r.K(function(){b.a.o(this.w[d].slice(0),function(b){b&&b.Cb!==m&&b.ha(a)})},this)},yb:function(){var a=0,b;for(b in this.w)this.w.hasOwnProperty(b)&&(a+=this.w[b].length);return a},extend:function(a){var d=this;if(a)for(var c in a){var e=
|
75 |
-
b.Ma[c];"function"==typeof e&&(d=e(d,a[c]))}return d}};b.Qa=function(a){return"function"==typeof a.ya&&"function"==typeof a.notifySubscribers};b.b("subscribable",b.S);b.b("isSubscribable",b.Qa);var C=[];b.r={mb:function(a){C.push({ha:a,La:[]})},end:function(){C.pop()},Wa:function(a){b.Qa(a)||j(Error("Only subscribable things can act as dependencies"));if(0<C.length){var d=C[C.length-1];d&&!(0<=b.a.i(d.La,a))&&(d.La.push(a),d.ha(a))}},K:function(a,b,c){try{return C.push(p),a.apply(b,c||[])}finally{C.pop()}}};
|
76 |
-
var ma={undefined:m,"boolean":m,number:m,string:m};b.m=function(a){function d(){if(0<arguments.length){if(!d.equalityComparer||!d.equalityComparer(c,arguments[0]))d.H(),c=arguments[0],d.G();return this}b.r.Wa(d);return c}var c=a;b.S.call(d);d.t=function(){return c};d.G=function(){d.notifySubscribers(c)};d.H=function(){d.notifySubscribers(c,"beforeChange")};b.a.extend(d,b.m.fn);b.p(d,"peek",d.t);b.p(d,"valueHasMutated",d.G);b.p(d,"valueWillMutate",d.H);return d};b.m.fn={equalityComparer:function(a,
|
77 |
-
b){return a===p||typeof a in ma?a===b:r}};var E=b.m.Kb="__ko_proto__";b.m.fn[E]=b.m;b.ma=function(a,d){return a===p||a===I||a[E]===I?r:a[E]===d?m:b.ma(a[E],d)};b.$=function(a){return b.ma(a,b.m)};b.Ra=function(a){return"function"==typeof a&&a[E]===b.m||"function"==typeof a&&a[E]===b.j&&a.zb?m:r};b.b("observable",b.m);b.b("isObservable",b.$);b.b("isWriteableObservable",b.Ra);b.R=function(a){0==arguments.length&&(a=[]);a!==p&&(a!==I&&!("length"in a))&&j(Error("The argument passed when initializing an observable array must be an array, or null, or undefined."));
|
78 |
-
var d=b.m(a);b.a.extend(d,b.R.fn);return d};b.R.fn={remove:function(a){for(var b=this.t(),c=[],e="function"==typeof a?a:function(b){return b===a},f=0;f<b.length;f++){var g=b[f];e(g)&&(0===c.length&&this.H(),c.push(g),b.splice(f,1),f--)}c.length&&this.G();return c},removeAll:function(a){if(a===I){var d=this.t(),c=d.slice(0);this.H();d.splice(0,d.length);this.G();return c}return!a?[]:this.remove(function(d){return 0<=b.a.i(a,d)})},destroy:function(a){var b=this.t(),c="function"==typeof a?a:function(b){return b===
|
79 |
-
a};this.H();for(var e=b.length-1;0<=e;e--)c(b[e])&&(b[e]._destroy=m);this.G()},destroyAll:function(a){return a===I?this.destroy(u(m)):!a?[]:this.destroy(function(d){return 0<=b.a.i(a,d)})},indexOf:function(a){var d=this();return b.a.i(d,a)},replace:function(a,b){var c=this.indexOf(a);0<=c&&(this.H(),this.t()[c]=b,this.G())}};b.a.o("pop push reverse shift sort splice unshift".split(" "),function(a){b.R.fn[a]=function(){var b=this.t();this.H();b=b[a].apply(b,arguments);this.G();return b}});b.a.o(["slice"],
|
80 |
-
function(a){b.R.fn[a]=function(){var b=this();return b[a].apply(b,arguments)}});b.b("observableArray",b.R);b.j=function(a,d,c){function e(){b.a.o(z,function(a){a.B()});z=[]}function f(){var a=h.throttleEvaluation;a&&0<=a?(clearTimeout(t),t=setTimeout(g,a)):g()}function g(){if(!q)if(n&&w())A();else{q=m;try{var a=b.a.V(z,function(a){return a.target});b.r.mb(function(c){var d;0<=(d=b.a.i(a,c))?a[d]=I:z.push(c.ya(f))});for(var c=s.call(d),e=a.length-1;0<=e;e--)a[e]&&z.splice(e,1)[0].B();n=m;h.notifySubscribers(l,
|
81 |
-
"beforeChange");l=c}finally{b.r.end()}h.notifySubscribers(l);q=r;z.length||A()}}function h(){if(0<arguments.length)return"function"===typeof v?v.apply(d,arguments):j(Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.")),this;n||g();b.r.Wa(h);return l}function k(){return!n||0<z.length}var l,n=r,q=r,s=a;s&&"object"==typeof s?(c=s,s=c.read):(c=c||{},s||(s=c.read));"function"!=typeof s&&j(Error("Pass a function that returns the value of the ko.computed"));
|
82 |
-
var v=c.write,G=c.disposeWhenNodeIsRemoved||c.W||p,w=c.disposeWhen||c.Ka||u(r),A=e,z=[],t=p;d||(d=c.owner);h.t=function(){n||g();return l};h.xb=function(){return z.length};h.zb="function"===typeof c.write;h.B=function(){A()};h.pa=k;b.S.call(h);b.a.extend(h,b.j.fn);b.p(h,"peek",h.t);b.p(h,"dispose",h.B);b.p(h,"isActive",h.pa);b.p(h,"getDependenciesCount",h.xb);c.deferEvaluation!==m&&g();if(G&&k()){A=function(){b.a.F.Xa(G,arguments.callee);e()};b.a.F.Ca(G,A);var D=w,w=function(){return!b.a.X(G)||D()}}return h};
|
83 |
-
b.Bb=function(a){return b.ma(a,b.j)};w=b.m.Kb;b.j[w]=b.m;b.j.fn={};b.j.fn[w]=b.j;b.b("dependentObservable",b.j);b.b("computed",b.j);b.b("isComputed",b.Bb);b.gb=function(a){0==arguments.length&&j(Error("When calling ko.toJS, pass the object you want to convert."));return ba(a,function(a){for(var c=0;b.$(a)&&10>c;c++)a=a();return a})};b.toJSON=function(a,d,c){a=b.gb(a);return b.a.xa(a,d,c)};b.b("toJS",b.gb);b.b("toJSON",b.toJSON);b.k={q:function(a){switch(b.a.u(a)){case "option":return a.__ko__hasDomDataOptionValue__===
|
84 |
-
m?b.a.f.get(a,b.c.options.sa):7>=b.a.Z?a.getAttributeNode("value").specified?a.value:a.text:a.value;case "select":return 0<=a.selectedIndex?b.k.q(a.options[a.selectedIndex]):I;default:return a.value}},T:function(a,d){switch(b.a.u(a)){case "option":switch(typeof d){case "string":b.a.f.set(a,b.c.options.sa,I);"__ko__hasDomDataOptionValue__"in a&&delete a.__ko__hasDomDataOptionValue__;a.value=d;break;default:b.a.f.set(a,b.c.options.sa,d),a.__ko__hasDomDataOptionValue__=m,a.value="number"===typeof d?
|
85 |
-
d:""}break;case "select":for(var c=a.options.length-1;0<=c;c--)if(b.k.q(a.options[c])==d){a.selectedIndex=c;break}break;default:if(d===p||d===I)d="";a.value=d}}};b.b("selectExtensions",b.k);b.b("selectExtensions.readValue",b.k.q);b.b("selectExtensions.writeValue",b.k.T);var ka=/\@ko_token_(\d+)\@/g,na=["true","false"],oa=/^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;b.g={Q:[],aa:function(a){var d=b.a.D(a);if(3>d.length)return[];"{"===d.charAt(0)&&(d=d.substring(1,d.length-1));a=[];for(var c=
|
86 |
-
p,e,f=0;f<d.length;f++){var g=d.charAt(f);if(c===p)switch(g){case '"':case "'":case "/":c=f,e=g}else if(g==e&&"\\"!==d.charAt(f-1)){g=d.substring(c,f+1);a.push(g);var h="@ko_token_"+(a.length-1)+"@",d=d.substring(0,c)+h+d.substring(f+1),f=f-(g.length-h.length),c=p}}e=c=p;for(var k=0,l=p,f=0;f<d.length;f++){g=d.charAt(f);if(c===p)switch(g){case "{":c=f;l=g;e="}";break;case "(":c=f;l=g;e=")";break;case "[":c=f,l=g,e="]"}g===l?k++:g===e&&(k--,0===k&&(g=d.substring(c,f+1),a.push(g),h="@ko_token_"+(a.length-
|
87 |
-
1)+"@",d=d.substring(0,c)+h+d.substring(f+1),f-=g.length-h.length,c=p))}e=[];d=d.split(",");c=0;for(f=d.length;c<f;c++)k=d[c],l=k.indexOf(":"),0<l&&l<k.length-1?(g=k.substring(l+1),e.push({key:P(k.substring(0,l),a),value:P(g,a)})):e.push({unknown:P(k,a)});return e},ba:function(a){var d="string"===typeof a?b.g.aa(a):a,c=[];a=[];for(var e,f=0;e=d[f];f++)if(0<c.length&&c.push(","),e.key){var g;a:{g=e.key;var h=b.a.D(g);switch(h.length&&h.charAt(0)){case "'":case '"':break a;default:g="'"+h+"'"}}e=e.value;
|
88 |
-
c.push(g);c.push(":");c.push(e);e=b.a.D(e);0<=b.a.i(na,b.a.D(e).toLowerCase())?e=r:(h=e.match(oa),e=h===p?r:h[1]?"Object("+h[1]+")"+h[2]:e);e&&(0<a.length&&a.push(", "),a.push(g+" : function(__ko_value) { "+e+" = __ko_value; }"))}else e.unknown&&c.push(e.unknown);d=c.join("");0<a.length&&(d=d+", '_ko_property_writers' : { "+a.join("")+" } ");return d},Eb:function(a,d){for(var c=0;c<a.length;c++)if(b.a.D(a[c].key)==d)return m;return r},ea:function(a,d,c,e,f){if(!a||!b.Ra(a)){if((a=d()._ko_property_writers)&&
|
89 |
-
a[c])a[c](e)}else(!f||a.t()!==e)&&a(e)}};b.b("expressionRewriting",b.g);b.b("expressionRewriting.bindingRewriteValidators",b.g.Q);b.b("expressionRewriting.parseObjectLiteral",b.g.aa);b.b("expressionRewriting.preProcessBindings",b.g.ba);b.b("jsonExpressionRewriting",b.g);b.b("jsonExpressionRewriting.insertPropertyAccessorsIntoJson",b.g.ba);var K="\x3c!--test--\x3e"===y.createComment("test").text,ja=K?/^\x3c!--\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*--\x3e$/:/^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/,ia=K?/^\x3c!--\s*\/ko\s*--\x3e$/:
|
90 |
-
/^\s*\/ko\s*$/,pa={ul:m,ol:m};b.e={I:{},childNodes:function(a){return B(a)?aa(a):a.childNodes},Y:function(a){if(B(a)){a=b.e.childNodes(a);for(var d=0,c=a.length;d<c;d++)b.removeNode(a[d])}else b.a.ka(a)},N:function(a,d){if(B(a)){b.e.Y(a);for(var c=a.nextSibling,e=0,f=d.length;e<f;e++)c.parentNode.insertBefore(d[e],c)}else b.a.N(a,d)},Va:function(a,b){B(a)?a.parentNode.insertBefore(b,a.nextSibling):a.firstChild?a.insertBefore(b,a.firstChild):a.appendChild(b)},Pa:function(a,d,c){c?B(a)?a.parentNode.insertBefore(d,
|
91 |
-
c.nextSibling):c.nextSibling?a.insertBefore(d,c.nextSibling):a.appendChild(d):b.e.Va(a,d)},firstChild:function(a){return!B(a)?a.firstChild:!a.nextSibling||H(a.nextSibling)?p:a.nextSibling},nextSibling:function(a){B(a)&&(a=$(a));return a.nextSibling&&H(a.nextSibling)?p:a.nextSibling},jb:function(a){return(a=B(a))?a[1]:p},Ta:function(a){if(pa[b.a.u(a)]){var d=a.firstChild;if(d){do if(1===d.nodeType){var c;c=d.firstChild;var e=p;if(c){do if(e)e.push(c);else if(B(c)){var f=$(c,m);f?c=f:e=[c]}else H(c)&&
|
92 |
-
(e=[c]);while(c=c.nextSibling)}if(c=e){e=d.nextSibling;for(f=0;f<c.length;f++)e?a.insertBefore(c[f],e):a.appendChild(c[f])}}while(d=d.nextSibling)}}}};b.b("virtualElements",b.e);b.b("virtualElements.allowedBindings",b.e.I);b.b("virtualElements.emptyNode",b.e.Y);b.b("virtualElements.insertAfter",b.e.Pa);b.b("virtualElements.prepend",b.e.Va);b.b("virtualElements.setDomNodeChildren",b.e.N);b.J=function(){this.Ha={}};b.a.extend(b.J.prototype,{nodeHasBindings:function(a){switch(a.nodeType){case 1:return a.getAttribute("data-bind")!=
|
93 |
-
p;case 8:return b.e.jb(a)!=p;default:return r}},getBindings:function(a,b){var c=this.getBindingsString(a,b);return c?this.parseBindingsString(c,b,a):p},getBindingsString:function(a){switch(a.nodeType){case 1:return a.getAttribute("data-bind");case 8:return b.e.jb(a);default:return p}},parseBindingsString:function(a,d,c){try{var e;if(!(e=this.Ha[a])){var f=this.Ha,g,h="with($context){with($data||{}){return{"+b.g.ba(a)+"}}}";g=new Function("$context","$element",h);e=f[a]=g}return e(d,c)}catch(k){j(Error("Unable to parse bindings.\nMessage: "+
|
94 |
-
k+";\nBindings value: "+a))}}});b.J.instance=new b.J;b.b("bindingProvider",b.J);b.c={};b.z=function(a,d,c){d?(b.a.extend(this,d),this.$parentContext=d,this.$parent=d.$data,this.$parents=(d.$parents||[]).slice(0),this.$parents.unshift(this.$parent)):(this.$parents=[],this.$root=a,this.ko=b);this.$data=a;c&&(this[c]=a)};b.z.prototype.createChildContext=function(a,d){return new b.z(a,this,d)};b.z.prototype.extend=function(a){var d=b.a.extend(new b.z,this);return b.a.extend(d,a)};b.eb=function(a,d){if(2==
|
95 |
-
arguments.length)b.a.f.set(a,"__ko_bindingContext__",d);else return b.a.f.get(a,"__ko_bindingContext__")};b.Fa=function(a,d,c){1===a.nodeType&&b.e.Ta(a);return X(a,d,c,m)};b.Ea=function(a,b){(1===b.nodeType||8===b.nodeType)&&Z(a,b,m)};b.Da=function(a,b){b&&(1!==b.nodeType&&8!==b.nodeType)&&j(Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node"));b=b||x.document.body;Y(a,b,m)};b.ja=function(a){switch(a.nodeType){case 1:case 8:var d=b.eb(a);if(d)return d;
|
96 |
-
if(a.parentNode)return b.ja(a.parentNode)}return I};b.pb=function(a){return(a=b.ja(a))?a.$data:I};b.b("bindingHandlers",b.c);b.b("applyBindings",b.Da);b.b("applyBindingsToDescendants",b.Ea);b.b("applyBindingsToNode",b.Fa);b.b("contextFor",b.ja);b.b("dataFor",b.pb);var fa={"class":"className","for":"htmlFor"};b.c.attr={update:function(a,d){var c=b.a.d(d())||{},e;for(e in c)if("string"==typeof e){var f=b.a.d(c[e]),g=f===r||f===p||f===I;g&&a.removeAttribute(e);8>=b.a.Z&&e in fa?(e=fa[e],g?a.removeAttribute(e):
|
97 |
-
a[e]=f):g||a.setAttribute(e,f.toString());"name"===e&&b.a.ab(a,g?"":f.toString())}}};b.c.checked={init:function(a,d,c){b.a.n(a,"click",function(){var e;if("checkbox"==a.type)e=a.checked;else if("radio"==a.type&&a.checked)e=a.value;else return;var f=d(),g=b.a.d(f);"checkbox"==a.type&&g instanceof Array?(e=b.a.i(g,a.value),a.checked&&0>e?f.push(a.value):!a.checked&&0<=e&&f.splice(e,1)):b.g.ea(f,c,"checked",e,m)});"radio"==a.type&&!a.name&&b.c.uniqueName.init(a,u(m))},update:function(a,d){var c=b.a.d(d());
|
98 |
-
"checkbox"==a.type?a.checked=c instanceof Array?0<=b.a.i(c,a.value):c:"radio"==a.type&&(a.checked=a.value==c)}};b.c.css={update:function(a,d){var c=b.a.d(d());if("object"==typeof c)for(var e in c){var f=b.a.d(c[e]);b.a.da(a,e,f)}else c=String(c||""),b.a.da(a,a.__ko__cssValue,r),a.__ko__cssValue=c,b.a.da(a,c,m)}};b.c.enable={update:function(a,d){var c=b.a.d(d());c&&a.disabled?a.removeAttribute("disabled"):!c&&!a.disabled&&(a.disabled=m)}};b.c.disable={update:function(a,d){b.c.enable.update(a,function(){return!b.a.d(d())})}};
|
99 |
-
b.c.event={init:function(a,d,c,e){var f=d()||{},g;for(g in f)(function(){var f=g;"string"==typeof f&&b.a.n(a,f,function(a){var g,n=d()[f];if(n){var q=c();try{var s=b.a.L(arguments);s.unshift(e);g=n.apply(e,s)}finally{g!==m&&(a.preventDefault?a.preventDefault():a.returnValue=r)}q[f+"Bubble"]===r&&(a.cancelBubble=m,a.stopPropagation&&a.stopPropagation())}})})()}};b.c.foreach={Sa:function(a){return function(){var d=a(),c=b.a.ua(d);if(!c||"number"==typeof c.length)return{foreach:d,templateEngine:b.C.oa};
|
100 |
-
b.a.d(d);return{foreach:c.data,as:c.as,includeDestroyed:c.includeDestroyed,afterAdd:c.afterAdd,beforeRemove:c.beforeRemove,afterRender:c.afterRender,beforeMove:c.beforeMove,afterMove:c.afterMove,templateEngine:b.C.oa}}},init:function(a,d){return b.c.template.init(a,b.c.foreach.Sa(d))},update:function(a,d,c,e,f){return b.c.template.update(a,b.c.foreach.Sa(d),c,e,f)}};b.g.Q.foreach=r;b.e.I.foreach=m;b.c.hasfocus={init:function(a,d,c){function e(e){a.__ko_hasfocusUpdating=m;var f=a.ownerDocument;"activeElement"in
|
101 |
-
f&&(e=f.activeElement===a);f=d();b.g.ea(f,c,"hasfocus",e,m);a.__ko_hasfocusUpdating=r}var f=e.bind(p,m),g=e.bind(p,r);b.a.n(a,"focus",f);b.a.n(a,"focusin",f);b.a.n(a,"blur",g);b.a.n(a,"focusout",g)},update:function(a,d){var c=b.a.d(d());a.__ko_hasfocusUpdating||(c?a.focus():a.blur(),b.r.K(b.a.Ba,p,[a,c?"focusin":"focusout"]))}};b.c.html={init:function(){return{controlsDescendantBindings:m}},update:function(a,d){b.a.ca(a,d())}};var da="__ko_withIfBindingData";Q("if");Q("ifnot",r,m);Q("with",m,r,function(a,
|
102 |
-
b){return a.createChildContext(b)});b.c.options={update:function(a,d,c){"select"!==b.a.u(a)&&j(Error("options binding applies only to SELECT elements"));for(var e=0==a.length,f=b.a.V(b.a.fa(a.childNodes,function(a){return a.tagName&&"option"===b.a.u(a)&&a.selected}),function(a){return b.k.q(a)||a.innerText||a.textContent}),g=a.scrollTop,h=b.a.d(d());0<a.length;)b.A(a.options[0]),a.remove(0);if(h){c=c();var k=c.optionsIncludeDestroyed;"number"!=typeof h.length&&(h=[h]);if(c.optionsCaption){var l=y.createElement("option");
|
103 |
-
b.a.ca(l,c.optionsCaption);b.k.T(l,I);a.appendChild(l)}d=0;for(var n=h.length;d<n;d++){var q=h[d];if(!q||!q._destroy||k){var l=y.createElement("option"),s=function(a,b,c){var d=typeof b;return"function"==d?b(a):"string"==d?a[b]:c},v=s(q,c.optionsValue,q);b.k.T(l,b.a.d(v));q=s(q,c.optionsText,v);b.a.cb(l,q);a.appendChild(l)}}h=a.getElementsByTagName("option");d=k=0;for(n=h.length;d<n;d++)0<=b.a.i(f,b.k.q(h[d]))&&(b.a.bb(h[d],m),k++);a.scrollTop=g;e&&"value"in c&&ea(a,b.a.ua(c.value),m);b.a.ub(a)}}};
|
104 |
-
b.c.options.sa="__ko.optionValueDomData__";b.c.selectedOptions={init:function(a,d,c){b.a.n(a,"change",function(){var e=d(),f=[];b.a.o(a.getElementsByTagName("option"),function(a){a.selected&&f.push(b.k.q(a))});b.g.ea(e,c,"value",f)})},update:function(a,d){"select"!=b.a.u(a)&&j(Error("values binding applies only to SELECT elements"));var c=b.a.d(d());c&&"number"==typeof c.length&&b.a.o(a.getElementsByTagName("option"),function(a){var d=0<=b.a.i(c,b.k.q(a));b.a.bb(a,d)})}};b.c.style={update:function(a,
|
105 |
-
d){var c=b.a.d(d()||{}),e;for(e in c)if("string"==typeof e){var f=b.a.d(c[e]);a.style[e]=f||""}}};b.c.submit={init:function(a,d,c,e){"function"!=typeof d()&&j(Error("The value for a submit binding must be a function"));b.a.n(a,"submit",function(b){var c,h=d();try{c=h.call(e,a)}finally{c!==m&&(b.preventDefault?b.preventDefault():b.returnValue=r)}})}};b.c.text={update:function(a,d){b.a.cb(a,d())}};b.e.I.text=m;b.c.uniqueName={init:function(a,d){if(d()){var c="ko_unique_"+ ++b.c.uniqueName.ob;b.a.ab(a,
|
106 |
-
c)}}};b.c.uniqueName.ob=0;b.c.value={init:function(a,d,c){function e(){h=r;var e=d(),f=b.k.q(a);b.g.ea(e,c,"value",f)}var f=["change"],g=c().valueUpdate,h=r;g&&("string"==typeof g&&(g=[g]),b.a.P(f,g),f=b.a.Ga(f));if(b.a.Z&&("input"==a.tagName.toLowerCase()&&"text"==a.type&&"off"!=a.autocomplete&&(!a.form||"off"!=a.form.autocomplete))&&-1==b.a.i(f,"propertychange"))b.a.n(a,"propertychange",function(){h=m}),b.a.n(a,"blur",function(){h&&e()});b.a.o(f,function(c){var d=e;b.a.Ob(c,"after")&&(d=function(){setTimeout(e,
|
107 |
-
0)},c=c.substring(5));b.a.n(a,c,d)})},update:function(a,d){var c="select"===b.a.u(a),e=b.a.d(d()),f=b.k.q(a),g=e!=f;0===e&&(0!==f&&"0"!==f)&&(g=m);g&&(f=function(){b.k.T(a,e)},f(),c&&setTimeout(f,0));c&&0<a.length&&ea(a,e,r)}};b.c.visible={update:function(a,d){var c=b.a.d(d()),e="none"!=a.style.display;c&&!e?a.style.display="":!c&&e&&(a.style.display="none")}};b.c.click={init:function(a,d,c,e){return b.c.event.init.call(this,a,function(){var a={};a.click=d();return a},c,e)}};b.v=function(){};b.v.prototype.renderTemplateSource=
|
108 |
-
function(){j(Error("Override renderTemplateSource"))};b.v.prototype.createJavaScriptEvaluatorBlock=function(){j(Error("Override createJavaScriptEvaluatorBlock"))};b.v.prototype.makeTemplateSource=function(a,d){if("string"==typeof a){d=d||y;var c=d.getElementById(a);c||j(Error("Cannot find template with ID "+a));return new b.l.h(c)}if(1==a.nodeType||8==a.nodeType)return new b.l.O(a);j(Error("Unknown template type: "+a))};b.v.prototype.renderTemplate=function(a,b,c,e){a=this.makeTemplateSource(a,e);
|
109 |
-
return this.renderTemplateSource(a,b,c)};b.v.prototype.isTemplateRewritten=function(a,b){return this.allowTemplateRewriting===r?m:this.makeTemplateSource(a,b).data("isRewritten")};b.v.prototype.rewriteTemplate=function(a,b,c){a=this.makeTemplateSource(a,c);b=b(a.text());a.text(b);a.data("isRewritten",m)};b.b("templateEngine",b.v);var qa=/(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9\-]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/gi,ra=/\x3c!--\s*ko\b\s*([\s\S]*?)\s*--\x3e/g;b.za={vb:function(a,
|
110 |
-
d,c){d.isTemplateRewritten(a,c)||d.rewriteTemplate(a,function(a){return b.za.Gb(a,d)},c)},Gb:function(a,b){return a.replace(qa,function(a,e,f,g,h,k,l){return W(l,e,b)}).replace(ra,function(a,e){return W(e,"\x3c!-- ko --\x3e",b)})},kb:function(a){return b.s.ra(function(d,c){d.nextSibling&&b.Fa(d.nextSibling,a,c)})}};b.b("__tr_ambtns",b.za.kb);b.l={};b.l.h=function(a){this.h=a};b.l.h.prototype.text=function(){var a=b.a.u(this.h),a="script"===a?"text":"textarea"===a?"value":"innerHTML";if(0==arguments.length)return this.h[a];
|
111 |
-
var d=arguments[0];"innerHTML"===a?b.a.ca(this.h,d):this.h[a]=d};b.l.h.prototype.data=function(a){if(1===arguments.length)return b.a.f.get(this.h,"templateSourceData_"+a);b.a.f.set(this.h,"templateSourceData_"+a,arguments[1])};b.l.O=function(a){this.h=a};b.l.O.prototype=new b.l.h;b.l.O.prototype.text=function(){if(0==arguments.length){var a=b.a.f.get(this.h,"__ko_anon_template__")||{};a.Aa===I&&a.ia&&(a.Aa=a.ia.innerHTML);return a.Aa}b.a.f.set(this.h,"__ko_anon_template__",{Aa:arguments[0]})};b.l.h.prototype.nodes=
|
112 |
-
function(){if(0==arguments.length)return(b.a.f.get(this.h,"__ko_anon_template__")||{}).ia;b.a.f.set(this.h,"__ko_anon_template__",{ia:arguments[0]})};b.b("templateSources",b.l);b.b("templateSources.domElement",b.l.h);b.b("templateSources.anonymousTemplate",b.l.O);var O;b.wa=function(a){a!=I&&!(a instanceof b.v)&&j(Error("templateEngine must inherit from ko.templateEngine"));O=a};b.va=function(a,d,c,e,f){c=c||{};(c.templateEngine||O)==I&&j(Error("Set a template engine before calling renderTemplate"));
|
113 |
-
f=f||"replaceChildren";if(e){var g=N(e);return b.j(function(){var h=d&&d instanceof b.z?d:new b.z(b.a.d(d)),k="function"==typeof a?a(h.$data,h):a,h=T(e,f,k,h,c);"replaceNode"==f&&(e=h,g=N(e))},p,{Ka:function(){return!g||!b.a.X(g)},W:g&&"replaceNode"==f?g.parentNode:g})}return b.s.ra(function(e){b.va(a,d,c,e,"replaceNode")})};b.Mb=function(a,d,c,e,f){function g(a,b){U(b,k);c.afterRender&&c.afterRender(b,a)}function h(d,e){k=f.createChildContext(b.a.d(d),c.as);k.$index=e;var g="function"==typeof a?
|
114 |
-
a(d,k):a;return T(p,"ignoreTargetNode",g,k,c)}var k;return b.j(function(){var a=b.a.d(d)||[];"undefined"==typeof a.length&&(a=[a]);a=b.a.fa(a,function(a){return c.includeDestroyed||a===I||a===p||!b.a.d(a._destroy)});b.r.K(b.a.$a,p,[e,a,h,c,g])},p,{W:e})};b.c.template={init:function(a,d){var c=b.a.d(d());if("string"!=typeof c&&!c.name&&(1==a.nodeType||8==a.nodeType))c=1==a.nodeType?a.childNodes:b.e.childNodes(a),c=b.a.Hb(c),(new b.l.O(a)).nodes(c);return{controlsDescendantBindings:m}},update:function(a,
|
115 |
-
d,c,e,f){d=b.a.d(d());c={};e=m;var g,h=p;"string"!=typeof d&&(c=d,d=c.name,"if"in c&&(e=b.a.d(c["if"])),e&&"ifnot"in c&&(e=!b.a.d(c.ifnot)),g=b.a.d(c.data));"foreach"in c?h=b.Mb(d||a,e&&c.foreach||[],c,a,f):e?(f="data"in c?f.createChildContext(g,c.as):f,h=b.va(d||a,f,c,a)):b.e.Y(a);f=h;(g=b.a.f.get(a,"__ko__templateComputedDomDataKey__"))&&"function"==typeof g.B&&g.B();b.a.f.set(a,"__ko__templateComputedDomDataKey__",f&&f.pa()?f:I)}};b.g.Q.template=function(a){a=b.g.aa(a);return 1==a.length&&a[0].unknown||
|
116 |
-
b.g.Eb(a,"name")?p:"This template engine does not support anonymous templates nested within its templates"};b.e.I.template=m;b.b("setTemplateEngine",b.wa);b.b("renderTemplate",b.va);b.a.Ja=function(a,b,c){a=a||[];b=b||[];return a.length<=b.length?S(a,b,"added","deleted",c):S(b,a,"deleted","added",c)};b.b("utils.compareArrays",b.a.Ja);b.a.$a=function(a,d,c,e,f){function g(a,b){t=l[b];w!==b&&(z[a]=t);t.na(w++);M(t.M);s.push(t);A.push(t)}function h(a,c){if(a)for(var d=0,e=c.length;d<e;d++)c[d]&&b.a.o(c[d].M,
|
117 |
-
function(b){a(b,d,c[d].U)})}d=d||[];e=e||{};var k=b.a.f.get(a,"setDomNodeChildrenFromArrayMapping_lastMappingResult")===I,l=b.a.f.get(a,"setDomNodeChildrenFromArrayMapping_lastMappingResult")||[],n=b.a.V(l,function(a){return a.U}),q=b.a.Ja(n,d),s=[],v=0,w=0,B=[],A=[];d=[];for(var z=[],n=[],t,D=0,C,E;C=q[D];D++)switch(E=C.moved,C.status){case "deleted":E===I&&(t=l[v],t.j&&t.j.B(),B.push.apply(B,M(t.M)),e.beforeRemove&&(d[D]=t,A.push(t)));v++;break;case "retained":g(D,v++);break;case "added":E!==I?
|
118 |
-
g(D,E):(t={U:C.value,na:b.m(w++)},s.push(t),A.push(t),k||(n[D]=t))}h(e.beforeMove,z);b.a.o(B,e.beforeRemove?b.A:b.removeNode);for(var D=0,k=b.e.firstChild(a),H;t=A[D];D++){t.M||b.a.extend(t,ha(a,c,t.U,f,t.na));for(v=0;q=t.M[v];k=q.nextSibling,H=q,v++)q!==k&&b.e.Pa(a,q,H);!t.Ab&&f&&(f(t.U,t.M,t.na),t.Ab=m)}h(e.beforeRemove,d);h(e.afterMove,z);h(e.afterAdd,n);b.a.f.set(a,"setDomNodeChildrenFromArrayMapping_lastMappingResult",s)};b.b("utils.setDomNodeChildrenFromArrayMapping",b.a.$a);b.C=function(){this.allowTemplateRewriting=
|
119 |
-
r};b.C.prototype=new b.v;b.C.prototype.renderTemplateSource=function(a){var d=!(9>b.a.Z)&&a.nodes?a.nodes():p;if(d)return b.a.L(d.cloneNode(m).childNodes);a=a.text();return b.a.ta(a)};b.C.oa=new b.C;b.wa(b.C.oa);b.b("nativeTemplateEngine",b.C);b.qa=function(){var a=this.Db=function(){if("undefined"==typeof F||!F.tmpl)return 0;try{if(0<=F.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}();this.renderTemplateSource=function(b,c,e){e=e||{};2>a&&j(Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later."));
|
120 |
-
var f=b.data("precompiled");f||(f=b.text()||"",f=F.template(p,"{{ko_with $item.koBindingContext}}"+f+"{{/ko_with}}"),b.data("precompiled",f));b=[c.$data];c=F.extend({koBindingContext:c},e.templateOptions);c=F.tmpl(f,b,c);c.appendTo(y.createElement("div"));F.fragments={};return c};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){y.write("<script type='text/html' id='"+a+"'>"+b+"\x3c/script>")};0<a&&(F.tmpl.tag.ko_code=
|
121 |
-
{open:"__.push($1 || '');"},F.tmpl.tag.ko_with={open:"with($1) {",close:"} "})};b.qa.prototype=new b.v;w=new b.qa;0<w.Db&&b.wa(w);b.b("jqueryTmplTemplateEngine",b.qa)}"function"===typeof require&&"object"===typeof exports&&"object"===typeof module?L(module.exports||exports):"function"===typeof define&&define.amd?define(["exports"],L):L(x.ko={});m;
|
122 |
-
})();
|
123 |
-
</script>
|
124 |
-
<?php endif; ?>
|
125 |
-
|
126 |
-
<script type="text/javascript">
|
127 |
-
/* json2.js
|
128 |
-
* See www.JSON.org/js.html*/
|
129 |
-
if(!this.JSON){JSON=function(){function f(n){return n<10?'0'+n:n;}
|
130 |
-
Date.prototype.toJSON=function(){return this.getUTCFullYear()+'-'+
|
131 |
-
f(this.getUTCMonth()+1)+'-'+
|
132 |
-
f(this.getUTCDate())+'T'+
|
133 |
-
f(this.getUTCHours())+':'+
|
134 |
-
f(this.getUTCMinutes())+':'+
|
135 |
-
f(this.getUTCSeconds())+'Z';};var m={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};function stringify(value,whitelist){var a,i,k,l,r=/["\\\x00-\x1f\x7f-\x9f]/g,v;switch(typeof value){case'string':return r.test(value)?'"'+value.replace(r,function(a){var c=m[a];if(c){return c;}
|
136 |
-
c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+
|
137 |
-
(c%16).toString(16);})+'"':'"'+value+'"';case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}
|
138 |
-
if(typeof value.toJSON==='function'){return stringify(value.toJSON());}
|
139 |
-
a=[];if(typeof value.length==='number'&&!(value.propertyIsEnumerable('length'))){l=value.length;for(i=0;i<l;i+=1){a.push(stringify(value[i],whitelist)||'null');}
|
140 |
-
return'['+a.join(',')+']';}
|
141 |
-
if(whitelist){l=whitelist.length;for(i=0;i<l;i+=1){k=whitelist[i];if(typeof k==='string'){v=stringify(value[k],whitelist);if(v){a.push(stringify(k)+':'+v);}}}}else{for(k in value){if(typeof k==='string'){v=stringify(value[k],whitelist);if(v){a.push(stringify(k)+':'+v);}}}}
|
142 |
-
return'{'+a.join(',')+'}';}}
|
143 |
-
return{stringify:stringify,parse:function(text,filter){var j;function walk(k,v){var i,n;if(v&&typeof v==='object'){for(i in v){if(Object.prototype.hasOwnProperty.apply(v,[i])){n=walk(i,v[i]);if(n!==undefined){v[i]=n;}}}}
|
144 |
-
return filter(k,v);}
|
145 |
-
if(/^[\],:{}\s]*$/.test(text.replace(/\\./g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){j=eval('('+text+')');return typeof filter==='function'?walk('',j):j;}
|
146 |
-
throw new SyntaxError('parseJSON');}};}();}
|
147 |
-
</script>
|
148 |
-
|
149 |
-
<script type="text/javascript">
|
150 |
-
/**
|
151 |
-
* password_strength_plugin.js
|
152 |
-
* Copyright (c) 20010 myPocket technologies (www.mypocket-technologies.com)
|
153 |
-
* @author Darren Mason (djmason9@gmail.com)
|
154 |
-
* @date 3/13/2009
|
155 |
-
* @projectDescription Password Strength Meter is a jQuery plug-in provide you smart algorithm to detect a password strength.
|
156 |
-
* Based on Firas Kassem orginal plugin - phiras.wordpress.com/2007/04/08/password-strength-meter-a-jquery-plugin/
|
157 |
-
* @version 1.0.1 */
|
158 |
-
(function(a){a.fn.shortPass="Too short";a.fn.badPass="Weak";a.fn.goodPass="Good";a.fn.strongPass="Strong";a.fn.samePassword="Username and Password identical.";a.fn.resultStyle="";a.fn.passStrength=function(b){var d={shortPass:"shortPass",badPass:"badPass",goodPass:"goodPass",strongPass:"strongPass",baseStyle:"testresult",userid:"",messageloc:1};
|
159 |
-
var c=a.extend(d,b);return this.each(function(){var e=a(this);a(e).unbind().keyup(function(){var f=a.fn.teststrength(a(this).val(),a(c.userid).val(),c);if(c.messageloc===1){a(this).next("."+c.baseStyle).remove();a(this).after('<span class="'+c.baseStyle+'"><span></span></span>');a(this).next("."+c.baseStyle).addClass(a(this).resultStyle).find("span").text(f)
|
160 |
-
}else{a(this).prev("."+c.baseStyle).remove();a(this).before('<span class="'+c.baseStyle+'"><span></span></span>');a(this).prev("."+c.baseStyle).addClass(a(this).resultStyle).find("span").text(f)}});a.fn.teststrength=function(f,i,g){var h=0;if(f.length<4){this.resultStyle=g.shortPass;return a(this).shortPass
|
161 |
-
}if(f.toLowerCase()==i.toLowerCase()){this.resultStyle=g.badPass;return a(this).samePassword}h+=f.length*4;h+=(a.fn.checkRepetition(1,f).length-f.length)*1;h+=(a.fn.checkRepetition(2,f).length-f.length)*1;h+=(a.fn.checkRepetition(3,f).length-f.length)*1;h+=(a.fn.checkRepetition(4,f).length-f.length)*1;
|
162 |
-
if(f.match(/(.*[0-9].*[0-9].*[0-9])/)){h+=5}if(f.match(/(.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~])/)){h+=5}if(f.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/)){h+=10}if(f.match(/([a-zA-Z])/)&&f.match(/([0-9])/)){h+=15}if(f.match(/([!,@,#,$,%,^,&,*,?,_,~])/)&&f.match(/([0-9])/)){h+=15}if(f.match(/([!,@,#,$,%,^,&,*,?,_,~])/)&&f.match(/([a-zA-Z])/)){h+=15
|
163 |
-
}if(f.match(/^\w+$/)||f.match(/^\d+$/)){h-=10}if(h<0){h=0}if(h>100){h=100}if(h<34){this.resultStyle=g.badPass;return a(this).badPass}if(h<68){this.resultStyle=g.goodPass;return a(this).goodPass}this.resultStyle=g.strongPass;return a(this).strongPass}})}})(jQuery);$.fn.checkRepetition=function(a,f){var d="";
|
164 |
-
for(var c=0;c<f.length;c++){var e=true;for(var b=0;b<a&&(b+c+a)<f.length;b++){e=e&&(f.charAt(b+c)==f.charAt(b+c+a))}if(b<a){e=false}if(e){c+=a-1;e=false}else{d+=f.charAt(c)}}return d};
|
165 |
-
</script>
|
166 |
-
|
167 |
-
|
168 |
-
<script type="text/javascript">
|
169 |
-
/*!
|
170 |
-
* Parsley.js
|
171 |
-
* Version 2.3.5 - built Sun, Feb 28th 2016, 6:25 am
|
172 |
-
* http://parsleyjs.org
|
173 |
-
* Guillaume Potier - <guillaume@wisembly.com>
|
174 |
-
* Marc-Andre Lafortune - <petroselinum@marc-andre.ca>
|
175 |
-
* MIT Licensed
|
176 |
-
*/
|
177 |
-
function _toConsumableArray(e){if(Array.isArray(e)){for(var t=0,i=Array(e.length);t<e.length;t++)i[t]=e[t];return i}return Array.from(e)}var _slice=Array.prototype.slice;!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],t):e.parsley=t(e.jQuery)}(this,function(e){"use strict";function t(e,t){return e.parsleyAdaptedCallback||(e.parsleyAdaptedCallback=function(){var i=Array.prototype.slice.call(arguments,0);i.unshift(this),e.apply(t||A,i)}),e.parsleyAdaptedCallback}function i(e){return 0===e.lastIndexOf(D,0)?e.substr(D.length):e}var n=1,r={},s={attr:function(e,t,i){var n,r,s,a=new RegExp("^"+t,"i");if("undefined"==typeof i)i={};else for(n in i)i.hasOwnProperty(n)&&delete i[n];if("undefined"==typeof e||"undefined"==typeof e[0])return i;for(s=e[0].attributes,n=s.length;n--;)r=s[n],r&&r.specified&&a.test(r.name)&&(i[this.camelize(r.name.slice(t.length))]=this.deserializeValue(r.value));return i},checkAttr:function(e,t,i){return e.is("["+t+i+"]")},setAttr:function(e,t,i,n){e[0].setAttribute(this.dasherize(t+i),String(n))},generateID:function(){return""+n++},deserializeValue:function(t){var i;try{return t?"true"==t||("false"==t?!1:"null"==t?null:isNaN(i=Number(t))?/^[\[\{]/.test(t)?e.parseJSON(t):t:i):t}catch(n){return t}},camelize:function(e){return e.replace(/-+(.)?/g,function(e,t){return t?t.toUpperCase():""})},dasherize:function(e){return e.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()},warn:function(){var e;window.console&&"function"==typeof window.console.warn&&(e=window.console).warn.apply(e,arguments)},warnOnce:function(e){r[e]||(r[e]=!0,this.warn.apply(this,arguments))},_resetWarnings:function(){r={}},trimString:function(e){return e.replace(/^\s+|\s+$/g,"")},namespaceEvents:function(t,i){return t=this.trimString(t||"").split(/\s+/),t[0]?e.map(t,function(e){return e+"."+i}).join(" "):""},objectCreate:Object.create||function(){var e=function(){};return function(t){if(arguments.length>1)throw Error("Second argument not supported");if("object"!=typeof t)throw TypeError("Argument must be an object");e.prototype=t;var i=new e;return e.prototype=null,i}}()},a=s,o={namespace:"data-parsley-",inputs:"input, textarea, select",excluded:"input[type=button], input[type=submit], input[type=reset], input[type=hidden]",priorityEnabled:!0,multiple:null,group:null,uiEnabled:!0,validationThreshold:3,focus:"first",trigger:!1,triggerAfterFailure:"input",errorClass:"parsley-error",successClass:"parsley-success",classHandler:function(e){},errorsContainer:function(e){},errorsWrapper:'<ul class="parsley-errors-list"></ul>',errorTemplate:"<li></li>"},l=function(){};l.prototype={asyncSupport:!0,actualizeOptions:function(){return a.attr(this.$element,this.options.namespace,this.domOptions),this.parent&&this.parent.actualizeOptions&&this.parent.actualizeOptions(),this},_resetOptions:function(e){this.domOptions=a.objectCreate(this.parent.options),this.options=a.objectCreate(this.domOptions);for(var t in e)e.hasOwnProperty(t)&&(this.options[t]=e[t]);this.actualizeOptions()},_listeners:null,on:function(e,t){this._listeners=this._listeners||{};var i=this._listeners[e]=this._listeners[e]||[];return i.push(t),this},subscribe:function(t,i){e.listenTo(this,t.toLowerCase(),i)},off:function(e,t){var i=this._listeners&&this._listeners[e];if(i)if(t)for(var n=i.length;n--;)i[n]===t&&i.splice(n,1);else delete this._listeners[e];return this},unsubscribe:function(t,i){e.unsubscribeTo(this,t.toLowerCase())},trigger:function(e,t,i){t=t||this;var n,r=this._listeners&&this._listeners[e];if(r)for(var s=r.length;s--;)if(n=r[s].call(t,t,i),n===!1)return n;return this.parent?this.parent.trigger(e,t,i):!0},reset:function(){if("ParsleyForm"!==this.__class__)return this._resetUI(),this._trigger("reset");for(var e=0;e<this.fields.length;e++)this.fields[e].reset();this._trigger("reset")},destroy:function(){if(this._destroyUI(),"ParsleyForm"!==this.__class__)return this.$element.removeData("Parsley"),this.$element.removeData("ParsleyFieldMultiple"),void this._trigger("destroy");for(var e=0;e<this.fields.length;e++)this.fields[e].destroy();this.$element.removeData("Parsley"),this._trigger("destroy")},asyncIsValid:function(e,t){return a.warnOnce("asyncIsValid is deprecated; please use whenValid instead"),this.whenValid({group:e,force:t})},_findRelated:function(){return this.options.multiple?this.parent.$element.find("["+this.options.namespace+'multiple="'+this.options.multiple+'"]'):this.$element}};var u={string:function(e){return e},integer:function(e){if(isNaN(e))throw'Requirement is not an integer: "'+e+'"';return parseInt(e,10)},number:function(e){if(isNaN(e))throw'Requirement is not a number: "'+e+'"';return parseFloat(e)},reference:function(t){var i=e(t);if(0===i.length)throw'No such reference: "'+t+'"';return i},"boolean":function(e){return"false"!==e},object:function(e){return a.deserializeValue(e)},regexp:function(e){var t="";return/^\/.*\/(?:[gimy]*)$/.test(e)?(t=e.replace(/.*\/([gimy]*)$/,"$1"),e=e.replace(new RegExp("^/(.*?)/"+t+"$"),"$1")):e="^"+e+"$",new RegExp(e,t)}},d=function(e,t){var i=e.match(/^\s*\[(.*)\]\s*$/);if(!i)throw'Requirement is not an array: "'+e+'"';var n=i[1].split(",").map(a.trimString);if(n.length!==t)throw"Requirement has "+n.length+" values when "+t+" are needed";return n},h=function(e,t){var i=u[e||"string"];if(!i)throw'Unknown requirement specification: "'+e+'"';return i(t)},p=function(e,t,i){var n=null,r={};for(var s in e)if(s){var a=i(s);"string"==typeof a&&(a=h(e[s],a)),r[s]=a}else n=h(e[s],t);return[n,r]},f=function(t){e.extend(!0,this,t)};f.prototype={validate:function(t,i){if(this.fn)return arguments.length>3&&(i=[].slice.call(arguments,1,-1)),this.fn.call(this,t,i);if(e.isArray(t)){if(!this.validateMultiple)throw"Validator `"+this.name+"` does not handle multiple values";return this.validateMultiple.apply(this,arguments)}if(this.validateNumber)return isNaN(t)?!1:(arguments[0]=parseFloat(arguments[0]),this.validateNumber.apply(this,arguments));if(this.validateString)return this.validateString.apply(this,arguments);throw"Validator `"+this.name+"` only handles multiple values"},parseRequirements:function(t,i){if("string"!=typeof t)return e.isArray(t)?t:[t];var n=this.requirementType;if(e.isArray(n)){for(var r=d(t,n.length),s=0;s<r.length;s++)r[s]=h(n[s],r[s]);return r}return e.isPlainObject(n)?p(n,t,i):[h(n,t)]},requirementType:"string",priority:2};var c=function(e,t){this.__class__="ParsleyValidatorRegistry",this.locale="en",this.init(e||{},t||{})},m={email:/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,number:/^-?(\d*\.)?\d+(e[-+]?\d+)?$/i,integer:/^-?\d+$/,digits:/^\d+$/,alphanum:/^\w+$/i,url:new RegExp("^(?:(?:https?|ftp)://)?(?:\\S+(?::\\S*)?@)?(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/\\S*)?$","i")};m.range=m.number;var g=function(e){var t=(""+e).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);return t?Math.max(0,(t[1]?t[1].length:0)-(t[2]?+t[2]:0)):0};c.prototype={init:function(t,i){this.catalog=i,this.validators=e.extend({},this.validators);for(var n in t)this.addValidator(n,t[n].fn,t[n].priority);window.Parsley.trigger("parsley:validator:init")},setLocale:function(e){if("undefined"==typeof this.catalog[e])throw new Error(e+" is not available in the catalog");return this.locale=e,this},addCatalog:function(e,t,i){return"object"==typeof t&&(this.catalog[e]=t),!0===i?this.setLocale(e):this},addMessage:function(e,t,i){return"undefined"==typeof this.catalog[e]&&(this.catalog[e]={}),this.catalog[e][t]=i,this},addMessages:function(e,t){for(var i in t)this.addMessage(e,i,t[i]);return this},addValidator:function(e,t,i){if(this.validators[e])a.warn('Validator "'+e+'" is already defined.');else if(o.hasOwnProperty(e))return void a.warn('"'+e+'" is a restricted keyword and is not a valid validator name.');return this._setValidator.apply(this,arguments)},updateValidator:function(e,t,i){return this.validators[e]?this._setValidator(this,arguments):(a.warn('Validator "'+e+'" is not already defined.'),this.addValidator.apply(this,arguments))},removeValidator:function(e){return this.validators[e]||a.warn('Validator "'+e+'" is not defined.'),delete this.validators[e],this},_setValidator:function(e,t,i){"object"!=typeof t&&(t={fn:t,priority:i}),t.validate||(t=new f(t)),this.validators[e]=t;for(var n in t.messages||{})this.addMessage(n,e,t.messages[n]);return this},getErrorMessage:function(e){var t;if("type"===e.name){var i=this.catalog[this.locale][e.name]||{};t=i[e.requirements]}else t=this.formatMessage(this.catalog[this.locale][e.name],e.requirements);return t||this.catalog[this.locale].defaultMessage||this.catalog.en.defaultMessage},formatMessage:function(e,t){if("object"==typeof t){for(var i in t)e=this.formatMessage(e,t[i]);return e}return"string"==typeof e?e.replace(/%s/i,t):""},validators:{notblank:{validateString:function(e){return/\S/.test(e)},priority:2},required:{validateMultiple:function(e){return e.length>0},validateString:function(e){return/\S/.test(e)},priority:512},type:{validateString:function(e,t){var i=arguments.length<=2||void 0===arguments[2]?{}:arguments[2],n=i.step,r=void 0===n?"1":n,s=i.base,a=void 0===s?0:s,o=m[t];if(!o)throw new Error("validator type `"+t+"` is not supported");if(!o.test(e))return!1;if("number"===t&&!/^any$/i.test(r||"")){var l=Number(e),u=Math.max(g(r),g(a));if(g(l)>u)return!1;var d=function(e){return Math.round(e*Math.pow(10,u))};if((d(l)-d(a))%d(r)!=0)return!1}return!0},requirementType:{"":"string",step:"string",base:"number"},priority:256},pattern:{validateString:function(e,t){return t.test(e)},requirementType:"regexp",priority:64},minlength:{validateString:function(e,t){return e.length>=t},requirementType:"integer",priority:30},maxlength:{validateString:function(e,t){return e.length<=t},requirementType:"integer",priority:30},length:{validateString:function(e,t,i){return e.length>=t&&e.length<=i},requirementType:["integer","integer"],priority:30},mincheck:{validateMultiple:function(e,t){return e.length>=t},requirementType:"integer",priority:30},maxcheck:{validateMultiple:function(e,t){return e.length<=t},requirementType:"integer",priority:30},check:{validateMultiple:function(e,t,i){return e.length>=t&&e.length<=i},requirementType:["integer","integer"],priority:30},min:{validateNumber:function(e,t){return e>=t},requirementType:"number",priority:30},max:{validateNumber:function(e,t){return t>=e},requirementType:"number",priority:30},range:{validateNumber:function(e,t,i){return e>=t&&i>=e},requirementType:["number","number"],priority:30},equalto:{validateString:function(t,i){var n=e(i);return n.length?t===n.val():t===i},priority:256}}};var y={},v=function T(e,t,i){for(var n=[],r=[],s=0;s<e.length;s++){for(var a=!1,o=0;o<t.length;o++)if(e[s].assert.name===t[o].assert.name){a=!0;break}a?r.push(e[s]):n.push(e[s])}return{kept:r,added:n,removed:i?[]:T(t,e,!0).added}};y.Form={_actualizeTriggers:function(){var e=this;this.$element.on("submit.Parsley",function(t){e.onSubmitValidate(t)}),this.$element.on("click.Parsley",'input[type="submit"], button[type="submit"]',function(t){e.onSubmitButton(t)}),!1!==this.options.uiEnabled&&this.$element.attr("novalidate","")},focus:function(){if(this._focusedField=null,!0===this.validationResult||"none"===this.options.focus)return null;for(var e=0;e<this.fields.length;e++){var t=this.fields[e];if(!0!==t.validationResult&&t.validationResult.length>0&&"undefined"==typeof t.options.noFocus&&(this._focusedField=t.$element,"first"===this.options.focus))break}return null===this._focusedField?null:this._focusedField.focus()},_destroyUI:function(){this.$element.off(".Parsley")}},y.Field={_reflowUI:function(){if(this._buildUI(),this._ui){var e=v(this.validationResult,this._ui.lastValidationResult);this._ui.lastValidationResult=this.validationResult,this._manageStatusClass(),this._manageErrorsMessages(e),this._actualizeTriggers(),!e.kept.length&&!e.added.length||this._failedOnce||(this._failedOnce=!0,this._actualizeTriggers())}},getErrorsMessages:function(){if(!0===this.validationResult)return[];for(var e=[],t=0;t<this.validationResult.length;t++)e.push(this.validationResult[t].errorMessage||this._getErrorMessage(this.validationResult[t].assert));return e},addError:function(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],i=t.message,n=t.assert,r=t.updateClass,s=void 0===r?!0:r;this._buildUI(),this._addError(e,{message:i,assert:n}),s&&this._errorClass()},updateError:function(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],i=t.message,n=t.assert,r=t.updateClass,s=void 0===r?!0:r;this._buildUI(),this._updateError(e,{message:i,assert:n}),s&&this._errorClass()},removeError:function(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],i=t.updateClass,n=void 0===i?!0:i;this._buildUI(),this._removeError(e),n&&this._manageStatusClass()},_manageStatusClass:function(){this.hasConstraints()&&this.needsValidation()&&!0===this.validationResult?this._successClass():this.validationResult.length>0?this._errorClass():this._resetClass()},_manageErrorsMessages:function(t){if("undefined"==typeof this.options.errorsMessagesDisabled){if("undefined"!=typeof this.options.errorMessage)return t.added.length||t.kept.length?(this._insertErrorWrapper(),0===this._ui.$errorsWrapper.find(".parsley-custom-error-message").length&&this._ui.$errorsWrapper.append(e(this.options.errorTemplate).addClass("parsley-custom-error-message")),this._ui.$errorsWrapper.addClass("filled").find(".parsley-custom-error-message").html(this.options.errorMessage)):this._ui.$errorsWrapper.removeClass("filled").find(".parsley-custom-error-message").remove();for(var i=0;i<t.removed.length;i++)this._removeError(t.removed[i].assert.name);for(i=0;i<t.added.length;i++)this._addError(t.added[i].assert.name,{message:t.added[i].errorMessage,assert:t.added[i].assert});for(i=0;i<t.kept.length;i++)this._updateError(t.kept[i].assert.name,{message:t.kept[i].errorMessage,assert:t.kept[i].assert})}},_addError:function(t,i){var n=i.message,r=i.assert;this._insertErrorWrapper(),this._ui.$errorsWrapper.addClass("filled").append(e(this.options.errorTemplate).addClass("parsley-"+t).html(n||this._getErrorMessage(r)))},_updateError:function(e,t){var i=t.message,n=t.assert;this._ui.$errorsWrapper.addClass("filled").find(".parsley-"+e).html(i||this._getErrorMessage(n))},_removeError:function(e){this._ui.$errorsWrapper.removeClass("filled").find(".parsley-"+e).remove()},_getErrorMessage:function(e){var t=e.name+"Message";return"undefined"!=typeof this.options[t]?window.Parsley.formatMessage(this.options[t],e.requirements):window.Parsley.getErrorMessage(e)},_buildUI:function(){if(!this._ui&&!1!==this.options.uiEnabled){var t={};this.$element.attr(this.options.namespace+"id",this.__id__),t.$errorClassHandler=this._manageClassHandler(),t.errorsWrapperId="parsley-id-"+(this.options.multiple?"multiple-"+this.options.multiple:this.__id__),t.$errorsWrapper=e(this.options.errorsWrapper).attr("id",t.errorsWrapperId),t.lastValidationResult=[],t.validationInformationVisible=!1,this._ui=t}},_manageClassHandler:function(){if("string"==typeof this.options.classHandler&&e(this.options.classHandler).length)return e(this.options.classHandler);var t=this.options.classHandler.call(this,this);return"undefined"!=typeof t&&t.length?t:!this.options.multiple||this.$element.is("select")?this.$element:this.$element.parent()},_insertErrorWrapper:function(){var t;if(0!==this._ui.$errorsWrapper.parent().length)return this._ui.$errorsWrapper.parent();if("string"==typeof this.options.errorsContainer){if(e(this.options.errorsContainer).length)return e(this.options.errorsContainer).append(this._ui.$errorsWrapper);a.warn("The errors container `"+this.options.errorsContainer+"` does not exist in DOM")}else"function"==typeof this.options.errorsContainer&&(t=this.options.errorsContainer.call(this,this));if("undefined"!=typeof t&&t.length)return t.append(this._ui.$errorsWrapper);var i=this.$element;return this.options.multiple&&(i=i.parent()),i.after(this._ui.$errorsWrapper)},_actualizeTriggers:function(){var e=this,t=this._findRelated();t.off(".Parsley"),this._failedOnce?t.on(a.namespaceEvents(this.options.triggerAfterFailure,"Parsley"),function(){e.validate()}):t.on(a.namespaceEvents(this.options.trigger,"Parsley"),function(t){e._eventValidate(t)})},_eventValidate:function(e){(!/key|input/.test(e.type)||this._ui&&this._ui.validationInformationVisible||!(this.getValue().length<=this.options.validationThreshold))&&this.validate()},_resetUI:function(){this._failedOnce=!1,this._actualizeTriggers(),"undefined"!=typeof this._ui&&(this._ui.$errorsWrapper.removeClass("filled").children().remove(),this._resetClass(),this._ui.lastValidationResult=[],this._ui.validationInformationVisible=!1)},_destroyUI:function(){this._resetUI(),"undefined"!=typeof this._ui&&this._ui.$errorsWrapper.remove(),delete this._ui},_successClass:function(){this._ui.validationInformationVisible=!0,this._ui.$errorClassHandler.removeClass(this.options.errorClass).addClass(this.options.successClass)},_errorClass:function(){this._ui.validationInformationVisible=!0,this._ui.$errorClassHandler.removeClass(this.options.successClass).addClass(this.options.errorClass)},_resetClass:function(){this._ui.$errorClassHandler.removeClass(this.options.successClass).removeClass(this.options.errorClass)}};var _=function(t,i,n){this.__class__="ParsleyForm",this.__id__=a.generateID(),this.$element=e(t),this.domOptions=i,this.options=n,this.parent=window.Parsley,this.fields=[],this.validationResult=null},w={pending:null,resolved:!0,rejected:!1};_.prototype={onSubmitValidate:function(e){var t=this;if(!0!==e.parsley){var i=this._$submitSource||this.$element.find('input[type="submit"], button[type="submit"]').first();if(this._$submitSource=null,this.$element.find(".parsley-synthetic-submit-button").prop("disabled",!0),!i.is("[formnovalidate]")){var n=this.whenValidate({event:e});"resolved"===n.state()&&!1!==this._trigger("submit")||(e.stopImmediatePropagation(),e.preventDefault(),"pending"===n.state()&&n.done(function(){t._submit(i)}))}}},onSubmitButton:function(t){this._$submitSource=e(t.target)},_submit:function(t){if(!1!==this._trigger("submit")){if(t){var i=this.$element.find(".parsley-synthetic-submit-button").prop("disabled",!1);0===i.length&&(i=e('<input class="parsley-synthetic-submit-button" type="hidden">').appendTo(this.$element)),i.attr({name:t.attr("name"),value:t.attr("value")})}this.$element.trigger(e.extend(e.Event("submit"),{parsley:!0}))}},validate:function(t){if(arguments.length>=1&&!e.isPlainObject(t)){a.warnOnce("Calling validate on a parsley form without passing arguments as an object is deprecated.");var i=_slice.call(arguments),n=i[0],r=i[1],s=i[2];t={group:n,force:r,event:s}}return w[this.whenValidate(t).state()]},whenValidate:function(){var t=this,i=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=i.group,r=i.force,s=i.event;this.submitEvent=s,s&&(this.submitEvent=e.extend({},s,{preventDefault:function(){a.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`"),t.validationResult=!1}})),this.validationResult=!0,this._trigger("validate"),this._refreshFields();var o=this._withoutReactualizingFormOptions(function(){return e.map(t.fields,function(e){return e.whenValidate({force:r,group:n})})}),l=function(){var i=e.Deferred();return!1===t.validationResult&&i.reject(),i.resolve().promise()};return e.when.apply(e,_toConsumableArray(o)).done(function(){t._trigger("success")}).fail(function(){t.validationResult=!1,t.focus(),t._trigger("error")}).always(function(){t._trigger("validated")}).pipe(l,l)},isValid:function(t){if(arguments.length>=1&&!e.isPlainObject(t)){a.warnOnce("Calling isValid on a parsley form without passing arguments as an object is deprecated.");var i=_slice.call(arguments),n=i[0],r=i[1];t={group:n,force:r}}return w[this.whenValid(t).state()]},whenValid:function(){var t=this,i=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=i.group,r=i.force;this._refreshFields();var s=this._withoutReactualizingFormOptions(function(){return e.map(t.fields,function(e){return e.whenValid({group:n,force:r})})});return e.when.apply(e,_toConsumableArray(s))},_refreshFields:function(){return this.actualizeOptions()._bindFields()},_bindFields:function(){var t=this,i=this.fields;return this.fields=[],this.fieldsMappedById={},this._withoutReactualizingFormOptions(function(){t.$element.find(t.options.inputs).not(t.options.excluded).each(function(e,i){var n=new window.Parsley.Factory(i,{},t);"ParsleyField"!==n.__class__&&"ParsleyFieldMultiple"!==n.__class__||!0===n.options.excluded||"undefined"==typeof t.fieldsMappedById[n.__class__+"-"+n.__id__]&&(t.fieldsMappedById[n.__class__+"-"+n.__id__]=n,t.fields.push(n))}),e(i).not(t.fields).each(function(e,t){t._trigger("reset")})}),this},_withoutReactualizingFormOptions:function(e){var t=this.actualizeOptions;this.actualizeOptions=function(){return this};var i=e();return this.actualizeOptions=t,i},_trigger:function(e){return this.trigger("form:"+e)}};var b=function(t,i,n,r,s){if(!/ParsleyField/.test(t.__class__))throw new Error("ParsleyField or ParsleyFieldMultiple instance expected");var a=window.Parsley._validatorRegistry.validators[i],o=new f(a);e.extend(this,{validator:o,name:i,requirements:n,priority:r||t.options[i+"Priority"]||o.priority,isDomConstraint:!0===s}),this._parseRequirements(t.options)},F=function(e){var t=e[0].toUpperCase();return t+e.slice(1)};b.prototype={validate:function(e,t){var i=this.requirementList.slice(0);return i.unshift(e),i.push(t),this.validator.validate.apply(this.validator,i)},_parseRequirements:function(e){var t=this;this.requirementList=this.validator.parseRequirements(this.requirements,function(i){return e[t.name+F(i)]})}};var C=function(t,i,n,r){this.__class__="ParsleyField",this.__id__=a.generateID(),this.$element=e(t),"undefined"!=typeof r&&(this.parent=r),this.options=n,this.domOptions=i,this.constraints=[],this.constraintsByName={},this.validationResult=[],this._bindConstraints()},$={pending:null,resolved:!0,rejected:!1};C.prototype={validate:function(t){arguments.length>=1&&!e.isPlainObject(t)&&(a.warnOnce("Calling validate on a parsley field without passing arguments as an object is deprecated."),t={options:t});var i=this.whenValidate(t);if(!i)return!0;switch(i.state()){case"pending":return null;case"resolved":return!0;case"rejected":return this.validationResult}},whenValidate:function(){var e=this,t=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],i=t.force,n=t.group;return this.refreshConstraints(),!n||this._isInGroup(n)?(this.value=this.getValue(),this._trigger("validate"),this.whenValid({force:i,value:this.value,_refreshed:!0}).always(function(){e._reflowUI()}).done(function(){e._trigger("success")}).fail(function(){e._trigger("error")}).always(function(){e._trigger("validated")})):void 0},hasConstraints:function(){return 0!==this.constraints.length},needsValidation:function(e){return"undefined"==typeof e&&(e=this.getValue()),e.length||this._isRequired()||"undefined"!=typeof this.options.validateIfEmpty?!0:!1},_isInGroup:function(t){return e.isArray(this.options.group)?-1!==e.inArray(t,this.options.group):this.options.group===t},isValid:function(t){if(arguments.length>=1&&!e.isPlainObject(t)){a.warnOnce("Calling isValid on a parsley field without passing arguments as an object is deprecated.");var i=_slice.call(arguments),n=i[0],r=i[1];t={force:n,value:r}}var s=this.whenValid(t);return s?$[s.state()]:!0},whenValid:function(){var t=this,i=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=i.force,r=void 0===n?!1:n,s=i.value,a=i.group,o=i._refreshed;if(o||this.refreshConstraints(),!a||this._isInGroup(a)){if(this.validationResult=!0,!this.hasConstraints())return e.when();if(("undefined"==typeof s||null===s)&&(s=this.getValue()),!this.needsValidation(s)&&!0!==r)return e.when();var l=this._getGroupedConstraints(),u=[];return e.each(l,function(i,n){var r=e.when.apply(e,_toConsumableArray(e.map(n,function(e){return t._validateConstraint(s,e)})));return u.push(r),"rejected"===r.state()?!1:void 0}),e.when.apply(e,u)}},_validateConstraint:function(t,i){var n=this,r=i.validate(t,this);return!1===r&&(r=e.Deferred().reject()),e.when(r).fail(function(e){!0===n.validationResult&&(n.validationResult=[]),n.validationResult.push({assert:i,errorMessage:"string"==typeof e&&e})})},getValue:function(){var e;return e="function"==typeof this.options.value?this.options.value(this):"undefined"!=typeof this.options.value?this.options.value:this.$element.val(),"undefined"==typeof e||null===e?"":this._handleWhitespace(e)},refreshConstraints:function(){return this.actualizeOptions()._bindConstraints()},addConstraint:function(e,t,i,n){if(window.Parsley._validatorRegistry.validators[e]){var r=new b(this,e,t,i,n);"undefined"!==this.constraintsByName[r.name]&&this.removeConstraint(r.name),this.constraints.push(r),this.constraintsByName[r.name]=r}return this},removeConstraint:function(e){for(var t=0;t<this.constraints.length;t++)if(e===this.constraints[t].name){this.constraints.splice(t,1);break}return delete this.constraintsByName[e],this},updateConstraint:function(e,t,i){return this.removeConstraint(e).addConstraint(e,t,i)},_bindConstraints:function(){for(var e=[],t={},i=0;i<this.constraints.length;i++)!1===this.constraints[i].isDomConstraint&&(e.push(this.constraints[i]),t[this.constraints[i].name]=this.constraints[i]);this.constraints=e,this.constraintsByName=t;for(var n in this.options)this.addConstraint(n,this.options[n],void 0,!0);return this._bindHtml5Constraints()},_bindHtml5Constraints:function(){(this.$element.hasClass("required")||this.$element.attr("required"))&&this.addConstraint("required",!0,void 0,!0),"string"==typeof this.$element.attr("pattern")&&this.addConstraint("pattern",this.$element.attr("pattern"),void 0,!0),"undefined"!=typeof this.$element.attr("min")&&"undefined"!=typeof this.$element.attr("max")?this.addConstraint("range",[this.$element.attr("min"),this.$element.attr("max")],void 0,!0):"undefined"!=typeof this.$element.attr("min")?this.addConstraint("min",this.$element.attr("min"),void 0,!0):"undefined"!=typeof this.$element.attr("max")&&this.addConstraint("max",this.$element.attr("max"),void 0,!0),"undefined"!=typeof this.$element.attr("minlength")&&"undefined"!=typeof this.$element.attr("maxlength")?this.addConstraint("length",[this.$element.attr("minlength"),this.$element.attr("maxlength")],void 0,!0):"undefined"!=typeof this.$element.attr("minlength")?this.addConstraint("minlength",this.$element.attr("minlength"),void 0,!0):"undefined"!=typeof this.$element.attr("maxlength")&&this.addConstraint("maxlength",this.$element.attr("maxlength"),void 0,!0);var e=this.$element.attr("type");return"undefined"==typeof e?this:"number"===e?this.addConstraint("type",["number",{step:this.$element.attr("step"),base:this.$element.attr("min")||this.$element.attr("value")}],void 0,!0):/^(email|url|range)$/i.test(e)?this.addConstraint("type",e,void 0,!0):this},_isRequired:function(){return"undefined"==typeof this.constraintsByName.required?!1:!1!==this.constraintsByName.required.requirements},_trigger:function(e){return this.trigger("field:"+e)},_handleWhitespace:function(e){return!0===this.options.trimValue&&a.warnOnce('data-parsley-trim-value="true" is deprecated, please use data-parsley-whitespace="trim"'),"squish"===this.options.whitespace&&(e=e.replace(/\s{2,}/g," ")),("trim"===this.options.whitespace||"squish"===this.options.whitespace||!0===this.options.trimValue)&&(e=a.trimString(e)),e},_getGroupedConstraints:function(){if(!1===this.options.priorityEnabled)return[this.constraints];for(var e=[],t={},i=0;i<this.constraints.length;i++){var n=this.constraints[i].priority;t[n]||e.push(t[n]=[]),t[n].push(this.constraints[i])}return e.sort(function(e,t){return t[0].priority-e[0].priority}),e}};var x=C,P=function(){this.__class__="ParsleyFieldMultiple"};P.prototype={addElement:function(e){return this.$elements.push(e),this},refreshConstraints:function(){var t;if(this.constraints=[],this.$element.is("select"))return this.actualizeOptions()._bindConstraints(),this;for(var i=0;i<this.$elements.length;i++)if(e("html").has(this.$elements[i]).length){t=this.$elements[i].data("ParsleyFieldMultiple").refreshConstraints().constraints;for(var n=0;n<t.length;n++)this.addConstraint(t[n].name,t[n].requirements,t[n].priority,t[n].isDomConstraint)}else this.$elements.splice(i,1);return this},getValue:function(){if("function"==typeof this.options.value)value=this.options.value(this);else if("undefined"!=typeof this.options.value)return this.options.value;if(this.$element.is("input[type=radio]"))return this._findRelated().filter(":checked").val()||"";if(this.$element.is("input[type=checkbox]")){var t=[];return this._findRelated().filter(":checked").each(function(){t.push(e(this).val())}),t}return this.$element.is("select")&&null===this.$element.val()?[]:this.$element.val()},_init:function(){return this.$elements=[this.$element],this}};var E=function(t,i,n){this.$element=e(t);var r=this.$element.data("Parsley");if(r)return"undefined"!=typeof n&&r.parent===window.Parsley&&(r.parent=n,r._resetOptions(r.options)),r;if(!this.$element.length)throw new Error("You must bind Parsley on an existing element.");if("undefined"!=typeof n&&"ParsleyForm"!==n.__class__)throw new Error("Parent instance must be a ParsleyForm instance");return this.parent=n||window.Parsley,this.init(i)};E.prototype={init:function(e){return this.__class__="Parsley",this.__version__="2.3.5",this.__id__=a.generateID(),this._resetOptions(e),this.$element.is("form")||a.checkAttr(this.$element,this.options.namespace,"validate")&&!this.$element.is(this.options.inputs)?this.bind("parsleyForm"):this.isMultiple()?this.handleMultiple():this.bind("parsleyField")},isMultiple:function(){return this.$element.is("input[type=radio], input[type=checkbox]")||this.$element.is("select")&&"undefined"!=typeof this.$element.attr("multiple")},handleMultiple:function(){var t,i,n=this;if(this.options.multiple||("undefined"!=typeof this.$element.attr("name")&&this.$element.attr("name").length?this.options.multiple=t=this.$element.attr("name"):"undefined"!=typeof this.$element.attr("id")&&this.$element.attr("id").length&&(this.options.multiple=this.$element.attr("id"))),this.$element.is("select")&&"undefined"!=typeof this.$element.attr("multiple"))return this.options.multiple=this.options.multiple||this.__id__,this.bind("parsleyFieldMultiple");if(!this.options.multiple)return a.warn("To be bound by Parsley, a radio, a checkbox and a multiple select input must have either a name or a multiple option.",this.$element),this;this.options.multiple=this.options.multiple.replace(/(:|\.|\[|\]|\{|\}|\$)/g,""),
|
178 |
-
"undefined"!=typeof t&&e('input[name="'+t+'"]').each(function(t,i){e(i).is("input[type=radio], input[type=checkbox]")&&e(i).attr(n.options.namespace+"multiple",n.options.multiple)});for(var r=this._findRelated(),s=0;s<r.length;s++)if(i=e(r.get(s)).data("Parsley"),"undefined"!=typeof i){this.$element.data("ParsleyFieldMultiple")||i.addElement(this.$element);break}return this.bind("parsleyField",!0),i||this.bind("parsleyFieldMultiple")},bind:function(t,i){var n;switch(t){case"parsleyForm":n=e.extend(new _(this.$element,this.domOptions,this.options),window.ParsleyExtend)._bindFields();break;case"parsleyField":n=e.extend(new x(this.$element,this.domOptions,this.options,this.parent),window.ParsleyExtend);break;case"parsleyFieldMultiple":n=e.extend(new x(this.$element,this.domOptions,this.options,this.parent),new P,window.ParsleyExtend)._init();break;default:throw new Error(t+"is not a supported Parsley type")}return this.options.multiple&&a.setAttr(this.$element,this.options.namespace,"multiple",this.options.multiple),"undefined"!=typeof i?(this.$element.data("ParsleyFieldMultiple",n),n):(this.$element.data("Parsley",n),n._actualizeTriggers(),n._trigger("init"),n)}};var V=e.fn.jquery.split(".");if(parseInt(V[0])<=1&&parseInt(V[1])<8)throw"The loaded version of jQuery is too old. Please upgrade to 1.8.x or better.";V.forEach||a.warn("Parsley requires ES5 to run properly. Please include https://github.com/es-shims/es5-shim");var M=e.extend(new l,{$element:e(document),actualizeOptions:null,_resetOptions:null,Factory:E,version:"2.3.5"});e.extend(x.prototype,y.Field,l.prototype),e.extend(_.prototype,y.Form,l.prototype),e.extend(E.prototype,l.prototype),e.fn.parsley=e.fn.psly=function(t){if(this.length>1){var i=[];return this.each(function(){i.push(e(this).parsley(t))}),i}return e(this).length?new E(this,t):void a.warn("You must bind Parsley on an existing element.")},"undefined"==typeof window.ParsleyExtend&&(window.ParsleyExtend={}),M.options=e.extend(a.objectCreate(o),window.ParsleyConfig),window.ParsleyConfig=M.options,window.Parsley=window.psly=M,window.ParsleyUtils=a;var O=window.Parsley._validatorRegistry=new c(window.ParsleyConfig.validators,window.ParsleyConfig.i18n);window.ParsleyValidator={},e.each("setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator".split(" "),function(t,i){window.Parsley[i]=e.proxy(O,i),window.ParsleyValidator[i]=function(){var e;return a.warnOnce("Accessing the method '"+i+"' through ParsleyValidator is deprecated. Simply call 'window.Parsley."+i+"(...)'"),(e=window.Parsley)[i].apply(e,arguments)}}),window.Parsley.UI=y,window.ParsleyUI={removeError:function(e,t,i){var n=!0!==i;return a.warnOnce("Accessing ParsleyUI is deprecated. Call 'removeError' on the instance directly. Please comment in issue 1073 as to your need to call this method."),e.removeError(t,{updateClass:n})},getErrorsMessages:function(e){return a.warnOnce("Accessing ParsleyUI is deprecated. Call 'getErrorsMessages' on the instance directly."),e.getErrorsMessages()}},e.each("addError updateError".split(" "),function(e,t){window.ParsleyUI[t]=function(e,i,n,r,s){var o=!0!==s;return a.warnOnce("Accessing ParsleyUI is deprecated. Call '"+t+"' on the instance directly. Please comment in issue 1073 as to your need to call this method."),e[t](i,{message:n,assert:r,updateClass:o})}}),/firefox/i.test(navigator.userAgent)&&e(document).on("change","select",function(t){e(t.target).trigger("input")}),!1!==window.ParsleyConfig.autoBind&&e(function(){e("[data-parsley-validate]").length&&e("[data-parsley-validate]").parsley()});var A=e({}),R=function(){a.warnOnce("Parsley's pubsub module is deprecated; use the 'on' and 'off' methods on parsley instances or window.Parsley")},D="parsley:";e.listen=function(e,n){var r;if(R(),"object"==typeof arguments[1]&&"function"==typeof arguments[2]&&(r=arguments[1],n=arguments[2]),"function"!=typeof n)throw new Error("Wrong parameters");window.Parsley.on(i(e),t(n,r))},e.listenTo=function(e,n,r){if(R(),!(e instanceof x||e instanceof _))throw new Error("Must give Parsley instance");if("string"!=typeof n||"function"!=typeof r)throw new Error("Wrong parameters");e.on(i(n),t(r))},e.unsubscribe=function(e,t){if(R(),"string"!=typeof e||"function"!=typeof t)throw new Error("Wrong arguments");window.Parsley.off(i(e),t.parsleyAdaptedCallback)},e.unsubscribeTo=function(e,t){if(R(),!(e instanceof x||e instanceof _))throw new Error("Must give Parsley instance");e.off(i(t))},e.unsubscribeAll=function(t){R(),window.Parsley.off(i(t)),e("form,input,textarea,select").each(function(){var n=e(this).data("Parsley");n&&n.off(i(t))})},e.emit=function(e,t){var n;R();var r=t instanceof x||t instanceof _,s=Array.prototype.slice.call(arguments,r?2:1);s.unshift(i(e)),r||(t=window.Parsley),(n=t).trigger.apply(n,_toConsumableArray(s))};e.extend(!0,M,{asyncValidators:{"default":{fn:function(e){return e.status>=200&&e.status<300},url:!1},reverse:{fn:function(e){return e.status<200||e.status>=300},url:!1}},addAsyncValidator:function(e,t,i,n){return M.asyncValidators[e]={fn:t,url:i||!1,options:n||{}},this}}),M.addValidator("remote",{requirementType:{"":"string",validator:"string",reverse:"boolean",options:"object"},validateString:function(t,i,n,r){var s,a,o={},l=n.validator||(!0===n.reverse?"reverse":"default");if("undefined"==typeof M.asyncValidators[l])throw new Error("Calling an undefined async validator: `"+l+"`");i=M.asyncValidators[l].url||i,i.indexOf("{value}")>-1?i=i.replace("{value}",encodeURIComponent(t)):o[r.$element.attr("name")||r.$element.attr("id")]=t;var u=e.extend(!0,n.options||{},M.asyncValidators[l].options);s=e.extend(!0,{},{url:i,data:o,type:"GET"},u),r.trigger("field:ajaxoptions",r,s),a=e.param(s),"undefined"==typeof M._remoteCache&&(M._remoteCache={});var d=M._remoteCache[a]=M._remoteCache[a]||e.ajax(s),h=function(){var t=M.asyncValidators[l].fn.call(r,d,i,n);return t||(t=e.Deferred().reject()),e.when(t)};return d.then(h,h)},priority:-1}),M.on("form:submit",function(){M._remoteCache={}}),window.ParsleyExtend.addAsyncValidator=function(){return ParsleyUtils.warnOnce("Accessing the method `addAsyncValidator` through an instance is deprecated. Simply call `Parsley.addAsyncValidator(...)`"),M.addAsyncValidator.apply(M,arguments)},M.addMessages("en",{defaultMessage:"This value seems to be invalid.",type:{email:"This value should be a valid email.",url:"This value should be a valid url.",number:"This value should be a valid number.",integer:"This value should be a valid integer.",digits:"This value should be digits.",alphanum:"This value should be alphanumeric."},notblank:"This value should not be blank.",required:"This value is required.",pattern:"This value seems to be invalid.",min:"This value should be greater than or equal to %s.",max:"This value should be lower than or equal to %s.",range:"This value should be between %s and %s.",minlength:"This value is too short. It should have %s characters or more.",maxlength:"This value is too long. It should have %s characters or fewer.",length:"This value length is invalid. It should be between %s and %s characters long.",mincheck:"You must select at least %s choices.",maxcheck:"You must select %s choices or fewer.",check:"You must select between %s and %s choices.",equalto:"This value should be the same."}),M.setLocale("en");var q=M;return q});
|
179 |
-
</script>
|
180 |
-
|
181 |
-
<script type="text/javascript">
|
182 |
-
/*!
|
183 |
-
* jQuery Modal (minified)
|
184 |
-
* Copyright (c) 2015 CreativeDream
|
185 |
-
* https://github.com/CreativeDream/jquery.modal
|
186 |
-
* Version: 1.2.3 (10-04-2015)
|
187 |
-
* Requires: jQuery v1.7.1 or later
|
188 |
-
* type: 'inverted', //Type of Modal Box (alert | confirm | prompt | success | warning | error | info | inverted | primary)
|
189 |
-
*/
|
190 |
-
function modal(t){return $.cModal(t)}!function(t){t.cModal=function(n){var e,o={type:"default",title:null,text:null,size:"normal",buttons:[{text:"OK",val:!0,onClick:function(){return!0}}],center:!0,autoclose:!1,callback:null,onShow:null,animate:!0,closeClick:!0,closable:!0,theme:"default",background:null,zIndex:1050,buttonText:{ok:"OK",yes:"Yes",cancel:"Cancel"},template:'<div class="modal-box"><div class="modal-inner"><div class="modal-title"><a class="modal-close-btn"></a></div><div class="modal-text"></div><div class="modal-buttons"></div></div></div>',_classes:{box:".modal-box",boxInner:".modal-inner",title:".modal-title",content:".modal-text",buttons:".modal-buttons",closebtn:".modal-close-btn"}},n=t.extend({},o,n),a=t("<div id='modal-window' />").hide(),l=n._classes.box,s=a.append(n.template),i={init:function(){t("#modal-window").remove(),i._setStyle(),i._modalShow(),i._modalConent(),a.on("click","a.modal-btn",function(){i._modalBtn(t(this))}).on("click",n._classes.closebtn,function(){e=!1,i._modalHide()}).click(function(t){n.closeClick&&"modal-window"==t.target.id&&(e=!1,i._modalHide())}),t(window).bind("keyup",i._keyUpF).resize(function(){var t=n.animate;n.animate=!1,i._position(),n.animate=t})},_setStyle:function(){a.css({position:"fixed",width:"100%",height:"100%",top:"0",left:"0","z-index":n.zIndex,overflow:"auto"}),a.find(n._classes.box).css({position:"absolute"})},_keyUpF:function(t){switch(t.keyCode){case 13:if(s.find("input:not(.modal-prompt-input),textarea").is(":focus"))return!1;i._modalBtn(a.find(n._classes.buttons+" a.modal-btn"+("undefined"!=typeof i.btnForEKey&&a.find(n._classes.buttons+" a.modal-btn:eq("+i.btnForEKey+")").size()>0?":eq("+i.btnForEKey+")":":last-child")));break;case 27:i._modalHide()}},_modalShow:function(){t("body").css({overflow:"hidden",width:t("body").innerWidth()}).append(s)},_modalHide:function(o){if(n.closable===!1)return!1;e="undefined"==typeof e?!1:e;var s=function(){if(null!=n.callback&&"function"==typeof n.callback&&0==n.callback(e,a,i.actions)?!1:!0){a.fadeOut(200,function(){t(this).remove(),t("body").css({overflow:"",width:""})});var o=100*parseFloat(t(l).css("top"))/parseFloat(t(l).parent().css("height"));t(l).stop(!0,!0).animate({top:o+(n.animate?3:0)+"%"},"fast")}};o?setTimeout(function(){s()},o):s(),t(window).unbind("keyup",i._keyUpF)},_modalConent:function(){var e=n._classes.title,o=n._classes.content,s=n._classes.buttons,d=n.buttonText,c=["alert","confirm","prompt"],u=["xenon","atlant","reseted"];if(-1==t.inArray(n.type,c)&&"default"!=n.type&&t(l).addClass("modal-type-"+n.type),t(l).addClass(n.size&&null!=n.size?"modal-size-"+n.size:"modal-size-normal"),n.theme&&null!=n.theme&&"default"!=n.theme&&t(l).addClass((-1==t.inArray(n.theme,u)?"":"modal-theme-")+n.theme),n.background&&null!=n.background&&a.css("background-color",n.background),n.title||null!=n.title?t(e).prepend("<h3>"+n.title+"</h3>"):t(e).remove(),"prompt"==n.type?n.text=(null!=n.text?n.text:"")+'<input type="text" name="modal-prompt-input" class="modal-prompt-input" autocomplete="off" autofocus="on" />':"",t(o).html(n.text),n.buttons||null!=n.buttons){var r="";switch(n.type){case"alert":r='<a class="modal-btn'+(n.buttons[0].addClass?" "+n.buttons[0].addClass:"")+'">'+d.ok+"</a>";break;case"confirm":r='<a class="modal-btn'+(n.buttons[0].addClass?" "+n.buttons[0].addClass:"")+'">'+d.cancel+'</a><a class="modal-btn '+(n.buttons[1]&&n.buttons[1].addClass?" "+n.buttons[1].addClass:"btn-light-blue")+'">'+d.yes+"</a>";break;case"prompt":r='<a class="modal-btn'+(n.buttons[0].addClass?" "+n.buttons[0].addClass:"")+'">'+d.cancel+'</a><a class="modal-btn '+(n.buttons[1]&&n.buttons[1].addClass?" "+n.buttons[1].addClass:"btn-light-blue")+'">'+d.ok+"</a>";break;default:n.buttons.length>0&&t.isArray(n.buttons)?t.each(n.buttons,function(t,n){var e=n.addClass&&"undefined"!=typeof n.addClass?" "+n.addClass:"";r+='<a class="modal-btn'+e+'">'+n.text+"</a>",n.eKey&&(i.btnForEKey=t)}):r+='<a class="modal-btn">'+d.ok+"</a>"}t(s).html(r)}else t(s).remove();if("prompt"==n.type&&$(".modal-prompt-input").focus(),n.autoclose){var m=n.buttons||null!=n.buttons?32*t(o).text().length:900;i._modalHide(900>m?900:m)}a.fadeIn(200,function(){null!=n.onShow?n.onShow(i.actions):null}),i._position()},_position:function(){var e,o,a;n.center?(e={top:t(window).height()<t(l).outerHeight()?1:50,left:50,marginTop:t(window).height()<t(l).outerHeight()?0:-t(l).outerHeight()/2,marginLeft:-t(l).outerWidth()/2},o={top:e.top-(n.animate?3:0)+"%",left:e.left+"%","margin-top":e.marginTop,"margin-left":e.marginLeft},a={top:e.top+"%"}):(e={top:t(window).height()<t(l).outerHeight()?1:10,left:50,marginTop:0,marginLeft:-t(l).outerWidth()/2},o={top:e.top-(n.animate?3:0)+"%",left:e.left+"%","margin-top":e.marginTop,"margin-left":e.marginLeft},a={top:e.top+"%"}),t(l).css(o).stop(!0,!0).animate(a,"fast")},_modalBtn:function(o){var l=!1,s=n.type,d=o.index(),c=n.buttons[d];if(t.inArray(s,["alert","confirm","prompt"])>-1)e=l=1==d?!0:!1,"prompt"==s&&(e=l=l&&a.find("input.modal-prompt-input").size()>0!=0?a.find("input.modal-prompt-input").val():!1),i._modalHide();else{if(o.hasClass("btn-disabled"))return!1;e=l=c&&c.val?c.val:!0,(!c.onClick||c.onClick(t.extend({val:l,bObj:o,bOpts:c},i.actions)))&&i._modalHide()}e=l},actions:{html:a,close:function(){i._modalHide()},getModal:function(){return a},getBox:function(){return a.find(n._classes.box)},getInner:function(){return a.find(n._classes.boxInner)},getTitle:function(){return a.find(n._classes.title)},getContet:function(){return a.find(n._classes.content)},getButtons:function(){return a.find(n._classes.buttons).find("a")},setTitle:function(t){return a.find(n._classes.title+" h3").html(t),a.find(n._classes.title+" h3").size()>0},setContent:function(t){return a.find(n._classes.content).html(t),a.find(n._classes.content).size()>0}}};return i.init(),i.actions}}(jQuery);
|
191 |
-
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/build/classes/class.csrf.php
DELETED
@@ -1,75 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
defined("DUPXABSPATH") or die("");
|
3 |
-
|
4 |
-
/******************************************************************
|
5 |
-
*
|
6 |
-
* Projectname: PHP Cross-Site Request Forgery (DUPX_CSRF) Protection Class
|
7 |
-
* Version: 1.0
|
8 |
-
* Author: Radovan Janjic <hi@radovanjanjic.com>
|
9 |
-
* Last modified: 19 06 2014
|
10 |
-
* Copyright (C): 2014 IT-radionica.com, All Rights Reserved
|
11 |
-
*
|
12 |
-
* GNU General Public License (Version 2, June 1991)
|
13 |
-
*
|
14 |
-
* This program is free software; you can redistribute
|
15 |
-
* it and/or modify it under the terms of the GNU
|
16 |
-
* General Public License as published by the Free
|
17 |
-
* Software Foundation; either version 2 of the License,
|
18 |
-
* or (at your option) any later version.
|
19 |
-
*
|
20 |
-
* This program is distributed in the hope that it will
|
21 |
-
* be useful, but WITHOUT ANY WARRANTY; without even the
|
22 |
-
* implied warranty of MERCHANTABILITY or FITNESS FOR A
|
23 |
-
* PARTICULAR PURPOSE. See the GNU General Public License
|
24 |
-
* for more details.
|
25 |
-
*
|
26 |
-
******************************************************************/
|
27 |
-
|
28 |
-
class DUPX_CSRF {
|
29 |
-
|
30 |
-
/** Session var name
|
31 |
-
* @var string
|
32 |
-
*/
|
33 |
-
public static $session = '_DUPX_CSRF';
|
34 |
-
|
35 |
-
/** Generate DUPX_CSRF value for form
|
36 |
-
* @param string $form - Form name as session key
|
37 |
-
* @return string - token
|
38 |
-
*/
|
39 |
-
static function generate($form = NULL) {
|
40 |
-
$token = DUPX_CSRF::token() . DUPX_CSRF::fingerprint();
|
41 |
-
$_SESSION[DUPX_CSRF::$session . '_' . $form] = $token;
|
42 |
-
return $token;
|
43 |
-
}
|
44 |
-
|
45 |
-
/** Check DUPX_CSRF value of form
|
46 |
-
* @param string $token - Token
|
47 |
-
* @param string $form - Form name as session key
|
48 |
-
* @return boolean
|
49 |
-
*/
|
50 |
-
public static function check($token, $form = NULL) {
|
51 |
-
if (isset($_SESSION[DUPX_CSRF::$session . '_' . $form]) && $_SESSION[DUPX_CSRF::$session . '_' . $form] == $token) { // token OK
|
52 |
-
return (substr($token, -32) == DUPX_CSRF::fingerprint()); // fingerprint OK?
|
53 |
-
}
|
54 |
-
return FALSE;
|
55 |
-
}
|
56 |
-
|
57 |
-
/** Generate token
|
58 |
-
* @param void
|
59 |
-
* @return string
|
60 |
-
*/
|
61 |
-
protected static function token() {
|
62 |
-
mt_srand((double) microtime() * 10000);
|
63 |
-
$charid = strtoupper(md5(uniqid(rand(), TRUE)));
|
64 |
-
return substr($charid, 0, 8) . substr($charid, 8, 4) . substr($charid, 12, 4) . substr($charid, 16, 4) . substr($charid, 20, 12);
|
65 |
-
}
|
66 |
-
|
67 |
-
/** Returns "digital fingerprint" of user
|
68 |
-
* @param void
|
69 |
-
* @return string - MD5 hashed data
|
70 |
-
*/
|
71 |
-
protected static function fingerprint() {
|
72 |
-
return strtoupper(md5(implode('|', array($_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_USER_AGENT']))));
|
73 |
-
}
|
74 |
-
}
|
75 |
-
?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/build/classes/class.db.php
DELETED
@@ -1,215 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
defined("DUPXABSPATH") or die("");
|
3 |
-
|
4 |
-
/**
|
5 |
-
* Lightweight abstraction layer for common simple database routines
|
6 |
-
*
|
7 |
-
* Standard: PSR-2
|
8 |
-
* @link http://www.php-fig.org/psr/psr-2 Full Documentation
|
9 |
-
*
|
10 |
-
* @package SC\DUPX\DB
|
11 |
-
*
|
12 |
-
*/
|
13 |
-
class DUPX_DB
|
14 |
-
{
|
15 |
-
|
16 |
-
/**
|
17 |
-
* MySQL connection wrapper with support for port
|
18 |
-
*
|
19 |
-
* @param string $host The server host name
|
20 |
-
* @param string $username The server DB user name
|
21 |
-
* @param string $password The server DB password
|
22 |
-
* @param string $dbname The server DB name
|
23 |
-
* @param int $port The server DB port
|
24 |
-
*
|
25 |
-
* @return database connection handle
|
26 |
-
*/
|
27 |
-
public static function connect($host, $username, $password, $dbname = '', $port = null)
|
28 |
-
{
|
29 |
-
//sock connections
|
30 |
-
if ('sock' === substr($host, -4)) {
|
31 |
-
$url_parts = parse_url($host);
|
32 |
-
$dbh = @mysqli_connect('localhost', $username, $password, $dbname, null, $url_parts['path']);
|
33 |
-
} else {
|
34 |
-
$dbh = @mysqli_connect($host, $username, $password, $dbname, $port);
|
35 |
-
}
|
36 |
-
return $dbh;
|
37 |
-
}
|
38 |
-
|
39 |
-
/**
|
40 |
-
* Count the tables in a given database
|
41 |
-
*
|
42 |
-
* @param obj $dbh A valid database link handle
|
43 |
-
* @param string $dbname Database to count tables in
|
44 |
-
*
|
45 |
-
* @return int The number of tables in the database
|
46 |
-
*/
|
47 |
-
public static function countTables($dbh, $dbname)
|
48 |
-
{
|
49 |
-
$res = mysqli_query($dbh, "SELECT COUNT(*) AS count FROM information_schema.tables WHERE table_schema = '".mysqli_real_escape_string($dbh, $dbname)."' ");
|
50 |
-
$row = mysqli_fetch_row($res);
|
51 |
-
return is_null($row) ? 0 : $row[0];
|
52 |
-
}
|
53 |
-
|
54 |
-
/**
|
55 |
-
* Returns the number of rows in a table
|
56 |
-
*
|
57 |
-
* @param obj $dbh A valid database link handle
|
58 |
-
* @param string $name A valid table name
|
59 |
-
*/
|
60 |
-
public static function countTableRows($dbh, $name)
|
61 |
-
{
|
62 |
-
$total = mysqli_query($dbh, "SELECT COUNT(*) FROM `".mysqli_real_escape_string($dbh, $name)."`");
|
63 |
-
if ($total) {
|
64 |
-
$total = @mysqli_fetch_array($total);
|
65 |
-
return $total[0];
|
66 |
-
} else {
|
67 |
-
return 0;
|
68 |
-
}
|
69 |
-
}
|
70 |
-
|
71 |
-
/**
|
72 |
-
* Returns the tables for a database as an array
|
73 |
-
*
|
74 |
-
* @param obj $dbh A valid database link handle
|
75 |
-
*
|
76 |
-
* @return array A list of all table names
|
77 |
-
*/
|
78 |
-
public static function getTables($dbh)
|
79 |
-
{
|
80 |
-
$query = @mysqli_query($dbh, 'SHOW TABLES');
|
81 |
-
if ($query) {
|
82 |
-
while ($table = @mysqli_fetch_array($query)) {
|
83 |
-
$all_tables[] = $table[0];
|
84 |
-
}
|
85 |
-
if (isset($all_tables) && is_array($all_tables)) {
|
86 |
-
return $all_tables;
|
87 |
-
}
|
88 |
-
}
|
89 |
-
return array();
|
90 |
-
}
|
91 |
-
|
92 |
-
/**
|
93 |
-
* Get the requested MySQL system variable
|
94 |
-
*
|
95 |
-
* @param obj $dbh A valid database link handle
|
96 |
-
* @param string $name The database variable name to lookup
|
97 |
-
*
|
98 |
-
* @return string the server variable to query for
|
99 |
-
*/
|
100 |
-
public static function getVariable($dbh, $name)
|
101 |
-
{
|
102 |
-
$result = @mysqli_query($dbh, "SHOW VARIABLES LIKE '".mysqli_real_escape_string($dbh, $name)."'");
|
103 |
-
$row = @mysqli_fetch_array($result);
|
104 |
-
@mysqli_free_result($result);
|
105 |
-
return isset($row[1]) ? $row[1] : null;
|
106 |
-
}
|
107 |
-
|
108 |
-
/**
|
109 |
-
* Gets the MySQL database version number
|
110 |
-
*
|
111 |
-
* @param obj $dbh A valid database link handle
|
112 |
-
* @param bool $full True: Gets the full version
|
113 |
-
* False: Gets only the numeric portion i.e. 5.5.6 or 10.1.2 (for MariaDB)
|
114 |
-
*
|
115 |
-
* @return false|string 0 on failure, version number on success
|
116 |
-
*/
|
117 |
-
public static function getVersion($dbh, $full = false)
|
118 |
-
{
|
119 |
-
if ($full) {
|
120 |
-
$version = self::getVariable($dbh, 'version');
|
121 |
-
} else {
|
122 |
-
$version = preg_replace('/[^0-9.].*/', '', self::getVariable($dbh, 'version'));
|
123 |
-
}
|
124 |
-
|
125 |
-
$version = is_null($version) ? null : $version;
|
126 |
-
return empty($version) ? 0 : $version;
|
127 |
-
}
|
128 |
-
|
129 |
-
/**
|
130 |
-
* Returns a more detailed string about the msyql server version
|
131 |
-
* For example on some systems the result is 5.5.5-10.1.21-MariaDB
|
132 |
-
* this format is helpful for providing the user a full overview
|
133 |
-
*
|
134 |
-
* @param conn $dbh Database connection handle
|
135 |
-
*
|
136 |
-
* @return string The full details of mysql
|
137 |
-
*/
|
138 |
-
public static function getServerInfo($dbh)
|
139 |
-
{
|
140 |
-
return mysqli_get_server_info($dbh);
|
141 |
-
}
|
142 |
-
|
143 |
-
/**
|
144 |
-
* Get an array of all supported collation names
|
145 |
-
*
|
146 |
-
* @param conn $dbh Database connection handle
|
147 |
-
*
|
148 |
-
* @return array
|
149 |
-
*/
|
150 |
-
public static function getSupportedCollationsList($dbh)
|
151 |
-
{
|
152 |
-
$collations = array();
|
153 |
-
|
154 |
-
$query = "SHOW COLLATION";
|
155 |
-
if ($result = $dbh->query($query)) {
|
156 |
-
|
157 |
-
while ($row = $result->fetch_assoc()) {
|
158 |
-
$collations[] = $row["Collation"];
|
159 |
-
}
|
160 |
-
|
161 |
-
}
|
162 |
-
$result->free();
|
163 |
-
|
164 |
-
return $collations;
|
165 |
-
}
|
166 |
-
|
167 |
-
/**
|
168 |
-
* Determine if a MySQL database supports a particular feature
|
169 |
-
*
|
170 |
-
* @param conn $dbh Database connection handle
|
171 |
-
* @param string $feature the feature to check for
|
172 |
-
*
|
173 |
-
* @return bool
|
174 |
-
*/
|
175 |
-
public static function hasAbility($dbh, $feature)
|
176 |
-
{
|
177 |
-
$version = self::getVersion($dbh);
|
178 |
-
|
179 |
-
switch (strtolower($feature)) {
|
180 |
-
case 'collation' :
|
181 |
-
case 'group_concat' :
|
182 |
-
case 'subqueries' :
|
183 |
-
return version_compare($version, '4.1', '>=');
|
184 |
-
case 'set_charset' :
|
185 |
-
return version_compare($version, '5.0.7', '>=');
|
186 |
-
};
|
187 |
-
return false;
|
188 |
-
}
|
189 |
-
|
190 |
-
/**
|
191 |
-
* Sets the MySQL connection's character set.
|
192 |
-
*
|
193 |
-
* @param resource $dbh The resource given by mysqli_connect
|
194 |
-
* @param string $charset The character set (optional)
|
195 |
-
* @param string $collate The collation (optional)
|
196 |
-
*
|
197 |
-
* @return bool True on success
|
198 |
-
*/
|
199 |
-
public static function setCharset($dbh, $charset = null, $collate = null)
|
200 |
-
{
|
201 |
-
$charset = (!isset($charset) ) ? $GLOBALS['DBCHARSET_DEFAULT'] : $charset;
|
202 |
-
$collate = (!isset($collate) ) ? $GLOBALS['DBCOLLATE_DEFAULT'] : $collate;
|
203 |
-
|
204 |
-
if (self::hasAbility($dbh, 'collation') && !empty($charset)) {
|
205 |
-
if (function_exists('mysqli_set_charset') && self::hasAbility($dbh, 'set_charset')) {
|
206 |
-
return mysqli_set_charset($dbh, $charset);
|
207 |
-
} else {
|
208 |
-
$sql = " SET NAMES ".mysqli_real_escape_string($dbh, $charset);
|
209 |
-
if (!empty($collate)) $sql .= " COLLATE ".mysqli_real_escape_string($dbh, $collate);
|
210 |
-
return mysqli_query($dbh, $sql);
|
211 |
-
}
|
212 |
-
}
|
213 |
-
}
|
214 |
-
}
|
215 |
-
?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/build/classes/class.engine.php
DELETED
@@ -1,450 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
defined("DUPXABSPATH") or die("");
|
3 |
-
|
4 |
-
/**
|
5 |
-
* Walks every table in db that then walks every row and column replacing searches with replaces
|
6 |
-
* large tables are split into 50k row blocks to save on memory.
|
7 |
-
*
|
8 |
-
* Standard: PSR-2
|
9 |
-
* @link http://www.php-fig.org/psr/psr-2 Full Documentation
|
10 |
-
*
|
11 |
-
* @package SC\DUPX\UpdateEngine
|
12 |
-
*
|
13 |
-
*/
|
14 |
-
class DUPX_UpdateEngine
|
15 |
-
{
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Used to report on all log errors into the installer-txt.log
|
19 |
-
*
|
20 |
-
* @param string $report The report error array of all error types
|
21 |
-
*
|
22 |
-
* @return string Writes the results of the update engine tables to the log
|
23 |
-
*/
|
24 |
-
public static function logErrors($report)
|
25 |
-
{
|
26 |
-
if (!empty($report['errsql'])) {
|
27 |
-
DUPX_Log::info("--------------------------------------");
|
28 |
-
DUPX_Log::info("DATA-REPLACE ERRORS (MySQL)");
|
29 |
-
foreach ($report['errsql'] as $error) {
|
30 |
-
DUPX_Log::info($error);
|
31 |
-
}
|
32 |
-
DUPX_Log::info("");
|
33 |
-
}
|
34 |
-
if (!empty($report['errser'])) {
|
35 |
-
DUPX_Log::info("--------------------------------------");
|
36 |
-
DUPX_Log::info("DATA-REPLACE ERRORS (Serialization):");
|
37 |
-
foreach ($report['errser'] as $error) {
|
38 |
-
DUPX_Log::info($error);
|
39 |
-
}
|
40 |
-
DUPX_Log::info("");
|
41 |
-
}
|
42 |
-
if (!empty($report['errkey'])) {
|
43 |
-
DUPX_Log::info("--------------------------------------");
|
44 |
-
DUPX_Log::info("DATA-REPLACE ERRORS (Key):");
|
45 |
-
DUPX_Log::info('Use SQL: SELECT @row := @row + 1 as row, t.* FROM some_table t, (SELECT @row := 0) r');
|
46 |
-
foreach ($report['errkey'] as $error) {
|
47 |
-
DUPX_Log::info($error);
|
48 |
-
}
|
49 |
-
}
|
50 |
-
}
|
51 |
-
|
52 |
-
/**
|
53 |
-
* Used to report on all log stats into the installer-txt.log
|
54 |
-
*
|
55 |
-
* @param string $report The report stats array of all error types
|
56 |
-
*
|
57 |
-
* @return string Writes the results of the update engine tables to the log
|
58 |
-
*/
|
59 |
-
public static function logStats($report)
|
60 |
-
{
|
61 |
-
if (!empty($report) && is_array($report)) {
|
62 |
-
$stats = "--------------------------------------\n";
|
63 |
-
$srchnum = 0;
|
64 |
-
foreach ($GLOBALS['REPLACE_LIST'] as $item) {
|
65 |
-
$srchnum++;
|
66 |
-
$stats .= sprintf("Search{$srchnum}:\t'%s' \nChange{$srchnum}:\t'%s' \n", $item['search'], $item['replace']);
|
67 |
-
}
|
68 |
-
$stats .= sprintf("SCANNED:\tTables:%d \t|\t Rows:%d \t|\t Cells:%d \n", $report['scan_tables'], $report['scan_rows'], $report['scan_cells']);
|
69 |
-
$stats .= sprintf("UPDATED:\tTables:%d \t|\t Rows:%d \t|\t Cells:%d \n", $report['updt_tables'], $report['updt_rows'], $report['updt_cells']);
|
70 |
-
$stats .= sprintf("ERRORS:\t\t%d \nRUNTIME:\t%f sec", $report['err_all'], $report['time']);
|
71 |
-
DUPX_Log::info($stats);
|
72 |
-
}
|
73 |
-
}
|
74 |
-
|
75 |
-
/**
|
76 |
-
* Returns only the text type columns of a table ignoring all numeric types
|
77 |
-
*
|
78 |
-
* @param obj $dbh A valid database link handle
|
79 |
-
* @param string $table A valid table name
|
80 |
-
*
|
81 |
-
* @return array All the column names of a table
|
82 |
-
*/
|
83 |
-
public static function getTextColumns($dbh, $table)
|
84 |
-
{
|
85 |
-
$type_where = "type NOT LIKE 'tinyint%' AND ";
|
86 |
-
$type_where .= "type NOT LIKE 'smallint%' AND ";
|
87 |
-
$type_where .= "type NOT LIKE 'mediumint%' AND ";
|
88 |
-
$type_where .= "type NOT LIKE 'int%' AND ";
|
89 |
-
$type_where .= "type NOT LIKE 'bigint%' AND ";
|
90 |
-
$type_where .= "type NOT LIKE 'float%' AND ";
|
91 |
-
$type_where .= "type NOT LIKE 'double%' AND ";
|
92 |
-
$type_where .= "type NOT LIKE 'decimal%' AND ";
|
93 |
-
$type_where .= "type NOT LIKE 'numeric%' AND ";
|
94 |
-
$type_where .= "type NOT LIKE 'date%' AND ";
|
95 |
-
$type_where .= "type NOT LIKE 'time%' AND ";
|
96 |
-
$type_where .= "type NOT LIKE 'year%' ";
|
97 |
-
|
98 |
-
$result = mysqli_query($dbh, "SHOW COLUMNS FROM `".mysqli_real_escape_string($dbh, $table)."` WHERE {$type_where}");
|
99 |
-
if (!$result) {
|
100 |
-
return null;
|
101 |
-
}
|
102 |
-
$fields = array();
|
103 |
-
if (mysqli_num_rows($result) > 0) {
|
104 |
-
while ($row = mysqli_fetch_assoc($result)) {
|
105 |
-
$fields[] = $row['Field'];
|
106 |
-
}
|
107 |
-
}
|
108 |
-
|
109 |
-
//Return Primary which is needed for index lookup
|
110 |
-
//$result = mysqli_query($dbh, "SHOW INDEX FROM `{$table}` WHERE KEY_NAME LIKE '%PRIMARY%'"); 1.1.15 updated
|
111 |
-
$result = mysqli_query($dbh, "SHOW INDEX FROM `".mysqli_real_escape_string($dbh, $table)."`");
|
112 |
-
if (mysqli_num_rows($result) > 0) {
|
113 |
-
while ($row = mysqli_fetch_assoc($result)) {
|
114 |
-
$fields[] = $row['Column_name'];
|
115 |
-
}
|
116 |
-
}
|
117 |
-
|
118 |
-
return (count($fields) > 0) ? $fields : null;
|
119 |
-
}
|
120 |
-
|
121 |
-
/**
|
122 |
-
* Begins the processing for replace logic
|
123 |
-
*
|
124 |
-
* @param mysql $dbh The db connection object
|
125 |
-
* @param array $list Key value pair of 'search' and 'replace' arrays
|
126 |
-
* @param array $tables The tables we want to look at
|
127 |
-
* @param array $fullsearch Search every column regardless of its data type
|
128 |
-
*
|
129 |
-
* @return array Collection of information gathered during the run.
|
130 |
-
*/
|
131 |
-
public static function load($dbh, $list = array(), $tables = array(), $fullsearch = false)
|
132 |
-
{
|
133 |
-
$report = array(
|
134 |
-
'scan_tables' => 0,
|
135 |
-
'scan_rows' => 0,
|
136 |
-
'scan_cells' => 0,
|
137 |
-
'updt_tables' => 0,
|
138 |
-
'updt_rows' => 0,
|
139 |
-
'updt_cells' => 0,
|
140 |
-
'errsql' => array(),
|
141 |
-
'errser' => array(),
|
142 |
-
'errkey' => array(),
|
143 |
-
'errsql_sum' => 0,
|
144 |
-
'errser_sum' => 0,
|
145 |
-
'errkey_sum' => 0,
|
146 |
-
'time' => '',
|
147 |
-
'err_all' => 0
|
148 |
-
);
|
149 |
-
|
150 |
-
function set_sql_column_safe(&$str) {
|
151 |
-
$str = "`$str`";
|
152 |
-
}
|
153 |
-
|
154 |
-
$profile_start = DUPX_U::getMicrotime();
|
155 |
-
if (is_array($tables) && !empty($tables)) {
|
156 |
-
|
157 |
-
foreach ($tables as $table) {
|
158 |
-
$report['scan_tables'] ++;
|
159 |
-
$columns = array();
|
160 |
-
|
161 |
-
// Get a list of columns in this table
|
162 |
-
$fields = mysqli_query($dbh, 'DESCRIBE '.mysqli_real_escape_string($dbh, $table));
|
163 |
-
while ($column = mysqli_fetch_array($fields)) {
|
164 |
-
$columns[$column['Field']] = $column['Key'] == 'PRI' ? true : false;
|
165 |
-
}
|
166 |
-
|
167 |
-
// Count the number of rows we have in the table if large we'll split into blocks
|
168 |
-
$row_count = mysqli_query($dbh, "SELECT COUNT(*) FROM `".mysqli_real_escape_string($dbh, $table)."`");
|
169 |
-
$rows_result = mysqli_fetch_array($row_count);
|
170 |
-
@mysqli_free_result($row_count);
|
171 |
-
$row_count = $rows_result[0];
|
172 |
-
if ($row_count == 0) {
|
173 |
-
DUPX_Log::info("{$table}^ ({$row_count})");
|
174 |
-
continue;
|
175 |
-
}
|
176 |
-
|
177 |
-
$page_size = 25000;
|
178 |
-
$offset = ($page_size + 1);
|
179 |
-
$pages = ceil($row_count / $page_size);
|
180 |
-
|
181 |
-
// Grab the columns of the table. Only grab text based columns because
|
182 |
-
// they are the only data types that should allow any type of search/replace logic
|
183 |
-
$colList = '*';
|
184 |
-
$colMsg = '*';
|
185 |
-
if (!$fullsearch) {
|
186 |
-
$colList = self::getTextColumns($dbh, $table);
|
187 |
-
if ($colList != null && is_array($colList)) {
|
188 |
-
array_walk($colList, set_sql_column_safe);
|
189 |
-
$colList = implode(',', $colList);
|
190 |
-
}
|
191 |
-
$colMsg = (empty($colList)) ? '*' : '~';
|
192 |
-
}
|
193 |
-
|
194 |
-
if (empty($colList)) {
|
195 |
-
DUPX_Log::info("{$table}^ ({$row_count})");
|
196 |
-
continue;
|
197 |
-
} else {
|
198 |
-
DUPX_Log::info("{$table}{$colMsg} ({$row_count})");
|
199 |
-
}
|
200 |
-
|
201 |
-
//Paged Records
|
202 |
-
for ($page = 0; $page < $pages; $page++) {
|
203 |
-
$current_row = 0;
|
204 |
-
$start = $page * $page_size;
|
205 |
-
$end = $start + $page_size;
|
206 |
-
$sql = sprintf("SELECT {$colList} FROM `%s` LIMIT %d, %d", mysqli_real_escape_string($dbh, $table), $start, $offset);
|
207 |
-
$data = mysqli_query($dbh, $sql);
|
208 |
-
|
209 |
-
if (!$data) $report['errsql'][] = mysqli_error($dbh);
|
210 |
-
|
211 |
-
$scan_count = ($row_count < $end) ? $row_count : $end;
|
212 |
-
DUPX_Log::info("\tScan => {$start} of {$scan_count}", 2);
|
213 |
-
|
214 |
-
//Loops every row
|
215 |
-
while ($row = mysqli_fetch_array($data)) {
|
216 |
-
$report['scan_rows'] ++;
|
217 |
-
$current_row++;
|
218 |
-
$upd_col = array();
|
219 |
-
$upd_sql = array();
|
220 |
-
$where_sql = array();
|
221 |
-
$upd = false;
|
222 |
-
$serial_err = 0;
|
223 |
-
$is_unkeyed = !in_array(true,$columns);
|
224 |
-
|
225 |
-
//Loops every cell
|
226 |
-
foreach ($columns as $column => $primary_key) {
|
227 |
-
$report['scan_cells'] ++;
|
228 |
-
$edited_data = $data_to_fix = $row[$column];
|
229 |
-
$base64converted = false;
|
230 |
-
$txt_found = false;
|
231 |
-
|
232 |
-
//Unkeyed table code
|
233 |
-
//Added this here to add all columns to $where_sql
|
234 |
-
//The if statement with $txt_found would skip additional columns
|
235 |
-
if($is_unkeyed && ! empty($data_to_fix)) {
|
236 |
-
$where_sql[] = $column.' = "'.mysqli_real_escape_string($dbh, $data_to_fix).'"';
|
237 |
-
}
|
238 |
-
|
239 |
-
//Only replacing string values
|
240 |
-
if (!empty($row[$column]) && !is_numeric($row[$column]) && $primary_key != 1) {
|
241 |
-
//Base 64 detection
|
242 |
-
if (base64_decode($row[$column], true)) {
|
243 |
-
$decoded = base64_decode($row[$column], true);
|
244 |
-
if (self::isSerialized($decoded)) {
|
245 |
-
$edited_data = $decoded;
|
246 |
-
$base64converted = true;
|
247 |
-
}
|
248 |
-
}
|
249 |
-
|
250 |
-
//Skip table cell if match not found
|
251 |
-
foreach ($list as $item) {
|
252 |
-
if (strpos($edited_data, $item['search']) !== false) {
|
253 |
-
$txt_found = true;
|
254 |
-
break;
|
255 |
-
}
|
256 |
-
}
|
257 |
-
if (!$txt_found) {
|
258 |
-
continue;
|
259 |
-
}
|
260 |
-
|
261 |
-
//Replace logic - level 1: simple check on any string or serialized strings
|
262 |
-
foreach ($list as $item) {
|
263 |
-
$edited_data = self::recursiveUnserializeReplace($item['search'], $item['replace'], $edited_data);
|
264 |
-
}
|
265 |
-
|
266 |
-
//Replace logic - level 2: repair serialized strings that have become broken
|
267 |
-
$serial_check = self::fixSerialString($edited_data);
|
268 |
-
if ($serial_check['fixed']) {
|
269 |
-
$edited_data = $serial_check['data'];
|
270 |
-
} elseif ($serial_check['tried'] && !$serial_check['fixed']) {
|
271 |
-
$serial_err++;
|
272 |
-
}
|
273 |
-
}
|
274 |
-
|
275 |
-
//Change was made
|
276 |
-
if ($edited_data != $data_to_fix || $serial_err > 0) {
|
277 |
-
$report['updt_cells'] ++;
|
278 |
-
//Base 64 encode
|
279 |
-
if ($base64converted) {
|
280 |
-
$edited_data = base64_encode($edited_data);
|
281 |
-
}
|
282 |
-
$upd_col[] = $column;
|
283 |
-
$upd_sql[] = $column.' = "'.mysqli_real_escape_string($dbh, $edited_data).'"';
|
284 |
-
$upd = true;
|
285 |
-
}
|
286 |
-
|
287 |
-
if ($primary_key) {
|
288 |
-
$where_sql[] = $column.' = "'.mysqli_real_escape_string($dbh, $data_to_fix).'"';
|
289 |
-
}
|
290 |
-
}
|
291 |
-
|
292 |
-
//PERFORM ROW UPDATE
|
293 |
-
if ($upd && !empty($where_sql)) {
|
294 |
-
$sql = "UPDATE `".mysqli_real_escape_string($dbh, $table)."` SET ".implode(', ', $upd_sql).' WHERE '.implode(' AND ', array_filter($where_sql));
|
295 |
-
$result = mysqli_query($dbh, $sql);
|
296 |
-
if ($result) {
|
297 |
-
if ($serial_err > 0) {
|
298 |
-
$report['errser'][] = "SELECT " . implode(', ', $upd_col) . " FROM `{$table}` WHERE " . implode(' AND ', array_filter($where_sql)) . ';';
|
299 |
-
}
|
300 |
-
$report['updt_rows']++;
|
301 |
-
} else {
|
302 |
-
$report['errsql'][] = ($GLOBALS["LOGGING"] == 1)
|
303 |
-
? 'DB ERROR: ' . mysqli_error($dbh)
|
304 |
-
: 'DB ERROR: ' . mysqli_error($dbh) . "\nSQL: [{$sql}]\n";
|
305 |
-
}
|
306 |
-
|
307 |
-
//DEBUG ONLY:
|
308 |
-
DUPX_Log::info("\t{$sql}\n", 3);
|
309 |
-
|
310 |
-
} elseif ($upd) {
|
311 |
-
$report['errkey'][] = sprintf("Row [%s] on Table [%s] requires a manual update.", $current_row, $table);
|
312 |
-
}
|
313 |
-
}
|
314 |
-
//DUPX_U::fcgiFlush();
|
315 |
-
@mysqli_free_result($data);
|
316 |
-
}
|
317 |
-
|
318 |
-
if ($upd) {
|
319 |
-
$report['updt_tables'] ++;
|
320 |
-
}
|
321 |
-
}
|
322 |
-
}
|
323 |
-
$profile_end = DUPX_U::getMicrotime();
|
324 |
-
$report['time'] = DUPX_U::elapsedTime($profile_end, $profile_start);
|
325 |
-
$report['errsql_sum'] = empty($report['errsql']) ? 0 : count($report['errsql']);
|
326 |
-
$report['errser_sum'] = empty($report['errser']) ? 0 : count($report['errser']);
|
327 |
-
$report['errkey_sum'] = empty($report['errkey']) ? 0 : count($report['errkey']);
|
328 |
-
$report['err_all'] = $report['errsql_sum'] + $report['errser_sum'] + $report['errkey_sum'];
|
329 |
-
return $report;
|
330 |
-
}
|
331 |
-
|
332 |
-
/**
|
333 |
-
* Take a serialized array and unserialized it replacing elements and
|
334 |
-
* unserializing any subordinate arrays and performing the replace.
|
335 |
-
*
|
336 |
-
* @param string $from String we're looking to replace.
|
337 |
-
* @param string $to What we want it to be replaced with
|
338 |
-
* @param array $data Used to pass any subordinate arrays back to in.
|
339 |
-
* @param bool $serialised Does the array passed via $data need serializing.
|
340 |
-
*
|
341 |
-
* @return array The original array with all elements replaced as needed.
|
342 |
-
*/
|
343 |
-
public static function recursiveUnserializeReplace($from = '', $to = '', $data = '', $serialised = false)
|
344 |
-
{
|
345 |
-
// some unseriliased data cannot be re-serialised eg. SimpleXMLElements
|
346 |
-
try {
|
347 |
-
if (is_string($data) && ($unserialized = @unserialize($data)) !== false) {
|
348 |
-
$data = self::recursiveUnserializeReplace($from, $to, $unserialized, true);
|
349 |
-
} elseif (is_array($data)) {
|
350 |
-
$_tmp = array();
|
351 |
-
foreach ($data as $key => $value) {
|
352 |
-
$_tmp[$key] = self::recursiveUnserializeReplace($from, $to, $value, false);
|
353 |
-
}
|
354 |
-
$data = $_tmp;
|
355 |
-
unset($_tmp);
|
356 |
-
|
357 |
-
/* CJL
|
358 |
-
Check for an update to the key of an array e.g. [http://localhost/projects/wpplugins/] => 1.41
|
359 |
-
This could have unintended consequences would need to enable with full-search needs more testing
|
360 |
-
if (array_key_exists($from, $data))
|
361 |
-
{
|
362 |
-
$data[$to] = $data[$from];
|
363 |
-
unset($data[$from]);
|
364 |
-
} */
|
365 |
-
} elseif (is_object($data)) {
|
366 |
-
/* RSR Old logic that didn't work with Beaver Builder - they didn't want to create a brand new
|
367 |
-
object instead reused the existing one...
|
368 |
-
$dataClass = get_class($data);
|
369 |
-
$_tmp = new $dataClass();
|
370 |
-
foreach ($data as $key => $value) {
|
371 |
-
$_tmp->$key = self::recursiveUnserializeReplace($from, $to, $value, false);
|
372 |
-
}
|
373 |
-
$data = $_tmp;
|
374 |
-
unset($_tmp); */
|
375 |
-
|
376 |
-
// RSR NEW LOGIC
|
377 |
-
$_tmp = $data;
|
378 |
-
$props = get_object_vars($data);
|
379 |
-
foreach ($props as $key => $value) {
|
380 |
-
$_tmp->$key = self::recursiveUnserializeReplace($from, $to, $value, false);
|
381 |
-
}
|
382 |
-
$data = $_tmp;
|
383 |
-
unset($_tmp);
|
384 |
-
} else {
|
385 |
-
if (is_string($data)) {
|
386 |
-
$data = str_replace($from, $to, $data);
|
387 |
-
}
|
388 |
-
}
|
389 |
-
|
390 |
-
if ($serialised) return serialize($data);
|
391 |
-
} catch (Exception $error) {
|
392 |
-
DUPX_Log::info("\nRECURSIVE UNSERIALIZE ERROR: With string\n".$error, 2);
|
393 |
-
}
|
394 |
-
return $data;
|
395 |
-
}
|
396 |
-
|
397 |
-
/**
|
398 |
-
* Test if a string in properly serialized
|
399 |
-
*
|
400 |
-
* @param string $data Any string type
|
401 |
-
*
|
402 |
-
* @return bool Is the string a serialized string
|
403 |
-
*/
|
404 |
-
public static function isSerialized($data)
|
405 |
-
{
|
406 |
-
$test = @unserialize(($data));
|
407 |
-
return ($test !== false || $test === 'b:0;') ? true : false;
|
408 |
-
}
|
409 |
-
|
410 |
-
/**
|
411 |
-
* Fixes the string length of a string object that has been serialized but the length is broken
|
412 |
-
*
|
413 |
-
* @param string $data The string ojbect to recalculate the size on.
|
414 |
-
*
|
415 |
-
* @return string A serialized string that fixes and string length types
|
416 |
-
*/
|
417 |
-
public static function fixSerialString($data)
|
418 |
-
{
|
419 |
-
$result = array('data' => $data, 'fixed' => false, 'tried' => false);
|
420 |
-
if (preg_match("/s:[0-9]+:/", $data)) {
|
421 |
-
if (!self::isSerialized($data)) {
|
422 |
-
$regex = '!(?<=^|;)s:(\d+)(?=:"(.*?)";(?:}|a:|s:|b:|d:|i:|o:|N;))!s';
|
423 |
-
$serial_string = preg_match('/^s:[0-9]+:"(.*$)/s', trim($data), $matches);
|
424 |
-
//Nested serial string
|
425 |
-
if ($serial_string) {
|
426 |
-
$inner = preg_replace_callback($regex, 'DUPX_UpdateEngine::fixStringCallback', rtrim($matches[1], '";'));
|
427 |
-
$serialized_fixed = 's:'.strlen($inner).':"'.$inner.'";';
|
428 |
-
} else {
|
429 |
-
$serialized_fixed = preg_replace_callback($regex, 'DUPX_UpdateEngine::fixStringCallback', $data);
|
430 |
-
}
|
431 |
-
|
432 |
-
if (self::isSerialized($serialized_fixed)) {
|
433 |
-
$result['data'] = $serialized_fixed;
|
434 |
-
$result['fixed'] = true;
|
435 |
-
}
|
436 |
-
$result['tried'] = true;
|
437 |
-
}
|
438 |
-
}
|
439 |
-
return $result;
|
440 |
-
}
|
441 |
-
|
442 |
-
/**
|
443 |
-
* The call back method call from via fixSerialString
|
444 |
-
*/
|
445 |
-
private static function fixStringCallback($matches)
|
446 |
-
{
|
447 |
-
return 's:'.strlen(($matches[2]));
|
448 |
-
}
|
449 |
-
}
|
450 |
-
?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/build/classes/class.logging.php
DELETED
@@ -1,67 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
defined("DUPXABSPATH") or die("");
|
3 |
-
|
4 |
-
define('ERR_CONFIG_FOUND', 'A wp-config.php already exists in this location. This error prevents users from accidentally overwriting the wrong directories contents. You have three options: <ul><li>Empty this root directory except for the package and installer and try again.</li><li>Delete just the wp-config.php file and try again. This will over-write all other files in the directory.</li><li>Check the "Manual package extraction" checkbox under advanced options to skip extraction</li></ul>');
|
5 |
-
define('ERR_ZIPNOTFOUND', 'The packaged zip file was not found. Be sure the zip package is in the same directory as the installer file and as the correct permissions. If you are trying to reinstall a package you can copy the package from the "' . DUPLICATOR_SSDIR_NAME . '" directory back up to your root which is the same location as your installer.php file.');
|
6 |
-
define('ERR_ZIPOPEN', 'Failed to open zip archive file. Please be sure the archive is completely downloaded before running the installer. Try to extract the archive manually to make sure the file is not corrupted.');
|
7 |
-
define('ERR_ZIPEXTRACTION', 'Errors extracting zip file. Portions or part of the zip archive did not extract correctly. Try to extract the archive manually with a client side program like unzip/win-zip/winrar or your hosts cPanel to make sure the file is not corrupted. If the file extracts correctly then there is an invalid file or directory that PHP is unable to extract. This can happen if your moving from one operating system to another where certain naming conventions work on one environment and not another. <br/><br/> <b>Workarounds:</b> <br/> 1. Create a new package and be sure to exclude any directories that have invalid names or files in them. This warning will be displayed on the scan results under "Name Checks". <br/> 2. Manually extract the zip file with a client side program or your hosts cPanel. Then under options in step 1 of this installer check the "Manual Archive Extraction" option and perform the install.');
|
8 |
-
define('ERR_ZIPMANUAL', "When choosing manual package extraction, the contents of the package must already be extracted and the wp-config.php and dup-database__{$GLOBALS['PACKAGE_HASH']}.sql files must be present in the same directory as the installer.php for the process to continue. Please manually extract the package into the current directory before continuing in manual extraction mode. Also validate that the wp-config.php and dup-database__[HASH].sql files are present.");
|
9 |
-
define('ERR_MAKELOG', 'PHP is having issues writing to the log file <b>' . DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']) . '\".$GLOBALS["LOG_FILE_NAME"]." .</b> In order for the Duplicator to proceed validate your owner/group and permission settings for PHP on this path. Try temporarily setting you permissions to 777 to see if the issue gets resolved. If you are on a shared hosting environment please contact your hosting company and tell them you are getting errors writing files to the path above when using PHP.');
|
10 |
-
define('ERR_ZIPARCHIVE', 'In order to extract the archive.zip file the PHP ZipArchive module must be installed. Please read the FAQ for more details. You can still install this package but you will need to check the Manual package extraction checkbox found in the Advanced Options. Please read the online user guide for details in performing a manual package extraction.');
|
11 |
-
define('ERR_MYSQLI_SUPPORT', 'In order to complete an install the mysqli extension for PHP is required. If you are on a hosted server please contact your host and request that mysqli be enabled. For more information visit: http://php.net/manual/en/mysqli.installation.php');
|
12 |
-
define('ERR_DBCONNECT', 'DATABASE CONNECTION FAILED!<br/>');
|
13 |
-
define('ERR_DBCONNECT_INFO', '<b>DATABASE CONNECTION FAILED!</b><br/>If the problem persists see the online FAQ for <a href="https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-100-q" target="_blank">recommended fixes</a>.');
|
14 |
-
define('ERR_DBCONNECT_CREATE', 'DATABASE CREATION FAILURE!<br/> Unable to create database "%s". Check to make sure the user has "Create" privileges. Some hosts will restrict creation of a database only through the cpanel. Try creating the database manually to proceed with installation. If the database already exists then check the radio button labeled "Connect and Remove All Data" which will remove all existing tables.');
|
15 |
-
define('ERR_DBTRYCLEAN', 'DATABASE CREATION FAILURE!<br/> Unable to remove all tables from database "%s".<br/> Please remove all tables from this database and try the installation again.');
|
16 |
-
define('ERR_DBCREATE', 'The database "%s" does not exists.<br/> Change mode to create in order to create a new database.');
|
17 |
-
define('ERR_DBEMPTY', 'The database "%s" has "%s" tables. The Duplicator only works with an EMPTY database. Enable the action "Connect and Remove All Data" radio button to remove all tables and or create a new database. Some hosting providers do not allow table removal from scripts. In this case you will need to login to your hosting providers control panel and remove the tables manually. Please contact your hosting provider for further details. Always backup all your data before proceeding!');
|
18 |
-
define('ERR_TESTDB_UTF8', 'UTF8 Characters were detected as part of the database connection string. If your connection fails be sure to update the MySQL my.ini configuration file setting to support UTF8 characters by enabling this option [character_set_server=utf8] and restarting the database server.');
|
19 |
-
define('ERR_TESTDB_VERSION_INFO', 'If the current version detected is below 5.5.3 (release on April 8th 2010) then support for utf8mb4 tables will not work. The utf8mb4 format is only supported in MySQL server 5.5.3+. It is highly recommended to upgrade your version of MySQL server on this server to be more compatible with recent releases of WordPress and avoid issues with install errors.');
|
20 |
-
define('ERR_TESTDB_VERSION_COMPAT', 'In order to avoid database incompatibility issues make sure the database versions between the build and installer servers are as close as possible. If the package was created on a newer database version than where it is being installed then you might run into issues.<br/><br/> It is best to make sure the server where the installer is running has the same or higher version number than where it was built. If the major and minor version are the same or close for example [5.7 to 5.6], then the migration should work without issues. A version pair of [5.7 to 5.1] is more likely to cause issues unless you have a very simple setup. If the versions are too far apart work with your hosting provider to upgrade the MySQL engine on this server.<br/><br/> <b>MariaDB:</b> If a version of 10.N.N shows then the database distribution is a MariaDB flavor of MySQL. While the distributions are very close there are some subtle differences. Some operating systems will report the version such as "5.5.5-10.1.21-MariaDB" showing the correlation of both. Please visit the online <a href="https://mariadb.com/kb/en/mariadb/mariadb-vs-mysql-compatibility/" target="_blank">MariaDB versus MySQL - Compatibility</a> page for more details.<br/><br/> Please note these messages are simply notices. It is highly recommended that you continue with the install process and closely monitor the <?php echo DUPX_U::esc_html($GLOBALS["LOG_FILE_NAME"]);?> file along with the install report found on step 3 of the installer. Be sure to look for any notices/warnings/errors in these locations to validate the install process did not detect any errors. If any issues are found please visit the FAQ pages and see the question <a href="https://snapcreek.com/duplicator/docs/faqs-tech/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=database_incompatibility#faq-installer-260-q" target="_blank">What if I get database errors or general warnings on the install report?</a>.');
|
21 |
-
|
22 |
-
/**
|
23 |
-
* Class used to log information to the installer-log.txt file
|
24 |
-
*
|
25 |
-
* Standard: PSR-2
|
26 |
-
* @link http://www.php-fig.org/psr/psr-2 Full Documentation
|
27 |
-
*
|
28 |
-
* @package SC\DUPX\Log
|
29 |
-
*
|
30 |
-
*/
|
31 |
-
class DUPX_Log
|
32 |
-
{
|
33 |
-
|
34 |
-
/**
|
35 |
-
* Used to write debug info to the text log file
|
36 |
-
*
|
37 |
-
* @param string $msg Any text data
|
38 |
-
* @param int $loglevel Log level
|
39 |
-
*
|
40 |
-
* @return string Write info to both the log and browser
|
41 |
-
*/
|
42 |
-
public static function info($msg, $logging = 1)
|
43 |
-
{
|
44 |
-
if ($logging <= $GLOBALS["LOGGING"]) {
|
45 |
-
@fwrite($GLOBALS["LOG_FILE_HANDLE"], "{$msg}\n");
|
46 |
-
}
|
47 |
-
}
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Used to write errors to the text log file
|
51 |
-
*
|
52 |
-
* @param string $msg Any text data
|
53 |
-
* @param int $loglevel Log level
|
54 |
-
*
|
55 |
-
* @return string Write errors to both the log and browser
|
56 |
-
*/
|
57 |
-
public static function error($msg)
|
58 |
-
{
|
59 |
-
$breaks = array("<br />","<br>","<br/>");
|
60 |
-
$log_msg = str_ireplace($breaks, "\r\n", $msg);
|
61 |
-
$log_msg = strip_tags($log_msg);
|
62 |
-
@fwrite($GLOBALS["LOG_FILE_HANDLE"], "\nINSTALLER ERROR:\n{$log_msg}\n");
|
63 |
-
@fclose($GLOBALS["LOG_FILE_HANDLE"]);
|
64 |
-
die("<div class='dupx-ui-error'><hr size='1' /><b style='color:#B80000;'>INSTALL ERROR!</b><br/>{$msg}</div>");
|
65 |
-
}
|
66 |
-
}
|
67 |
-
?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/build/classes/class.server.php
DELETED
@@ -1,183 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
defined("DUPXABSPATH") or die("");
|
3 |
-
|
4 |
-
/**
|
5 |
-
* Lightweight abstraction layer for common simple server based routines
|
6 |
-
*
|
7 |
-
* Standard: PSR-2
|
8 |
-
* @link http://www.php-fig.org/psr/psr-2 Full Documentation
|
9 |
-
*
|
10 |
-
* @package SC\DUPX\Server
|
11 |
-
*
|
12 |
-
*/
|
13 |
-
class DUPX_Server
|
14 |
-
{
|
15 |
-
/**
|
16 |
-
* Returns true if safe mode is enabled
|
17 |
-
*/
|
18 |
-
public static $php_safe_mode_on = false;
|
19 |
-
|
20 |
-
/**
|
21 |
-
* The servers current PHP version
|
22 |
-
*/
|
23 |
-
public static $php_version = 0;
|
24 |
-
|
25 |
-
/**
|
26 |
-
* The minimum PHP version the installer will support
|
27 |
-
*/
|
28 |
-
public static $php_version_min = "5.2.7";
|
29 |
-
|
30 |
-
/**
|
31 |
-
* Is the current servers version of PHP safe to use with the installer
|
32 |
-
*/
|
33 |
-
public static $php_version_safe = false;
|
34 |
-
|
35 |
-
|
36 |
-
/**
|
37 |
-
* Is PHP 5.3 or better running
|
38 |
-
*/
|
39 |
-
public static $php_version_53_plus;
|
40 |
-
|
41 |
-
/**
|
42 |
-
* Used to init the static properties
|
43 |
-
*/
|
44 |
-
public static function init()
|
45 |
-
{
|
46 |
-
self::$php_safe_mode_on = in_array(strtolower(@ini_get('safe_mode')), array('on', 'yes', 'true', 1, "1"));
|
47 |
-
self::$php_version = phpversion();
|
48 |
-
self::$php_version_safe = DUPX_U::isVersion(self::$php_version_min);
|
49 |
-
self::$php_version_53_plus = DUPX_U::isVersion('5.3.0');
|
50 |
-
}
|
51 |
-
|
52 |
-
/**
|
53 |
-
* Is the directory provided writable by PHP
|
54 |
-
*
|
55 |
-
* @param string $path A physical directory path
|
56 |
-
*
|
57 |
-
* @return bool Returns true if PHP can write to the path provided
|
58 |
-
*/
|
59 |
-
public static function isDirWritable($path)
|
60 |
-
{
|
61 |
-
if (!@is_writeable($path)) return false;
|
62 |
-
|
63 |
-
if (is_dir($path)) {
|
64 |
-
if ($dh = @opendir($path)) {
|
65 |
-
closedir($dh);
|
66 |
-
} else {
|
67 |
-
return false;
|
68 |
-
}
|
69 |
-
}
|
70 |
-
return true;
|
71 |
-
}
|
72 |
-
|
73 |
-
/**
|
74 |
-
* Can this server process in shell_exec mode
|
75 |
-
*
|
76 |
-
* @return bool Returns true is the server can run shell_exec commands
|
77 |
-
*/
|
78 |
-
public static function hasShellExec()
|
79 |
-
{
|
80 |
-
if (array_intersect(array('shell_exec', 'escapeshellarg', 'escapeshellcmd', 'extension_loaded'), array_map('trim', explode(',', @ini_get('disable_functions'))))) return false;
|
81 |
-
|
82 |
-
//Suhosin: http://www.hardened-php.net/suhosin/
|
83 |
-
//Will cause PHP to silently fail.
|
84 |
-
if (extension_loaded('suhosin')) return false;
|
85 |
-
|
86 |
-
// Can we issue a simple echo command?
|
87 |
-
if (!@shell_exec('echo duplicator')) return false;
|
88 |
-
|
89 |
-
return true;
|
90 |
-
}
|
91 |
-
|
92 |
-
/**
|
93 |
-
* Returns the path where the zip command can be called on this server
|
94 |
-
*
|
95 |
-
* @return string The path to where the zip command can be processed
|
96 |
-
*/
|
97 |
-
public static function getUnzipPath()
|
98 |
-
{
|
99 |
-
$filepath = null;
|
100 |
-
if (self::hasShellExec()) {
|
101 |
-
if (shell_exec('hash unzip 2>&1') == NULL) {
|
102 |
-
$filepath = 'unzip';
|
103 |
-
} else {
|
104 |
-
$try_paths = array(
|
105 |
-
'/usr/bin/unzip',
|
106 |
-
'/opt/local/bin/unzip');
|
107 |
-
foreach ($try_paths as $path) {
|
108 |
-
if (file_exists($path)) {
|
109 |
-
$filepath = $path;
|
110 |
-
break;
|
111 |
-
}
|
112 |
-
}
|
113 |
-
}
|
114 |
-
}
|
115 |
-
return $filepath;
|
116 |
-
}
|
117 |
-
|
118 |
-
|
119 |
-
/**
|
120 |
-
* A safe method used to copy larger files
|
121 |
-
*
|
122 |
-
* @param string $source The path to the file being copied
|
123 |
-
* @param string $destination The path to the file being made
|
124 |
-
*
|
125 |
-
* @return bool True if the file was copied
|
126 |
-
*/
|
127 |
-
public static function copyFile($source, $destination)
|
128 |
-
{
|
129 |
-
try {
|
130 |
-
$sp = fopen($source, 'r');
|
131 |
-
$op = fopen($destination, 'w');
|
132 |
-
|
133 |
-
while (!feof($sp)) {
|
134 |
-
$buffer = fread($sp, 512); // use a buffer of 512 bytes
|
135 |
-
fwrite($op, $buffer);
|
136 |
-
}
|
137 |
-
// close handles
|
138 |
-
fclose($op);
|
139 |
-
fclose($sp);
|
140 |
-
return true;
|
141 |
-
|
142 |
-
} catch (Exception $ex) {
|
143 |
-
return false;
|
144 |
-
}
|
145 |
-
}
|
146 |
-
|
147 |
-
|
148 |
-
/**
|
149 |
-
* Returns an array of zip files found in the current executing directory
|
150 |
-
*
|
151 |
-
* @return array of zip files
|
152 |
-
*/
|
153 |
-
public static function getZipFiles()
|
154 |
-
{
|
155 |
-
$files = array();
|
156 |
-
foreach (glob("*.zip") as $name) {
|
157 |
-
if (file_exists($name)) {
|
158 |
-
$files[] = $name;
|
159 |
-
}
|
160 |
-
}
|
161 |
-
|
162 |
-
if (count($files) > 0) {
|
163 |
-
return $files;
|
164 |
-
}
|
165 |
-
|
166 |
-
//FALL BACK: Windows XP has bug with glob,
|
167 |
-
//add secondary check for PHP lameness
|
168 |
-
if ($dh = opendir('.')) {
|
169 |
-
while (false !== ($name = readdir($dh))) {
|
170 |
-
$ext = substr($name, strrpos($name, '.') + 1);
|
171 |
-
if (in_array($ext, array("zip"))) {
|
172 |
-
$files[] = $name;
|
173 |
-
}
|
174 |
-
}
|
175 |
-
closedir($dh);
|
176 |
-
}
|
177 |
-
|
178 |
-
return $files;
|
179 |
-
}
|
180 |
-
}
|
181 |
-
//INIT Class Properties
|
182 |
-
DUPX_Server::init();
|
183 |
-
?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/build/classes/config/class.conf.srv.php
DELETED
@@ -1,113 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
defined("DUPXABSPATH") or die("");
|
3 |
-
/**
|
4 |
-
* Class used to update and edit web server configuration files
|
5 |
-
*
|
6 |
-
* Standard: PSR-2
|
7 |
-
* @link http://www.php-fig.org/psr/psr-2 Full Documentation
|
8 |
-
*
|
9 |
-
* @package SC\DUPX\ServerConfig
|
10 |
-
*
|
11 |
-
*/
|
12 |
-
class DUPX_ServerConfig
|
13 |
-
{
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Clear .htaccess and web.config files and backup
|
17 |
-
*
|
18 |
-
* @return null
|
19 |
-
*/
|
20 |
-
public static function reset()
|
21 |
-
{
|
22 |
-
|
23 |
-
|
24 |
-
DUPX_Log::info("\nWEB SERVER CONFIGURATION FILE RESET:");
|
25 |
-
$timeStamp = date("ymdHis");
|
26 |
-
|
27 |
-
//Apache
|
28 |
-
@copy('.htaccess', ".htaccess.{$timeStamp}.orig");
|
29 |
-
@unlink('.htaccess');
|
30 |
-
@file_put_contents('.htaccess', "#Reset by Duplicator Installer. Original can be found in .htaccess.{$timeStamp}.orig");
|
31 |
-
|
32 |
-
//IIS
|
33 |
-
@copy('web.config', "web.config.{$timeStamp}.orig");
|
34 |
-
@unlink('web.config');
|
35 |
-
$xml_contents = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
|
36 |
-
$xml_contents .= "<!-- Reset by Duplicator Installer. Original can be found in web.config.{$timeStamp}.orig -->\n";
|
37 |
-
$xml_contents .= "<configuration></configuration>\n";
|
38 |
-
@file_put_contents('web.config', $xml_contents);
|
39 |
-
|
40 |
-
//.user.ini - For WordFence
|
41 |
-
@copy('.user.ini', ".user.ini.{$timeStamp}.orig");
|
42 |
-
@unlink('.user.ini');
|
43 |
-
|
44 |
-
DUPX_Log::info("- Backup of .htaccess/web.config made to *.{$timeStamp}.orig");
|
45 |
-
DUPX_Log::info("- Reset of .htaccess/web.config files");
|
46 |
-
|
47 |
-
|
48 |
-
@chmod('.htaccess', 0644);
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Resets the .htaccess file to a very slimed down version with new paths
|
53 |
-
*
|
54 |
-
* @return null
|
55 |
-
*/
|
56 |
-
public static function setup($dbh)
|
57 |
-
{
|
58 |
-
if (!isset($_POST['url_new'])) {
|
59 |
-
return;
|
60 |
-
}
|
61 |
-
|
62 |
-
DUPX_Log::info("\nWEB SERVER CONFIGURATION FILE BASIC SETUP:");
|
63 |
-
$post_url_old = DUPX_U::sanitize_text_field($_POST['url_old']);
|
64 |
-
$currdata = parse_url($_POST['url_old']);
|
65 |
-
$post_url_new = DUPX_U::sanitize_text_field($_POST['url_new']);
|
66 |
-
$newdata = parse_url($post_url_new);
|
67 |
-
$currpath = DUPX_U::addSlash(isset($currdata['path']) ? $currdata['path'] : "");
|
68 |
-
$newpath = DUPX_U::addSlash(isset($newdata['path']) ? $newdata['path'] : "");
|
69 |
-
$timestamp = date("Y-m-d H:i:s");
|
70 |
-
$update_msg = "# This file was updated by Duplicator on {$timestamp}. See .htaccess.orig for the original .htaccess file.\n";
|
71 |
-
$update_msg .= "# Please note that other plugins and resources write to this file. If the time-stamp above is different\n";
|
72 |
-
$update_msg .= "# than the current time-stamp on the file system then another resource has updated this file.\n";
|
73 |
-
$update_msg .= "# Duplicator only writes to this file once during the install process while running the installer.php file.\n";
|
74 |
-
|
75 |
-
$empty_htaccess = false;
|
76 |
-
$query_result = @mysqli_query($dbh, "SELECT option_value FROM `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` WHERE option_name = 'permalink_structure' ");
|
77 |
-
|
78 |
-
//If the permalink is set to Plain then don't update the rewrite rules
|
79 |
-
if ($query_result) {
|
80 |
-
$row = @mysqli_fetch_array($query_result);
|
81 |
-
if ($row != null) {
|
82 |
-
$permalink_structure = trim($row[0]);
|
83 |
-
$empty_htaccess = empty($permalink_structure);
|
84 |
-
}
|
85 |
-
}
|
86 |
-
|
87 |
-
if ($empty_htaccess) {
|
88 |
-
$tmp_htaccess = "{$update_msg}";
|
89 |
-
DUPX_Log::info("- No permalink structures set creating blank .htaccess file.");
|
90 |
-
} else {
|
91 |
-
$tmp_htaccess = <<<HTACCESS
|
92 |
-
{$update_msg}
|
93 |
-
# BEGIN WordPress
|
94 |
-
<IfModule mod_rewrite.c>
|
95 |
-
RewriteEngine On
|
96 |
-
RewriteBase {$newpath}
|
97 |
-
RewriteRule ^index\.php$ - [L]
|
98 |
-
RewriteCond %{REQUEST_FILENAME} !-f
|
99 |
-
RewriteCond %{REQUEST_FILENAME} !-d
|
100 |
-
RewriteRule . {$newpath}index.php [L]
|
101 |
-
</IfModule>
|
102 |
-
# END WordPress
|
103 |
-
HTACCESS;
|
104 |
-
DUPX_Log::info("- Preparing .htaccess file with basic setup.");
|
105 |
-
}
|
106 |
-
|
107 |
-
file_put_contents('.htaccess', $tmp_htaccess);
|
108 |
-
@chmod('.htaccess', 0644);
|
109 |
-
DUPX_Log::info("Basic .htaccess file edit complete. If using IIS web.config this process will need to be done manually.");
|
110 |
-
|
111 |
-
}
|
112 |
-
}
|
113 |
-
?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/build/classes/config/class.conf.wp.php
DELETED
@@ -1,246 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
defined("DUPXABSPATH") or die("");
|
3 |
-
/**
|
4 |
-
* Class used to update and edit and update the wp-config.php
|
5 |
-
*
|
6 |
-
* Standard: PSR-2
|
7 |
-
* @link http://www.php-fig.org/psr/psr-2 Full Documentation
|
8 |
-
*
|
9 |
-
* @package SC\DUPX\WPConfig
|
10 |
-
*
|
11 |
-
*/
|
12 |
-
class DUPX_WPConfig
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* Updates the web server config files in Step 3
|
16 |
-
*
|
17 |
-
* @return null
|
18 |
-
*/
|
19 |
-
public static function updateStandard()
|
20 |
-
{
|
21 |
-
if (!file_exists('wp-config.php')) {
|
22 |
-
DUPX_Log::info('WARNING: Unable to locate wp-config.php file during standard update process. Be sure the file is present in your archive.');
|
23 |
-
return;
|
24 |
-
}
|
25 |
-
|
26 |
-
$root_path = DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']);
|
27 |
-
$wpconfig = @file_get_contents('wp-config.php', true);
|
28 |
-
|
29 |
-
$db_port = is_int($_POST['dbport']) ? DUPX_U::sanitize_text_field($_POST['dbport']) : 3306;
|
30 |
-
$db_host = ($db_port == 3306) ? DUPX_U::sanitize_text_field($_POST['dbhost']) : DUPX_U::sanitize_text_field($_POST['dbhost']).':'.DUPX_U::sanitize_text_field($db_port);
|
31 |
-
$db_name = isset($_POST['dbname']) ? DUPX_U::sanitize_text_field($_POST['dbname']) : null;
|
32 |
-
$db_user = isset($_POST['dbuser']) ? DUPX_U::sanitize_text_field($_POST['dbuser']) : null;
|
33 |
-
$db_pass = isset($_POST['dbpass']) ? DUPX_U::sanitize_text_field($_POST['dbpass']) : null;
|
34 |
-
|
35 |
-
$patterns = array(
|
36 |
-
"/'DB_NAME',\s*'.*?'/",
|
37 |
-
"/'DB_USER',\s*'.*?'/",
|
38 |
-
"/'DB_PASSWORD',\s*'.*?'/",
|
39 |
-
"/'DB_HOST',\s*'.*?'/"
|
40 |
-
);
|
41 |
-
|
42 |
-
$replace = array(
|
43 |
-
"'DB_NAME', " . "'{$db_name}'",
|
44 |
-
"'DB_USER', " . "'{$db_user}'",
|
45 |
-
"'DB_PASSWORD', " . "'{$db_pass}'",
|
46 |
-
"'DB_HOST', " . "'{$db_host}'"
|
47 |
-
);
|
48 |
-
|
49 |
-
//SSL CHECKS
|
50 |
-
if ($_POST['ssl_admin']) {
|
51 |
-
if (!strstr($wpconfig, 'FORCE_SSL_ADMIN')) {
|
52 |
-
$wpconfig = $wpconfig.PHP_EOL."define('FORCE_SSL_ADMIN', true);";
|
53 |
-
}
|
54 |
-
} else {
|
55 |
-
array_push($patterns, "/'FORCE_SSL_ADMIN',\s*true/");
|
56 |
-
array_push($replace, "'FORCE_SSL_ADMIN', false");
|
57 |
-
}
|
58 |
-
|
59 |
-
//CACHE CHECKS
|
60 |
-
if ($_POST['cache_wp']) {
|
61 |
-
if (!strstr($wpconfig, 'WP_CACHE')) {
|
62 |
-
$wpconfig = $wpconfig.PHP_EOL."define('WP_CACHE', true);";
|
63 |
-
}
|
64 |
-
} else {
|
65 |
-
array_push($patterns, "/'WP_CACHE',\s*true/");
|
66 |
-
array_push($replace, "'WP_CACHE', false");
|
67 |
-
}
|
68 |
-
if (!$_POST['cache_path']) {
|
69 |
-
array_push($patterns, "/'WPCACHEHOME',\s*'.*?'/");
|
70 |
-
array_push($replace, "'WPCACHEHOME', ''");
|
71 |
-
}
|
72 |
-
|
73 |
-
if (!is_writable("{$root_path}/wp-config.php")) {
|
74 |
-
if (file_exists("{$root_path}/wp-config.php")) {
|
75 |
-
chmod("{$root_path}/wp-config.php", 0644) ? DUPX_Log::info('File Permission Update: wp-config.php set to 0644') : DUPX_Log::info('WARNING: Unable to update file permissions and write to wp-config.php. Please visit the online FAQ for setting file permissions and work with your hosting provider or server administrator to enable this installer.php script to write to the wp-config.php file.');
|
76 |
-
} else {
|
77 |
-
DUPX_Log::info('WARNING: Unable to locate wp-config.php file. Be sure the file is present in your archive.');
|
78 |
-
}
|
79 |
-
}
|
80 |
-
|
81 |
-
// array_map replaced because of installer error in PHP 5.2.9 - Cannot call method self::customEscape() or method does not exist in installer.php on line 1480
|
82 |
-
// $replace = array_map('self::customEscape', $replace);
|
83 |
-
foreach ($replace as $key=>$val) {
|
84 |
-
$replace[$key] = self::customEscape($val);
|
85 |
-
}
|
86 |
-
|
87 |
-
$wpconfig = preg_replace($patterns, $replace, $wpconfig);
|
88 |
-
|
89 |
-
file_put_contents('wp-config.php', $wpconfig);
|
90 |
-
$wpconfig = null;
|
91 |
-
}
|
92 |
-
|
93 |
-
/**
|
94 |
-
* Updates the web server config files in Step 3
|
95 |
-
*
|
96 |
-
* @return null
|
97 |
-
*/
|
98 |
-
public static function updateExtended()
|
99 |
-
{
|
100 |
-
$config_file = '';
|
101 |
-
if (!file_exists('wp-config.php')) {
|
102 |
-
return $config_file;
|
103 |
-
}
|
104 |
-
|
105 |
-
$root_path = DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']);
|
106 |
-
$wpconfig_path = "{$root_path}/wp-config.php";
|
107 |
-
$config_file = @file_get_contents($wpconfig_path, true);
|
108 |
-
|
109 |
-
$patterns = array(
|
110 |
-
"/('|\")WP_HOME.*?\)\s*;/",
|
111 |
-
"/('|\")WP_SITEURL.*?\)\s*;/");
|
112 |
-
|
113 |
-
$post_url_new = DUPX_U::sanitize_text_field($_POST['url_new']);
|
114 |
-
$replace = array(
|
115 |
-
"'WP_HOME', '".$post_url_new."');",
|
116 |
-
"'WP_SITEURL', '".$post_url_new."');");
|
117 |
-
|
118 |
-
//Not sure how well tokenParser works on all servers so only using for not critical constants at this point.
|
119 |
-
//$count checks for dynamic variable types such as: define('WP_TEMP_DIR', 'D:/' . $var . 'somepath/');
|
120 |
-
//which should not be updated.
|
121 |
-
$defines = self::tokenParser($wpconfig_path);
|
122 |
-
|
123 |
-
//WP_CONTENT_DIR
|
124 |
-
if (isset($defines['WP_CONTENT_DIR'])) {
|
125 |
-
$post_path_old = DUPX_U::sanitize_text_field($_POST['path_old']);
|
126 |
-
$post_path_new = DUPX_U::sanitize_text_field($_POST['path_new']);
|
127 |
-
$val = str_replace($post_path_old, $post_path_new, DUPX_U::setSafePath($defines['WP_CONTENT_DIR']), $count);
|
128 |
-
if ($count > 0) {
|
129 |
-
array_push($patterns, "/('|\")WP_CONTENT_DIR.*?\)\s*;/");
|
130 |
-
array_push($replace, "'WP_CONTENT_DIR', '{$val}');");
|
131 |
-
}
|
132 |
-
}
|
133 |
-
|
134 |
-
//WP_CONTENT_URL
|
135 |
-
if (isset($defines['WP_CONTENT_URL'])) {
|
136 |
-
$post_url_old = DUPX_U::sanitize_text_field($_POST['url_old']);
|
137 |
-
$post_url_new = DUPX_U::sanitize_text_field($_POST['url_new']);
|
138 |
-
$val = str_replace($post_url_old . '/', $post_url_new . '/', $defines['WP_CONTENT_URL'], $count);
|
139 |
-
if ($count > 0) {
|
140 |
-
array_push($patterns, "/('|\")WP_CONTENT_URL.*?\)\s*;/");
|
141 |
-
array_push($replace, "'WP_CONTENT_URL', '{$val}');");
|
142 |
-
}
|
143 |
-
}
|
144 |
-
|
145 |
-
//WP_TEMP_DIR
|
146 |
-
if (isset($defines['WP_TEMP_DIR'])) {
|
147 |
-
$post_path_old = DUPX_U::sanitize_text_field($_POST['path_old']);
|
148 |
-
$post_path_new = DUPX_U::sanitize_text_field($_POST['path_new']);
|
149 |
-
$val = str_replace($post_path_old, $post_path_new, DUPX_U::setSafePath($defines['WP_TEMP_DIR']) , $count);
|
150 |
-
if ($count > 0) {
|
151 |
-
array_push($patterns, "/('|\")WP_TEMP_DIR.*?\)\s*;/");
|
152 |
-
array_push($replace, "'WP_TEMP_DIR', '{$val}');");
|
153 |
-
}
|
154 |
-
}
|
155 |
-
|
156 |
-
//DOMAIN_CURRENT_SITE
|
157 |
-
if (isset($defines['DOMAIN_CURRENT_SITE'])) {
|
158 |
-
$post_url_new = DUPX_U::sanitize_text_field($_POST['url_new']);
|
159 |
-
$mu_newDomainHost = parse_url($post_url_new, PHP_URL_HOST);
|
160 |
-
array_push($patterns, "/('|\")DOMAIN_CURRENT_SITE.*?\)\s*;/");
|
161 |
-
array_push($replace, "'DOMAIN_CURRENT_SITE', '{$mu_newDomainHost}');");
|
162 |
-
}
|
163 |
-
|
164 |
-
//PATH_CURRENT_SITE
|
165 |
-
if (isset($defines['PATH_CURRENT_SITE'])) {
|
166 |
-
$post_url_new = DUPX_U::sanitize_text_field($_POST['url_new']);
|
167 |
-
$mu_newUrlPath = parse_url($post_url_new, PHP_URL_PATH);
|
168 |
-
array_push($patterns, "/('|\")PATH_CURRENT_SITE.*?\)\s*;/");
|
169 |
-
array_push($replace, "'PATH_CURRENT_SITE', '{$mu_newUrlPath}');");
|
170 |
-
}
|
171 |
-
|
172 |
-
$config_file = preg_replace($patterns, $replace, $config_file);
|
173 |
-
file_put_contents($wpconfig_path, $config_file);
|
174 |
-
$config_file = file_get_contents($wpconfig_path, true);
|
175 |
-
|
176 |
-
return $config_file;
|
177 |
-
}
|
178 |
-
|
179 |
-
/**
|
180 |
-
* Used to parse the wp-config.php file
|
181 |
-
*
|
182 |
-
* @return null
|
183 |
-
*/
|
184 |
-
public static function tokenParser($wpconfig_path)
|
185 |
-
{
|
186 |
-
$defines = array();
|
187 |
-
$wpconfig_file = @file_get_contents($wpconfig_path);
|
188 |
-
|
189 |
-
if (!function_exists('token_get_all')) {
|
190 |
-
DUPX_Log::info("\nNOTICE: PHP function 'token_get_all' does not exist so skipping WP_CONTENT_DIR and WP_CONTENT_URL processing.");
|
191 |
-
return $defines;
|
192 |
-
}
|
193 |
-
|
194 |
-
if ($wpconfig_file === false) {
|
195 |
-
return $defines;
|
196 |
-
}
|
197 |
-
|
198 |
-
$defines = array();
|
199 |
-
$tokens = token_get_all($wpconfig_file);
|
200 |
-
$token = reset($tokens);
|
201 |
-
while ($token) {
|
202 |
-
if (is_array($token)) {
|
203 |
-
if ($token[0] == T_WHITESPACE || $token[0] == T_COMMENT || $token[0] == T_DOC_COMMENT) {
|
204 |
-
// do nothing
|
205 |
-
} else if ($token[0] == T_STRING && strtolower($token[1]) == 'define') {
|
206 |
-
$state = 1;
|
207 |
-
} else if ($state == 2 && self::isConstant($token[0])) {
|
208 |
-
$key = $token[1];
|
209 |
-
$state = 3;
|
210 |
-
} else if ($state == 4 && self::isConstant($token[0])) {
|
211 |
-
$value = $token[1];
|
212 |
-
$state = 5;
|
213 |
-
}
|
214 |
-
} else {
|
215 |
-
$symbol = trim($token);
|
216 |
-
if ($symbol == '(' && $state == 1) {
|
217 |
-
$state = 2;
|
218 |
-
} else if ($symbol == ',' && $state == 3) {
|
219 |
-
$state = 4;
|
220 |
-
} else if ($symbol == ')' && $state == 5) {
|
221 |
-
$defines[self::tokenStrip($key)] = self::tokenStrip($value);
|
222 |
-
$state = 0;
|
223 |
-
}
|
224 |
-
}
|
225 |
-
$token = next($tokens);
|
226 |
-
}
|
227 |
-
|
228 |
-
return $defines;
|
229 |
-
}
|
230 |
-
|
231 |
-
private static function tokenStrip($value)
|
232 |
-
{
|
233 |
-
return preg_replace('!^([\'"])(.*)\1$!', '$2', $value);
|
234 |
-
}
|
235 |
-
|
236 |
-
private static function customEscape($str)
|
237 |
-
{
|
238 |
-
return str_replace('\\', '\\\\', $str);
|
239 |
-
}
|
240 |
-
|
241 |
-
private static function isConstant($token)
|
242 |
-
{
|
243 |
-
return $token == T_CONSTANT_ENCAPSED_STRING || $token == T_STRING || $token == T_LNUMBER || $token == T_DNUMBER;
|
244 |
-
}
|
245 |
-
}
|
246 |
-
?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/build/ctrls/ctrl.step1.php
DELETED
@@ -1,148 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
defined("DUPXABSPATH") or die("");
|
3 |
-
|
4 |
-
//POST PARAMS
|
5 |
-
$_POST['archive_engine'] = isset($_POST['archive_engine']) ? DUPX_U::sanitize_text_field($_POST['archive_engine']) : 'manual';
|
6 |
-
$_POST['archive_filetime'] = (isset($_POST['archive_filetime'])) ? DUPX_U::sanitize_text_field($_POST['archive_filetime']) : 'current';
|
7 |
-
$_POST['retain_config'] = (isset($_POST['retain_config']) && $_POST['retain_config'] == '1') ? true : false;
|
8 |
-
$_POST['exe_safe_mode'] = (isset($_POST['exe_safe_mode'])) ? DUPX_U::sanitize_text_field($_POST['exe_safe_mode']) : 0;
|
9 |
-
//LOGGING
|
10 |
-
$POST_LOG = $_POST;
|
11 |
-
unset($POST_LOG['dbpass']);
|
12 |
-
ksort($POST_LOG);
|
13 |
-
|
14 |
-
//PAGE VARS
|
15 |
-
$php_max_time = @ini_get("max_execution_time");
|
16 |
-
$php_max_time = ($php_max_time == 0) ? "[0] time limit restriction disabled" : "[{$php_max_time}] time limit restriction enabled";
|
17 |
-
$root_path = DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']);
|
18 |
-
$package_path = "{$root_path}/{$GLOBALS['FW_PACKAGE_NAME']}";
|
19 |
-
$ajax1_start = DUPX_U::getMicrotime();
|
20 |
-
$zip_support = class_exists('ZipArchive') ? 'Enabled' : 'Not Enabled';
|
21 |
-
$JSON = array();
|
22 |
-
$JSON['pass'] = 0;
|
23 |
-
|
24 |
-
/** JSON RESPONSE: Most sites have warnings turned off by default, but if they're turned on the warnings
|
25 |
-
cause errors in the JSON data Here we hide the status so warning level is reset at it at the end */
|
26 |
-
if (!headers_sent()) {
|
27 |
-
header('Content-Type: application/json');
|
28 |
-
}
|
29 |
-
$ajax1_error_level = error_reporting();
|
30 |
-
error_reporting(E_ERROR);
|
31 |
-
|
32 |
-
//===============================
|
33 |
-
//ERROR MESSAGES
|
34 |
-
//===============================
|
35 |
-
($GLOBALS['LOG_FILE_HANDLE'] != false) or DUPX_Log::error(ERR_MAKELOG);
|
36 |
-
|
37 |
-
if (!$GLOBALS['FW_ARCHIVE_ONLYDB']) {
|
38 |
-
//ERR_ZIPMANUAL
|
39 |
-
$post_archive_engine = DUPX_U::sanitize_text_field($_POST['archive_engine']);
|
40 |
-
if ($post_archive_engine == 'manual') {
|
41 |
-
if (!file_exists("wp-config.php") && !file_exists("dup-database__{$GLOBALS['PACKAGE_HASH']}.sql")) {
|
42 |
-
DUPX_Log::error(ERR_ZIPMANUAL);
|
43 |
-
}
|
44 |
-
} else {
|
45 |
-
//ERR_CONFIG_FOUND
|
46 |
-
(!file_exists('wp-config.php'))
|
47 |
-
or DUPX_Log::error(ERR_CONFIG_FOUND);
|
48 |
-
//ERR_ZIPNOTFOUND
|
49 |
-
(is_readable("{$package_path}"))
|
50 |
-
or DUPX_Log::error(ERR_ZIPNOTFOUND);
|
51 |
-
}
|
52 |
-
}
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
DUPX_Log::info("********************************************************************************");
|
57 |
-
DUPX_Log::info('* DUPLICATOR-LITE: INSTALL-LOG');
|
58 |
-
DUPX_Log::info("* VERSION: {$GLOBALS['FW_DUPLICATOR_VERSION']}");
|
59 |
-
DUPX_Log::info('* STEP-1 START @ '.@date('h:i:s'));
|
60 |
-
DUPX_Log::info('* NOTICE: Do NOT post this data to public sites or forums');
|
61 |
-
DUPX_Log::info("********************************************************************************");
|
62 |
-
DUPX_Log::info("PHP VERSION:\t".phpversion().' | SAPI: '.php_sapi_name());
|
63 |
-
DUPX_Log::info("PHP TIME LIMIT:\t{$php_max_time}");
|
64 |
-
DUPX_Log::info("PHP MEMORY:\t".$GLOBALS['PHP_MEMORY_LIMIT'].' | SUHOSIN: '.$GLOBALS['PHP_SUHOSIN_ON']);
|
65 |
-
DUPX_Log::info("SERVER:\t\t{$_SERVER['SERVER_SOFTWARE']}");
|
66 |
-
DUPX_Log::info("DOC ROOT:\t{$root_path}");
|
67 |
-
DUPX_Log::info("DOC ROOT 755:\t".var_export($GLOBALS['CHOWN_ROOT_PATH'], true));
|
68 |
-
DUPX_Log::info("LOG FILE 644:\t".var_export($GLOBALS['CHOWN_LOG_PATH'], true));
|
69 |
-
DUPX_Log::info("REQUEST URL:\t{$GLOBALS['URL_PATH']}");
|
70 |
-
DUPX_Log::info("SAFE MODE :\t{$_POST['exe_safe_mode']}");
|
71 |
-
|
72 |
-
$log = "--------------------------------------\n";
|
73 |
-
$log .= "POST DATA\n";
|
74 |
-
$log .= "--------------------------------------\n";
|
75 |
-
$log .= print_r($POST_LOG, true);
|
76 |
-
DUPX_Log::info($log, 2);
|
77 |
-
|
78 |
-
$log = "--------------------------------------\n";
|
79 |
-
$log .= "ARCHIVE EXTRACTION\n";
|
80 |
-
$log .= "--------------------------------------\n";
|
81 |
-
$log .= "NAME:\t{$GLOBALS['FW_PACKAGE_NAME']}\n";
|
82 |
-
$log .= "SIZE:\t".DUPX_U::readableByteSize(@filesize($GLOBALS['FW_PACKAGE_NAME']))."\n";
|
83 |
-
$log .= "ZIP:\t{$zip_support} (ZipArchive Support)";
|
84 |
-
DUPX_Log::info($log);
|
85 |
-
|
86 |
-
|
87 |
-
if ($_POST['archive_engine'] == 'manual') {
|
88 |
-
DUPX_Log::info("\n** PACKAGE EXTRACTION IS IN MANUAL MODE ** \n");
|
89 |
-
} else {
|
90 |
-
if (!class_exists('ZipArchive')) {
|
91 |
-
DUPX_Log::info("ERROR: Stopping install process. Trying to extract without ZipArchive module installed. Please use the 'Manual Package extraction' mode to extract zip file.");
|
92 |
-
DUPX_Log::error(ERR_ZIPARCHIVE);
|
93 |
-
}
|
94 |
-
|
95 |
-
$target = $root_path;
|
96 |
-
$zip = new ZipArchive();
|
97 |
-
if ($zip->open($GLOBALS['FW_PACKAGE_NAME']) === TRUE) {
|
98 |
-
|
99 |
-
DUPX_Log::info("\n>>> START EXTRACTION:");
|
100 |
-
if (!$zip->extractTo($target)) {
|
101 |
-
DUPX_Log::error(ERR_ZIPEXTRACTION);
|
102 |
-
}
|
103 |
-
$log = print_r($zip, true);
|
104 |
-
|
105 |
-
//Keep original timestamp on the file
|
106 |
-
if ($_POST['archive_filetime'] == 'original') {
|
107 |
-
$log .= "File timestamp is 'Original' mode.\n";
|
108 |
-
for ($idx = 0; $s = $zip->statIndex($idx); $idx++) {
|
109 |
-
touch($target.DIRECTORY_SEPARATOR.$s['name'], $s['mtime']);
|
110 |
-
}
|
111 |
-
} else {
|
112 |
-
$now = date("Y-m-d H:i:s");
|
113 |
-
$log .= "File timestamp is 'Current' mode: {$now}\n";
|
114 |
-
}
|
115 |
-
|
116 |
-
$close_response = $zip->close();
|
117 |
-
$log .= "<<< EXTRACTION COMPLETE: " . var_export($close_response, true);
|
118 |
-
DUPX_Log::info($log);
|
119 |
-
} else {
|
120 |
-
DUPX_Log::error(ERR_ZIPOPEN);
|
121 |
-
}
|
122 |
-
}
|
123 |
-
|
124 |
-
//===============================
|
125 |
-
//RESET SERVER CONFIG FILES
|
126 |
-
//===============================
|
127 |
-
if ($_POST['retain_config']) {
|
128 |
-
DUPX_Log::info("\nNOTICE: Manual update of permalinks required see: Admin > Settings > Permalinks > Click Save Changes");
|
129 |
-
DUPX_Log::info("Retaining the original htaccess, user.ini or web.config files may cause issues with the setup of this site.");
|
130 |
-
DUPX_Log::info("If you run into issues during or after the install process please uncheck the 'Config Files' checkbox labeled:");
|
131 |
-
DUPX_Log::info("'Retain original .htaccess, .user.ini and web.config' from Step 1 and re-run the installer. Backups of the");
|
132 |
-
DUPX_Log::info("orginal config files will be made and can be merged per required directive.");
|
133 |
-
} else {
|
134 |
-
DUPX_ServerConfig::reset();
|
135 |
-
}
|
136 |
-
|
137 |
-
|
138 |
-
//FINAL RESULTS
|
139 |
-
$ajax1_end = DUPX_U::getMicrotime();
|
140 |
-
$ajax1_sum = DUPX_U::elapsedTime($ajax1_end, $ajax1_start);
|
141 |
-
DUPX_Log::info("\nSTEP-1 COMPLETE @ " . @date('h:i:s') . " - RUNTIME: {$ajax1_sum}");
|
142 |
-
|
143 |
-
|
144 |
-
$JSON['pass'] = 1;
|
145 |
-
echo json_encode($JSON);
|
146 |
-
error_reporting($ajax1_error_level);
|
147 |
-
die('');
|
148 |
-
?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/build/ctrls/ctrl.step2.php
DELETED
@@ -1,499 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
defined("DUPXABSPATH") or die("");
|
3 |
-
|
4 |
-
//POST PARAMS
|
5 |
-
$_POST['dbaction'] = isset($_POST['dbaction']) ? DUPX_U::sanitize_text_field($_POST['dbaction']) : 'create';
|
6 |
-
|
7 |
-
if (isset($_POST['dbhost'])) {
|
8 |
-
$post_db_host = DUPX_U::sanitize_text_field($_POST['dbhost']);
|
9 |
-
$_POST['dbhost'] = DUPX_U::sanitize_text_field($post_db_host);
|
10 |
-
} else {
|
11 |
-
$_POST['dbhost'] = null;
|
12 |
-
}
|
13 |
-
|
14 |
-
if (isset($_POST['dbname'])) {
|
15 |
-
$post_db_name = DUPX_U::sanitize_text_field($_POST['dbname']);
|
16 |
-
$_POST['dbname'] = trim($post_db_name);
|
17 |
-
} else {
|
18 |
-
$_POST['dbname'] = null;
|
19 |
-
}
|
20 |
-
|
21 |
-
$_POST['dbuser'] = isset($_POST['dbuser']) ? DUPX_U::sanitize_text_field($_POST['dbuser']) : null;
|
22 |
-
$_POST['dbpass'] = isset($_POST['dbpass']) ? DUPX_U::sanitize_text_field($_POST['dbpass']) : null;
|
23 |
-
|
24 |
-
if (isset($_POST['dbcharset'])) {
|
25 |
-
$post_db_charset = DUPX_U::sanitize_text_field($_POST['dbcharset']);
|
26 |
-
$_POST['dbcharset'] = trim($post_db_charset);
|
27 |
-
} else {
|
28 |
-
$_POST['dbcharset'] = $GLOBALS['DBCHARSET_DEFAULT'];
|
29 |
-
}
|
30 |
-
|
31 |
-
if (isset($_POST['dbcollate'])) {
|
32 |
-
$post_db_collate = DUPX_U::sanitize_text_field($_POST['dbcollate']);
|
33 |
-
$_POST['dbcollate'] = trim($post_db_collate);
|
34 |
-
} else {
|
35 |
-
$_POST['dbcollate'] = $GLOBALS['DBCOLLATE_DEFAULT'];
|
36 |
-
}
|
37 |
-
|
38 |
-
$_POST['dbnbsp'] = (isset($_POST['dbnbsp']) && $_POST['dbnbsp'] == '1') ? true : false;
|
39 |
-
$_POST['ssl_admin'] = (isset($_POST['ssl_admin'])) ? true : false;
|
40 |
-
$_POST['cache_wp'] = (isset($_POST['cache_wp'])) ? true : false;
|
41 |
-
$_POST['cache_path'] = (isset($_POST['cache_path'])) ? true : false;
|
42 |
-
$_POST['retain_config'] = (isset($_POST['retain_config']) && $_POST['retain_config'] == '1') ? true : false;
|
43 |
-
$_POST['dbcollatefb'] = isset($_POST['dbcollatefb']) ? DUPX_U::sanitize_text_field($_POST['dbcollatefb']) : false;
|
44 |
-
|
45 |
-
//LOGGING
|
46 |
-
$POST_LOG = $_POST;
|
47 |
-
unset($POST_LOG['dbpass']);
|
48 |
-
ksort($POST_LOG);
|
49 |
-
|
50 |
-
//PAGE VARS
|
51 |
-
$date_time = @date('h:i:s');
|
52 |
-
$root_path = DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']);
|
53 |
-
$ajax2_start = DUPX_U::getMicrotime();
|
54 |
-
$JSON = array();
|
55 |
-
$JSON['pass'] = 0;
|
56 |
-
|
57 |
-
/** JSON RESPONSE: Most sites have warnings turned off by default, but if they're turned on the warnings
|
58 |
-
cause errors in the JSON data Here we hide the status so warning level is reset at it at the end*/
|
59 |
-
$ajax1_error_level = error_reporting();
|
60 |
-
error_reporting(E_ERROR);
|
61 |
-
|
62 |
-
//====================================================================================================
|
63 |
-
//DATABASE TEST CONNECTION
|
64 |
-
//====================================================================================================
|
65 |
-
if (isset($_GET['dbtest']))
|
66 |
-
{
|
67 |
-
$html = "";
|
68 |
-
$baseport = parse_url($_POST['dbhost'], PHP_URL_PORT);
|
69 |
-
$dbConn = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass'], null, $_POST['dbport']);
|
70 |
-
$dbErr = mysqli_connect_error();
|
71 |
-
|
72 |
-
$dbFound = mysqli_select_db($dbConn, $_POST['dbname']);
|
73 |
-
$port_view = (is_int($baseport) || substr($_POST['dbhost'], -1) == ":") ? "Port=[Set in Host]" : "Port=".DUPX_U::esc_html($_POST['dbport']);
|
74 |
-
|
75 |
-
$tstSrv = ($dbConn) ? "<div class='dupx-pass'>Success</div>" : "<div class='dupx-fail'>Fail</div>";
|
76 |
-
$tstDB = ($dbFound) ? "<div class='dupx-pass'>Success</div>" : "<div class='dupx-fail'>Fail</div>";
|
77 |
-
|
78 |
-
$dbversion_info = DUPX_DB::getServerInfo($dbConn);
|
79 |
-
$dbversion_info = empty($dbversion_info) ? 'no connection' : $dbversion_info;
|
80 |
-
$dbversion_info_fail = $dbConn && version_compare(DUPX_DB::getVersion($dbConn), '5.5.3') < 0;
|
81 |
-
|
82 |
-
$dbversion_compat = DUPX_DB::getVersion($dbConn);
|
83 |
-
$dbversion_compat = empty($dbversion_compat) ? 'no connection' : $dbversion_compat;
|
84 |
-
$dbversion_compat_fail = $dbConn && version_compare($dbversion_compat, $GLOBALS['FW_VERSION_DB']) < 0;
|
85 |
-
|
86 |
-
$tstInfo = ($dbversion_info_fail)
|
87 |
-
? "<div class='dupx-notice'>".DUPX_U::esc_html($dbversion_info)."</div>"
|
88 |
-
: "<div class='dupx-pass'>".DUPX_U::esc_html($dbversion_info)."</div>";
|
89 |
-
|
90 |
-
$tstCompat = ($dbversion_compat_fail)
|
91 |
-
? "<div class='dupx-notice'>This Server: [".DUPX_U::esc_html($dbversion_compat)."] -- Package Server: [".DUPX_U::esc_html($GLOBALS['FW_VERSION_DB'])."]</div>"
|
92 |
-
: "<div class='dupx-pass'>This Server: [".DUPX_U::esc_html($dbversion_compat)."] -- Package Server: [".DUPX_U::esc_html($GLOBALS['FW_VERSION_DB'])."]</div>";
|
93 |
-
|
94 |
-
$html .= "
|
95 |
-
<div class='s2-db-test'>
|
96 |
-
<small>
|
97 |
-
Using Connection String:<br/>
|
98 |
-
Host=".DUPX_U::esc_html($_POST['dbhost'])."; Database=".DUPX_U::esc_html($_POST['dbname'])."; Uid=".DUPX_U::esc_html($_POST['dbuser'])."; Pwd=".DUPX_U::esc_html($_POST['dbpass'])."; {$port_view}
|
99 |
-
</small>
|
100 |
-
<table class='s2-db-test-dtls'>
|
101 |
-
<tr>
|
102 |
-
<td>Host:</td>
|
103 |
-
<td>".$tstSrv."</td>
|
104 |
-
</tr>
|
105 |
-
<tr>
|
106 |
-
<td>Database:</td>
|
107 |
-
<td>".$tstDB."</td>
|
108 |
-
</tr>
|
109 |
-
<tr>
|
110 |
-
<td>Version:</td>
|
111 |
-
<td>".$tstInfo."</td>
|
112 |
-
</tr>
|
113 |
-
<tr>
|
114 |
-
<td>Compatibility:</td>
|
115 |
-
<td>".$tstCompat."</td>
|
116 |
-
</tr>
|
117 |
-
</table>";
|
118 |
-
|
119 |
-
//--------------------------------
|
120 |
-
//WARNING: Unable to connect
|
121 |
-
$html .= (!$dbConn || !$dbFound)
|
122 |
-
? "<div class='warn-msg'>" . ERR_DBCONNECT_INFO . "</div>"
|
123 |
-
: '';
|
124 |
-
|
125 |
-
//WARNING: DB has tables with create option
|
126 |
-
if ($_POST['dbaction'] == 'create')
|
127 |
-
{
|
128 |
-
$tblcount = DUPX_DB::countTables($dbConn, $_POST['dbname']);
|
129 |
-
$html .= ($tblcount > 0)
|
130 |
-
? "<div class='warn-msg'><b>WARNING:</b> " . sprintf(ERR_DBEMPTY, DUPX_U::esc_html($_POST['dbname']), DUPX_U::esc_html($tblcount)) . "</div>"
|
131 |
-
: '';
|
132 |
-
}
|
133 |
-
|
134 |
-
//WARNNG: Input has utf8
|
135 |
-
$dbConnItems = array($_POST['dbhost'], $_POST['dbuser'], $_POST['dbname'],$_POST['dbpass']);
|
136 |
-
$dbUTF8_tst = false;
|
137 |
-
foreach ($dbConnItems as $value) {
|
138 |
-
if (DUPX_U::isNonASCII($value)) {
|
139 |
-
$dbUTF8_tst = true;
|
140 |
-
break;
|
141 |
-
}
|
142 |
-
}
|
143 |
-
|
144 |
-
//WARNING: UTF8 Data in Connection String
|
145 |
-
$html .= (!$dbConn && $dbUTF8_tst)
|
146 |
-
? "<div class='warn-msg'><b>WARNING:</b> " . ERR_TESTDB_UTF8 . "</div>"
|
147 |
-
: '';
|
148 |
-
|
149 |
-
//NOTICE: Version Too Low
|
150 |
-
$html .= ($dbversion_info_fail)
|
151 |
-
? "<div class='warn-msg'><b>NOTICE:</b> " . ERR_TESTDB_VERSION_INFO . "</div>"
|
152 |
-
: '';
|
153 |
-
|
154 |
-
//NOTICE: Version Incompatibility
|
155 |
-
$html .= ($dbversion_compat_fail)
|
156 |
-
? "<div class='warn-msg'><b>NOTICE:</b> " . ERR_TESTDB_VERSION_COMPAT . "</div>"
|
157 |
-
: '';
|
158 |
-
|
159 |
-
$html .= "</div>";
|
160 |
-
die($html);
|
161 |
-
}
|
162 |
-
|
163 |
-
//===============================
|
164 |
-
//ERROR MESSAGES
|
165 |
-
//===============================
|
166 |
-
|
167 |
-
//ERR_MAKELOG
|
168 |
-
($GLOBALS['LOG_FILE_HANDLE'] != false) or DUPX_Log::error(ERR_MAKELOG);
|
169 |
-
|
170 |
-
//ERR_MYSQLI_SUPPORT
|
171 |
-
function_exists('mysqli_connect') or DUPX_Log::error(ERR_MYSQLI_SUPPORT);
|
172 |
-
|
173 |
-
//ERR_DBCONNECT
|
174 |
-
$dbh = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass'], null, $_POST['dbport']);
|
175 |
-
@mysqli_query($dbh, "SET wait_timeout = ".mysqli_real_escape_string($dbh, $GLOBALS['DB_MAX_TIME']));
|
176 |
-
($dbh) or DUPX_Log::error(ERR_DBCONNECT . mysqli_connect_error());
|
177 |
-
if ($_POST['dbaction'] == 'empty') {
|
178 |
-
mysqli_select_db($dbh, $_POST['dbname']) or DUPX_Log::error(sprintf(ERR_DBCREATE, $_POST['dbname']));
|
179 |
-
}
|
180 |
-
//ERR_DBEMPTY
|
181 |
-
if ($_POST['dbaction'] == 'create' ) {
|
182 |
-
$tblcount = DUPX_DB::countTables($dbh, $_POST['dbname']);
|
183 |
-
if ($tblcount > 0) {
|
184 |
-
DUPX_Log::error(sprintf(ERR_DBEMPTY, $_POST['dbname'], $tblcount));
|
185 |
-
}
|
186 |
-
}
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
$log = <<<LOG
|
191 |
-
\n\n********************************************************************************
|
192 |
-
* DUPLICATOR-LITE: INSTALL-LOG
|
193 |
-
* STEP-2 START @ {$date_time}
|
194 |
-
* NOTICE: Do NOT post to public sites or forums
|
195 |
-
********************************************************************************
|
196 |
-
LOG;
|
197 |
-
DUPX_Log::info($log);
|
198 |
-
|
199 |
-
$log = "--------------------------------------\n";
|
200 |
-
$log .= "POST DATA\n";
|
201 |
-
$log .= "--------------------------------------\n";
|
202 |
-
$log .= print_r($POST_LOG, true);
|
203 |
-
DUPX_Log::info($log, 2);
|
204 |
-
|
205 |
-
|
206 |
-
//====================================================================================================
|
207 |
-
//DATABASE ROUTINES
|
208 |
-
//====================================================================================================
|
209 |
-
$log = '';
|
210 |
-
$faq_url = $GLOBALS['FAQ_URL'];
|
211 |
-
$utm_prefix = '?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=';
|
212 |
-
$db_file_size = filesize("dup-database__{$GLOBALS['PACKAGE_HASH']}.sql");
|
213 |
-
$php_mem = $GLOBALS['PHP_MEMORY_LIMIT'];
|
214 |
-
$php_mem_range = DUPX_U::getBytes($GLOBALS['PHP_MEMORY_LIMIT']);
|
215 |
-
$php_mem_range = $php_mem_range == null ? 0 : $php_mem_range - 5000000; //5 MB Buffer
|
216 |
-
|
217 |
-
//Fatal Memory errors from file_get_contents is not catchable.
|
218 |
-
//Try to warn ahead of time with a buffer in memory difference
|
219 |
-
if ($db_file_size >= $php_mem_range && $php_mem_range != 0)
|
220 |
-
{
|
221 |
-
$db_file_size = DUPX_U::readableByteSize($db_file_size);
|
222 |
-
$msg = "\nWARNING: The database script is '{$db_file_size}' in size. The PHP memory allocation is set\n";
|
223 |
-
$msg .= "at '{$php_mem}'. There is a high possibility that the installer script will fail with\n";
|
224 |
-
$msg .= "a memory allocation error when trying to load the dup-database__{$GLOBALS['PACKAGE_HASH']}.sql file. It is\n";
|
225 |
-
$msg .= "recommended to increase the 'memory_limit' setting in the php.ini config file.\n";
|
226 |
-
$msg .= "see: {$faq_url}{$utm_prefix}inst_step2_lgdbscript#faq-trouble-056-q \n";
|
227 |
-
DUPX_Log::info($msg);
|
228 |
-
}
|
229 |
-
|
230 |
-
@chmod("{$root_path}/dup-database__{$GLOBALS['PACKAGE_HASH']}.sql", 0777);
|
231 |
-
$sql_file = file_get_contents("dup-database__{$GLOBALS['PACKAGE_HASH']}.sql", true);
|
232 |
-
|
233 |
-
//ERROR: Reading database.sql file
|
234 |
-
if ($sql_file === FALSE || strlen($sql_file) < 10)
|
235 |
-
{
|
236 |
-
$msg = "<b>Unable to read the dup-database__{$GLOBALS['PACKAGE_HASH']}.sql file from the archive. Please check these items:</b> <br/>";
|
237 |
-
$msg .= "1. Validate permissions and/or group-owner rights on these items: <br/>";
|
238 |
-
$msg .= " - File: dup-database__{$GLOBALS['PACKAGE_HASH']}.sql <br/> - Directory: [{$root_path}] <br/>";
|
239 |
-
$msg .= "<i>see: <a href='{$faq_url}{$utm_prefix}inst_step2_dbperms#faq-trouble-055-q' target='_blank'>{$faq_url}#faq-trouble-055-q</a></i> <br/>";
|
240 |
-
$msg .= "2. Validate the dup-database__{$GLOBALS['PACKAGE_HASH']}.sql file exists and is in the root of the archive.zip file <br/>";
|
241 |
-
$msg .= "<i>see: <a href='{$faq_url}{$utm_prefix}inst_step2_sqlroot#faq-installer-020-q' target='_blank'>{$faq_url}#faq-installer-020-q</a></i> <br/>";
|
242 |
-
DUPX_Log::error($msg);
|
243 |
-
}
|
244 |
-
|
245 |
-
//Removes invalid space characters
|
246 |
-
//Complex Subject See: http://webcollab.sourceforge.net/unicode.html
|
247 |
-
if ($_POST['dbnbsp'])
|
248 |
-
{
|
249 |
-
DUPX_Log::info("NOTICE: Ran fix non-breaking space characters\n");
|
250 |
-
$sql_file = preg_replace('/\xC2\xA0/', ' ', $sql_file);
|
251 |
-
}
|
252 |
-
|
253 |
-
//Write new contents to install-data.sql
|
254 |
-
$sql_file_copy_status = file_put_contents($GLOBALS['SQL_FILE_NAME'], $sql_file);
|
255 |
-
$sql_result_file_data = explode(";\n", $sql_file);
|
256 |
-
$sql_result_file_length = count($sql_result_file_data);
|
257 |
-
$sql_result_file_path = "{$root_path}/{$GLOBALS['SQL_FILE_NAME']}";
|
258 |
-
$sql_file = null;
|
259 |
-
$db_collatefb_log = '';
|
260 |
-
|
261 |
-
if($_POST['dbcollatefb']){
|
262 |
-
$supportedCollations = DUPX_DB::getSupportedCollationsList($dbh);
|
263 |
-
$collation_arr = array(
|
264 |
-
'utf8mb4_unicode_520_ci',
|
265 |
-
'utf8mb4_unicode_520',
|
266 |
-
'utf8mb4_unicode_ci',
|
267 |
-
'utf8mb4',
|
268 |
-
'utf8_unicode_520_ci',
|
269 |
-
'utf8_unicode_520',
|
270 |
-
'utf8_unicode_ci',
|
271 |
-
'utf8'
|
272 |
-
);
|
273 |
-
$latest_supported_collation = '';
|
274 |
-
$latest_supported_index = -1;
|
275 |
-
|
276 |
-
foreach ($collation_arr as $key => $val){
|
277 |
-
if(in_array($val,$supportedCollations)){
|
278 |
-
$latest_supported_collation = $val;
|
279 |
-
$latest_supported_index = $key;
|
280 |
-
break;
|
281 |
-
}
|
282 |
-
}
|
283 |
-
|
284 |
-
//No need to replace if current DB is up to date
|
285 |
-
if($latest_supported_index != 0){
|
286 |
-
for($i=0; $i < $latest_supported_index; $i++){
|
287 |
-
foreach ($sql_result_file_data as $index => $col_sql_query){
|
288 |
-
if(strpos($col_sql_query,$collation_arr[$i]) !== false){
|
289 |
-
$sql_result_file_data[$index] = str_replace($collation_arr[$i], $latest_supported_collation, $col_sql_query);
|
290 |
-
if(strpos($collation_arr[$i],'utf8mb4') !== false && strpos($latest_supported_collation,'utf8mb4') === false){
|
291 |
-
$sql_result_file_data[$index] = str_replace('utf8mb4','utf8',$sql_result_file_data[$index]);
|
292 |
-
}
|
293 |
-
$sub_query = str_replace("\n", '', substr($col_sql_query, 0, 75));
|
294 |
-
$db_collatefb_log .= " - Collation '{$collation_arr[$i]}' set to '{$latest_supported_collation}' on query [{$sub_query}...]\n";
|
295 |
-
}
|
296 |
-
}
|
297 |
-
}
|
298 |
-
}
|
299 |
-
}
|
300 |
-
|
301 |
-
//WARNING: Create installer-data.sql failed
|
302 |
-
if ($sql_file_copy_status === FALSE || filesize($sql_result_file_path) == 0 || !is_readable($sql_result_file_path))
|
303 |
-
{
|
304 |
-
$sql_file_size = DUPX_U::readableByteSize(filesize("dup-database__{$GLOBALS['PACKAGE_HASH']}.sql"));
|
305 |
-
$msg = "\nWARNING: Unable to properly copy dup-database__{$GLOBALS['PACKAGE_HASH']}.sql ({$sql_file_size}) to {$GLOBALS['SQL_FILE_NAME']}. Please check these items:\n";
|
306 |
-
$msg .= "- Validate permissions and/or group-owner rights on dup-database__{$GLOBALS['PACKAGE_HASH']}.sql and directory [{$root_path}] \n";
|
307 |
-
$msg .= "- see: {$faq_url}{$utm_prefix}inst_step2_copydbsql#faq-trouble-055-q \n";
|
308 |
-
DUPX_Log::info($msg);
|
309 |
-
}
|
310 |
-
|
311 |
-
//=================================
|
312 |
-
//START DB RUN
|
313 |
-
@mysqli_query($dbh, "SET wait_timeout = ".mysqli_real_escape_string($dbh, $GLOBALS['DB_MAX_TIME']));
|
314 |
-
@mysqli_query($dbh, "SET max_allowed_packet = ".mysqli_real_escape_string($dbh, $GLOBALS['DB_MAX_PACKETS']));
|
315 |
-
DUPX_DB::setCharset($dbh, $_POST['dbcharset'], $_POST['dbcollate']);
|
316 |
-
|
317 |
-
//Will set mode to null only for this db handle session
|
318 |
-
//sql_mode can cause db create issues on some systems
|
319 |
-
$qry_session_custom = true;
|
320 |
-
switch ($_POST['dbmysqlmode']) {
|
321 |
-
case 'DISABLE':
|
322 |
-
@mysqli_query($dbh, "SET SESSION sql_mode = ''");
|
323 |
-
break;
|
324 |
-
case 'CUSTOM':
|
325 |
-
$dbmysqlmode_opts = $_POST['dbmysqlmode_opts'];
|
326 |
-
$qry_session_custom = @mysqli_query($dbh, "SET SESSION sql_mode = '".mysqli_real_escape_string($dbh, $dbmysqlmode_opts)."'");
|
327 |
-
if ($qry_session_custom == false) {
|
328 |
-
$sql_error = mysqli_error($dbh);
|
329 |
-
$log = "WARNING: Trying to set a custom sql_mode setting issue has been detected:\n{$sql_error}.\n";
|
330 |
-
$log .= "For more details visit: http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html\n";
|
331 |
-
}
|
332 |
-
break;
|
333 |
-
}
|
334 |
-
|
335 |
-
//Set defaults in-case the variable could not be read
|
336 |
-
$dbvar_maxtime = DUPX_DB::getVariable($dbh, 'wait_timeout');
|
337 |
-
$dbvar_maxpacks = DUPX_DB::getVariable($dbh, 'max_allowed_packet');
|
338 |
-
$dbvar_sqlmode = DUPX_DB::getVariable($dbh, 'sql_mode');
|
339 |
-
$dbvar_maxtime = is_null($dbvar_maxtime) ? 300 : $dbvar_maxtime;
|
340 |
-
$dbvar_maxpacks = is_null($dbvar_maxpacks) ? 1048576 : $dbvar_maxpacks;
|
341 |
-
$dbvar_sqlmode = empty($dbvar_sqlmode) ? 'NOT_SET' : $dbvar_sqlmode;
|
342 |
-
$dbvar_version = DUPX_DB::getVersion($dbh);
|
343 |
-
$sql_file_size1 = DUPX_U::readableByteSize(@filesize("dup-database__{$GLOBALS['PACKAGE_HASH']}.sql"));
|
344 |
-
$sql_file_size2 = DUPX_U::readableByteSize(@filesize("{$GLOBALS['SQL_FILE_NAME']}"));
|
345 |
-
$db_collatefb = isset($_POST['dbcollatefb']) ? 'On' : 'Off';
|
346 |
-
|
347 |
-
|
348 |
-
DUPX_Log::info("--------------------------------------");
|
349 |
-
DUPX_Log::info("DATABASE ENVIRONMENT");
|
350 |
-
DUPX_Log::info("--------------------------------------");
|
351 |
-
DUPX_Log::info("MYSQL VERSION:\tThis Server: {$dbvar_version} -- Build Server: {$GLOBALS['FW_VERSION_DB']}");
|
352 |
-
DUPX_Log::info("FILE SIZE:\tdup-database__{$GLOBALS['PACKAGE_HASH']}.sql ({$sql_file_size1}) - dup-installer-data__{$GLOBALS['PACKAGE_HASH']}.sql ({$sql_file_size2})");
|
353 |
-
DUPX_Log::info("TIMEOUT:\t{$dbvar_maxtime}");
|
354 |
-
DUPX_Log::info("MAXPACK:\t{$dbvar_maxpacks}");
|
355 |
-
DUPX_Log::info("SQLMODE:\t{$dbvar_sqlmode}");
|
356 |
-
DUPX_Log::info("NEW SQL FILE:\t[{$sql_result_file_path}]");
|
357 |
-
DUPX_Log::info("COLLATE RESET:\t{$db_collatefb}\n{$db_collatefb_log}");
|
358 |
-
|
359 |
-
if ($qry_session_custom == false) {
|
360 |
-
DUPX_Log::info("\n{$log}\n");
|
361 |
-
}
|
362 |
-
|
363 |
-
//CREATE DB
|
364 |
-
switch ($_POST['dbaction']) {
|
365 |
-
case "create":
|
366 |
-
mysqli_query($dbh, "CREATE DATABASE IF NOT EXISTS `".mysqli_real_escape_string($dbh, $_POST['dbname'])."`");
|
367 |
-
mysqli_select_db($dbh, mysqli_real_escape_string($dbh, $_POST['dbname']))
|
368 |
-
or DUPX_Log::error(sprintf(ERR_DBCONNECT_CREATE, $_POST['dbname']));
|
369 |
-
break;
|
370 |
-
case "empty":
|
371 |
-
//DROP DB TABLES
|
372 |
-
$drop_log = "Database already empty. Ready for install.";
|
373 |
-
$sql = "SHOW FULL TABLES WHERE Table_Type != 'VIEW'";
|
374 |
-
$found_tables = null;
|
375 |
-
if ($result = mysqli_query($dbh, $sql)) {
|
376 |
-
while ($row = mysqli_fetch_row($result)) {
|
377 |
-
$found_tables[] = $row[0];
|
378 |
-
}
|
379 |
-
if (count($found_tables) > 0) {
|
380 |
-
foreach ($found_tables as $table_name) {
|
381 |
-
$sql = "DROP TABLE `".mysqli_real_escape_string($dbh, $_POST['dbname'])."`.`".mysqli_real_escape_string($dbh, $table_name)."`";
|
382 |
-
if (!$result = mysqli_query($dbh, $sql)) {
|
383 |
-
DUPX_Log::error(sprintf(ERR_DBTRYCLEAN, $_POST['dbname']));
|
384 |
-
}
|
385 |
-
}
|
386 |
-
}
|
387 |
-
$drop_log = count($found_tables);
|
388 |
-
}
|
389 |
-
break;
|
390 |
-
}
|
391 |
-
|
392 |
-
|
393 |
-
//WRITE DATA
|
394 |
-
DUPX_Log::info("--------------------------------------");
|
395 |
-
DUPX_Log::info("DATABASE RESULTS");
|
396 |
-
DUPX_Log::info("--------------------------------------");
|
397 |
-
$profile_start = DUPX_U::getMicrotime();
|
398 |
-
$fcgi_buffer_pool = 5000;
|
399 |
-
$fcgi_buffer_count = 0;
|
400 |
-
$dbquery_rows = 0;
|
401 |
-
$dbtable_rows = 1;
|
402 |
-
$dbquery_errs = 0;
|
403 |
-
$counter = 0;
|
404 |
-
@mysqli_autocommit($dbh, false);
|
405 |
-
|
406 |
-
while ($counter < $sql_result_file_length) {
|
407 |
-
|
408 |
-
$query_strlen = strlen(trim($sql_result_file_data[$counter]));
|
409 |
-
|
410 |
-
if ($dbvar_maxpacks < $query_strlen) {
|
411 |
-
|
412 |
-
DUPX_Log::info("**ERROR** Query size limit [length={$query_strlen}] [sql=" . substr($sql_result_file_data[$counter], 0, 75) . "...]");
|
413 |
-
$dbquery_errs++;
|
414 |
-
|
415 |
-
} elseif ($query_strlen > 0) {
|
416 |
-
|
417 |
-
@mysqli_free_result(@mysqli_query($dbh, ($sql_result_file_data[$counter])));
|
418 |
-
$err = mysqli_error($dbh);
|
419 |
-
|
420 |
-
//Check to make sure the connection is alive
|
421 |
-
if (!empty($err)) {
|
422 |
-
|
423 |
-
if (!mysqli_ping($dbh)) {
|
424 |
-
mysqli_close($dbh);
|
425 |
-
$dbh = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass'], $_POST['dbname'], $_POST['dbport'] );
|
426 |
-
// Reset session setup
|
427 |
-
@mysqli_query($dbh, "SET wait_timeout = ".mysqli_real_escape_string($dbh, $GLOBALS['DB_MAX_TIME']));
|
428 |
-
DUPX_DB::setCharset($dbh, $_POST['dbcharset'], $_POST['dbcollate']);
|
429 |
-
}
|
430 |
-
DUPX_Log::info("**ERROR** database error write '{$err}' - [sql=" . substr($sql_result_file_data[$counter], 0, 75) . "...]");
|
431 |
-
$dbquery_errs++;
|
432 |
-
|
433 |
-
//Buffer data to browser to keep connection open
|
434 |
-
} else {
|
435 |
-
if ($GLOBALS['DB_FCGI_FLUSH'] && $fcgi_buffer_count++ > $fcgi_buffer_pool) {
|
436 |
-
$fcgi_buffer_count = 0;
|
437 |
-
DUPX_U::fcgiFlush();
|
438 |
-
}
|
439 |
-
$dbquery_rows++;
|
440 |
-
}
|
441 |
-
}
|
442 |
-
$counter++;
|
443 |
-
}
|
444 |
-
@mysqli_commit($dbh);
|
445 |
-
@mysqli_autocommit($dbh, true);
|
446 |
-
|
447 |
-
DUPX_Log::info("ERRORS FOUND:\t{$dbquery_errs}");
|
448 |
-
DUPX_Log::info("TABLES DROPPED:\t{$drop_log}");
|
449 |
-
DUPX_Log::info("QUERIES RAN:\t{$dbquery_rows}\n");
|
450 |
-
|
451 |
-
$dbtable_count = 0;
|
452 |
-
if ($result = mysqli_query($dbh, "SHOW TABLES")) {
|
453 |
-
while ($row = mysqli_fetch_array($result, MYSQLI_NUM)) {
|
454 |
-
$table_rows = DUPX_DB::countTableRows($dbh, $row[0]);
|
455 |
-
$dbtable_rows += $table_rows;
|
456 |
-
DUPX_Log::info("{$row[0]}: ({$table_rows})");
|
457 |
-
$dbtable_count++;
|
458 |
-
}
|
459 |
-
@mysqli_free_result($result);
|
460 |
-
}
|
461 |
-
|
462 |
-
if ($dbtable_count == 0) {
|
463 |
-
DUPX_Log::error("No tables where created during step 2 of the install. Please review the <a href='".$GLOBALS["LOG_FILE_NAME"]."' target='install_log'>".$GLOBALS["LOG_FILE_NAME"]."</a> file for
|
464 |
-
ERROR messages. You may have to manually run the installer-data_[HASH].sql with a tool like phpmyadmin to validate the data input. If you have enabled compatibility mode
|
465 |
-
during the package creation process then the database server version your using may not be compatible with this script.\n");
|
466 |
-
}
|
467 |
-
|
468 |
-
|
469 |
-
//DATA CLEANUP: Perform Transient Cache Cleanup
|
470 |
-
//Remove all duplicator entries and record this one since this is a new install.
|
471 |
-
$dbdelete_count = 0;
|
472 |
-
@mysqli_query($dbh, "DELETE FROM `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."duplicator_packages`");
|
473 |
-
$dbdelete_count1 = @mysqli_affected_rows($dbh) or 0;
|
474 |
-
@mysqli_query($dbh, "DELETE FROM `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` WHERE `option_name` LIKE ('_transient%') OR `option_name` LIKE ('_site_transient%')");
|
475 |
-
$dbdelete_count2 = @mysqli_affected_rows($dbh) or 0;
|
476 |
-
$dbdelete_count = (abs($dbdelete_count1) + abs($dbdelete_count2));
|
477 |
-
DUPX_Log::info("\nRemoved '{$dbdelete_count}' cache/transient rows");
|
478 |
-
//Reset Duplicator Options
|
479 |
-
foreach ($GLOBALS['FW_OPTS_DELETE'] as $value) {
|
480 |
-
mysqli_query($dbh, "DELETE FROM `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` WHERE `option_name` = '".mysqli_real_escape_string($dbh, $value)."'");
|
481 |
-
}
|
482 |
-
|
483 |
-
@mysqli_close($dbh);
|
484 |
-
|
485 |
-
//FINAL RESULTS
|
486 |
-
$profile_end = DUPX_U::getMicrotime();
|
487 |
-
$ajax2_end = DUPX_U::getMicrotime();
|
488 |
-
$ajax1_sum = DUPX_U::elapsedTime($ajax2_end, $ajax2_start);
|
489 |
-
DUPX_Log::info("\nCREATE/INSTALL RUNTIME: " . DUPX_U::elapsedTime($profile_end, $profile_start));
|
490 |
-
DUPX_Log::info('STEP-2 COMPLETE @ ' . @date('h:i:s') . " - RUNTIME: {$ajax1_sum}");
|
491 |
-
|
492 |
-
$JSON['pass'] = 1;
|
493 |
-
$JSON['table_count'] = $dbtable_count;
|
494 |
-
$JSON['table_rows'] = $dbtable_rows;
|
495 |
-
$JSON['query_errs'] = $dbquery_errs;
|
496 |
-
echo json_encode($JSON);
|
497 |
-
error_reporting($ajax1_error_level);
|
498 |
-
die('');
|
499 |
-
?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/build/ctrls/ctrl.step3.php
DELETED
@@ -1,390 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
defined("DUPXABSPATH") or die("");
|
3 |
-
|
4 |
-
// Exit if accessed directly from admin
|
5 |
-
if (function_exists('duplicator_secure_check')) {
|
6 |
-
duplicator_secure_check();
|
7 |
-
}
|
8 |
-
|
9 |
-
/** JSON RESPONSE: Most sites have warnings turned off by default, but if they're turned on the warnings
|
10 |
-
cause errors in the JSON data Here we hide the status so warning level is reset at it at the end*/
|
11 |
-
$ajax2_error_level = error_reporting();
|
12 |
-
error_reporting(E_ERROR);
|
13 |
-
|
14 |
-
//====================================================================================================
|
15 |
-
//DATABASE UPDATES
|
16 |
-
//====================================================================================================
|
17 |
-
|
18 |
-
$ajax2_start = DUPX_U::getMicrotime();
|
19 |
-
|
20 |
-
//POST PARAMS
|
21 |
-
if (isset($_POST['dbhost'])) {
|
22 |
-
$post_db_host = DUPX_U::sanitize_text_field($_POST['dbhost']);
|
23 |
-
$_POST['dbhost'] = trim($post_db_host);
|
24 |
-
} else {
|
25 |
-
$_POST['dbhost'] = null;
|
26 |
-
}
|
27 |
-
|
28 |
-
if (isset($_POST['dbname'])) {
|
29 |
-
$post_db_name = DUPX_U::sanitize_text_field($_POST['dbname']);
|
30 |
-
$_POST['dbname'] = trim($post_db_name);
|
31 |
-
} else {
|
32 |
-
$_POST['dbname'] = null;
|
33 |
-
}
|
34 |
-
|
35 |
-
|
36 |
-
$_POST['dbuser'] = isset($_POST['dbuser']) ? DUPX_U::sanitize_text_field($_POST['dbuser']) : null;
|
37 |
-
$_POST['dbpass'] = isset($_POST['dbpass']) ? DUPX_U::sanitize_text_field($_POST['dbpass']) : null;
|
38 |
-
|
39 |
-
if (isset($_POST['blogname'])) {
|
40 |
-
$post_blog_name = DUPX_U::sanitize_text_field($_POST['blogname']);
|
41 |
-
$_POST['blogname'] = trim($post_blog_name);
|
42 |
-
} else {
|
43 |
-
$_POST['blogname'] = '';
|
44 |
-
}
|
45 |
-
|
46 |
-
$_POST['postguid'] = isset($_POST['postguid']) && $_POST['postguid'] == 1 ? 1 : 0;
|
47 |
-
$_POST['fullsearch'] = isset($_POST['fullsearch']) && $_POST['fullsearch'] == 1 ? 1 : 0;
|
48 |
-
|
49 |
-
if (isset($_POST['path_old'])) {
|
50 |
-
$post_path_old = DUPX_U::sanitize_text_field($_POST['path_old']);
|
51 |
-
$_POST['path_old'] = trim($post_path_old);
|
52 |
-
} else {
|
53 |
-
$_POST['path_old'] = null;
|
54 |
-
}
|
55 |
-
|
56 |
-
if (isset($_POST['path_new'])) {
|
57 |
-
$post_path_new = DUPX_U::sanitize_text_field($_POST['path_new']);
|
58 |
-
$_POST['path_new'] = trim($post_path_new);
|
59 |
-
} else {
|
60 |
-
$_POST['path_new'] = null;
|
61 |
-
}
|
62 |
-
|
63 |
-
|
64 |
-
$_POST['siteurl'] = isset($_POST['siteurl']) ? rtrim(trim($_POST['siteurl']), '/') : null;
|
65 |
-
$_POST['tables'] = isset($_POST['tables']) && is_array($_POST['tables']) ? array_map('stripcslashes', $_POST['tables']) : array();
|
66 |
-
$_POST['url_old'] = isset($_POST['url_old']) ? trim($_POST['url_old']) : null;
|
67 |
-
$_POST['url_new'] = isset($_POST['url_new']) ? rtrim(trim($_POST['url_new']), '/') : null;
|
68 |
-
$_POST['retain_config'] = (isset($_POST['retain_config']) && $_POST['retain_config'] == '1') ? true : false;
|
69 |
-
$_POST['exe_safe_mode'] = isset($_POST['exe_safe_mode']) ? DUPX_U::sanitize_text_field($_POST['exe_safe_mode']) : 0;
|
70 |
-
|
71 |
-
|
72 |
-
//MYSQL CONNECTION: If inputs are bad then die
|
73 |
-
$dbh = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], html_entity_decode($_POST['dbpass']), $_POST['dbname'], $_POST['dbport']);
|
74 |
-
$dbConnError = (mysqli_connect_error()) ? 'Error: '.mysqli_connect_error() : 'Unable to Connect';
|
75 |
-
if (!$dbh) {
|
76 |
-
$msg = "Unable to connect with the following parameters: <br/> <b>HOST:</b> {$_POST['dbhost']}<br/> <b>DATABASE:</b> {$_POST['dbname']}<br/>";
|
77 |
-
$msg .= "<b>Connection Error:</b> {$dbConnError}";
|
78 |
-
DUPX_Log::error($msg);
|
79 |
-
}
|
80 |
-
|
81 |
-
$charset_server = @mysqli_character_set_name($dbh);
|
82 |
-
@mysqli_query($dbh, "SET wait_timeout = ".mysqli_real_escape_string($dbh, $GLOBALS['DB_MAX_TIME']));
|
83 |
-
DUPX_DB::setCharset($dbh, $_POST['dbcharset'], $_POST['dbcollate']);
|
84 |
-
|
85 |
-
|
86 |
-
//LOGGING
|
87 |
-
$POST_LOG = $_POST;
|
88 |
-
unset($POST_LOG['tables']);
|
89 |
-
unset($POST_LOG['plugins']);
|
90 |
-
unset($POST_LOG['dbpass']);
|
91 |
-
ksort($POST_LOG);
|
92 |
-
|
93 |
-
$date = @date('h:i:s');
|
94 |
-
$charset_client = @mysqli_character_set_name($dbh);
|
95 |
-
|
96 |
-
$log = <<<LOG
|
97 |
-
\n\n********************************************************************************
|
98 |
-
* DUPLICATOR-LITE: INSTALL-LOG
|
99 |
-
* STEP-3 START @ {$date}
|
100 |
-
* NOTICE: Do NOT post to public sites or forums
|
101 |
-
********************************************************************************
|
102 |
-
CHARSET SERVER:\t{$charset_server}
|
103 |
-
CHARSET CLIENT:\t{$charset_client}
|
104 |
-
LOG;
|
105 |
-
DUPX_Log::info($log);
|
106 |
-
|
107 |
-
//Detailed logging
|
108 |
-
$log = "--------------------------------------\n";
|
109 |
-
$log .= "POST DATA\n";
|
110 |
-
$log .= "--------------------------------------\n";
|
111 |
-
$log .= print_r($POST_LOG, true);
|
112 |
-
$log .= "--------------------------------------\n";
|
113 |
-
$log .= "SCANNED TABLES\n";
|
114 |
-
$log .= "--------------------------------------\n";
|
115 |
-
$log .= (isset($_POST['tables']) && count($_POST['tables'] > 0))
|
116 |
-
? print_r($_POST['tables'], true)
|
117 |
-
: 'No tables selected to update';
|
118 |
-
$log .= "--------------------------------------\n";
|
119 |
-
$log .= "KEEP PLUGINS ACTIVE\n";
|
120 |
-
$log .= "--------------------------------------\n";
|
121 |
-
$log .= (isset($_POST['plugins']) && count($_POST['plugins'] > 0))
|
122 |
-
? print_r($_POST['plugins'], true)
|
123 |
-
: 'No plugins selected for activation';
|
124 |
-
DUPX_Log::info($log, 2);
|
125 |
-
|
126 |
-
//UPDATE SETTINGS
|
127 |
-
$blog_name = $_POST['blogname'];
|
128 |
-
$plugin_list = (isset($_POST['plugins'])) ? $_POST['plugins'] : array();
|
129 |
-
// Force Duplicator active so we the security cleanup will be available
|
130 |
-
if (!in_array('duplicator/duplicator.php', $plugin_list)) {
|
131 |
-
$plugin_list[] = 'duplicator/duplicator.php';
|
132 |
-
}
|
133 |
-
$serial_plugin_list = @serialize($plugin_list);
|
134 |
-
|
135 |
-
mysqli_query($dbh, "UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` SET option_value = '{$blog_name}' WHERE option_name = 'blogname' ");
|
136 |
-
mysqli_query($dbh, "UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` SET option_value = '{$serial_plugin_list}' WHERE option_name = 'active_plugins' ");
|
137 |
-
|
138 |
-
$log = "--------------------------------------\n";
|
139 |
-
$log .= "SERIALIZER ENGINE\n";
|
140 |
-
$log .= "[*] scan every column\n";
|
141 |
-
$log .= "[~] scan only text columns\n";
|
142 |
-
$log .= "[^] no searchable columns\n";
|
143 |
-
$log .= "--------------------------------------";
|
144 |
-
DUPX_Log::info($log);
|
145 |
-
|
146 |
-
$url_old_json = str_replace('"', "", json_encode($_POST['url_old']));
|
147 |
-
$url_new_json = str_replace('"', "", json_encode($_POST['url_new']));
|
148 |
-
$path_old_json = str_replace('"', "", json_encode($_POST['path_old']));
|
149 |
-
$path_new_json = str_replace('"', "", json_encode($_POST['path_new']));
|
150 |
-
|
151 |
-
//DIRS PATHS
|
152 |
-
array_push($GLOBALS['REPLACE_LIST'],
|
153 |
-
array('search' => $_POST['path_old'], 'replace' => $_POST['path_new']),
|
154 |
-
array('search' => $path_old_json, 'replace' => $path_new_json),
|
155 |
-
array('search' => urlencode($_POST['path_old']), 'replace' => urlencode($_POST['path_new'])),
|
156 |
-
array('search' => rtrim(DUPX_U::unsetSafePath($_POST['path_old']), '\\'), 'replace' => rtrim($_POST['path_new'], '/'))
|
157 |
-
);
|
158 |
-
|
159 |
-
|
160 |
-
//SEARCH WITH NO PROTOCAL: RAW "//"
|
161 |
-
$url_old_raw = str_ireplace(array('http://', 'https://'), '//', $_POST['url_old']);
|
162 |
-
$url_new_raw = str_ireplace(array('http://', 'https://'), '//', $_POST['url_new']);
|
163 |
-
$url_old_raw_json = str_replace('"', "", json_encode($url_old_raw));
|
164 |
-
$url_new_raw_json = str_replace('"', "", json_encode($url_new_raw));
|
165 |
-
array_push($GLOBALS['REPLACE_LIST'],
|
166 |
-
//RAW
|
167 |
-
array('search' => $url_old_raw, 'replace' => $url_new_raw),
|
168 |
-
array('search' => $url_old_raw_json, 'replace' => $url_new_raw_json),
|
169 |
-
array('search' => urlencode($url_old_raw), 'replace' => urlencode($url_new_raw))
|
170 |
-
);
|
171 |
-
|
172 |
-
|
173 |
-
//SEARCH HTTP(S) EXPLICIT REQUEST
|
174 |
-
//Because the raw replace above has already changed all urls just fix https/http issue
|
175 |
-
//if the user has explicitly asked other-wise word boundary issues will occur:
|
176 |
-
//Old site: http://mydomain.com/somename/
|
177 |
-
//New site: http://mydomain.com/somename-dup/
|
178 |
-
//Result: http://mydomain.com/somename-dup-dup/
|
179 |
-
if (stristr($_POST['url_old'], 'http:') && stristr($_POST['url_new'], 'https:') ) {
|
180 |
-
$url_old_http = str_ireplace('https:', 'http:', $_POST['url_new']);
|
181 |
-
$url_new_http = $_POST['url_new'];
|
182 |
-
$url_old_http_json = str_replace('"', "", json_encode($url_old_http));
|
183 |
-
$url_new_http_json = str_replace('"', "", json_encode($url_new_http));
|
184 |
-
|
185 |
-
} elseif(stristr($_POST['url_old'], 'https:') && stristr($_POST['url_new'], 'http:')) {
|
186 |
-
$url_old_http = str_ireplace('http:', 'https:', $_POST['url_new']);
|
187 |
-
$url_new_http = $_POST['url_new'];
|
188 |
-
$url_old_http_json = str_replace('"', "", json_encode($url_old_http));
|
189 |
-
$url_new_http_json = str_replace('"', "", json_encode($url_new_http));
|
190 |
-
}
|
191 |
-
if(isset($url_old_http)){
|
192 |
-
array_push($GLOBALS['REPLACE_LIST'],
|
193 |
-
array('search' => $url_old_http, 'replace' => $url_new_http),
|
194 |
-
array('search' => $url_old_http_json, 'replace' => $url_new_http_json),
|
195 |
-
array('search' => urlencode($url_old_http), 'replace' => urlencode($url_new_http))
|
196 |
-
);
|
197 |
-
}
|
198 |
-
|
199 |
-
//Remove trailing slashes
|
200 |
-
function _dupx_array_rtrim(&$value) {
|
201 |
-
$value = rtrim($value, '\/');
|
202 |
-
}
|
203 |
-
array_walk_recursive($GLOBALS['REPLACE_LIST'], _dupx_array_rtrim);
|
204 |
-
|
205 |
-
@mysqli_autocommit($dbh, false);
|
206 |
-
$report = DUPX_UpdateEngine::load($dbh, $GLOBALS['REPLACE_LIST'], $_POST['tables'], $_POST['fullsearch']);
|
207 |
-
@mysqli_commit($dbh);
|
208 |
-
@mysqli_autocommit($dbh, true);
|
209 |
-
|
210 |
-
|
211 |
-
//BUILD JSON RESPONSE
|
212 |
-
$JSON = array();
|
213 |
-
$JSON['step2'] = json_decode(urldecode($_POST['json']));
|
214 |
-
$JSON['step3'] = $report;
|
215 |
-
$JSON['step3']['warn_all'] = 0;
|
216 |
-
$JSON['step3']['warnlist'] = array();
|
217 |
-
|
218 |
-
DUPX_UpdateEngine::logStats($report);
|
219 |
-
DUPX_UpdateEngine::logErrors($report);
|
220 |
-
|
221 |
-
//Reset the postguid data
|
222 |
-
if ($_POST['postguid']) {
|
223 |
-
mysqli_query($dbh, "UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."posts` SET guid = REPLACE(guid, '".mysqli_real_escape_string($dbh, $_POST['url_new'])."', '".mysqli_real_escape_string($dbh, $_POST['url_old'])."')");
|
224 |
-
$update_guid = @mysqli_affected_rows($dbh) or 0;
|
225 |
-
DUPX_Log::info("Reverted '{$update_guid}' post guid columns back to '{$_POST['url_old']}'");
|
226 |
-
}
|
227 |
-
|
228 |
-
/** FINAL UPDATES: Must happen after the global replace to prevent double pathing
|
229 |
-
http://xyz.com/abc01 will become http://xyz.com/abc0101 with trailing data */
|
230 |
-
mysqli_query($dbh, "UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` SET option_value = '".mysqli_real_escape_string($dbh, $_POST['url_new'])."' WHERE option_name = 'home' ");
|
231 |
-
mysqli_query($dbh, "UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` SET option_value = '".mysqli_real_escape_string($dbh, $_POST['siteurl'])."' WHERE option_name = 'siteurl' ");
|
232 |
-
mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` (option_value, option_name) VALUES('".mysqli_real_escape_string($dbh, $_POST['exe_safe_mode'])."','duplicator_exe_safe_mode')");
|
233 |
-
|
234 |
-
//===============================================
|
235 |
-
//CONFIGURATION FILE UPDATES
|
236 |
-
//===============================================
|
237 |
-
DUPX_Log::info("\n====================================");
|
238 |
-
DUPX_Log::info('CONFIGURATION FILE UPDATES:');
|
239 |
-
DUPX_Log::info("====================================\n");
|
240 |
-
DUPX_WPConfig::updateStandard();
|
241 |
-
$config_file = DUPX_WPConfig::updateExtended();
|
242 |
-
DUPX_Log::info("UPDATED WP-CONFIG: {$root_path}/wp-config.php' (if present)");
|
243 |
-
|
244 |
-
//Web Server Config Updates
|
245 |
-
if (!isset($_POST['url_new']) || $_POST['retain_config']) {
|
246 |
-
DUPX_Log::info("\nNOTICE: Manual update of permalinks required see: Admin > Settings > Permalinks > Click Save Changes");
|
247 |
-
DUPX_Log::info("Retaining the original htaccess, user.ini or web.config files may cause issues with the setup of this site.");
|
248 |
-
DUPX_Log::info("If you run into issues during or after the install process please uncheck the 'Config Files' checkbox labeled:");
|
249 |
-
DUPX_Log::info("'Retain original .htaccess, .user.ini and web.config' from Step 1 and re-run the installer. Backups of the");
|
250 |
-
DUPX_Log::info("orginal config files will be made and can be merged per required directive.");
|
251 |
-
} else {
|
252 |
-
DUPX_ServerConfig::setup($dbh);
|
253 |
-
}
|
254 |
-
|
255 |
-
|
256 |
-
//===============================================
|
257 |
-
//GENERAL UPDATES & CLEANUP
|
258 |
-
//===============================================
|
259 |
-
DUPX_Log::info("\n====================================");
|
260 |
-
DUPX_Log::info('GENERAL UPDATES & CLEANUP:');
|
261 |
-
DUPX_Log::info("====================================\n");
|
262 |
-
|
263 |
-
/** CREATE NEW USER LOGIC */
|
264 |
-
if (strlen($_POST['wp_username']) >= 4 && strlen($_POST['wp_password']) >= 6) {
|
265 |
-
$post_wp_username = DUPX_U::sanitize_text_field($_POST['wp_username']);
|
266 |
-
$post_wp_password = DUPX_U::sanitize_text_field($_POST['wp_password']);
|
267 |
-
|
268 |
-
$post_wp_username = mysqli_real_escape_string($dbh, $post_wp_username);
|
269 |
-
$post_wp_password = mysqli_real_escape_string($dbh, $post_wp_password);
|
270 |
-
|
271 |
-
$newuser_check = mysqli_query($dbh, "SELECT COUNT(*) AS count FROM `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."users` WHERE user_login = '{$post_wp_username}' ");
|
272 |
-
$newuser_row = mysqli_fetch_row($newuser_check);
|
273 |
-
$newuser_count = is_null($newuser_row) ? 0 : $newuser_row[0];
|
274 |
-
|
275 |
-
if ($newuser_count == 0) {
|
276 |
-
|
277 |
-
$newuser_datetime = @date("Y-m-d H:i:s");
|
278 |
-
$newuser_security = mysqli_real_escape_string($dbh, 'a:1:{s:13:"administrator";s:1:"1";}');
|
279 |
-
|
280 |
-
$newuser_test1 = @mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."users`
|
281 |
-
(`user_login`, `user_pass`, `user_nicename`, `user_email`, `user_registered`, `user_activation_key`, `user_status`, `display_name`)
|
282 |
-
VALUES ('{$post_wp_username}', MD5('{$post_wp_password}'), '{$post_wp_username}', '', '{$newuser_datetime}', '', '0', '{$post_wp_username}')");
|
283 |
-
|
284 |
-
$newuser_insert_id = mysqli_insert_id($dbh);
|
285 |
-
|
286 |
-
$newuser_test2 = @mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."usermeta`
|
287 |
-
(`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser_insert_id}', '".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."capabilities', '{$newuser_security}')");
|
288 |
-
|
289 |
-
$newuser_test3 = @mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."usermeta`
|
290 |
-
(`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser_insert_id}', '".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."user_level', '10')");
|
291 |
-
|
292 |
-
//Misc Meta-Data Settings:
|
293 |
-
@mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser_insert_id}', 'rich_editing', 'true')");
|
294 |
-
@mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser_insert_id}', 'admin_color', 'fresh')");
|
295 |
-
@mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser_insert_id}', 'nickname', '{$post_wp_username}')");
|
296 |
-
|
297 |
-
if ($newuser_test1 && $newuser_test2 && $newuser_test3) {
|
298 |
-
DUPX_Log::info("NEW WP-ADMIN USER: New username '{$_POST['wp_username']}' was created successfully \n ");
|
299 |
-
} else {
|
300 |
-
$newuser_warnmsg = "NEW WP-ADMIN USER: Failed to create the user '{".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."}' \n ";
|
301 |
-
$JSON['step3']['warnlist'][] = $newuser_warnmsg;
|
302 |
-
DUPX_Log::info($newuser_warnmsg);
|
303 |
-
}
|
304 |
-
}
|
305 |
-
else {
|
306 |
-
$newuser_warnmsg = "NEW WP-ADMIN USER: Username '{$_POST['wp_username']}' already exists in the database. Unable to create new account \n";
|
307 |
-
$JSON['step3']['warnlist'][] = $newuser_warnmsg;
|
308 |
-
DUPX_Log::info($newuser_warnmsg);
|
309 |
-
}
|
310 |
-
}
|
311 |
-
|
312 |
-
/** ==============================
|
313 |
-
* MU Updates*/
|
314 |
-
$mu_newDomain = parse_url($_POST['url_new']);
|
315 |
-
$mu_oldDomain = parse_url($_POST['url_old']);
|
316 |
-
$mu_newDomainHost = $mu_newDomain['host'];
|
317 |
-
$mu_oldDomainHost = $mu_oldDomain['host'];
|
318 |
-
$mu_newUrlPath = parse_url($_POST['url_new'], PHP_URL_PATH);
|
319 |
-
$mu_oldUrlPath = parse_url($_POST['url_old'], PHP_URL_PATH);
|
320 |
-
|
321 |
-
//Force a path for PATH_CURRENT_SITE
|
322 |
-
$mu_newUrlPath = (empty($mu_newUrlPath) || ($mu_newUrlPath == '/')) ? '/' : rtrim($mu_newUrlPath, '/') . '/';
|
323 |
-
$mu_oldUrlPath = (empty($mu_oldUrlPath) || ($mu_oldUrlPath == '/')) ? '/' : rtrim($mu_oldUrlPath, '/') . '/';
|
324 |
-
|
325 |
-
$mu_updates = @mysqli_query($dbh, "UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."blogs` SET domain = '".mysqli_real_escape_string($dbh, $mu_newDomainHost)."' WHERE domain = '".mysqli_real_escape_string($dbh, $mu_oldDomainHost)."'");
|
326 |
-
if ($mu_updates) {
|
327 |
-
DUPX_Log::info("Update MU table blogs: domain {$mu_newDomainHost} ");
|
328 |
-
DUPX_Log::info("UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."blogs` SET domain = '".mysqli_real_escape_string($dbh, $mu_newDomainHost)."' WHERE domain = '".mysqli_real_escape_string($dbh, $mu_oldDomainHost)."'");
|
329 |
-
}
|
330 |
-
|
331 |
-
|
332 |
-
//Create snapshots directory in order to
|
333 |
-
//compensate for permissions on some servers
|
334 |
-
if (!file_exists(DUPLICATOR_SSDIR_NAME)) {
|
335 |
-
mkdir(DUPLICATOR_SSDIR_NAME, 0755);
|
336 |
-
DUPX_Log::info("- Created directory ". DUPLICATOR_SSDIR_NAME);
|
337 |
-
}
|
338 |
-
$fp = fopen(DUPLICATOR_SSDIR_NAME . '/index.php', 'w');
|
339 |
-
fclose($fp);
|
340 |
-
DUPX_Log::info("- Created file ". DUPLICATOR_SSDIR_NAME . '/index.php');
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
//===============================================
|
345 |
-
//NOTICES TESTS
|
346 |
-
//===============================================
|
347 |
-
DUPX_Log::info("\n====================================");
|
348 |
-
DUPX_Log::info("NOTICES");
|
349 |
-
DUPX_Log::info("====================================\n");
|
350 |
-
$config_vars = array('WPCACHEHOME', 'COOKIE_DOMAIN', 'WP_SITEURL', 'WP_HOME', 'WP_TEMP_DIR');
|
351 |
-
$config_found = DUPX_U::getListValues($config_vars, $config_file);
|
352 |
-
|
353 |
-
//Config File:
|
354 |
-
if (! empty($config_found)) {
|
355 |
-
$msg = "NOTICE: The wp-config.php has the following values set [" . implode(", ", $config_found) . "]. \n";
|
356 |
-
$msg .= 'Please validate these values are correct in your wp-config.php file. See the codex link for more details: https://codex.wordpress.org/Editing_wp-config.php';
|
357 |
-
$JSON['step3']['warnlist'][] = $msg;
|
358 |
-
DUPX_Log::info($msg);
|
359 |
-
}
|
360 |
-
|
361 |
-
//Database:
|
362 |
-
$result = @mysqli_query($dbh, "SELECT option_value FROM `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` WHERE option_name IN ('upload_url_path','upload_path')");
|
363 |
-
if ($result) {
|
364 |
-
while ($row = mysqli_fetch_row($result)) {
|
365 |
-
if (strlen($row[0])) {
|
366 |
-
$msg = "NOTICE: The media settings values in the table '{$GLOBALS['FW_TABLEPREFIX']}options' has at least one the following values ['upload_url_path','upload_path'] set. \n";
|
367 |
-
$msg .= "Please validate these settings by logging into your wp-admin and going to Settings->Media area and validating the 'Uploading Files' section";
|
368 |
-
$JSON['step3']['warnlist'][] = $msg;
|
369 |
-
DUPX_Log::info($msg);
|
370 |
-
break;
|
371 |
-
}
|
372 |
-
}
|
373 |
-
}
|
374 |
-
|
375 |
-
if (empty($JSON['step3']['warnlist'])) {
|
376 |
-
DUPX_Log::info("No Notices Found\n");
|
377 |
-
}
|
378 |
-
|
379 |
-
$JSON['step3']['warn_all'] = empty($JSON['step3']['warnlist']) ? 0 : count($JSON['step3']['warnlist']);
|
380 |
-
|
381 |
-
mysqli_close($dbh);
|
382 |
-
|
383 |
-
$ajax2_end = DUPX_U::getMicrotime();
|
384 |
-
$ajax2_sum = DUPX_U::elapsedTime($ajax2_end, $ajax2_start);
|
385 |
-
DUPX_Log::info("\nSTEP 3 COMPLETE @ " . @date('h:i:s') . " - RUNTIME: {$ajax2_sum}\n\n");
|
386 |
-
|
387 |
-
$JSON['step3']['pass'] = 1;
|
388 |
-
error_reporting($ajax2_error_level);
|
389 |
-
die(json_encode($JSON));
|
390 |
-
?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/build/main.installer.php
DELETED
@@ -1,418 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/*
|
3 |
-
Copyright 2011-17 snapcreek.com
|
4 |
-
|
5 |
-
This program is free software; you can redistribute it and/or modify
|
6 |
-
it under the terms of the GNU General Public License, version 3, as
|
7 |
-
published by the Free Software Foundation.
|
8 |
-
|
9 |
-
This program is distributed in the hope that it will be useful,
|
10 |
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11 |
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12 |
-
GNU General Public License for more details.
|
13 |
-
|
14 |
-
You should have received a copy of the GNU General Public License
|
15 |
-
along with this program; if not, write to the Free Software
|
16 |
-
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
17 |
-
GPL v3 https://www.gnu.org/licenses/gpl-3.0.en.html
|
18 |
-
*/
|
19 |
-
|
20 |
-
if ( !defined('DUPXABSPATH') )
|
21 |
-
define('DUPXABSPATH', dirname(__FILE__) . '/');
|
22 |
-
|
23 |
-
if (file_exists('dtoken.php')) {
|
24 |
-
//This is most likely inside the snapshot folder.
|
25 |
-
|
26 |
-
//DOWNLOAD ONLY: (Only enable download from within the snapshot directory)
|
27 |
-
if (isset($_GET['get']) && isset($_GET['file'])) {
|
28 |
-
//Clean the input, strip out anything not alpha-numeric or "_.", so restricts
|
29 |
-
//only downloading files in same folder, and removes risk of allowing directory
|
30 |
-
//separators in other charsets (vulnerability in older IIS servers), also
|
31 |
-
//strips out anything that might cause it to use an alternate stream since
|
32 |
-
//that would require :// near the front.
|
33 |
-
$filename = preg_replace('/[^a-zA-Z0-9_.]*/','',$_GET['file']);
|
34 |
-
if (strlen($filename) && file_exists($filename) && (strstr($filename, '_installer.php'))) {
|
35 |
-
//Attempt to push the file to the browser
|
36 |
-
header('Content-Description: File Transfer');
|
37 |
-
header('Content-Type: application/octet-stream');
|
38 |
-
header('Content-Disposition: attachment; filename=installer.php');
|
39 |
-
header('Content-Transfer-Encoding: binary');
|
40 |
-
header('Expires: 0');
|
41 |
-
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
|
42 |
-
header('Pragma: public');
|
43 |
-
header('Content-Length: ' . filesize($filename));
|
44 |
-
@ob_clean();
|
45 |
-
@flush();
|
46 |
-
if (@readfile($filename) == false) {
|
47 |
-
$data = file_get_contents($filename);
|
48 |
-
if ($data == false) {
|
49 |
-
die("Unable to read installer file. The server currently has readfile and file_get_contents disabled on this server. Please contact your server admin to remove this restriction");
|
50 |
-
} else {
|
51 |
-
print $data;
|
52 |
-
}
|
53 |
-
}
|
54 |
-
} else {
|
55 |
-
header("HTTP/1.1 404 Not Found", true, 404);
|
56 |
-
header("Status: 404 Not Found");
|
57 |
-
}
|
58 |
-
}
|
59 |
-
//Prevent Access from rovers or direct browsing in snapshop directory, or when
|
60 |
-
//requesting to download a file, should not go past this point.
|
61 |
-
exit;
|
62 |
-
}
|
63 |
-
|
64 |
-
/* ==============================================================================================
|
65 |
-
ADVANCED FEATURES - Allows admins to perform aditional logic on the import.
|
66 |
-
|
67 |
-
$GLOBALS['REPLACE_LIST']
|
68 |
-
Add additional search and replace items to step 2 for the serialize engine.
|
69 |
-
Place directly below $GLOBALS['REPLACE_LIST'] variable below your items
|
70 |
-
EXAMPLE:
|
71 |
-
array_push($GLOBALS['REPLACE_LIST'], array('search' => 'https://oldurl/', 'replace' => 'https://newurl/'));
|
72 |
-
array_push($GLOBALS['REPLACE_LIST'], array('search' => 'ftps://oldurl/', 'replace' => 'ftps://newurl/'));
|
73 |
-
================================================================================================= */
|
74 |
-
|
75 |
-
// Some machines don’t have this set so just do it here.
|
76 |
-
date_default_timezone_set('UTC');
|
77 |
-
|
78 |
-
//PATCH FOR IIS: Does not support REQUEST_URI
|
79 |
-
if (!isset($_SERVER['REQUEST_URI'])) {
|
80 |
-
$_SERVER['REQUEST_URI'] = substr($_SERVER['PHP_SELF'],0);
|
81 |
-
if (isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING'] != "") {
|
82 |
-
$_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
|
83 |
-
}
|
84 |
-
}
|
85 |
-
|
86 |
-
//COMPARE VALUES
|
87 |
-
$GLOBALS['DUPX_DEBUG'] = false;
|
88 |
-
$GLOBALS['DUPX_DBPASS_CHECK'] = true;
|
89 |
-
$GLOBALS['FW_CREATED'] = '%fwrite_created%';
|
90 |
-
$GLOBALS['FW_VERSION_DUP'] = '%fwrite_version_dup%';
|
91 |
-
$GLOBALS['FW_VERSION_WP'] = '%fwrite_version_wp%';
|
92 |
-
$GLOBALS['FW_VERSION_DB'] = '%fwrite_version_db%';
|
93 |
-
$GLOBALS['FW_VERSION_PHP'] = '%fwrite_version_php%';
|
94 |
-
$GLOBALS['FW_VERSION_OS'] = '%fwrite_version_os%';
|
95 |
-
//GENERAL
|
96 |
-
$GLOBALS['FW_TABLEPREFIX'] = '%fwrite_wp_tableprefix%';
|
97 |
-
$GLOBALS['FW_URL_OLD'] = '%fwrite_url_old%';
|
98 |
-
$GLOBALS['FW_PACKAGE_NAME'] = '%fwrite_archive_name%';
|
99 |
-
$GLOBALS['FW_PACKAGE_NOTES'] = '%fwrite_package_notes%';
|
100 |
-
$GLOBALS['FW_PACKAGE_EST_SIZE'] = '%fwrite_package_size%';
|
101 |
-
$GLOBALS['FW_SECURE_NAME'] = '%fwrite_secure_name%';
|
102 |
-
$GLOBALS['FW_DBHOST'] = '%fwrite_dbhost%';
|
103 |
-
$GLOBALS['FW_DBHOST'] = empty($GLOBALS['FW_DBHOST']) ? 'localhost' : $GLOBALS['FW_DBHOST'];
|
104 |
-
$GLOBALS['FW_DBPORT'] = '%fwrite_dbport%';
|
105 |
-
$GLOBALS['FW_DBPORT'] = empty($GLOBALS['FW_DBPORT']) ? 3306 : $GLOBALS['FW_DBPORT'];
|
106 |
-
$GLOBALS['FW_DBNAME'] = '%fwrite_dbname%';
|
107 |
-
$GLOBALS['FW_DBUSER'] = '%fwrite_dbuser%';
|
108 |
-
$GLOBALS['FW_DBPASS'] = '%fwrite_dbpass%';
|
109 |
-
$GLOBALS['FW_SECUREON'] = '%fwrite_secureon%';
|
110 |
-
$GLOBALS['FW_SECUREPASS'] = '%fwrite_securepass%';
|
111 |
-
$GLOBALS['FW_BLOGNAME'] = '%fwrite_blogname%';
|
112 |
-
$GLOBALS['FW_WPROOT'] = '%fwrite_wproot%';
|
113 |
-
$GLOBALS['FW_WPLOGIN_URL'] = '%fwrite_wplogin_url%';
|
114 |
-
$GLOBALS['FW_OPTS_DELETE'] = json_decode("%fwrite_opts_delete%", true);
|
115 |
-
$GLOBALS['FW_DUPLICATOR_VERSION'] = '%fwrite_duplicator_version%';
|
116 |
-
$GLOBALS['FW_ARCHIVE_ONLYDB'] = '%fwrite_archive_onlydb%';
|
117 |
-
$GLOBALS['PACKAGE_HASH'] = '%package_hash%';
|
118 |
-
|
119 |
-
//DATABASE SETUP: all time in seconds
|
120 |
-
$GLOBALS['DB_MAX_TIME'] = 5000;
|
121 |
-
$GLOBALS['DB_MAX_PACKETS'] = 268435456;
|
122 |
-
$GLOBALS['DB_FCGI_FLUSH'] = false;
|
123 |
-
ini_set('mysql.connect_timeout', '5000');
|
124 |
-
|
125 |
-
//PHP SETUP: all time in seconds
|
126 |
-
ini_set('memory_limit', '2048M');
|
127 |
-
ini_set("max_execution_time", '5000');
|
128 |
-
ini_set("max_input_time", '5000');
|
129 |
-
ini_set('default_socket_timeout', '5000');
|
130 |
-
@set_time_limit(0);
|
131 |
-
|
132 |
-
$GLOBALS['DBCHARSET_DEFAULT'] = 'utf8';
|
133 |
-
$GLOBALS['DBCOLLATE_DEFAULT'] = 'utf8_general_ci';
|
134 |
-
$GLOBALS['FAQ_URL'] = 'https://snapcreek.com/duplicator/docs/faqs-tech';
|
135 |
-
$GLOBALS['NOW_DATE'] = @date("Y-m-d-H:i:s");
|
136 |
-
$GLOBALS['DB_RENAME_PREFIX'] = 'x-bak__';
|
137 |
-
|
138 |
-
//UPDATE TABLE SETTINGS
|
139 |
-
$GLOBALS['REPLACE_LIST'] = array();
|
140 |
-
|
141 |
-
|
142 |
-
/** ================================================================================================
|
143 |
-
END ADVANCED FEATURES: Do not edit below here.
|
144 |
-
=================================================================================================== */
|
145 |
-
|
146 |
-
//CONSTANTS
|
147 |
-
define("DUPLICATOR_INIT", 1);
|
148 |
-
define("DUPLICATOR_SSDIR_NAME", 'wp-snapshots'); //This should match DUPLICATOR_SSDIR_NAME in duplicator.php
|
149 |
-
|
150 |
-
//SHARED POST PARMS
|
151 |
-
$_POST['action_step'] = isset($_POST['action_step']) ? DUPX_U::sanitize_text_field($_POST['action_step']) : "0";
|
152 |
-
$_POST['secure-pass'] = isset($_POST['secure-pass']) ? DUPX_U::sanitize_text_field($_POST['secure-pass']) : '';
|
153 |
-
|
154 |
-
if ($GLOBALS['FW_SECUREON']) {
|
155 |
-
$pass_hasher = new DUPX_PasswordHash(8, FALSE);
|
156 |
-
$post_secure_pass = DUPX_U::sanitize_text_field($_POST['secure-pass']);
|
157 |
-
$pass_check = $pass_hasher->CheckPassword(base64_encode($post_secure_pass), $GLOBALS['FW_SECUREPASS']);
|
158 |
-
if (! $pass_check) {
|
159 |
-
$_POST['action_step'] = 0;
|
160 |
-
}
|
161 |
-
}
|
162 |
-
|
163 |
-
/** Host has several combinations :
|
164 |
-
localhost | localhost:55 | localhost: | http://localhost | http://localhost:55 */
|
165 |
-
if (isset($_POST['dbhost'])) {
|
166 |
-
$post_db_host = DUPX_U::sanitize_text_field($_POST['dbhost']);
|
167 |
-
$_POST['dbhost'] = DUPX_U::sanitize_text_field($post_db_host);
|
168 |
-
} else {
|
169 |
-
$_POST['dbhost'] = null;
|
170 |
-
}
|
171 |
-
|
172 |
-
if (isset($_POST['dbport'])) {
|
173 |
-
$post_db_port = DUPX_U::sanitize_text_field($_POST['dbport']);
|
174 |
-
$_POST['dbport'] = trim($post_db_port);
|
175 |
-
} else {
|
176 |
-
$_POST['dbport'] = 3306;
|
177 |
-
}
|
178 |
-
|
179 |
-
$_POST['dbuser'] = isset($_POST['dbuser']) ? DUPX_U::sanitize_text_field($_POST['dbuser']) : null;
|
180 |
-
|
181 |
-
if (isset($_POST['dbpass'])) {
|
182 |
-
$post_db_pass = DUPX_U::sanitize_text_field($_POST['dbpass']);
|
183 |
-
$_POST['dbpass'] = trim($post_db_pass);
|
184 |
-
} else {
|
185 |
-
$_POST['dbpass'] = null;
|
186 |
-
}
|
187 |
-
|
188 |
-
|
189 |
-
if (isset($_POST['dbname'])) {
|
190 |
-
$post_db_name = DUPX_U::sanitize_text_field($_POST['dbname']);
|
191 |
-
$_POST['dbname'] = trim($post_db_name);
|
192 |
-
} else {
|
193 |
-
$_POST['dbname'] = null;
|
194 |
-
}
|
195 |
-
|
196 |
-
if (isset($_POST['dbcharset'])) {
|
197 |
-
$post_db_charset = DUPX_U::sanitize_text_field($_POST['dbcharset']);
|
198 |
-
$_POST['dbcharset'] = trim($post_db_charset);
|
199 |
-
} else {
|
200 |
-
$_POST['dbcharset'] = $GLOBALS['DBCHARSET_DEFAULT'];
|
201 |
-
}
|
202 |
-
|
203 |
-
if (isset($_POST['dbcollate'])) {
|
204 |
-
$post_db_collate = DUPX_U::sanitize_text_field($_POST['dbcollate']);
|
205 |
-
$_POST['dbcollate'] = trim($post_db_collate);
|
206 |
-
} else {
|
207 |
-
$_POST['dbcollate'] = $GLOBALS['DBCOLLATE_DEFAULT'];
|
208 |
-
}
|
209 |
-
|
210 |
-
//GLOBALS
|
211 |
-
// Constants which are dependent on the $GLOBALS['DUPX_AC']
|
212 |
-
$GLOBALS['SQL_FILE_NAME'] = "dup-installer-data__{$GLOBALS['PACKAGE_HASH']}.sql";
|
213 |
-
$GLOBALS['LOG_FILE_NAME'] = "dup-installer-log__{$GLOBALS['PACKAGE_HASH']}.txt";
|
214 |
-
$GLOBALS['LOGGING'] = isset($_POST['logging']) ? DUPX_U::sanitize_text_field($_POST['logging']) : 1;
|
215 |
-
$GLOBALS['CURRENT_ROOT_PATH'] = dirname(__FILE__);
|
216 |
-
$GLOBALS['CHOWN_ROOT_PATH'] = @chmod("{$GLOBALS['CURRENT_ROOT_PATH']}", 0755);
|
217 |
-
$GLOBALS['CHOWN_LOG_PATH'] = @chmod("{$GLOBALS['CURRENT_ROOT_PATH']}/{$GLOBALS['LOG_FILE_NAME']}", 0644);
|
218 |
-
$GLOBALS['URL_SSL'] = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? true : false;
|
219 |
-
$GLOBALS['URL_PATH'] = ($GLOBALS['URL_SSL']) ? "https://{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}" : "http://{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}";
|
220 |
-
$GLOBALS['PHP_MEMORY_LIMIT'] = ini_get('memory_limit') === false ? 'n/a' : ini_get('memory_limit');
|
221 |
-
$GLOBALS['PHP_SUHOSIN_ON'] = extension_loaded('suhosin') ? 'enabled' : 'disabled';
|
222 |
-
$GLOBALS['ARCHIVE_PATH'] = $GLOBALS['CURRENT_ROOT_PATH'] . '/' . $GLOBALS['FW_PACKAGE_NAME'];
|
223 |
-
$GLOBALS['ARCHIVE_PATH'] = str_replace("\\", "/", $GLOBALS['ARCHIVE_PATH']);
|
224 |
-
if (isset($_GET["view"])) {
|
225 |
-
$GLOBALS["VIEW"] = $_GET["view"];
|
226 |
-
} elseif (!empty($_POST["view"])) {
|
227 |
-
$GLOBALS["VIEW"] = $_POST["view"];
|
228 |
-
} else {
|
229 |
-
$GLOBALS["VIEW"] = 'step1';
|
230 |
-
}
|
231 |
-
|
232 |
-
//Restart log if user starts from step 1
|
233 |
-
if ($_POST['action_step'] == 1 && ! isset($_GET['help'])) {
|
234 |
-
$GLOBALS['LOG_FILE_HANDLE'] = @fopen($GLOBALS['LOG_FILE_NAME'], "w+");
|
235 |
-
} else {
|
236 |
-
$GLOBALS['LOG_FILE_HANDLE'] = @fopen($GLOBALS['LOG_FILE_NAME'], "a+");
|
237 |
-
}
|
238 |
-
?>
|
239 |
-
@@CLASS.U.PHP@@
|
240 |
-
@@CLASS.CSRF.PHP@@
|
241 |
-
@@CLASS.SERVER.PHP@@
|
242 |
-
@@CLASS.DB.PHP@@
|
243 |
-
@@CLASS.LOGGING.PHP@@
|
244 |
-
@@CLASS.ENGINE.PHP@@
|
245 |
-
@@CLASS.CONF.WP.PHP@@
|
246 |
-
@@CLASS.CONF.SRV.PHP@@
|
247 |
-
@@CLASS.HTTP.PHP@@
|
248 |
-
@@CLASS.PASSWORD.PHP@@
|
249 |
-
<?php
|
250 |
-
// CSRF checking
|
251 |
-
if (!empty($GLOBAL['view'])) {
|
252 |
-
$csrf_views = array(
|
253 |
-
'secure',
|
254 |
-
'step1',
|
255 |
-
'step2',
|
256 |
-
'step3',
|
257 |
-
'step4',
|
258 |
-
);
|
259 |
-
if (in_array($GLOBAL['view'], $csrf_views)) {
|
260 |
-
if (!DUPX_CSRF::check($_POST['csrf_token'], $GLOBAL['view'])) {
|
261 |
-
die('CSRF security issue for the view: '.$GLOBAL['view']);
|
262 |
-
}
|
263 |
-
}
|
264 |
-
}
|
265 |
-
|
266 |
-
if (isset($_POST['action_ajax'])) :
|
267 |
-
|
268 |
-
if ($GLOBALS['FW_SECUREON']) {
|
269 |
-
$pass_hasher = new DUPX_PasswordHash(8, FALSE);
|
270 |
-
$pass_check = $pass_hasher->CheckPassword(base64_encode($_POST['secure-pass']), $GLOBALS['FW_SECUREPASS']);
|
271 |
-
if (! $pass_check) {
|
272 |
-
die("Unauthorized Access: Please provide a password!");
|
273 |
-
}
|
274 |
-
}
|
275 |
-
|
276 |
-
//Alternative control switch structer will not work in this case
|
277 |
-
//see: http://php.net/manual/en/control-structures.alternative-syntax.php
|
278 |
-
//Some clients will create double spaces such as the FTP client which
|
279 |
-
//will break example found online
|
280 |
-
switch ($_POST['action_ajax']) :
|
281 |
-
|
282 |
-
case "1": ?>@@CTRL.STEP1.PHP@@<?php break;
|
283 |
-
|
284 |
-
case "2": ?>@@CTRL.STEP2.PHP@@<?php break;
|
285 |
-
|
286 |
-
case "3": ?>@@CTRL.STEP3.PHP@@<?php break;
|
287 |
-
|
288 |
-
endswitch;
|
289 |
-
|
290 |
-
@fclose($GLOBALS["LOG_FILE_HANDLE"]);
|
291 |
-
die("");
|
292 |
-
|
293 |
-
endif;
|
294 |
-
?>
|
295 |
-
|
296 |
-
<!DOCTYPE html>
|
297 |
-
<html>
|
298 |
-
<head>
|
299 |
-
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
300 |
-
<meta name="robots" content="noindex,nofollow">
|
301 |
-
<title>Duplicator</title>
|
302 |
-
@@INC.LIBS.CSS.PHP@@
|
303 |
-
@@INC.CSS.PHP@@
|
304 |
-
@@INC.LIBS.JS.PHP@@
|
305 |
-
@@INC.JS.PHP@@
|
306 |
-
</head>
|
307 |
-
<body>
|
308 |
-
|
309 |
-
<div id="content">
|
310 |
-
<!-- =========================================
|
311 |
-
HEADER TEMPLATE: Common header on all steps -->
|
312 |
-
<table cellspacing="0" class="dupx-header">
|
313 |
-
<tr>
|
314 |
-
<td style="width:100%;">
|
315 |
-
<div style="font-size:26px; padding:7px 0 7px 0">
|
316 |
-
<!-- !!DO NOT CHANGE/EDIT OR REMOVE PRODUCT NAME!!
|
317 |
-
If your interested in Private Label Rights please contact us at the URL below to discuss
|
318 |
-
customizations to product labeling: http://snapcreek.com -->
|
319 |
-
Duplicator
|
320 |
-
</div>
|
321 |
-
</td>
|
322 |
-
<td class="dupx-header-version">
|
323 |
-
<a href="javascript:void(0)" onclick="DUPX.showServerInfo()">version: <?php echo DUPX_U::esc_html($GLOBALS['FW_DUPLICATOR_VERSION']); ?></a><br/>
|
324 |
-
<a href="?help=1" target="_blank">help</a>
|
325 |
-
<?php
|
326 |
-
echo ' » <a href="?help=1#secure" target="_blank">';
|
327 |
-
echo ($GLOBALS['FW_SECUREON']) ? 'locked</a>' : '<i class="secure-unlocked">unlocked</i></a>';
|
328 |
-
?>
|
329 |
-
</td>
|
330 |
-
</tr>
|
331 |
-
</table>
|
332 |
-
|
333 |
-
<div style="position: relative">
|
334 |
-
<div class="installer-mode">
|
335 |
-
<?php
|
336 |
-
echo 'Mode: ';
|
337 |
-
echo ($GLOBALS['FW_ARCHIVE_ONLYDB']) ? 'Database Only' : 'Standard';
|
338 |
-
?>
|
339 |
-
</div>
|
340 |
-
</div>
|
341 |
-
|
342 |
-
<!-- =========================================
|
343 |
-
FORM DATA: Data Steps -->
|
344 |
-
<div id="content-inner">
|
345 |
-
<?php
|
346 |
-
|
347 |
-
if (! isset($_GET['help'])) {
|
348 |
-
switch ($_POST['action_step']) {
|
349 |
-
case "0" :
|
350 |
-
?> @@VIEW.INIT1.PHP@@ <?php
|
351 |
-
break;
|
352 |
-
case "1" :
|
353 |
-
?> @@VIEW.STEP1.PHP@@ <?php
|
354 |
-
break;
|
355 |
-
case "2" :
|
356 |
-
?> @@VIEW.STEP2.PHP@@ <?php
|
357 |
-
break;
|
358 |
-
case "3" :
|
359 |
-
?> @@VIEW.STEP3.PHP@@ <?php
|
360 |
-
break;
|
361 |
-
case "4" :
|
362 |
-
?> @@VIEW.STEP4.PHP@@ <?php
|
363 |
-
break;
|
364 |
-
}
|
365 |
-
} else {
|
366 |
-
?> @@VIEW.HELP.PHP@@ <?php
|
367 |
-
}
|
368 |
-
|
369 |
-
?>
|
370 |
-
</div>
|
371 |
-
</div><br/>
|
372 |
-
|
373 |
-
|
374 |
-
<!-- CONFIRM DIALOG -->
|
375 |
-
<div id="dialog-server-info" style="display:none">
|
376 |
-
<!-- DETAILS -->
|
377 |
-
<div class="dlg-serv-info">
|
378 |
-
<?php
|
379 |
-
$ini_path = php_ini_loaded_file();
|
380 |
-
$ini_max_time = ini_get('max_execution_time');
|
381 |
-
$ini_memory = ini_get('memory_limit');
|
382 |
-
?>
|
383 |
-
<div class="hdr">Current Server</div>
|
384 |
-
<label>Web Server:</label> <?php echo DUPX_U::esc_html($_SERVER['SERVER_SOFTWARE']); ?><br/>
|
385 |
-
<label>Operating System:</label> <?php echo DUPX_U::esc_html(PHP_OS); ?><br/>
|
386 |
-
<label>PHP Version:</label> <?php echo DUPX_U::esc_html(DUPX_Server::$php_version); ?><br/>
|
387 |
-
<label>PHP INI Path:</label> <?php echo empty($ini_path ) ? 'Unable to detect loaded php.ini file' : $ini_path; ?> <br/>
|
388 |
-
<label>PHP SAPI:</label> <?php echo DUPX_U::esc_html(php_sapi_name()); ?><br/>
|
389 |
-
<label>PHP ZIP Archive:</label> <?php echo class_exists('ZipArchive') ? 'Is Installed' : 'Not Installed'; ?> <br/>
|
390 |
-
<label>PHP max_execution_time:</label> <?php echo $ini_max_time === false ? 'unable to find' : DUPX_U::esc_html($ini_max_time); ?><br/>
|
391 |
-
<label>PHP memory_limit:</label> <?php echo empty($ini_memory) ? 'unable to find' : DUPX_U::esc_html($ini_memory); ?><br/>
|
392 |
-
|
393 |
-
<br/>
|
394 |
-
<div class="hdr">Package Server</div>
|
395 |
-
<div class="info-txt">The server where the package was created</div>
|
396 |
-
<label>Plugin Version:</label> <?php echo DUPX_U::esc_html($GLOBALS['FW_VERSION_DUP']); ?><br/>
|
397 |
-
<label>WordPress Version:</label> <?php echo DUPX_U::esc_html($GLOBALS['FW_VERSION_WP']); ?><br/>
|
398 |
-
<label>PHP Version:</label> <?php echo DUPX_U::esc_html($GLOBALS['FW_VERSION_PHP']); ?><br/>
|
399 |
-
<label>Database Version:</label> <?php echo DUPX_U::esc_html($GLOBALS['FW_VERSION_DB']); ?><br/>
|
400 |
-
<label>Operating System:</label> <?php echo DUPX_U::esc_html($GLOBALS['FW_VERSION_OS']); ?><br/>
|
401 |
-
<br/><br/>
|
402 |
-
</div>
|
403 |
-
</div>
|
404 |
-
|
405 |
-
<script>
|
406 |
-
/* Server Info Dialog*/
|
407 |
-
DUPX.showServerInfo = function()
|
408 |
-
{
|
409 |
-
modal({
|
410 |
-
type: 'alert',
|
411 |
-
title: 'Server Information',
|
412 |
-
text: $('#dialog-server-info').html()
|
413 |
-
});
|
414 |
-
}
|
415 |
-
</script>
|
416 |
-
|
417 |
-
</body>
|
418 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/build/view.step1.php
DELETED
@@ -1,798 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
defined("DUPXABSPATH") or die("");
|
3 |
-
//VIEW: STEP 1- INPUT
|
4 |
-
|
5 |
-
//ARCHIVE FILE
|
6 |
-
$arcStatus = (file_exists($GLOBALS['ARCHIVE_PATH'])) ? 'Pass' : 'Fail';
|
7 |
-
$arcFormat = ($arcStatus == 'Pass') ? 'Pass' : 'StatusFailed';
|
8 |
-
$arcSize = @filesize($GLOBALS['ARCHIVE_PATH']);
|
9 |
-
$arcSize = is_numeric($arcSize) ? $arcSize : 0;
|
10 |
-
$zip_archive_enabled = class_exists('ZipArchive') ? 'Enabled' : 'Not Enabled';
|
11 |
-
|
12 |
-
$arcSizeRatio = (((1.0) * $arcSize) / $GLOBALS['FW_PACKAGE_EST_SIZE']) * 100;
|
13 |
-
$arcSizeStatus = ($arcSizeRatio > 90) ? 'Pass' : 'Fail';
|
14 |
-
|
15 |
-
//ARCHIVE FORMAT
|
16 |
-
if ($arcStatus) {
|
17 |
-
if (class_exists('ZipArchive')){
|
18 |
-
$zip = new ZipArchive();
|
19 |
-
if($zip->open($GLOBALS['ARCHIVE_PATH']) === TRUE ) {
|
20 |
-
|
21 |
-
$arcFilePath = basename($GLOBALS['ARCHIVE_PATH']);
|
22 |
-
$arcFilePath = substr($arcFilePath, 0, strrpos($arcFilePath, "."));
|
23 |
-
//Some systems the __MACOSX folder can cause issues on others it works fine removing
|
24 |
-
//until further reports are discovered, removed on 04-06-2018
|
25 |
-
//$badFiles = array('__MACOSX', $arcFilePath);
|
26 |
-
$badFiles = array('', $arcFilePath);
|
27 |
-
$goodFiles = array("dup-database__{$GLOBALS['PACKAGE_HASH']}.sql", 'installer-backup.php');
|
28 |
-
$goodFilesFound = true;
|
29 |
-
$badFilesFound = false;
|
30 |
-
|
31 |
-
foreach ($badFiles as $val) {
|
32 |
-
if (is_numeric($zip->locateName("{$val}/"))) {
|
33 |
-
$badFilesFound = true;
|
34 |
-
break;
|
35 |
-
}
|
36 |
-
}
|
37 |
-
|
38 |
-
foreach ($goodFiles as $val) {
|
39 |
-
if ($zip->locateName($val) !== true) {
|
40 |
-
$goodFilesFound = false;
|
41 |
-
}
|
42 |
-
}
|
43 |
-
|
44 |
-
$arcFormat = ($goodFilesFound == false && $badFilesFound == true) ? 'Fail' : 'Pass';
|
45 |
-
}
|
46 |
-
} else {
|
47 |
-
$arcFormat = 'NoZipArchive';
|
48 |
-
}
|
49 |
-
}
|
50 |
-
|
51 |
-
$all_arc = ($arcStatus == 'Pass' && $arcFormat != 'Fail' && $arcSizeStatus == 'Pass') ? 'Pass' : 'Fail';
|
52 |
-
|
53 |
-
//REQUIRMENTS
|
54 |
-
$req = array();
|
55 |
-
$req['01'] = DUPX_Server::isDirWritable($GLOBALS["CURRENT_ROOT_PATH"]) ? 'Pass' : 'Fail';
|
56 |
-
$req['02'] = 'Pass'; //Place-holder for future check
|
57 |
-
$req['03'] = 'Pass'; //Place-holder for future check;
|
58 |
-
$req['04'] = function_exists('mysqli_connect') ? 'Pass' : 'Fail';
|
59 |
-
$req['05'] = DUPX_Server::$php_version_safe ? 'Pass' : 'Fail';
|
60 |
-
$all_req = in_array('Fail', $req) ? 'Fail' : 'Pass';
|
61 |
-
|
62 |
-
//NOTICES
|
63 |
-
$openbase = ini_get("open_basedir");
|
64 |
-
$scanfiles = @scandir($GLOBALS["CURRENT_ROOT_PATH"]);
|
65 |
-
$scancount = is_array($scanfiles) ? (count($scanfiles)) : -1;
|
66 |
-
$datetime1 = $GLOBALS['FW_CREATED'];
|
67 |
-
$datetime2 = date("Y-m-d H:i:s");
|
68 |
-
$fulldays = round(abs(strtotime($datetime1) - strtotime($datetime2))/86400);
|
69 |
-
$root_path = DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']);
|
70 |
-
$wpconf_path = "{$root_path}/wp-config.php";
|
71 |
-
$max_time_zero = @set_time_limit(0);
|
72 |
-
$max_time_size = 314572800; //300MB
|
73 |
-
$max_time_ini = ini_get('max_execution_time');
|
74 |
-
$max_time_warn = (is_numeric($max_time_ini) && $max_time_ini < 31 && $max_time_ini > 0) && $arcSize > $max_time_size;
|
75 |
-
|
76 |
-
|
77 |
-
$notice = array();
|
78 |
-
if (!$GLOBALS['FW_ARCHIVE_ONLYDB']) {
|
79 |
-
$notice['01'] = ! file_exists($wpconf_path) ? 'Good' : 'Warn';
|
80 |
-
$notice['02'] = $scancount <= 35 ? 'Good' : 'Warn';
|
81 |
-
}
|
82 |
-
$notice['03'] = $fulldays <= 120 ? 'Good' : 'Warn';
|
83 |
-
$notice['04'] = 'Good'; //Place-holder for future check
|
84 |
-
$notice['05'] = DUPX_Server::$php_version_53_plus ? 'Good' : 'Warn';
|
85 |
-
$notice['06'] = empty($openbase) ? 'Good' : 'Warn';
|
86 |
-
$notice['07'] = ! $max_time_warn ? 'Good' : 'Warn';
|
87 |
-
$all_notice = in_array('Warn', $notice) ? 'Warn' : 'Good';
|
88 |
-
|
89 |
-
//SUMMATION
|
90 |
-
$req_success = ($all_req == 'Pass');
|
91 |
-
$req_notice = ($all_notice == 'Good');
|
92 |
-
$all_success = ($req_success && $req_notice);
|
93 |
-
$agree_msg = "To enable this button the checkbox above under the 'Terms & Notices' must be checked.";
|
94 |
-
|
95 |
-
//Get Size Data
|
96 |
-
$projectedSize = DUPX_U::readableByteSize($GLOBALS['FW_PACKAGE_EST_SIZE']);
|
97 |
-
$actualSize = DUPX_U::readableByteSize($arcSize);
|
98 |
-
?>
|
99 |
-
|
100 |
-
|
101 |
-
<form id='s1-input-form' method="post" class="content-form" >
|
102 |
-
<input type="hidden" name="action_ajax" value="1" />
|
103 |
-
<input type="hidden" name="action_step" value="1" />
|
104 |
-
<input type="hidden" name="secure-pass" value="<?php echo DUPX_U::esc_attr($_POST['secure-pass']); ?>" />
|
105 |
-
|
106 |
-
<div class="hdr-main">
|
107 |
-
Step <span class="step">1</span> of 4: Deployment
|
108 |
-
</div>
|
109 |
-
<br/>
|
110 |
-
|
111 |
-
|
112 |
-
<!-- ====================================
|
113 |
-
ARCHIVE
|
114 |
-
==================================== -->
|
115 |
-
<div class="hdr-sub1" id="s1-area-archive-file-link" data-type="toggle" data-target="#s1-area-archive-file">
|
116 |
-
<a href="javascript:void(0)"><i class="dupx-plus-square"></i> Archive</a>
|
117 |
-
<div class="<?php echo ($all_arc == 'Pass') ? 'status-badge-pass' : 'status-badge-fail'; ?>" style="float:right">
|
118 |
-
<?php echo ($all_arc == 'Pass') ? 'Pass' : 'Fail'; ?>
|
119 |
-
</div>
|
120 |
-
</div>
|
121 |
-
<div id="s1-area-archive-file" style="display:none">
|
122 |
-
|
123 |
-
<table class="s1-archive-local">
|
124 |
-
<tr>
|
125 |
-
<td colspan="2"><div class="hdr-sub3">Site Details</div></td>
|
126 |
-
</tr>
|
127 |
-
<tr>
|
128 |
-
<td>Site:</td>
|
129 |
-
<td><?php echo DUPX_U::esc_html($GLOBALS['FW_BLOGNAME']);?> </td>
|
130 |
-
</tr>
|
131 |
-
<tr>
|
132 |
-
<td>Notes:</td>
|
133 |
-
<td><?php echo strlen($GLOBALS['FW_PACKAGE_NOTES']) ? DUPX_U::esc_html($GLOBALS['FW_PACKAGE_NOTES']) : " - no notes - ";?></td>
|
134 |
-
</tr>
|
135 |
-
<?php if ($GLOBALS['FW_ARCHIVE_ONLYDB']) :?>
|
136 |
-
<tr>
|
137 |
-
<td>Mode:</td>
|
138 |
-
<td>Archive only database was enabled during package package creation.</td>
|
139 |
-
</tr>
|
140 |
-
<?php endif; ?>
|
141 |
-
</table>
|
142 |
-
|
143 |
-
<table class="s1-archive-local">
|
144 |
-
<tr>
|
145 |
-
<td colspan="2"><div class="hdr-sub3">File Details</div></td>
|
146 |
-
</tr>
|
147 |
-
<tr>
|
148 |
-
<td>Status:</td>
|
149 |
-
<td>
|
150 |
-
<?php if ($arcStatus != 'Fail') : ?>
|
151 |
-
<span class="dupx-pass">Archive File Found</span>
|
152 |
-
<?php else : ?>
|
153 |
-
<div class="s1-archive-failed-msg">
|
154 |
-
<b class="dupx-fail">Archive File Not Found!</b><br/>
|
155 |
-
The installer file and the archive are bound together as a package when the archive is built. They must be downloaded together and used
|
156 |
-
together at install time. The archive file name should <u>not</u> be changed when it is downloaded because the file name is strongly bound
|
157 |
-
to the installer. When downloading the package files make sure both files are from the same package line in the packages view within the
|
158 |
-
Duplicator WordPress admin.
|
159 |
-
<br/><br/>
|
160 |
-
|
161 |
-
The full archive file name must be <u>exactly</u> the same as when it was built (character for character), or the installer will not work properly.
|
162 |
-
To find out the exact archive name that is bound to this installer open the installer.php file with a text editor and search for the text
|
163 |
-
$GLOBALS['FW_PACKAGE_NAME']. Check to see what that value is assigned to and that should be the name of the archive file placed in the same path
|
164 |
-
as this installer.
|
165 |
-
<br/><br/>
|
166 |
-
|
167 |
-
The following zip files were found at the deployment path:
|
168 |
-
<?php
|
169 |
-
//DETECT ARCHIVE FILES
|
170 |
-
$zip_files = DUPX_Server::getZipFiles();
|
171 |
-
$zip_count = count($zip_files);
|
172 |
-
|
173 |
-
if ($zip_count >= 1) {
|
174 |
-
echo "<ol style='padding:10px 20px 0 20px; font-style:italic'>";
|
175 |
-
foreach($zip_files as $file) {
|
176 |
-
echo "<li> '{$file}'</li>";
|
177 |
-
}
|
178 |
-
echo "</ol>";
|
179 |
-
} else {
|
180 |
-
echo "<br/><br/> <i>- No zip files found -</i>";
|
181 |
-
}
|
182 |
-
?>
|
183 |
-
</div>
|
184 |
-
<?php endif; ?>
|
185 |
-
</td>
|
186 |
-
</tr>
|
187 |
-
<tr>
|
188 |
-
<tr>
|
189 |
-
<td>Path:</td>
|
190 |
-
<td><?php echo "{$GLOBALS['CURRENT_ROOT_PATH']}";?> </td>
|
191 |
-
</tr>
|
192 |
-
<td>Size:</td>
|
193 |
-
<td>
|
194 |
-
<?php if ($arcSizeStatus == 'Pass' ) : ?>
|
195 |
-
<?php echo "{$actualSize}"?>
|
196 |
-
<?php elseif ($arcStatus == 'Fail') : ?>
|
197 |
-
<span class="dupx-fail">Archive file not found!</span>
|
198 |
-
<?php else : ?>
|
199 |
-
<div class="s1-archive-failed-msg">
|
200 |
-
<b class='dupx-fail'>Archive File Size Incorrect!</b><br/>
|
201 |
-
The archive is showing a size that is currently as <b><?php echo DUPX_U::esc_html($actualSize); ?></b>. Its estimated file size should be around
|
202 |
-
<b><?php echo DUPX_U::esc_html($projectedSize); ?></b>. The archive file may not have been fully downloaded to the server. If so please wait for the file
|
203 |
-
to completely download and then refresh this page.<br/><br/>
|
204 |
-
|
205 |
-
This warning is only shown when the file has more than a 10% size ratio difference from when it was originally built. Please review the file sizes
|
206 |
-
to make sure the archive was downloaded to this server correctly when the download is complete.
|
207 |
-
</div>
|
208 |
-
<?php endif; ?>
|
209 |
-
</td>
|
210 |
-
</tr>
|
211 |
-
<tr>
|
212 |
-
<td>Format:</td>
|
213 |
-
<td>
|
214 |
-
<?php if ($arcFormat == 'Pass') : ?>
|
215 |
-
<span class="dupx-pass">Good structure</span>
|
216 |
-
<?php elseif ($arcFormat == 'StatusFailed') : ?>
|
217 |
-
<span class="dupx-fail">Unable to validate format</span><br/>
|
218 |
-
<?php elseif ($arcFormat == 'NoZipArchive') : ?>
|
219 |
-
<div class="s1-archive-failed-msg">
|
220 |
-
The PHP extraction library <a href="http://php.net/manual/en/book.zip.php" target="_help">ZipArchive</a> was not found on this server. There are a few options:
|
221 |
-
<ol>
|
222 |
-
<li>Contact your host to enable the this PHP library. <a href="http://php.net/manual/en/zip.installation.php" target="_help">[more info]</a></li>
|
223 |
-
<li>Enable 'Manual package extraction' in the options menu and <a href="https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-015-q" target="_help">Manually extract the archive</a></li>
|
224 |
-
</ol>
|
225 |
-
</div>
|
226 |
-
<?php else : ?>
|
227 |
-
<div class="s1-archive-failed-msg">
|
228 |
-
<b class="dupx-fail">Invalid Archive Format Detected!</b><br/>
|
229 |
-
The archive files contents must be laid out in a specific format. If the format has been changed the install process will error out.
|
230 |
-
<br/><br/>
|
231 |
-
|
232 |
-
This scenario is rare but can happen on some systems during the download and upload process of the zip without a user being aware of
|
233 |
-
the issue. Please check the contents of the zip archive and be sure its contents match the layout of your site.
|
234 |
-
<br/><br/>
|
235 |
-
|
236 |
-
Files such as dup-database_[HASH].sql and wp-config.php should be at the root of the archive. For more details see the FAQ article
|
237 |
-
<a href="https://snapcreek.com/duplicator/docs/faqs-tech/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=invalid_ar_fmt#faq-installer-020-q" target="_help">The archive format is changing on my Mac what might be the problem?</a>
|
238 |
-
</div>
|
239 |
-
<?php endif; ?>
|
240 |
-
</td>
|
241 |
-
</tr>
|
242 |
-
</table>
|
243 |
-
|
244 |
-
</div>
|
245 |
-
<br/><br/>
|
246 |
-
|
247 |
-
|
248 |
-
<!-- ====================================
|
249 |
-
VALIDATION
|
250 |
-
==================================== -->
|
251 |
-
<div class="hdr-sub1" id="s1-area-sys-setup-link" data-type="toggle" data-target="#s1-area-sys-setup">
|
252 |
-
<a href="javascript:void(0)"><i class="dupx-plus-square"></i> Validation</a>
|
253 |
-
<div class="<?php echo ($req_success) ? 'status-badge-pass' : 'status-badge-fail'; ?>" style="float:right">
|
254 |
-
<?php echo ($req_success) ? 'Pass' : 'Fail'; ?>
|
255 |
-
</div>
|
256 |
-
</div>
|
257 |
-
<div id="s1-area-sys-setup" style="display:none">
|
258 |
-
<div class='info-top'>The system validation checks help to make sure the system is ready for install.</div>
|
259 |
-
|
260 |
-
<!-- *** REQUIREMENTS *** -->
|
261 |
-
<div class="s1-reqs" id="s1-reqs-all">
|
262 |
-
<div class="header">
|
263 |
-
<table class="s1-checks-area">
|
264 |
-
<tr>
|
265 |
-
<td class="title">Requirements <small>(must pass)</small></td>
|
266 |
-
<td class="toggle"><a href="javascript:void(0)" onclick="DUPX.toggleAll('#s1-reqs-all')">[toggle]</a></td>
|
267 |
-
</tr>
|
268 |
-
</table>
|
269 |
-
</div>
|
270 |
-
|
271 |
-
<!-- REQ 1 -->
|
272 |
-
<?php
|
273 |
-
$status_1 = strtolower($req['01']);
|
274 |
-
?>
|
275 |
-
<div class="status <?php echo DUPX_U::esc_html($status_1); ?>"><?php echo DUPX_U::esc_html($req['01']); ?></div>
|
276 |
-
<div class="title" data-type="toggle" data-target="#s1-reqs01">+ Permissions</div>
|
277 |
-
<div class="info" id="s1-reqs01">
|
278 |
-
<table>
|
279 |
-
<tr>
|
280 |
-
<td><b>Deployment Path:</b> </td>
|
281 |
-
<td><i><?php echo "{$GLOBALS['CURRENT_ROOT_PATH']}"; ?></i> </td>
|
282 |
-
</tr>
|
283 |
-
<tr>
|
284 |
-
<td><b>Suhosin Extension:</b> </td>
|
285 |
-
<td><?php echo extension_loaded('suhosin') ? "<i class='dupx-fail'>Enabled</i>" : "<i class='dupx-pass'>Disabled</i>"; ?> </td>
|
286 |
-
</tr>
|
287 |
-
<tr>
|
288 |
-
<td><b>PHP Safe Mode:</b> </td>
|
289 |
-
<td><?php echo (DUPX_Server::$php_safe_mode_on) ? "<i class='dupx-fail'>Enabled</i>" : "<i class='dupx-pass'>Disabled</i>"; ?> </td>
|
290 |
-
</tr>
|
291 |
-
</table><br/>
|
292 |
-
|
293 |
-
The deployment path above must be writable by PHP in order to extract the archive file. Incorrect permissions and extension such as
|
294 |
-
<a href="https://suhosin.org/stories/index.html" target="_blank">suhosin</a> can sometimes interfere with PHP being able to write/extract files.
|
295 |
-
Please see the <a href="https://snapcreek.com/duplicator/docs/faqs-tech/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=installer_perms#faq-trouble-055-q" target="_blank">FAQ permission</a> help link for complete details.
|
296 |
-
PHP with <a href='http://php.net/manual/en/features.safe-mode.php' target='_blank'>safe mode</a> should be disabled. If this test fails
|
297 |
-
please contact your hosting provider or server administrator to disable PHP safe mode.
|
298 |
-
</div>
|
299 |
-
|
300 |
-
<!-- REQ 2
|
301 |
-
<div class="status <?php echo strtolower($req['02']); ?>"><?php echo DUPX_U::esc_html($req['02']); ?></div>
|
302 |
-
<div class="title" data-type="toggle" data-target="#s1-reqs02">+ Place Holder</div>
|
303 |
-
<div class="info" id="s1-reqs02"></div>-->
|
304 |
-
|
305 |
-
<!-- REQ 3
|
306 |
-
<div class="status <?php echo strtolower($req['03']); ?>"><?php echo DUPX_U::esc_html($req['03']); ?></div>
|
307 |
-
<div class="title" data-type="toggle" data-target="#s1-reqs03">+ Place Holder</div>
|
308 |
-
<div class="info" id="s1-reqs03"></div> -->
|
309 |
-
|
310 |
-
<!-- REQ 4 -->
|
311 |
-
<?php
|
312 |
-
$status_4 = strtolower($req['04']);
|
313 |
-
?>
|
314 |
-
<div class="status <?php echo DUPX_U::esc_html($status_4); ?>"><?php echo DUPX_U::esc_html($req['04']); ?></div>
|
315 |
-
<div class="title" data-type="toggle" data-target="#s1-reqs04">+ PHP Mysqli</div>
|
316 |
-
<div class="info" id="s1-reqs04">
|
317 |
-
Support for the PHP <a href='http://us2.php.net/manual/en/mysqli.installation.php' target='_blank'>mysqli extension</a> is required.
|
318 |
-
Please contact your hosting provider or server administrator to enable the mysqli extension. <i>The detection for this call uses
|
319 |
-
the function_exists('mysqli_connect') call.</i>
|
320 |
-
</div>
|
321 |
-
|
322 |
-
<!-- REQ 5 -->
|
323 |
-
<?php
|
324 |
-
$status_5 = strtolower($req['05']);
|
325 |
-
?>
|
326 |
-
<div class="status <?php echo DUPX_U::esc_html($status_5); ?>"><?php echo DUPX_U::esc_html($req['05']); ?></div>
|
327 |
-
<div class="title" data-type="toggle" data-target="#s1-reqs05">+ PHP Min Version</div>
|
328 |
-
<div class="info" id="s1-reqs05">
|
329 |
-
This server is running PHP: <b><?php echo DUPX_Server::$php_version ?></b>. <i>A minimum of PHP 5.2.17 is required</i>.
|
330 |
-
Contact your hosting provider or server administrator and let them know you would like to upgrade your PHP version.
|
331 |
-
</div>
|
332 |
-
</div><br/>
|
333 |
-
|
334 |
-
|
335 |
-
<!-- *** NOTICES *** -->
|
336 |
-
<div class="s1-reqs" id="s1-notice-all">
|
337 |
-
<div class="header">
|
338 |
-
<table class="s1-checks-area">
|
339 |
-
<tr>
|
340 |
-
<td class="title">Notices <small>(optional)</small></td>
|
341 |
-
<td class="toggle"><a href="javascript:void(0)" onclick="DUPX.toggleAll('#s1-notice-all')">[toggle]</a></td>
|
342 |
-
</tr>
|
343 |
-
</table>
|
344 |
-
</div>
|
345 |
-
|
346 |
-
<?php if (!$GLOBALS['FW_ARCHIVE_ONLYDB']) :?>
|
347 |
-
|
348 |
-
<!-- NOTICE 1 -->
|
349 |
-
<div class="status <?php echo ($notice['01'] == 'Good') ? 'pass' : 'fail' ?>"><?php echo DUPX_U::esc_html($notice['01']); ?></div>
|
350 |
-
<div class="title" data-type="toggle" data-target="#s1-notice01">+ Configuration File</div>
|
351 |
-
<div class="info" id="s1-notice01">
|
352 |
-
Duplicator works best by placing the installer and archive files into an empty directory. If a wp-config.php file is found in the extraction
|
353 |
-
directory it might indicate that a pre-existing WordPress site exists which can lead to a bad install.
|
354 |
-
<br/><br/>
|
355 |
-
<b>Options:</b>
|
356 |
-
<ul style="margin-bottom: 0">
|
357 |
-
<li>If the archive was already manually extracted then <a href="javascript:void(0)" onclick="DUPX.getManaualArchiveOpt()">[Enable Manual Archive Extraction]</a></li>
|
358 |
-
<li>If the wp-config file is not needed then remove it.</li>
|
359 |
-
</ul>
|
360 |
-
</div>
|
361 |
-
|
362 |
-
<!-- NOTICE 2 -->
|
363 |
-
<div class="status <?php echo ($notice['02'] == 'Good') ? 'pass' : 'fail' ?>"><?php echo DUPX_U::esc_html($notice['02']); ?></div>
|
364 |
-
<div class="title" data-type="toggle" data-target="#s1-notice02">+ Directory Setup</div>
|
365 |
-
<div class="info" id="s1-notice02">
|
366 |
-
<b>Deployment Path:</b> <i><?php echo DUPX_U::esc_html($GLOBALS['CURRENT_ROOT_PATH']); ?></i>
|
367 |
-
<br/><br/>
|
368 |
-
There are currently <?php echo "<b>[{$scancount}]</b>";?> items in the deployment path. These items will be overwritten if they also exist
|
369 |
-
inside the archive file. The notice is to prevent overwriting an existing site or trying to install on-top of one which
|
370 |
-
can have un-intended results. <i>This notice shows if it detects more than 40 items.</i>
|
371 |
-
|
372 |
-
<br/><br/>
|
373 |
-
<b>Options:</b>
|
374 |
-
<ul style="margin-bottom: 0">
|
375 |
-
<li>If the archive was already manually extracted then <a href="javascript:void(0)" onclick="DUPX.getManaualArchiveOpt()">[Enable Manual Archive Extraction]</a></li>
|
376 |
-
<li>If the files/directories are not the same as those in the archive then this notice can be ignored.</li>
|
377 |
-
<li>Remove the files if they are not needed and refresh this page.</li>
|
378 |
-
</ul>
|
379 |
-
</div>
|
380 |
-
|
381 |
-
<?php endif; ?>
|
382 |
-
|
383 |
-
<!-- NOTICE 3 -->
|
384 |
-
<div class="status <?php echo ($notice['03'] == 'Good') ? 'pass' : 'fail' ?>"><?php echo DUPX_U::esc_html($notice['03']); ?></div>
|
385 |
-
<div class="title" data-type="toggle" data-target="#s1-notice03">+ Package Age</div>
|
386 |
-
<div class="info" id="s1-notice03">
|
387 |
-
<?php echo "The package is {$fulldays} day(s) old. Packages older than 120 days might be considered stale. If you are comfortable with a package that that was created over "
|
388 |
-
. "four months ago please ignore this notice."; ?>
|
389 |
-
</div>
|
390 |
-
|
391 |
-
<!-- NOTICE 4
|
392 |
-
<div class="status <?php echo ($notice['04'] == 'Good') ? 'pass' : 'fail' ?>"><?php echo DUPX_U::esc_html($notice['04']); ?></div>
|
393 |
-
<div class="title" data-type="toggle" data-target="#s1-notice04">+ Placeholder</div>
|
394 |
-
<div class="info" id="s1-notice04">
|
395 |
-
</div>-->
|
396 |
-
|
397 |
-
<!-- NOTICE 5 -->
|
398 |
-
<div class="status <?php echo ($notice['05'] == 'Good') ? 'pass' : 'fail' ?>"><?php echo DUPX_U::esc_html($notice['05']); ?></div>
|
399 |
-
<div class="title" data-type="toggle" data-target="#s1-notice05">+ PHP Version 5.2</div>
|
400 |
-
<div class="info" id="s1-notice05">
|
401 |
-
<?php
|
402 |
-
$currentPHP = DUPX_Server::$php_version;
|
403 |
-
$cssStyle = DUPX_Server::$php_version_53_plus ? 'color:green' : 'color:red';
|
404 |
-
echo "<b style='{$cssStyle}'>This server is currently running PHP version [{$currentPHP}]</b>.<br/>"
|
405 |
-
. "Duplicator allows PHP 5.2 to be used during install but does not officially support it. If your using PHP 5.2 we strongly recommend NOT using it and having your "
|
406 |
-
. "host upgrade to a newer more stable, secure and widely supported version. The <a href='http://php.net/eol.php' target='_blank'>end of life for PHP 5.2</a> "
|
407 |
-
. "was in January of 2011 and is not recommended for use.<br/><br/>";
|
408 |
-
|
409 |
-
echo "Many plugin and theme authors are no longer supporting PHP 5.2 and trying to use it can result in site wide problems and compatibility warnings and errors. "
|
410 |
-
. "Please note if you continue with the install using PHP 5.2 the Duplicator support team will not be able to help with issues or troubleshooting your site. "
|
411 |
-
. "If your server is running <b>PHP 5.3+</b> please feel free to reach out for help if you run into issues with your migration/install.";
|
412 |
-
?>
|
413 |
-
</div>
|
414 |
-
|
415 |
-
<!-- NOTICE 6 -->
|
416 |
-
<div class="status <?php echo ($notice['06'] == 'Good') ? 'pass' : 'fail' ?>"><?php echo DUPX_U::esc_html($notice['06']); ?></div>
|
417 |
-
<div class="title" data-type="toggle" data-target="#s1-notice06">+ PHP Open Base</div>
|
418 |
-
<div class="info" id="s1-notice06">
|
419 |
-
<b>Open BaseDir:</b> <i><?php echo $notice['06'] == 'Good' ? "<i class='dupx-pass'>Disabled</i>" : "<i class='dupx-fail'>Enabled</i>"; ?></i>
|
420 |
-
<br/><br/>
|
421 |
-
|
422 |
-
If <a href="http://www.php.net/manual/en/ini.core.php#ini.open-basedir" target="_blank">open_basedir</a> is enabled and you're
|
423 |
-
having issues getting your site to install properly; please work with your host and follow these steps to prevent issues:
|
424 |
-
<ol style="margin:7px; line-height:19px">
|
425 |
-
<li>Disable the open_basedir setting in the php.ini file</li>
|
426 |
-
<li>If the host will not disable, then add the path below to the open_basedir setting in the php.ini<br/>
|
427 |
-
<i style="color:maroon">"<?php echo str_replace('\\', '/', dirname( __FILE__ )); ?>"</i>
|
428 |
-
</li>
|
429 |
-
<li>Save the settings and restart the web server</li>
|
430 |
-
</ol>
|
431 |
-
Note: This warning will still show if you choose option #2 and open_basedir is enabled, but should allow the installer to run properly. Please work with your
|
432 |
-
hosting provider or server administrator to set this up correctly.
|
433 |
-
</div>
|
434 |
-
|
435 |
-
<!-- NOTICE 7 -->
|
436 |
-
<div class="status <?php echo ($notice['07'] == 'Good') ? 'pass' : 'fail' ?>"><?php echo DUPX_U::esc_html($notice['07']); ?></div>
|
437 |
-
<div class="title" data-type="toggle" data-target="#s1-notice07">+ PHP Timeout</div>
|
438 |
-
<div class="info" id="s1-notice07">
|
439 |
-
<b>Archive Size:</b> <?php echo DUPX_U::readableByteSize($arcSize) ?> <small>(detection limit is set at <?php echo DUPX_U::readableByteSize($max_time_size) ?>) </small><br/>
|
440 |
-
<b>PHP max_execution_time:</b> <?php echo "{$max_time_ini}"; ?> <small>(zero means no limit)</small> <br/>
|
441 |
-
<b>PHP set_time_limit:</b> <?php echo ($max_time_zero) ? '<i style="color:green">Success</i>' : '<i style="color:maroon">Failed</i>' ?>
|
442 |
-
<br/><br/>
|
443 |
-
|
444 |
-
The PHP <a href="http://php.net/manual/en/info.configuration.php#ini.max-execution-time" target="_blank">max_execution_time</a> setting is used to
|
445 |
-
determine how long a PHP process is allowed to run. If the setting is too small and the archive file size is too large then PHP may not have enough
|
446 |
-
time to finish running before the process is killed causing a timeout.
|
447 |
-
<br/><br/>
|
448 |
-
|
449 |
-
Duplicator attempts to turn off the timeout by using the
|
450 |
-
<a href="http://php.net/manual/en/function.set-time-limit.php" target="_blank">set_time_limit</a> setting. If this notice shows as a warning then it is
|
451 |
-
still safe to continue with the install. However, if a timeout occurs then you will need to consider working with the max_execution_time setting or extracting the
|
452 |
-
archive file using the 'Manual package extraction' method.
|
453 |
-
Please see the <a href="https://snapcreek.com/duplicator/docs/faqs-tech/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=installer_timeout#faq-trouble-100-q" target="_blank">FAQ timeout</a> help link for more details.
|
454 |
-
|
455 |
-
</div>
|
456 |
-
</div>
|
457 |
-
</div>
|
458 |
-
<br/><br/>
|
459 |
-
|
460 |
-
|
461 |
-
<!-- ====================================
|
462 |
-
OPTIONS
|
463 |
-
==================================== -->
|
464 |
-
<div class="hdr-sub1" data-type="toggle" data-target="#s1-area-adv-opts">
|
465 |
-
<a href="javascript:void(0)"><i class="dupx-plus-square"></i> Options</a>
|
466 |
-
</div>
|
467 |
-
<div id="s1-area-adv-opts" style="display:none">
|
468 |
-
<div class="help-target"><a href="?help#help-s1" target="_blank">[help]</a></div>
|
469 |
-
<br/>
|
470 |
-
<div class="hdr-sub3">General</div>
|
471 |
-
<table class="dupx-opts dupx-advopts">
|
472 |
-
<tr>
|
473 |
-
<td>Extraction:</td>
|
474 |
-
<td>
|
475 |
-
|
476 |
-
<select id="archive_engine" name="archive_engine" size="2">
|
477 |
-
<option value="manual">Manual Archive Extraction</option>
|
478 |
-
<?php
|
479 |
-
//ZIP-ARCHIVE
|
480 |
-
echo (! $zip_archive_enabled)
|
481 |
-
? '<option disabled="true">PHP ZipArchive (not detected on server)</option>'
|
482 |
-
: '<option value="ziparchive" selected="true">PHP ZipArchive</option>';
|
483 |
-
?>
|
484 |
-
</select>
|
485 |
-
</td>
|
486 |
-
</tr>
|
487 |
-
</table>
|
488 |
-
<br>
|
489 |
-
<br>
|
490 |
-
<div class="hdr-sub3">Advanced</div>
|
491 |
-
<table class="dupx-opts dupx-advopts">
|
492 |
-
<tr>
|
493 |
-
<td>Safe Mode:</td>
|
494 |
-
<td>
|
495 |
-
<select name="exe_safe_mode" id="exe_safe_mode" onchange="DUPX.onSafeModeSwitch();" style="width:200px;">
|
496 |
-
<option value="0">Off</option>
|
497 |
-
<option value="1">Basic</option>
|
498 |
-
<option value="2">Advance</option>
|
499 |
-
</select>
|
500 |
-
</td>
|
501 |
-
</tr>
|
502 |
-
<tr>
|
503 |
-
<td>Config Files:</td>
|
504 |
-
<td>
|
505 |
-
<input type="checkbox" name="retain_config" id="retain_config" value="1" />
|
506 |
-
<label for="retain_config" style="font-weight: normal">Retain original .htaccess, .user.ini and web.config</label>
|
507 |
-
</td>
|
508 |
-
</tr>
|
509 |
-
<tr>
|
510 |
-
<td>File Times:</td>
|
511 |
-
<td>
|
512 |
-
<input type="radio" name="archive_filetime" id="archive_filetime_now" value="current" checked="checked" /> <label class="radio" for="archive_filetime_now" title='Set the files current date time to now'>Current</label>
|
513 |
-
<input type="radio" name="archive_filetime" id="archive_filetime_orginal" value="original" /> <label class="radio" for="archive_filetime_orginal" title="Keep the files date time the same">Original</label>
|
514 |
-
</td>
|
515 |
-
</tr>
|
516 |
-
<tr>
|
517 |
-
<td>Logging:</td>
|
518 |
-
<td>
|
519 |
-
<input type="radio" name="logging" id="logging-light" value="1" checked="true"> <label for="logging-light">Light</label>
|
520 |
-
<input type="radio" name="logging" id="logging-detailed" value="2"> <label for="logging-detailed">Detailed</label>
|
521 |
-
<input type="radio" name="logging" id="logging-debug" value="3"> <label for="logging-debug">Debug</label>
|
522 |
-
</td>
|
523 |
-
</tr>
|
524 |
-
</table>
|
525 |
-
<br/><br/>
|
526 |
-
|
527 |
-
<!-- *** SETUP HELP *** -->
|
528 |
-
<div class="hdr-sub3">Setup Help</div>
|
529 |
-
<div id='s1-area-setup-help'>
|
530 |
-
<div style="padding:10px 0px 0px 10px;line-height:22px">
|
531 |
-
<table style='width:100%'>
|
532 |
-
<tr>
|
533 |
-
<td style="width:200px">
|
534 |
-
» Watch the <a href="https://snapcreek.com/duplicator/docs/faqs-tech/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=installer_vid_tutor#faq-resource-070-q" target="_blank">video tutorials</a> <br/>
|
535 |
-
» Read helpful <a href="https://snapcreek.com/duplicator/docs/faqs-tech/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=installer_help_art" target="_blank">articles</a> <br/>
|
536 |
-
</td>
|
537 |
-
<td>
|
538 |
-
» Visit the <a href="https://snapcreek.com/duplicator/docs/quick-start/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=inst_quickstart" target="_blank">quick start guides</a> <br/>
|
539 |
-
» Browse the <a href="https://snapcreek.com/duplicator/docs/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=installer_online_docs" target="_blank">online docs</a> <br/>
|
540 |
-
</td>
|
541 |
-
</tr>
|
542 |
-
</table>
|
543 |
-
</div>
|
544 |
-
</div><br/>
|
545 |
-
|
546 |
-
</div>
|
547 |
-
<br/><br/>
|
548 |
-
|
549 |
-
<!-- ====================================
|
550 |
-
NOTICES
|
551 |
-
==================================== -->
|
552 |
-
<div id="dialog-server-notice" style="display:none">
|
553 |
-
<div id="s1-warning-msg">
|
554 |
-
<b>TERMS & NOTICES</b> <br/><br/>
|
555 |
-
|
556 |
-
<b>Disclaimer:</b>
|
557 |
-
The Duplicator software and installer should be used at your own risk. Users should always back up or have backups of your database and files before running this installer.
|
558 |
-
If you're not sure about how to use this tool then please enlist the guidance of a technical professional. <u>Always</u> test this installer in a sandbox environment
|
559 |
-
before trying to deploy into a production environment. Be sure that if anything happens during the install that you have a backup recovery plan in place. By accepting
|
560 |
-
this agreement the users of this software do not hold liable Snapcreek LLC or any of its affiliates/members liable for any issues that might occur during use of this software.
|
561 |
-
<br/><br/>
|
562 |
-
|
563 |
-
|
564 |
-
<b>Database:</b>
|
565 |
-
Do not connect to an existing database unless you are 100% sure you want to remove all of it's data. Connecting to a database that already exists will permanently
|
566 |
-
DELETE all data in that database. This tool is designed to populate and fill a database with NEW data from a duplicated database using the SQL script in the
|
567 |
-
package name above.
|
568 |
-
<br/><br/>
|
569 |
-
|
570 |
-
<b>Setup:</b>
|
571 |
-
Only the archive and installer file should be in the install directory, unless you have manually extracted the package and checked the
|
572 |
-
'Manual Package Extraction' checkbox. All other files will be OVERWRITTEN during install. Make sure you have full backups of all your databases and files
|
573 |
-
before continuing with an installation. Manual extraction requires that all contents in the package are extracted to the same directory as the installer file.
|
574 |
-
Manual extraction is only needed when your server does not support the ZipArchive extension. Please see the online help for more details.
|
575 |
-
<br/><br/>
|
576 |
-
|
577 |
-
<b>After Install:</b> When you are done with the installation you must remove these files/directories:
|
578 |
-
<ul>
|
579 |
-
<li>installer.php</li>
|
580 |
-
<li>installer-backup.php</li>
|
581 |
-
<li>dup-installer-data_[HASH].sql</li>
|
582 |
-
<li>dup-database_[HASH].sql</li>
|
583 |
-
<li>dup-installer-log_[HASH].txt</li>
|
584 |
-
<li>[HASH]_archive.zip</li>
|
585 |
-
</ul>
|
586 |
-
|
587 |
-
These files contain sensitive information and should not remain on a production system for system integrity and security protection.
|
588 |
-
<br/><br/>
|
589 |
-
|
590 |
-
<b>License Overview</b><br/>
|
591 |
-
Duplicator is licensed under the GPL v3 https://www.gnu.org/licenses/gpl-3.0.en.html including the following disclaimers and limitation of liability.
|
592 |
-
<br/><br/>
|
593 |
-
|
594 |
-
<b>Disclaimer of Warranty</b><br/>
|
595 |
-
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
596 |
-
PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
597 |
-
FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
|
598 |
-
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
599 |
-
<br/><br/>
|
600 |
-
|
601 |
-
<b>Limitation of Liability</b><br/>
|
602 |
-
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS
|
603 |
-
PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
604 |
-
PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO
|
605 |
-
OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
606 |
-
<br/><br/>
|
607 |
-
</div>
|
608 |
-
</div>
|
609 |
-
|
610 |
-
<div id="s1-warning-check">
|
611 |
-
<input id="accept-warnings" name="accpet-warnings" type="checkbox" onclick="DUPX.acceptWarning()" />
|
612 |
-
<label for="accept-warnings">I have read and accept all <a href="javascript:void(0)" onclick="DUPX.showNotices()">terms & notices</a> <small style="font-style:italic">(required to continue)</small></label><br/>
|
613 |
-
</div>
|
614 |
-
|
615 |
-
|
616 |
-
<?php if (! $req_success || $all_arc == 'Fail') :?>
|
617 |
-
<div class="s1-err-msg">
|
618 |
-
<i>
|
619 |
-
This installation will not be able to proceed until the 'Archive' and 'Validation' sections pass. Please adjust your servers settings or contact your
|
620 |
-
server administrator, hosting provider or visit the resources below for additional help.
|
621 |
-
</i>
|
622 |
-
<div style="padding:10px">
|
623 |
-
» <a href="https://snapcreek.com/duplicator/docs/faqs-tech/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=inst_validfail_techfaq" target="_blank">Technical FAQs</a> <br/>
|
624 |
-
» <a href="https://snapcreek.com/support/docs/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=inst_validfail_onlinedocs" target="_blank">Online Documentation</a> <br/>
|
625 |
-
</div>
|
626 |
-
</div> <br/><br/>
|
627 |
-
<?php else : ?>
|
628 |
-
<br/><br/><br/>
|
629 |
-
<br/><br/><br/>
|
630 |
-
<div class="dupx-footer-buttons">
|
631 |
-
<button id="s1-deploy-btn" type="button" class="default-btn" onclick="DUPX.runExtraction()" title="<?php echo DUPX_U::esc_js($agree_msg); ?>"> Next </button>
|
632 |
-
</div>
|
633 |
-
<?php endif; ?>
|
634 |
-
|
635 |
-
</form>
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
<!-- =========================================
|
640 |
-
VIEW: STEP 1 - AJAX RESULT
|
641 |
-
Auto Posts to view.step2.php
|
642 |
-
========================================= -->
|
643 |
-
<form id='s1-result-form' method="post" class="content-form" style="display:none">
|
644 |
-
|
645 |
-
<div class="dupx-logfile-link"><a href="<?php echo DUPX_U::esc_attr($GLOBALS["LOG_FILE_NAME"]);?>" target="install_log">dup-installer-log.txt</a></div>
|
646 |
-
<div class="hdr-main">
|
647 |
-
Step <span class="step">1</span> of 4: Deployment
|
648 |
-
</div>
|
649 |
-
|
650 |
-
<!-- POST PARAMS -->
|
651 |
-
<div class="dupx-debug">
|
652 |
-
<input type="hidden" name="action_step" value="2" />
|
653 |
-
<input type="hidden" name="secure-pass" value="<?php echo DUPX_U::esc_attr($_POST['secure-pass']); ?>" />
|
654 |
-
<input type="hidden" name="logging" id="ajax-logging" />
|
655 |
-
<input type="hidden" name="exe_safe_mode" id="exe-safe-mode" value="0" />
|
656 |
-
<input type="hidden" name="retain_config" id="ajax-retain-config" />
|
657 |
-
<input type="hidden" name="json" id="ajax-json" />
|
658 |
-
<textarea id='ajax-json-debug' name='json_debug_view'></textarea>
|
659 |
-
<input type='submit' value='manual submit'>
|
660 |
-
</div>
|
661 |
-
|
662 |
-
<!-- PROGRESS BAR -->
|
663 |
-
<div id="progress-area">
|
664 |
-
<div style="width:500px; margin:auto">
|
665 |
-
<h3>Running Deployment Processes Please Wait...</h3>
|
666 |
-
<div id="progress-bar"></div>
|
667 |
-
<i>This may take several minutes</i>
|
668 |
-
</div>
|
669 |
-
</div>
|
670 |
-
|
671 |
-
<!-- AJAX SYSTEM ERROR -->
|
672 |
-
<div id="ajaxerr-area" style="display:none">
|
673 |
-
<p>Please try again an issue has occurred.</p>
|
674 |
-
<div style="padding: 0px 10px 10px 0px;">
|
675 |
-
<div id="ajaxerr-data">An unknown issue has occurred with the file and database set up process. Please see the <?php echo DUPX_U::esc_html($GLOBALS["LOG_FILE_NAME"]);?> file for more details.</div>
|
676 |
-
<div style="text-align:center; margin:10px auto 0px auto">
|
677 |
-
<input type="button" class="default-btn" onclick="DUPX.hideErrorResult()" value="« Try Again" /><br/><br/>
|
678 |
-
<i style='font-size:11px'>See online help for more details at <a href='https://snapcreek.com/ticket?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=inst_ajaxerr_ticket' target='_blank'>snapcreek.com</a></i>
|
679 |
-
</div>
|
680 |
-
</div>
|
681 |
-
</div>
|
682 |
-
</form>
|
683 |
-
|
684 |
-
<script>
|
685 |
-
DUPX.getManaualArchiveOpt = function ()
|
686 |
-
{
|
687 |
-
$("html, body").animate({scrollTop: $(document).height()}, 1500);
|
688 |
-
$("a[data-target='#s1-area-adv-opts']").find('i').removeClass('dupx-plus-square').addClass('dupx-minus-square');
|
689 |
-
$('#s1-area-adv-opts').show(1000);
|
690 |
-
$('select#archive_engine').val('manual').focus();
|
691 |
-
};
|
692 |
-
|
693 |
-
/** Performs Ajax post to extract files and create db
|
694 |
-
* Timeout (10000000 = 166 minutes) */
|
695 |
-
DUPX.runExtraction = function()
|
696 |
-
{
|
697 |
-
var $form = $('#s1-input-form');
|
698 |
-
|
699 |
-
//1800000 = 30 minutes
|
700 |
-
//If the extraction takes longer than 30 minutes then user
|
701 |
-
//will probably want to do a manual extraction or even FTP
|
702 |
-
$.ajax({
|
703 |
-
type: "POST",
|
704 |
-
timeout:1800000,
|
705 |
-
dataType: "json",
|
706 |
-
url: window.location.href,
|
707 |
-
data: $form.serialize(),
|
708 |
-
beforeSend: function() {
|
709 |
-
DUPX.showProgressBar();
|
710 |
-
$form.hide();
|
711 |
-
$('#s1-result-form').show();
|
712 |
-
},
|
713 |
-
success: function(data) {
|
714 |
-
var dataJSON = JSON.stringify(data);
|
715 |
-
$("#ajax-json-debug").val(dataJSON);
|
716 |
-
if (typeof(data) != 'undefined' && data.pass == 1) {
|
717 |
-
$("#ajax-logging").val($("input:radio[name=logging]:checked").val());
|
718 |
-
$("#ajax-retain-config").val($("#retain_config").is(":checked") ? 1 : 0);
|
719 |
-
$("#exe-safe-mode").val($("#exe_safe_mode").val());
|
720 |
-
$("#ajax-json").val(escape(dataJSON));
|
721 |
-
<?php if (! $GLOBALS['DUPX_DEBUG']) : ?>
|
722 |
-
setTimeout(function() {$('#s1-result-form').submit();}, 500);
|
723 |
-
<?php endif; ?>
|
724 |
-
$('#progress-area').fadeOut(1000);
|
725 |
-
} else {
|
726 |
-
$('#ajaxerr-data').html('Error Processing Step 1');
|
727 |
-
DUPX.hideProgressBar();
|
728 |
-
}
|
729 |
-
},
|
730 |
-
error: function(xhr) {
|
731 |
-
var status = "<b>Server Code:</b> " + xhr.status + "<br/>";
|
732 |
-
status += "<b>Status:</b> " + xhr.statusText + "<br/>";
|
733 |
-
status += "<b>Response:</b> " + xhr.responseText + "";
|
734 |
-
status += "<hr/><b>Additional Troubleshooting Tips:</b><br/>";
|
735 |
-
status += "- Check the <a href='<?php echo DUPX_U::esc_js($GLOBALS["LOG_FILE_NAME"]);?>' target='install_log'>dup-installer-log.txt</a> file for warnings or errors.<br/>";
|
736 |
-
status += "- Check the web server and PHP error logs. <br/>";
|
737 |
-
status += "- For timeout issues visit the <a href='https://snapcreek.com/duplicator/docs/faqs-tech/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=inst_ajaxextract_tofaq#faq-trouble-100-q' target='_blank'>Timeout FAQ Section</a><br/>";
|
738 |
-
$('#ajaxerr-data').html(status);
|
739 |
-
DUPX.hideProgressBar();
|
740 |
-
}
|
741 |
-
});
|
742 |
-
|
743 |
-
};
|
744 |
-
|
745 |
-
/** Accetps Useage Warning */
|
746 |
-
DUPX.acceptWarning = function()
|
747 |
-
{
|
748 |
-
if ($("#accept-warnings").is(':checked')) {
|
749 |
-
$("#s1-deploy-btn").removeAttr("disabled");
|
750 |
-
$("#s1-deploy-btn").removeAttr("title");
|
751 |
-
} else {
|
752 |
-
$("#s1-deploy-btn").attr("disabled", "true");
|
753 |
-
$("#s1-deploy-btn").attr("title", "<?php echo DUPX_U::esc_js($agree_msg); ?>");
|
754 |
-
}
|
755 |
-
}
|
756 |
-
|
757 |
-
/** Server Terms Dialog*/
|
758 |
-
DUPX.showNotices = function()
|
759 |
-
{
|
760 |
-
modal({
|
761 |
-
type: 'alert',
|
762 |
-
title: 'Terms and Notices',
|
763 |
-
text: $('#dialog-server-notice').html()
|
764 |
-
});
|
765 |
-
}
|
766 |
-
|
767 |
-
|
768 |
-
/** Go back on AJAX result view */
|
769 |
-
DUPX.hideErrorResult = function()
|
770 |
-
{
|
771 |
-
$('#s1-result-form').hide();
|
772 |
-
$('#s1-input-form').show(200);
|
773 |
-
}
|
774 |
-
|
775 |
-
DUPX.onSafeModeSwitch = function ()
|
776 |
-
{
|
777 |
-
var mode = $('#exe_safe_mode').val();
|
778 |
-
if(mode == 0){
|
779 |
-
$("#retain_config").removeAttr("disabled");
|
780 |
-
}else if(mode == 1 || mode ==2){
|
781 |
-
if($("#retain_config").is(':checked'))
|
782 |
-
$("#retain_config").removeAttr("checked");
|
783 |
-
$("#retain_config").attr("disabled", true);
|
784 |
-
}
|
785 |
-
|
786 |
-
$('#exe-safe-mode').val(mode);
|
787 |
-
console.log("mode set to"+mode);
|
788 |
-
}
|
789 |
-
|
790 |
-
//DOCUMENT LOAD
|
791 |
-
$(document).ready(function()
|
792 |
-
{
|
793 |
-
DUPX.acceptWarning();
|
794 |
-
$("*[data-type='toggle']").click(DUPX.toggleClick);
|
795 |
-
<?php echo ($all_arc == 'Fail') ? "$('#s1-area-archive-file-link').trigger('click');" : ""; ?>
|
796 |
-
<?php echo (! $all_success) ? "$('#s1-area-sys-setup-link').trigger('click');" : ""; ?>
|
797 |
-
})
|
798 |
-
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/build/view.step2.php
DELETED
@@ -1,441 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
defined("DUPXABSPATH") or die("");
|
3 |
-
|
4 |
-
if (isset($_POST['logging'])) {
|
5 |
-
$post_logging = DUPX_U::sanitize_text_field($_POST['logging']);
|
6 |
-
$_POST['logging'] = trim($post_logging);
|
7 |
-
}
|
8 |
-
|
9 |
-
if (isset($_POST['exe_safe_mode'])) {
|
10 |
-
$_POST['exe_safe_mode'] = DUPX_U::sanitize_text_field($_POST['exe_safe_mode']);
|
11 |
-
} else {
|
12 |
-
$_POST['exe_safe_mode'] = 0;
|
13 |
-
}
|
14 |
-
?>
|
15 |
-
|
16 |
-
|
17 |
-
<!-- =========================================
|
18 |
-
VIEW: STEP 2- INPUT -->
|
19 |
-
<form id='s2-input-form' method="post" class="content-form" data-parsley-validate="true" data-parsley-excluded="input[type=hidden], [disabled], :hidden">
|
20 |
-
<input type="hidden" name="action_ajax" value="2" />
|
21 |
-
<input type="hidden" name="action_step" value="2" />
|
22 |
-
<input type="hidden" name="logging" id="logging" value="<?php echo DUPX_U::esc_attr($_POST['logging']); ?>" />
|
23 |
-
<input type="hidden" name="secure-pass" value="<?php echo DUPX_U::esc_attr($_POST['secure-pass']); ?>" />
|
24 |
-
|
25 |
-
<div class="dupx-logfile-link"><a href="<?php echo DUPX_U::esc_attr($GLOBALS["LOG_FILE_NAME"]);?>?now=<?php echo DUPX_U::esc_attr($GLOBALS['NOW_DATE']); ?>" target="install_log">dup-installer-log.txt</a></div>
|
26 |
-
<div class="hdr-main">
|
27 |
-
Step <span class="step">2</span> of 4: Install Database
|
28 |
-
</div>
|
29 |
-
|
30 |
-
<div class="s2-btngrp">
|
31 |
-
<input id="s2-basic-btn" type="button" value="Basic" class="active" onclick="DUPX.togglePanels('basic')" />
|
32 |
-
<input id="s2-cpnl-btn" type="button" value="cPanel" class="in-active" onclick="DUPX.togglePanels('cpanel')" />
|
33 |
-
</div>
|
34 |
-
|
35 |
-
|
36 |
-
<!-- =========================================
|
37 |
-
BASIC PANEL -->
|
38 |
-
<div id="s2-basic-pane">
|
39 |
-
<div class="hdr-sub1" data-type="toggle" data-target="#s2-area-setup">
|
40 |
-
<a href="javascript:void(0)"><i class="dupx-minus-square"></i> Setup</a>
|
41 |
-
</div>
|
42 |
-
<div id="s2-area-setup">
|
43 |
-
<table class="dupx-opts">
|
44 |
-
<tr>
|
45 |
-
<td>Action:</td>
|
46 |
-
<td>
|
47 |
-
<select name="dbaction" id="dbaction">
|
48 |
-
<option value="create">Create New Database</option>
|
49 |
-
<option value="empty" selected="true">Connect and Remove All Data</option>
|
50 |
-
</select>
|
51 |
-
</td>
|
52 |
-
</tr>
|
53 |
-
<tr>
|
54 |
-
<td>Host:</td>
|
55 |
-
<td>
|
56 |
-
<table class="s2-opts-dbhost">
|
57 |
-
<tr>
|
58 |
-
<td><input type="text" name="dbhost" id="dbhost" required="true" value="<?php echo DUPX_U::esc_attr($GLOBALS['FW_DBHOST']); ?>" placeholder="localhost" style="width:450px" /></td>
|
59 |
-
<td style="vertical-align:top">
|
60 |
-
<input id="s2-dbport-btn" type="button" onclick="DUPX.togglePort()" class="s2-small-btn" value="Port: <?php echo DUPX_U::esc_attr($GLOBALS['FW_DBPORT']); ?>" />
|
61 |
-
<input name="dbport" id="dbport" type="text" style="width:80px; display:none" value="<?php echo DUPX_U::esc_attr($GLOBALS['FW_DBPORT']); ?>" />
|
62 |
-
</td>
|
63 |
-
</tr>
|
64 |
-
</table>
|
65 |
-
</td>
|
66 |
-
</tr>
|
67 |
-
<tr>
|
68 |
-
<td>Database:</td>
|
69 |
-
<td>
|
70 |
-
<input type="text" name="dbname" id="dbname" required="true" value="<?php echo DUPX_U::esc_attr($GLOBALS['FW_DBNAME']); ?>" placeholder="new or existing database name" />
|
71 |
-
<div id="s2-warning-emptydb">
|
72 |
-
<label for="accept-warnings">Warning: The selected 'Action' above will remove <u>all data</u> from this database!</label>
|
73 |
-
</div>
|
74 |
-
</td>
|
75 |
-
</tr>
|
76 |
-
<tr>
|
77 |
-
<td>User:</td>
|
78 |
-
<td><input type="text" name="dbuser" id="dbuser" required="true" value="<?php echo DUPX_U::esc_attr($GLOBALS['FW_DBUSER']); ?>" placeholder="valid database username" /></td>
|
79 |
-
</tr>
|
80 |
-
<tr>
|
81 |
-
<td>Password:</td>
|
82 |
-
<td><input type="text" name="dbpass" id="dbpass" value="<?php echo DUPX_U::esc_attr($GLOBALS['FW_DBPASS']); ?>" placeholder="valid database user password" /></td>
|
83 |
-
</tr>
|
84 |
-
</table>
|
85 |
-
</div>
|
86 |
-
|
87 |
-
<!-- =========================================
|
88 |
-
DIALOG: DB CONNECTION CHECK -->
|
89 |
-
<div id="s2-dbconn">
|
90 |
-
<div id="s2-dbconn-status" style="display:none">
|
91 |
-
<div style="padding: 0px 10px 10px 10px;">
|
92 |
-
<div id="s2-dbconn-test-msg" style="min-height:80px"></div>
|
93 |
-
</div>
|
94 |
-
<small><input type="button" onclick="$('#s2-dbconn-status').hide(500)" class="s2-small-btn" value="Hide Message" /></small>
|
95 |
-
</div>
|
96 |
-
</div><br/>
|
97 |
-
|
98 |
-
<!-- ====================================
|
99 |
-
OPTIONS
|
100 |
-
==================================== -->
|
101 |
-
<div class="hdr-sub1" data-type="toggle" data-target="#s2-area-adv-opts">
|
102 |
-
<a href="javascript:void(0)"><i class="dupx-plus-square"></i> Options</a>
|
103 |
-
</div>
|
104 |
-
<div id='s2-area-adv-opts' style="display:none">
|
105 |
-
<div class="help-target"><a href="?help#help-s2" target="_blank">[help]</a></div>
|
106 |
-
|
107 |
-
<table class="dupx-opts dupx-advopts">
|
108 |
-
<tr>
|
109 |
-
<td>Legacy:</td>
|
110 |
-
<td><input type="checkbox" name="dbcollatefb" id="dbcollatefb" value="1" /> <label for="dbcollatefb">Apply legacy collation fallback support for unknown collations types</label></td>
|
111 |
-
</tr>
|
112 |
-
<tr>
|
113 |
-
<td>Spacing:</td>
|
114 |
-
<td colspan="2">
|
115 |
-
<input type="checkbox" name="dbnbsp" id="dbnbsp" value="1" /> <label for="dbnbsp">Fix non-breaking space characters</label>
|
116 |
-
</td>
|
117 |
-
</tr>
|
118 |
-
<tr>
|
119 |
-
<td style="vertical-align:top">Mode:</td>
|
120 |
-
<td colspan="2">
|
121 |
-
<input type="radio" name="dbmysqlmode" id="dbmysqlmode_1" checked="true" value="DEFAULT"/> <label for="dbmysqlmode_1">Default</label>
|
122 |
-
<input type="radio" name="dbmysqlmode" id="dbmysqlmode_2" value="DISABLE"/> <label for="dbmysqlmode_2">Disable</label>
|
123 |
-
<input type="radio" name="dbmysqlmode" id="dbmysqlmode_3" value="CUSTOM"/> <label for="dbmysqlmode_3">Custom</label>
|
124 |
-
<div id="dbmysqlmode_3_view" style="display:none; padding:5px">
|
125 |
-
<input type="text" name="dbmysqlmode_opts" value="" /><br/>
|
126 |
-
<small>Separate additional <a href="?help#help-mysql-mode" target="_blank">sql modes</a> with commas & no spaces.<br/>
|
127 |
-
Example: <i>NO_ENGINE_SUBSTITUTION,NO_ZERO_IN_DATE,...</i>.</small>
|
128 |
-
</div>
|
129 |
-
</td>
|
130 |
-
</tr>
|
131 |
-
<tr><td style="width:130px">Charset:</td><td><input type="text" name="dbcharset" id="dbcharset" value="<?php echo DUPX_U::esc_attr($_POST['dbcharset']) ?>" /> </td></tr>
|
132 |
-
<tr><td>Collation:</td><td><input type="text" name="dbcollate" id="dbcollate" value="<?php echo DUPX_U::esc_attr($_POST['dbcollate']); ?>" /> </tr>
|
133 |
-
</table>
|
134 |
-
|
135 |
-
</div>
|
136 |
-
<br/><br/><br/>
|
137 |
-
<br/><br/><br/>
|
138 |
-
|
139 |
-
<div class="dupx-footer-buttons">
|
140 |
-
<input type="button" onclick="DUPX.testDatabase()" class="default-btn" value="Test Database" />
|
141 |
-
<input id="dup-step2-deploy-btn" type="button" class="default-btn" value=" Next " onclick="DUPX.confirmDeployment()" />
|
142 |
-
</div>
|
143 |
-
|
144 |
-
|
145 |
-
</div>
|
146 |
-
|
147 |
-
|
148 |
-
<!-- =========================================
|
149 |
-
C-PANEL PANEL -->
|
150 |
-
<div id="s2-cpnl-pane">
|
151 |
-
<div class="s2-gopro">
|
152 |
-
<h2>cPanel Connectivity</h2>
|
153 |
-
|
154 |
-
<?php if( DUPX_U::isURLActive($_SERVER['SERVER_NAME'], 2083) ): ?>
|
155 |
-
<div class='s2-cpanel-login'>
|
156 |
-
<b>Login to this server's cPanel</b><br/>
|
157 |
-
<a href=<?php echo DUPX_U::esc_url('https://'.$_SERVER['SERVER_NAME'].':2083'); ?>" target="cpanel" style="color:#fff">[<?php echo DUPX_U::esc_html($_SERVER['SERVER_NAME']); ?>:2083]</a>
|
158 |
-
</div>
|
159 |
-
<?php else : ?>
|
160 |
-
<div class='s2-cpanel-off'>
|
161 |
-
<b>This server does not appear to support cPanel!</b><br/>
|
162 |
-
Consider <a href="https://snapcreek.com/wordpress-hosting/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_content=free_install_no_cpanel&utm_campaign=duplicator_pro" target="cpanel" style="color:#fff;font-weight:bold">upgrading</a> to a host that does.<br/>
|
163 |
-
</div>
|
164 |
-
<?php endif; ?>
|
165 |
-
|
166 |
-
|
167 |
-
<div style="text-align: center; font-size: 14px">
|
168 |
-
Want <span style="font-style: italic;">even easier</span> installs?
|
169 |
-
<a target="_blank" href="https://snapcreek.com/duplicator/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_content=free_install_step2&utm_campaign=duplicator_pro"><b>Duplicator Pro</b></a>
|
170 |
-
allows the following <b>right from the installer:</b>
|
171 |
-
</div>
|
172 |
-
<ul>
|
173 |
-
<li>Directly login to cPanel</li>
|
174 |
-
<li>Instantly create new databases & users</li>
|
175 |
-
<li>Preview and select existing databases & users</li>
|
176 |
-
</ul>
|
177 |
-
<small>
|
178 |
-
Note: Hosts that support cPanel provide remote access to server resources, allowing operations such as direct database and user creation.
|
179 |
-
Since the <a target="_blank" href="https://snapcreek.com/duplicator/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_content=free_install_cpanel_note&utm_campaign=duplicator_pro">Duplicator Pro</a>
|
180 |
-
installer can directly access cPanel, it dramatically speeds up your workflow.
|
181 |
-
</small>
|
182 |
-
</div>
|
183 |
-
</div>
|
184 |
-
|
185 |
-
</form>
|
186 |
-
|
187 |
-
|
188 |
-
<!-- =========================================
|
189 |
-
VIEW: STEP 2 - AJAX RESULT
|
190 |
-
Auto Posts to view.step3.php
|
191 |
-
========================================= -->
|
192 |
-
<form id='s2-result-form' method="post" class="content-form" style="display:none">
|
193 |
-
|
194 |
-
<div class="dupx-logfile-link"><a href="<?php echo DUPX_U::esc_attr($GLOBALS["LOG_FILE_NAME"]);?>" target="install_log">dup-installer-log.txt</a></div>
|
195 |
-
<div class="hdr-main">
|
196 |
-
Step <span class="step">2</span> of 4: Install Database
|
197 |
-
</div>
|
198 |
-
|
199 |
-
<!-- POST PARAMS -->
|
200 |
-
<div class="dupx-debug">
|
201 |
-
<input type="hidden" name="secure-pass" value="<?php echo DUPX_U::esc_attr($_POST['secure-pass']); ?>" />
|
202 |
-
<input type="hidden" name="action_step" value="3" />
|
203 |
-
<input type="hidden" name="logging" id="ajax-logging" />
|
204 |
-
<input type="hidden" name="retain_config" value="<?php echo DUPX_U::esc_attr($_POST['retain_config']); ?>" />
|
205 |
-
<input type="hidden" name="exe_safe_mode" id="exe-safe-mode" value="<?php echo DUPX_U::esc_attr($_POST['exe_safe_mode']); ?>"/>
|
206 |
-
<input type="hidden" name="dbhost" id="ajax-dbhost" />
|
207 |
-
<input type="hidden" name="dbport" id="ajax-dbport" />
|
208 |
-
<input type="hidden" name="dbuser" id="ajax-dbuser" />
|
209 |
-
<input type="hidden" name="dbpass" id="ajax-dbpass" />
|
210 |
-
<input type="hidden" name="dbname" id="ajax-dbname" />
|
211 |
-
<input type="hidden" name="json" id="ajax-json" />
|
212 |
-
<input type="hidden" name="dbcharset" id="ajax-dbcharset" />
|
213 |
-
<input type="hidden" name="dbcollate" id="ajax-dbcollate" />
|
214 |
-
<br/>
|
215 |
-
<input type='submit' value='manual submit'>
|
216 |
-
</div>
|
217 |
-
|
218 |
-
<!-- PROGRESS BAR -->
|
219 |
-
<div id="progress-area">
|
220 |
-
<div style="width:500px; margin:auto">
|
221 |
-
<h3>Installing Database Please Wait...</h3>
|
222 |
-
<div id="progress-bar"></div>
|
223 |
-
<i>This may take several minutes</i>
|
224 |
-
</div>
|
225 |
-
</div>
|
226 |
-
|
227 |
-
<!-- AJAX SYSTEM ERROR -->
|
228 |
-
<div id="ajaxerr-area" style="display:none">
|
229 |
-
<p>Please try again an issue has occurred.</p>
|
230 |
-
<div style="padding: 0px 10px 10px 0px;">
|
231 |
-
<div id="ajaxerr-data">An unknown issue has occurred with the file and database set up process. Please see the dup-installer-log.txt file for more details.</div>
|
232 |
-
<div style="text-align:center; margin:10px auto 0px auto">
|
233 |
-
<input type="button" class="default-btn" onclick='DUPX.hideErrorResult()' value="« Try Again" /><br/><br/>
|
234 |
-
<i style='font-size:11px'>See online help for more details at <a href='https://snapcreek.com/ticket?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=inst_ajaxstep2_ticket' target='_blank'>snapcreek.com</a></i>
|
235 |
-
</div>
|
236 |
-
</div>
|
237 |
-
</div>
|
238 |
-
</form>
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
<!-- CONFIRM DIALOG -->
|
243 |
-
<div id="dialog-confirm-content" style="display:none">
|
244 |
-
<div style="padding:0 0 25px 0">
|
245 |
-
<b>Run installer with these settings?</b>
|
246 |
-
</div>
|
247 |
-
|
248 |
-
<b>Database Settings:</b><br/>
|
249 |
-
<table style="margin-left:20px">
|
250 |
-
<tr>
|
251 |
-
<td><b>Server:</b></td>
|
252 |
-
<td><i id="dlg-dbhost"></i></td>
|
253 |
-
</tr>
|
254 |
-
<tr>
|
255 |
-
<td><b>Name:</b></td>
|
256 |
-
<td><i id="dlg-dbname"></i></td>
|
257 |
-
</tr>
|
258 |
-
<tr>
|
259 |
-
<td><b>User:</b></td>
|
260 |
-
<td><i id="dlg-dbuser"></i></td>
|
261 |
-
</tr>
|
262 |
-
</table>
|
263 |
-
<br/><br/>
|
264 |
-
|
265 |
-
<small> WARNING: Be sure these database parameters are correct! Entering the wrong information WILL overwrite an existing database.
|
266 |
-
Make sure to have backups of all your data before proceeding.</small><br/>
|
267 |
-
</div>
|
268 |
-
|
269 |
-
|
270 |
-
<script>
|
271 |
-
DUPX.escapeHtml = function(unsafe) {
|
272 |
-
return unsafe
|
273 |
-
.replace(/&/g, "&")
|
274 |
-
.replace(/</g, "<")
|
275 |
-
.replace(/>/g, ">")
|
276 |
-
.replace(/"/g, """)
|
277 |
-
.replace(/'/g, "'");
|
278 |
-
}
|
279 |
-
/* Confirm Dialog to validate run */
|
280 |
-
DUPX.confirmDeployment = function()
|
281 |
-
{
|
282 |
-
var $form = $('#s2-input-form');
|
283 |
-
$form.parsley().validate();
|
284 |
-
if (!$form.parsley().isValid()) {
|
285 |
-
return;
|
286 |
-
}
|
287 |
-
|
288 |
-
$('#dlg-dbhost').html(DUPX.escapeHtml($("#dbhost").val()));
|
289 |
-
$('#dlg-dbname').html(DUPX.escapeHtml($("#dbname").val()));
|
290 |
-
$('#dlg-dbuser').html(DUPX.escapeHtml($("#dbuser").val()));
|
291 |
-
|
292 |
-
modal({
|
293 |
-
type: 'confirm',
|
294 |
-
title: 'Install Confirmation',
|
295 |
-
text: $('#dialog-confirm-content').html(),
|
296 |
-
callback: function(result)
|
297 |
-
{
|
298 |
-
if (result == true) {
|
299 |
-
DUPX.runDeployment();
|
300 |
-
}
|
301 |
-
}
|
302 |
-
});
|
303 |
-
}
|
304 |
-
|
305 |
-
|
306 |
-
/* Performs Ajax post to extract files and create db
|
307 |
-
* Timeout (10000000 = 166 minutes) */
|
308 |
-
DUPX.runDeployment = function()
|
309 |
-
{
|
310 |
-
var $form = $('#s2-input-form');
|
311 |
-
var dbhost = $("#dbhost").val();
|
312 |
-
var dbname = $("#dbname").val();
|
313 |
-
var dbuser = $("#dbuser").val();
|
314 |
-
|
315 |
-
$.ajax({
|
316 |
-
type: "POST",
|
317 |
-
timeout: 1800000,
|
318 |
-
dataType: "json",
|
319 |
-
url: window.location.href,
|
320 |
-
data: $form.serialize(),
|
321 |
-
beforeSend: function() {
|
322 |
-
DUPX.showProgressBar();
|
323 |
-
$form.hide();
|
324 |
-
$('#s2-result-form').show();
|
325 |
-
},
|
326 |
-
success: function(data, textStatus, xhr){
|
327 |
-
if (typeof(data) != 'undefined' && data.pass == 1) {
|
328 |
-
$("#ajax-dbhost").val($("#dbhost").val());
|
329 |
-
$("#ajax-dbport").val($("#dbport").val());
|
330 |
-
$("#ajax-dbuser").val($("#dbuser").val());
|
331 |
-
$("#ajax-dbpass").val($("#dbpass").val());
|
332 |
-
$("#ajax-dbname").val($("#dbname").val());
|
333 |
-
$("#ajax-dbcharset").val($("#dbcharset").val());
|
334 |
-
$("#ajax-dbcollate").val($("#dbcollate").val());
|
335 |
-
$("#ajax-logging").val($("#logging").val());
|
336 |
-
$("#ajax-json").val(escape(JSON.stringify(data)));
|
337 |
-
<?php if (! $GLOBALS['DUPX_DEBUG']) : ?>
|
338 |
-
setTimeout(function() {$('#s2-result-form').submit();}, 500);
|
339 |
-
<?php endif; ?>
|
340 |
-
$('#progress-area').fadeOut(1000);
|
341 |
-
} else {
|
342 |
-
DUPX.hideProgressBar();
|
343 |
-
}
|
344 |
-
},
|
345 |
-
error: function(xhr) {
|
346 |
-
var status = "<b>Server Code:</b> " + xhr.status + "<br/>";
|
347 |
-
status += "<b>Status:</b> " + xhr.statusText + "<br/>";
|
348 |
-
status += "<b>Response:</b> " + xhr.responseText + "";
|
349 |
-
status += "<hr/><b>Additional Troubleshooting Tips:</b><br/>";
|
350 |
-
status += "- Check the <a href='<?php echo DUPX_U::esc_js($GLOBALS["LOG_FILE_NAME"]);?>' target='install_log'>dup-installer-log.txt</a> file for warnings or errors.<br/>";
|
351 |
-
status += "- Check the web server and PHP error logs. <br/>";
|
352 |
-
status += "- For timeout issues visit the <a href='https://snapcreek.com/duplicator/docs/faqs-tech/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=inst_step2deploy_timout#faq-trouble-100-q' target='_blank'>Timeout FAQ Section</a><br/>";
|
353 |
-
$('#ajaxerr-data').html(status);
|
354 |
-
DUPX.hideProgressBar();
|
355 |
-
}
|
356 |
-
});
|
357 |
-
|
358 |
-
}
|
359 |
-
|
360 |
-
/**
|
361 |
-
* Toggles the cpanel Login area */
|
362 |
-
DUPX.togglePanels = function (pane)
|
363 |
-
{
|
364 |
-
$('#s2-basic-pane, #s2-cpnl-pane').hide();
|
365 |
-
$('#s2-basic-btn, #s2-cpnl-btn').removeClass('active in-active');
|
366 |
-
if (pane == 'basic') {
|
367 |
-
$('#s2-basic-pane').show();
|
368 |
-
$('#s2-basic-btn').addClass('active');
|
369 |
-
$('#s2-cpnl-btn').addClass('in-active');
|
370 |
-
} else {
|
371 |
-
$('#s2-cpnl-pane').show(200);
|
372 |
-
$('#s2-cpnl-btn').addClass('active');
|
373 |
-
$('#s2-basic-btn').addClass('in-active');
|
374 |
-
}
|
375 |
-
}
|
376 |
-
|
377 |
-
|
378 |
-
/** Go back on AJAX result view */
|
379 |
-
DUPX.hideErrorResult = function()
|
380 |
-
{
|
381 |
-
$('#s2-result-form').hide();
|
382 |
-
$('#s2-input-form').show(200);
|
383 |
-
}
|
384 |
-
|
385 |
-
|
386 |
-
/** Shows results of database connection
|
387 |
-
* Timeout (45000 = 45 secs) */
|
388 |
-
DUPX.testDatabase = function ()
|
389 |
-
{
|
390 |
-
$.ajax({
|
391 |
-
type: "POST",
|
392 |
-
timeout: 45000,
|
393 |
-
url: window.location.href + '?' + 'dbtest=1',
|
394 |
-
data: $('#s2-input-form').serialize(),
|
395 |
-
success: function(data){ $('#s2-dbconn-test-msg').html(data); },
|
396 |
-
error: function(data){ alert('An error occurred while testing the database connection! Contact your server admin to make sure the connection inputs are correct!'); }
|
397 |
-
});
|
398 |
-
|
399 |
-
$('#s2-dbconn-test-msg').html("Attempting Connection. Please wait...");
|
400 |
-
$("#s2-dbconn-status").show(100);
|
401 |
-
|
402 |
-
}
|
403 |
-
|
404 |
-
|
405 |
-
DUPX.showDeleteWarning = function ()
|
406 |
-
{
|
407 |
-
($('#dbaction').val() == 'empty')
|
408 |
-
? $('#s2-warning-emptydb').show(200)
|
409 |
-
: $('#s2-warning-emptydb').hide(200);
|
410 |
-
}
|
411 |
-
|
412 |
-
|
413 |
-
DUPX.togglePort = function ()
|
414 |
-
{
|
415 |
-
$('#s2-dbport-btn').hide();
|
416 |
-
$('#dbport').show();
|
417 |
-
}
|
418 |
-
|
419 |
-
|
420 |
-
//DOCUMENT LOAD
|
421 |
-
$(document).ready(function()
|
422 |
-
{
|
423 |
-
$('#dup-s2-dialog-data').appendTo('#dup-s2-result-container');
|
424 |
-
$("select#dbaction").click(DUPX.showDeleteWarning);
|
425 |
-
DUPX.showDeleteWarning();
|
426 |
-
|
427 |
-
//MySQL Mode
|
428 |
-
$("input[name=dbmysqlmode]").click(function() {
|
429 |
-
if ($(this).val() == 'CUSTOM') {
|
430 |
-
$('#dbmysqlmode_3_view').show();
|
431 |
-
} else {
|
432 |
-
$('#dbmysqlmode_3_view').hide();
|
433 |
-
}
|
434 |
-
});
|
435 |
-
|
436 |
-
if ($("input[name=dbmysqlmode]:checked").val() == 'CUSTOM') {
|
437 |
-
$('#dbmysqlmode_3_view').show();
|
438 |
-
}
|
439 |
-
$("*[data-type='toggle']").click(DUPX.toggleClick);
|
440 |
-
});
|
441 |
-
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/build/view.step3.php
DELETED
@@ -1,340 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
defined("DUPXABSPATH") or die("");
|
3 |
-
|
4 |
-
$dbh = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass'], $_POST['dbname'], $_POST['dbport']);
|
5 |
-
|
6 |
-
$all_tables = DUPX_DB::getTables($dbh);
|
7 |
-
$active_plugins = DUPX_U::getActivePlugins($dbh);
|
8 |
-
|
9 |
-
$old_path = $GLOBALS['FW_WPROOT'];
|
10 |
-
$new_path = DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']);
|
11 |
-
$new_path = ((strrpos($old_path, '/') + 1) == strlen($old_path)) ? DUPX_U::addSlash($new_path) : $new_path;
|
12 |
-
$_POST['exe_safe_mode'] = isset($_POST['exe_safe_mode']) ? $_POST['exe_safe_mode'] : 0;
|
13 |
-
?>
|
14 |
-
|
15 |
-
|
16 |
-
<!-- =========================================
|
17 |
-
VIEW: STEP 3- INPUT -->
|
18 |
-
<form id='s3-input-form' method="post" class="content-form">
|
19 |
-
|
20 |
-
<!-- POST PARAMS -->
|
21 |
-
<input type="hidden" name="action_ajax" value="3" />
|
22 |
-
<input type="hidden" name="action_step" value="3" />
|
23 |
-
<input type="hidden" name="logging" value="<?php echo DUPX_U::esc_attr($_POST['logging']); ?>" />
|
24 |
-
<input type="hidden" name="retain_config" value="<?php echo DUPX_U::esc_attr($_POST['retain_config']); ?>" />
|
25 |
-
<input type="hidden" name="json" value="<?php echo DUPX_U::esc_attr($_POST['json']); ?>" />
|
26 |
-
<input type="hidden" name="dbhost" value="<?php echo DUPX_U::esc_attr($_POST['dbhost']); ?>" />
|
27 |
-
<input type="hidden" name="dbport" value="<?php echo DUPX_U::esc_attr($_POST['dbport']); ?>" />
|
28 |
-
<input type="hidden" name="dbuser" value="<?php echo DUPX_U::esc_attr($_POST['dbuser']); ?>" />
|
29 |
-
<input type="hidden" name="dbpass" value="<?php echo DUPX_U::esc_attr($_POST['dbpass']); ?>" />
|
30 |
-
<input type="hidden" name="dbname" value="<?php echo DUPX_U::esc_attr($_POST['dbname']); ?>" />
|
31 |
-
<input type="hidden" name="dbcharset" value="<?php echo DUPX_U::esc_attr($_POST['dbcharset']); ?>" />
|
32 |
-
<input type="hidden" name="dbcollate" value="<?php echo DUPX_U::esc_attr($_POST['dbcollate']); ?>" />
|
33 |
-
<input type="hidden" name="exe_safe_mode" id="exe-safe-mode" value="<?php echo DUPX_U::esc_attr($_POST['exe_safe_mode']); ?>" />
|
34 |
-
<input type="hidden" name="secure-pass" value="<?php echo DUPX_U::esc_attr($_POST['secure-pass']); ?>" />
|
35 |
-
|
36 |
-
<div class="dupx-logfile-link"><a href="<?php echo DUPX_U::esc_attr($GLOBALS["LOG_FILE_NAME"]);?>?now=<?php echo DUPX_U::esc_attr($GLOBALS['NOW_DATE']); ?>" target="install_log">dup-installer-log.txt</a></div>
|
37 |
-
<div class="hdr-main">
|
38 |
-
Step <span class="step">3</span> of 4: Update Data
|
39 |
-
</div>
|
40 |
-
|
41 |
-
<!-- ====================================
|
42 |
-
NEW SETTINGS
|
43 |
-
==================================== -->
|
44 |
-
<div class="hdr-sub1" style="margin-top:8px" data-type="toggle" data-target="#s3-new-settings">
|
45 |
-
<a href="javascript:void(0)"><i class="dupx-minus-square"></i> New Settings</a>
|
46 |
-
</div>
|
47 |
-
<div id='s3-new-settings'>
|
48 |
-
<table class="s3-table-inputs">
|
49 |
-
<tr>
|
50 |
-
<td style="width:80px">URL:</td>
|
51 |
-
<td>
|
52 |
-
<input type="text" name="url_new" id="url_new" value="" />
|
53 |
-
<a href="javascript:DUPX.getNewURL('url_new')" style="font-size:12px">get</a>
|
54 |
-
</td>
|
55 |
-
</tr>
|
56 |
-
<tr>
|
57 |
-
<td>Path:</td>
|
58 |
-
<td><input type="text" name="path_new" id="path_new" value="<?php echo DUPX_U::esc_attr($new_path); ?>" /></td>
|
59 |
-
</tr>
|
60 |
-
<tr>
|
61 |
-
<td>Title:</td>
|
62 |
-
<td><input type="text" name="blogname" id="blogname" value="<?php echo DUPX_U::esc_attr($GLOBALS['FW_BLOGNAME']); ?>" /></td>
|
63 |
-
</tr>
|
64 |
-
</table>
|
65 |
-
</div>
|
66 |
-
<br/><br/>
|
67 |
-
|
68 |
-
<!-- ====================================
|
69 |
-
OPTIONS
|
70 |
-
==================================== -->
|
71 |
-
<div class="hdr-sub1" data-type="toggle" data-target="#s3-adv-opts">
|
72 |
-
<a href="javascript:void(0)"><i class="dupx-plus-square"></i> Options</a>
|
73 |
-
</div>
|
74 |
-
<div id='s3-adv-opts' style="display:none;">
|
75 |
-
<div class="help-target"><a href="?help#help-s3" target="_blank">[help]</a></div>
|
76 |
-
<br/>
|
77 |
-
|
78 |
-
<div class="hdr-sub3">New Admin Account</div>
|
79 |
-
<div style="text-align: center; margin-top:7px">
|
80 |
-
<i style="color:gray;font-size: 11px">This feature is optional. If the username already exists the account will NOT be created or updated.</i>
|
81 |
-
</div>
|
82 |
-
<table class="s3-table-inputs">
|
83 |
-
<tr>
|
84 |
-
<td>Username:</td>
|
85 |
-
<td><input type="text" name="wp_username" id="wp_username" value="" title="4 characters minimum" placeholder="(4 or more characters)" /></td>
|
86 |
-
</tr>
|
87 |
-
<tr>
|
88 |
-
<td valign="top">Password:</td>
|
89 |
-
<td><input type="text" name="wp_password" id="wp_password" value="" title="6 characters minimum" placeholder="(6 or more characters)" /></td>
|
90 |
-
</tr>
|
91 |
-
</table>
|
92 |
-
<br/><br/>
|
93 |
-
|
94 |
-
<div class="hdr-sub3">Scan Options</div>
|
95 |
-
<table class="s3-table-inputs">
|
96 |
-
<tr>
|
97 |
-
<td>Site URL:</td>
|
98 |
-
<td>
|
99 |
-
<input type="text" name="siteurl" id="siteurl" value="" />
|
100 |
-
<a href="javascript:DUPX.getNewURL('siteurl')" style="font-size:12px">get</a><br/>
|
101 |
-
</td>
|
102 |
-
</tr>
|
103 |
-
<tr>
|
104 |
-
<td>Old URL:</td>
|
105 |
-
<td>
|
106 |
-
<input type="text" name="url_old" id="url_old" value="<?php echo DUPX_U::esc_attr($GLOBALS['FW_URL_OLD']); ?>" readonly="readonly" class="readonly" />
|
107 |
-
<a href="javascript:DUPX.editOldURL()" id="edit_url_old" style="font-size:12px">edit</a>
|
108 |
-
</td>
|
109 |
-
</tr>
|
110 |
-
<tr>
|
111 |
-
<td>Old Path:</td>
|
112 |
-
<td>
|
113 |
-
<input type="text" name="path_old" id="path_old" value="<?php echo DUPX_U::esc_attr($old_path); ?>" readonly="readonly" class="readonly" />
|
114 |
-
<a href="javascript:DUPX.editOldPath()" id="edit_path_old" style="font-size:12px">edit</a>
|
115 |
-
</td>
|
116 |
-
</tr>
|
117 |
-
</table><br/>
|
118 |
-
|
119 |
-
<table>
|
120 |
-
<tr>
|
121 |
-
<td style="padding-right:10px">
|
122 |
-
<b>Scan Tables:</b>
|
123 |
-
<div class="s3-allnonelinks">
|
124 |
-
<a href="javascript:void(0)" onclick="$('#tables option').prop('selected',true);">[All]</a>
|
125 |
-
<a href="javascript:void(0)" onclick="$('#tables option').prop('selected',false);">[None]</a>
|
126 |
-
</div><br style="clear:both" />
|
127 |
-
<select id="tables" name="tables[]" multiple="multiple">
|
128 |
-
<?php
|
129 |
-
foreach( $all_tables as $table ) {
|
130 |
-
echo '<option selected="selected" value="' . DUPX_U::esc_attr( $table ) . '">' . DUPX_U::esc_html($table) . '</option>';
|
131 |
-
}
|
132 |
-
?>
|
133 |
-
</select>
|
134 |
-
</td>
|
135 |
-
<td valign="top">
|
136 |
-
<b>Activate Plugins:</b>
|
137 |
-
<?php echo ($_POST['exe_safe_mode'] > 0) ? '<small class="s3-warn">Safe Mode Enabled</small>' : '' ; ?>
|
138 |
-
<div class="s3-allnonelinks" style="<?php echo ($_POST['exe_safe_mode']>0)? 'display:none':''; ?>">
|
139 |
-
<a href="javascript:void(0)" onclick="$('#plugins option').prop('selected',true);">[All]</a>
|
140 |
-
<a href="javascript:void(0)" onclick="$('#plugins option').prop('selected',false);">[None]</a>
|
141 |
-
</div><br style="clear:both" />
|
142 |
-
<select id="plugins" name="plugins[]" multiple="multiple" <?php echo ($_POST['exe_safe_mode'] > 0) ? 'disabled="disabled"' : ''; ?>>
|
143 |
-
<?php
|
144 |
-
$selected_string = ($_POST['exe_safe_mode'] > 0) ? '' : 'selected="selected"';
|
145 |
-
foreach ($active_plugins as $plugin) {
|
146 |
-
$plug_name = dirname($plugin);
|
147 |
-
echo "<option {$selected_string} value='".DUPX_U::esc_attr($plugin)."'>".DUPX_U::esc_html($plug_name)."</option>";
|
148 |
-
}
|
149 |
-
?>
|
150 |
-
</select>
|
151 |
-
</td>
|
152 |
-
</tr>
|
153 |
-
</table>
|
154 |
-
<br/>
|
155 |
-
|
156 |
-
<input type="checkbox" name="fullsearch" id="fullsearch" value="1" /> <label for="fullsearch">Use Database Full Search Mode </label><br/>
|
157 |
-
<input type="checkbox" name="postguid" id="postguid" value="1" /> <label for="postguid">Keep Post GUID Unchanged</label><br/>
|
158 |
-
<br/><br/>
|
159 |
-
|
160 |
-
<!-- WP-CONFIG -->
|
161 |
-
<div class="hdr-sub3">WP-Config File</div>
|
162 |
-
<table class="dupx-opts dupx-advopts">
|
163 |
-
<tr>
|
164 |
-
<td>Cache:</td>
|
165 |
-
<td style="width:125px"><input type="checkbox" name="cache_wp" id="cache_wp" /> <label for="cache_wp">Keep Enabled</label></td>
|
166 |
-
<td><input type="checkbox" name="cache_path" id="cache_path" /> <label for="cache_path">Keep Home Path</label></td>
|
167 |
-
</tr>
|
168 |
-
<tr>
|
169 |
-
<td>SSL:</td>
|
170 |
-
<td><input type="checkbox" name="ssl_admin" id="ssl_admin" /> <label for="ssl_admin">Enforce on Admin</label></td>
|
171 |
-
<td></td>
|
172 |
-
</tr>
|
173 |
-
</table>
|
174 |
-
<br/><br/><br/>
|
175 |
-
<br/><br/>
|
176 |
-
</div>
|
177 |
-
|
178 |
-
<div class="dupx-footer-buttons">
|
179 |
-
<input id="dup-step3-next" class="default-btn" type="button" value=" Next " onclick="DUPX.runUpdate()" />
|
180 |
-
</div>
|
181 |
-
</form>
|
182 |
-
|
183 |
-
|
184 |
-
<!-- =========================================
|
185 |
-
VIEW: STEP 3 - AJAX RESULT
|
186 |
-
========================================= -->
|
187 |
-
<form id='s3-result-form' method="post" class="content-form" style="display:none">
|
188 |
-
|
189 |
-
<div class="dupx-logfile-link"><a href="<?php echo DUPX_U::esc_attr($GLOBALS["LOG_FILE_NAME"]);?>" target="install_log">dup-installer-log.txt</a></div>
|
190 |
-
<div class="hdr-main">
|
191 |
-
Step <span class="step">3</span> of 4: Update Data
|
192 |
-
</div>
|
193 |
-
|
194 |
-
<!-- POST PARAMS -->
|
195 |
-
<div class="dupx-debug">
|
196 |
-
<input type="hidden" name="secure-pass" value="<?php echo DUPX_U::esc_attr($_POST['secure-pass']); ?>" />
|
197 |
-
<input type="hidden" name="action_step" value="4" />
|
198 |
-
<input type="hidden" name="retain_config" value="<?php echo DUPX_U::esc_attr($_POST['retain_config']); ?>" />
|
199 |
-
<input type="hidden" name="exe_safe_mode" id="exe-safe-mode" value="<?php echo DUPX_U::esc_attr($_POST['exe_safe_mode']); ?>"/>
|
200 |
-
<input type="hidden" name="url_new" id="ajax-url_new" />
|
201 |
-
<input type="hidden" name="json" id="ajax-json" />
|
202 |
-
<br/>
|
203 |
-
<input type='submit' value='manual submit'>
|
204 |
-
</div>
|
205 |
-
|
206 |
-
<!-- PROGRESS BAR -->
|
207 |
-
<div id="progress-area">
|
208 |
-
<div style="width:500px; margin:auto">
|
209 |
-
<h3>Updating Data Replacements Please Wait...</h3>
|
210 |
-
<div id="progress-bar"></div>
|
211 |
-
<i>This may take several minutes</i>
|
212 |
-
</div>
|
213 |
-
</div>
|
214 |
-
|
215 |
-
<!-- AJAX SYSTEM ERROR -->
|
216 |
-
<div id="ajaxerr-area" style="display:none">
|
217 |
-
<p>Please try again an issue has occurred.</p>
|
218 |
-
<div style="padding: 0px 10px 10px 10px;">
|
219 |
-
<div id="ajaxerr-data">An unknown issue has occurred with the update data set up process. Please see the dup-installer-log.txt file for more details.</div>
|
220 |
-
<div style="text-align:center; margin:10px auto 0px auto">
|
221 |
-
<input type="button" class="default-btn" onclick='DUPX.hideErrorResult2()' value="« Try Again" /><br/><br/>
|
222 |
-
<i style='font-size:11px'>See online help for more details at <a href='https://snapcreek.com/ticket?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=inst_step3_ajax' target='_blank'>snapcreek.com</a></i>
|
223 |
-
</div>
|
224 |
-
</div>
|
225 |
-
</div>
|
226 |
-
</form>
|
227 |
-
|
228 |
-
<script>
|
229 |
-
/**
|
230 |
-
* Timeout (10000000 = 166 minutes) */
|
231 |
-
DUPX.runUpdate = function()
|
232 |
-
{
|
233 |
-
//Validation
|
234 |
-
var wp_username = $.trim($("#wp_username").val()).length || 0;
|
235 |
-
var wp_password = $.trim($("#wp_password").val()).length || 0;
|
236 |
-
|
237 |
-
if ( $.trim($("#url_new").val()) == "" ) {alert("The 'New URL' field is required!"); return false;}
|
238 |
-
if ( $.trim($("#siteurl").val()) == "" ) {alert("The 'Site URL' field is required!"); return false;}
|
239 |
-
if (wp_username >= 1 && wp_username < 4) {alert("The New Admin Account 'Username' must be four or more characters"); return false;}
|
240 |
-
if (wp_username >= 4 && wp_password < 6) {alert("The New Admin Account 'Password' must be six or more characters"); return false;}
|
241 |
-
|
242 |
-
$.ajax({
|
243 |
-
type: "POST",
|
244 |
-
timeout: 1800000,
|
245 |
-
dataType: "json",
|
246 |
-
url: window.location.href,
|
247 |
-
data: $('#s3-input-form').serialize(),
|
248 |
-
beforeSend: function() {
|
249 |
-
DUPX.showProgressBar();
|
250 |
-
$('#s3-input-form').hide();
|
251 |
-
$('#s3-result-form').show();
|
252 |
-
},
|
253 |
-
success: function(data){
|
254 |
-
if (typeof(data) != 'undefined' && data.step3.pass == 1) {
|
255 |
-
$("#ajax-url_new").val($("#url_new").val());
|
256 |
-
$("#ajax-json").val(escape(JSON.stringify(data)));
|
257 |
-
<?php if (! $GLOBALS['DUPX_DEBUG']) : ?>
|
258 |
-
setTimeout(function(){$('#s3-result-form').submit();}, 500);
|
259 |
-
<?php endif; ?>
|
260 |
-
$('#progress-area').fadeOut(1000);
|
261 |
-
} else {
|
262 |
-
DUPX.hideProgressBar();
|
263 |
-
}
|
264 |
-
},
|
265 |
-
error: function(xhr) {
|
266 |
-
var status = "<b>Server Code:</b> " + xhr.status + "<br/>";
|
267 |
-
status += "<b>Status:</b> " + xhr.statusText + "<br/>";
|
268 |
-
status += "<b>Response:</b> " + xhr.responseText + "";
|
269 |
-
status += "<hr/><b>Additional Troubleshooting Tips:</b><br/>";
|
270 |
-
status += "- Check the <a href='<?php echo DUPX_U::esc_attr($GLOBALS["LOG_FILE_NAME"]);?>' target='install_log'>dup-installer-log.txt</a> file for warnings or errors.<br/>";
|
271 |
-
status += "- Check the web server and PHP error logs. <br/>";
|
272 |
-
status += "- For timeout issues visit the <a href='https://snapcreek.com/duplicator/docs/faqs-tech/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=inst_step3_ajax_rundepl#faq-trouble-100-q' target='_blank'>Timeout FAQ Section</a><br/>";
|
273 |
-
$('#ajaxerr-data').html(status);
|
274 |
-
DUPX.hideProgressBar();
|
275 |
-
}
|
276 |
-
});
|
277 |
-
}
|
278 |
-
|
279 |
-
/** Returns the windows active url */
|
280 |
-
DUPX.getNewURL = function(id)
|
281 |
-
{
|
282 |
-
var filename= window.location.pathname.split('/').pop() || 'installer.php' ;
|
283 |
-
var path = window.location.href.replace(filename, '').replace(/\/$/, '');
|
284 |
-
$("#" + id).val(path);
|
285 |
-
}
|
286 |
-
|
287 |
-
/** Allows user to edit the package url */
|
288 |
-
DUPX.editOldURL = function()
|
289 |
-
{
|
290 |
-
var msg = 'This is the URL that was generated when the package was created.\n';
|
291 |
-
msg += 'Changing this value may cause issues with the install process.\n\n';
|
292 |
-
msg += 'Only modify this value if you know exactly what the value should be.\n';
|
293 |
-
msg += 'See "General Settings" in the WordPress Administrator for more details.\n\n';
|
294 |
-
msg += 'Are you sure you want to continue?';
|
295 |
-
|
296 |
-
if (confirm(msg)) {
|
297 |
-
$("#url_old").removeAttr('readonly');
|
298 |
-
$("#url_old").removeClass('readonly');
|
299 |
-
$('#edit_url_old').hide('slow');
|
300 |
-
}
|
301 |
-
}
|
302 |
-
|
303 |
-
/** Allows user to edit the package path */
|
304 |
-
DUPX.editOldPath = function()
|
305 |
-
{
|
306 |
-
var msg = 'This is the SERVER URL that was generated when the package was created.\n';
|
307 |
-
msg += 'Changing this value may cause issues with the install process.\n\n';
|
308 |
-
msg += 'Only modify this value if you know exactly what the value should be.\n';
|
309 |
-
msg += 'Are you sure you want to continue?';
|
310 |
-
|
311 |
-
if (confirm(msg)) {
|
312 |
-
$("#path_old").removeAttr('readonly');
|
313 |
-
$("#path_old").removeClass('readonly');
|
314 |
-
$('#edit_path_old').hide('slow');
|
315 |
-
}
|
316 |
-
}
|
317 |
-
|
318 |
-
/** Go back on AJAX result view */
|
319 |
-
DUPX.hideErrorResult2 = function()
|
320 |
-
{
|
321 |
-
$('#s3-result-form').hide();
|
322 |
-
$('#s3-input-form').show(200);
|
323 |
-
}
|
324 |
-
|
325 |
-
//DOCUMENT LOAD
|
326 |
-
$(document).ready(function()
|
327 |
-
{
|
328 |
-
DUPX.getNewURL('url_new');
|
329 |
-
DUPX.getNewURL('siteurl');
|
330 |
-
$("*[data-type='toggle']").click(DUPX.toggleClick);
|
331 |
-
$("#wp_password").passStrength({
|
332 |
-
shortPass: "top_shortPass",
|
333 |
-
badPass: "top_badPass",
|
334 |
-
goodPass: "top_goodPass",
|
335 |
-
strongPass: "top_strongPass",
|
336 |
-
baseStyle: "top_testresult",
|
337 |
-
userid: "#wp_username",
|
338 |
-
messageloc: 1 });
|
339 |
-
});
|
340 |
-
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/dup-installer/assets/font-awesome/css/font-awesome.min.css
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
/*!
|
2 |
+
* Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
|
3 |
+
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
|
4 |
+
*/@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:bef
|