Import any XML or CSV File to WordPress - Version 3.0

Version Description

  • Free edition of 3.0 pro release
Download this release

Release Info

Developer soflyy
Plugin Icon 128x128 Import any XML or CSV File to WordPress
Version 3.0
Comparing to
See all releases

Code changes from version 2.14 to 3.0

Files changed (78) hide show
  1. actions/admin_menu.php +6 -6
  2. actions/admin_notices.php +4 -2
  3. actions/wp_loaded.php +1 -3
  4. classes/chunk.php +358 -0
  5. classes/download.php +39 -0
  6. classes/helper.php +10 -7
  7. config/options.php +2 -1
  8. controllers/admin/import.php +762 -609
  9. controllers/admin/manage.php +233 -52
  10. controllers/admin/settings.php +135 -5
  11. controllers/controller/admin.php +24 -13
  12. helpers/get_file_curl.php +90 -0
  13. helpers/import_custom_meta_box.php +29 -0
  14. helpers/pmxi_functions.php +285 -0
  15. libraries/XmlImportCsvParse.php +84 -1281
  16. libraries/XmlImportParser.php +13 -3
  17. libraries/XmlImportTemplateCodeGenerator.php +59 -61
  18. libraries/XmlImportTemplateParser.php +12 -61
  19. libraries/ast/XmlImportAstSpintax.php +2 -5
  20. libraries/pclzip.lib.php +5697 -0
  21. models/file/record.php +11 -5
  22. models/import/record.php +618 -565
  23. plugin.php +138 -22
  24. readme.txt +41 -26
  25. schema.php +16 -2
  26. screenshot-1.png +0 -0
  27. screenshot-2.png +0 -0
  28. screenshot-3.png +0 -0
  29. screenshot-4.png +0 -0
  30. static/css/admin.css +497 -36
  31. static/img/loading.gif +0 -0
  32. static/img/loading.png +0 -0
  33. static/img/progress_animated.gif +0 -0
  34. static/js/admin.js +164 -19
  35. static/js/jquery/css/redmond/images/animated-overlay.gif +0 -0
  36. static/js/jquery/css/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  37. static/js/jquery/css/redmond/images/ui-bg_flat_0_aaaaaa_40x100_1.png +0 -0
  38. static/js/jquery/css/redmond/images/ui-bg_flat_55_fbec88_40x100.png +0 -0
  39. static/js/jquery/css/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
  40. static/js/jquery/css/redmond/images/ui-bg_glass_85_dfeffc_1x400.png +0 -0
  41. static/js/jquery/css/redmond/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  42. static/js/jquery/css/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
  43. static/js/jquery/css/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
  44. static/js/jquery/css/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
  45. static/js/jquery/css/redmond/images/ui-icons_217bc0_256x240.png +0 -0
  46. static/js/jquery/css/redmond/images/ui-icons_2e83ff_256x240.png +0 -0
  47. static/js/jquery/css/redmond/images/ui-icons_469bdd_256x240.png +0 -0
  48. static/js/jquery/css/redmond/images/ui-icons_6da8d5_256x240.png +0 -0
  49. static/js/jquery/css/redmond/images/ui-icons_cd0a0a_256x240.png +0 -0
  50. static/js/jquery/css/redmond/images/ui-icons_d8e7f3_256x240.png +0 -0
  51. static/js/jquery/css/redmond/images/ui-icons_f9bd01_256x240.png +0 -0
  52. static/js/jquery/css/redmond/jquery-ui.css +1177 -0
  53. static/js/jquery/jquery.mjs.nestedSortable.js +1 -1
  54. static/js/jquery/moment.js +6 -0
  55. static/js/plupload/plupload.flash.swf +0 -0
  56. static/js/plupload/plupload.full.js +2 -0
  57. static/js/plupload/plupload.silverlight.xap +0 -0
  58. static/js/plupload/wplupload.js +116 -0
  59. static/js/pmxi.js +1 -8
  60. views/admin/import/element_after.php +46 -27
  61. views/admin/import/evaluate.php +9 -4
  62. views/admin/import/index.php +83 -62
  63. views/admin/import/options.php +131 -375
  64. views/admin/import/options/_author_template.php +20 -0
  65. views/admin/import/options/_buttons_template.php +61 -0
  66. views/admin/import/options/_categories_template.php +53 -0
  67. views/admin/import/options/_custom_fields_template.php +43 -0
  68. views/admin/import/options/_featured_template.php +27 -0
  69. views/admin/import/options/_main_options_template.php +96 -0
  70. views/admin/import/options/_reimport_template.php +132 -0
  71. views/admin/import/options/_taxonomies_template.php +53 -0
  72. views/admin/import/process.php +92 -11
  73. views/admin/import/tag.php +7 -4
  74. views/admin/import/template.php +80 -69
  75. views/admin/manage/delete.php +4 -2
  76. views/admin/manage/index.php +56 -35
  77. views/admin/manage/update.php +1 -1
  78. views/admin/settings/index.php +2 -3
actions/admin_menu.php CHANGED
@@ -5,18 +5,18 @@
5
 
6
  function pmxi_admin_menu() {
7
  global $menu, $submenu;
8
-
9
  if (current_user_can('manage_options')) { // admin management options
10
-
11
  add_menu_page(__('WP All Import', 'pmxi_plugin'), __('All Import', 'pmxi_plugin'), 'manage_options', 'pmxi-admin-home', array(PMXI_Plugin::getInstance(), 'adminDispatcher'), PMXI_Plugin::ROOT_URL . '/static/img/xmlicon.png');
12
  // workaround to rename 1st option to `Home`
13
- $submenu['pmxi-admin-home'] = array();
14
  add_submenu_page('pmxi-admin-home', __('Import XML', 'pmxi_plugin') . ' ‹ ' . __('WP All Import', 'pmxi_plugin'), __('New Import', 'pmxi_plugin'), 'manage_options', 'pmxi-admin-import', array(PMXI_Plugin::getInstance(), 'adminDispatcher'));
15
  add_submenu_page('pmxi-admin-home', __('Manage Previous Imports', 'pmxi_plugin') . ' ‹ ' . __('WP All Import', 'pmxi_plugin'), __('Manage Imports', 'pmxi_plugin'), 'manage_options', 'pmxi-admin-manage', array(PMXI_Plugin::getInstance(), 'adminDispatcher'));
16
  add_submenu_page('pmxi-admin-home', __('Settings', 'pmxi_plugin') . ' ‹ ' . __('WP All Import', 'pmxi_plugin'), __('Settings', 'pmxi_plugin'), 'manage_options', 'pmxi-admin-settings', array(PMXI_Plugin::getInstance(), 'adminDispatcher'));
17
- //add_submenu_page('pmxi-admin-home', __('WP All Import', 'pmxi_plugin'), __('About', 'pmxi_plugin'), 'manage_options', 'pmxi-admin-home', array(PMXI_Plugin::getInstance(), 'adminDispatcher'));
18
  // add_submenu_page('pmxi-admin-home', __('Help', 'pmxi_plugin') . ' ‹ ' . __('WP All Import', 'pmxi_plugin'), __('Help', 'pmxi_plugin'), 'manage_options', 'pmxi-admin-help', array(PMXI_Plugin::getInstance(), 'adminDispatcher'));
19
-
20
- }
21
  }
22
 
5
 
6
  function pmxi_admin_menu() {
7
  global $menu, $submenu;
8
+
9
  if (current_user_can('manage_options')) { // admin management options
10
+
11
  add_menu_page(__('WP All Import', 'pmxi_plugin'), __('All Import', 'pmxi_plugin'), 'manage_options', 'pmxi-admin-home', array(PMXI_Plugin::getInstance(), 'adminDispatcher'), PMXI_Plugin::ROOT_URL . '/static/img/xmlicon.png');
12
  // workaround to rename 1st option to `Home`
13
+ $submenu['pmxi-admin-home'] = array();
14
  add_submenu_page('pmxi-admin-home', __('Import XML', 'pmxi_plugin') . ' ‹ ' . __('WP All Import', 'pmxi_plugin'), __('New Import', 'pmxi_plugin'), 'manage_options', 'pmxi-admin-import', array(PMXI_Plugin::getInstance(), 'adminDispatcher'));
15
  add_submenu_page('pmxi-admin-home', __('Manage Previous Imports', 'pmxi_plugin') . ' ‹ ' . __('WP All Import', 'pmxi_plugin'), __('Manage Imports', 'pmxi_plugin'), 'manage_options', 'pmxi-admin-manage', array(PMXI_Plugin::getInstance(), 'adminDispatcher'));
16
  add_submenu_page('pmxi-admin-home', __('Settings', 'pmxi_plugin') . ' ‹ ' . __('WP All Import', 'pmxi_plugin'), __('Settings', 'pmxi_plugin'), 'manage_options', 'pmxi-admin-settings', array(PMXI_Plugin::getInstance(), 'adminDispatcher'));
17
+ // add_submenu_page('pmxi-admin-home', __('WP All Import', 'pmxi_plugin'), __('About', 'pmxi_plugin'), 'manage_options', 'pmxi-admin-home', array(PMXI_Plugin::getInstance(), 'adminDispatcher'));
18
  // add_submenu_page('pmxi-admin-home', __('Help', 'pmxi_plugin') . ' ‹ ' . __('WP All Import', 'pmxi_plugin'), __('Help', 'pmxi_plugin'), 'manage_options', 'pmxi-admin-help', array(PMXI_Plugin::getInstance(), 'adminDispatcher'));
19
+
20
+ }
21
  }
22
 
actions/admin_notices.php CHANGED
@@ -2,13 +2,15 @@
2
 
3
  function pmxi_admin_notices() {
4
  // notify user if history folder is not writable
5
- if ( ! is_dir(PMXI_Plugin::ROOT_DIR . '/history') or ! is_writable(PMXI_Plugin::ROOT_DIR . '/history')) {
 
 
6
  ?>
7
  <div class="error"><p>
8
  <?php printf(
9
  __('<b>%s Plugin</b>: History folder %s must be writable for the plugin to function properly. Please deactivate the plugin, set proper permissions to the folder and activate the plugin again.', 'pmxi_plugin'),
10
  PMXI_Plugin::getInstance()->getName(),
11
- PMXI_Plugin::ROOT_DIR . '/history'
12
  ) ?>
13
  </p></div>
14
  <?php
2
 
3
  function pmxi_admin_notices() {
4
  // notify user if history folder is not writable
5
+ $uploads = wp_upload_dir();
6
+
7
+ if ( ! is_dir($uploads['basedir'] . '/wpallimport_history') or ! is_writable($uploads['basedir'] . '/wpallimport_history')) {
8
  ?>
9
  <div class="error"><p>
10
  <?php printf(
11
  __('<b>%s Plugin</b>: History folder %s must be writable for the plugin to function properly. Please deactivate the plugin, set proper permissions to the folder and activate the plugin again.', 'pmxi_plugin'),
12
  PMXI_Plugin::getInstance()->getName(),
13
+ $uploads['basedir'] . '/wpallimport_history'
14
  ) ?>
15
  </p></div>
16
  <?php
actions/wp_loaded.php CHANGED
@@ -2,8 +2,6 @@
2
 
3
  function pmxi_wp_loaded() {
4
 
5
- ini_set("max_input_time", PMXI_Plugin::getInstance()->getOption('max_input_time'));
6
- ini_set("max_execution_time", PMXI_Plugin::getInstance()->getOption('max_execution_time'));
7
 
8
- wp_enqueue_script('pmxi-script', PMXI_Plugin::getInstance()->getRelativePath() . '/static/js/pmxi.js', array('jquery'));
9
  }
2
 
3
  function pmxi_wp_loaded() {
4
 
 
 
5
 
6
+
7
  }
classes/chunk.php ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Chunk
4
+ *
5
+ * Reads a large file in as chunks for easier parsing.
6
+ *
7
+ * The chunks returned are whole <$this->options['element']/>s found within file.
8
+ *
9
+ * Each call to read() returns the whole element including start and end tags.
10
+ *
11
+ * Tested with a 1.8MB file, extracted 500 elements in 0.11s
12
+ * (with no work done, just extracting the elements)
13
+ *
14
+ * Usage:
15
+ * <code>
16
+ * // initialize the object
17
+ * $file = new Chunk('chunk-test.xml', array('element' => 'Chunk'));
18
+ *
19
+ * // loop through the file until all lines are read
20
+ * while ($xml = $file->read()) {
21
+ * // do whatever you want with the string
22
+ * $o = simplexml_load_string($xml);
23
+ * }
24
+ * </code>
25
+ *
26
+ * @package default
27
+ * @author Dom Hastings
28
+ */
29
+ class PMXI_Chunk {
30
+ /**
31
+ * options
32
+ *
33
+ * @var array Contains all major options
34
+ * @access public
35
+ */
36
+ public $options = array(
37
+ 'path' => './', // string The path to check for $file in
38
+ 'element' => '', // string The XML element to return
39
+ 'chunkSize' => 4096, // integer The amount of bytes to retrieve in each chunk
40
+ 'type' => 'upload'
41
+ );
42
+
43
+ /**
44
+ * file
45
+ *
46
+ * @var string The filename being read
47
+ * @access public
48
+ */
49
+ public $file = '';
50
+ /**
51
+ * pointer
52
+ *
53
+ * @var integer The current position the file is being read from
54
+ * @access public
55
+ */
56
+ public $pointer = 0;
57
+
58
+ public $cloud = array();
59
+
60
+ /**
61
+ * handle
62
+ *
63
+ * @var resource The fopen() resource
64
+ * @access private
65
+ */
66
+ private $handle = null;
67
+ /**
68
+ * reading
69
+ *
70
+ * @var boolean Whether the script is currently reading the file
71
+ * @access private
72
+ */
73
+ private $reading = false;
74
+ /**
75
+ * readBuffer
76
+ *
77
+ * @var string Used to make sure start tags aren't missed
78
+ * @access private
79
+ */
80
+ private $readBuffer = '';
81
+
82
+ /**
83
+ * __construct
84
+ *
85
+ * Builds the Chunk object
86
+ *
87
+ * @param string $file The filename to work with
88
+ * @param array $options The options with which to parse the file
89
+ * @author Dom Hastings
90
+ * @access public
91
+ */
92
+ public function __construct($file, $options = array(), $pointer = 0) {
93
+ // merge the options together
94
+ $this->options = array_merge($this->options, (is_array($options) ? $options : array()));
95
+
96
+ // check that the path ends with a /
97
+ if (substr($this->options['path'], -1) != '/') {
98
+ $this->options['path'] .= '/';
99
+ }
100
+
101
+ // normalize the filename
102
+ $file_base = basename($file);
103
+
104
+ // make sure chunkSize is an int
105
+ $this->options['chunkSize'] = intval($this->options['chunkSize']);
106
+
107
+ // check it's valid
108
+ if ($this->options['chunkSize'] < 64) {
109
+ $this->options['chunkSize'] = 1024;
110
+ }
111
+
112
+ $this->pointer = $pointer;
113
+
114
+ // set the filename
115
+ $this->file = ($this->options['path'] != './') ? realpath($this->options['path'].$file_base) : $file;
116
+
117
+ // check the file exists
118
+ if (!file_exists($this->file)){
119
+ throw new Exception('File doesn\'t exist');
120
+ }
121
+
122
+ // open the file
123
+ $this->handle = fopen($this->file, 'rb');
124
+
125
+ // check the file opened successfully
126
+ if (!$this->handle) {
127
+ throw new Exception('Error opening file for reading');
128
+ }
129
+
130
+ }
131
+
132
+ /**
133
+ * __destruct
134
+ *
135
+ * Cleans up
136
+ *
137
+ * @return void
138
+ * @author Dom Hastings
139
+ * @access public
140
+ */
141
+ public function __destruct() {
142
+ // close the file resource
143
+ fclose($this->handle);
144
+ }
145
+
146
+ /**
147
+ * read
148
+ *
149
+ * Reads the first available occurence of the XML element $this->options['element']
150
+ *
151
+ * @return string The XML string from $this->file
152
+ * @author Dom Hastings
153
+ * @access public
154
+ */
155
+ public function read() {
156
+ // check we have an element specified
157
+ if (!empty($this->options['element'])) {
158
+ // trim it
159
+ $element = trim($this->options['element']);
160
+
161
+ } else {
162
+ $element = '';
163
+ }
164
+
165
+ // initialize the buffer
166
+ $buffer = false;
167
+
168
+ // if the element is empty, then start auto detect root element tag name
169
+ if (empty($element)) {
170
+ // let the script know we're reading
171
+ $this->reading = true;
172
+ $founded_tags = array();
173
+ // read in the whole doc, cos we don't know what's wanted
174
+ while ($this->reading) {
175
+ $c = fread($this->handle, $this->options['chunkSize']);
176
+ if ( preg_match_all("/<\\w+\\s*[^<]*\\s*\/?>/i", $c, $matches, PREG_PATTERN_ORDER) ){
177
+ foreach ($matches[0] as $tag) {
178
+ $tag = explode(" ",trim(str_replace(array('<','>','/'), '', $tag)));
179
+ array_push($founded_tags, $tag[0]);
180
+ }
181
+ }
182
+ $this->reading = (!feof($this->handle));
183
+ }
184
+
185
+ // we must be looking for a specific element
186
+ }
187
+
188
+ if (empty($element) and !empty($founded_tags)) {
189
+
190
+ $element_counts = array_count_values($founded_tags);
191
+
192
+ if (!empty($element_counts)){
193
+
194
+ $this->cloud = array_slice($element_counts, 0, 2);
195
+
196
+ foreach ($element_counts as $tag => $count) {
197
+ if ($count > 1 and empty($this->options['element'])) {
198
+ $this->options['element'] = $element = $tag;
199
+ }
200
+ elseif ($count > 1){
201
+ $this->cloud[$tag] = $count;
202
+ }
203
+ }
204
+ }
205
+
206
+ }
207
+
208
+ // return it all if element doesn't founded
209
+ if (empty($element))
210
+ return false;
211
+
212
+ // we must be looking for a specific element
213
+ //}
214
+
215
+ // initialize the buffer
216
+ $buffer = false;
217
+
218
+ // set up the strings to find
219
+ $open = '<'.$element;
220
+ $close = '</'.$element.'>';
221
+
222
+ // let the script know we're reading
223
+ $this->reading = true;
224
+
225
+ // reset the global buffer
226
+ $this->readBuffer = '';
227
+
228
+ // this is used to ensure all data is read, and to make sure we don't send the start data again by mistake
229
+ $store = false;
230
+
231
+ // seek to the position we need in the file
232
+ fseek($this->handle, $this->pointer);
233
+
234
+ // start reading
235
+ while ($this->reading && !feof($this->handle)) {
236
+
237
+ // store the chunk in a temporary variable
238
+ $tmp = fread($this->handle, $this->options['chunkSize']);
239
+
240
+ // update the global buffer
241
+ $this->readBuffer .= $tmp;
242
+
243
+ // check for the open string
244
+ $checkOpen = strpos($tmp, $open." ");
245
+ if (!$checkOpen) $checkOpen = strpos($tmp, $open.">");
246
+
247
+ // if it wasn't in the new buffer
248
+ if (!$checkOpen && !($store)) {
249
+ // check the full buffer (in case it was only half in this buffer)
250
+ $checkOpen = strpos($this->readBuffer, $open." ");
251
+ if (!$checkOpen) $checkOpen = strpos($this->readBuffer, $open.">");
252
+
253
+ // if it was in there
254
+ if ($checkOpen) {
255
+ // set it to the remainder
256
+ $checkOpen = $checkOpen % $this->options['chunkSize'];
257
+ }
258
+ }
259
+
260
+ // check for the close string
261
+ $checkClose = strpos($tmp, $close);
262
+ $withoutcloseelement = false;
263
+ if (!$checkClose){
264
+ $checkClose = (preg_match_all("/\/>\s*".$open."\s*/", $this->readBuffer, $matches)) ? strpos($this->readBuffer, $matches[0][0]) : false;
265
+ if ($checkClose)
266
+ $withoutcloseelement = true;
267
+ else{
268
+ /*$checkClose = (preg_match_all("/\s*\/>\s*<\/", $this->readBuffer, $matches)) ? strpos($this->readBuffer, $matches[0][0]) : false;
269
+ if ($checkClose)
270
+ $withoutcloseelement = true;*/
271
+ }
272
+ }
273
+
274
+ // if it wasn't in the new buffer
275
+ if (!$checkClose && ($store)) {
276
+ // check the full buffer (in case it was only half in this buffer)
277
+ $checkClose = strpos($this->readBuffer, $close);
278
+
279
+ $withoutcloseelement = false;
280
+ if (!$checkClose){
281
+ $checkClose = (preg_match_all("/\/>\s*".$open."\s*/", $this->readBuffer, $matches)) ? strpos($this->readBuffer, $matches[0][0]) : false;
282
+ if ($checkClose)
283
+ $withoutcloseelement = true;
284
+ else{
285
+ /*$checkClose = (preg_match_all("//>\\s*<\//", $this->readBuffer, $matches)) ? strpos($this->readBuffer, $matches[0][0]) : false;
286
+ if ($checkClose)
287
+ $withoutcloseelement = true;*/
288
+ }
289
+ }
290
+ // if it was in there
291
+ if ($checkClose) {
292
+ // set it to the remainder plus the length of the close string itself
293
+ if (!$withoutcloseelement){
294
+ $checkClose = ($checkClose + strlen($close)) % $this->options['chunkSize'];
295
+ }else{
296
+ $checkClose = ($checkClose + strlen("/>")) % $this->options['chunkSize'];
297
+ }
298
+ }
299
+
300
+ // if it was
301
+ } elseif ($checkClose) {
302
+ // add the length of the close string itself
303
+ if ( ! $withoutcloseelement)
304
+ $checkClose += strlen($close);
305
+ else
306
+ $checkClose += strlen("/>"); // "/>" symbols
307
+ }
308
+
309
+ // if we've found the opening string and we're not already reading another element
310
+ if ($checkOpen !== false && !($store)) {
311
+ // if we're found the end element too
312
+ if ($checkClose !== false) {
313
+ // append the string only between the start and end element
314
+ $buffer .= substr($tmp, $checkOpen, ($checkClose - $checkOpen));
315
+
316
+ // update the pointer
317
+ $this->pointer += $checkClose;
318
+
319
+ // let the script know we're done
320
+ $this->reading = false;
321
+
322
+ } else {
323
+ // append the data we know to be part of this element
324
+ $buffer .= substr($tmp, $checkOpen);
325
+
326
+ // update the pointer
327
+ $this->pointer += $this->options['chunkSize'];
328
+
329
+ // let the script know we're gonna be storing all the data until we find the close element
330
+ $store = true;
331
+ }
332
+
333
+ // if we've found the closing element
334
+ } elseif ($checkClose !== false) {
335
+ // update the buffer with the data upto and including the close tag
336
+ $buffer .= substr($tmp, 0, $checkClose);
337
+
338
+ // update the pointer
339
+ $this->pointer += $checkClose;
340
+
341
+ // let the script know we're done
342
+ $this->reading = false;
343
+
344
+ // if we've found the closing element, but half in the previous chunk
345
+ } elseif ($store) {
346
+ // update the buffer
347
+ $buffer .= $tmp;
348
+
349
+ // and the pointer
350
+ $this->pointer += $this->options['chunkSize'];
351
+ }
352
+
353
+ }
354
+
355
+ // return the element (or the whole file if we're not looking for elements)
356
+ return $buffer;
357
+ }
358
+ }
classes/download.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class PMXI_Download
4
+ {
5
+
6
+ static public function zip($file_name)
7
+ {
8
+
9
+ header('Content-type: application/zip');
10
+ header("Content-Disposition: attachment; filename=\"".basename($file_name)."\"");
11
+ readfile($file_name);
12
+ die;
13
+ }
14
+
15
+ static public function xls($file_name)
16
+ {
17
+ header("Content-Type: application/vnd.ms-excel; charset=UTF-8");
18
+ header("Content-Disposition: attachment; filename=\"".basename($file_name)."\"");
19
+ readfile($file_name);
20
+ die;
21
+ }
22
+
23
+ static public function csv($file_name)
24
+ {
25
+ header("Content-Type: text/plain; charset=UTF-8");
26
+ header("Content-Disposition: attachment; filename=\"".basename($file_name)."\"");
27
+ readfile($file_name);
28
+ die;
29
+ }
30
+
31
+ static public function xml($file_name)
32
+ {
33
+ header("Content-Type: application/xhtml+xml; charset=UTF-8");
34
+ header("Content-Disposition: attachment; filename=\"".basename($file_name)."\"");
35
+ readfile($file_name);
36
+ die;
37
+ }
38
+
39
+ }
classes/helper.php CHANGED
@@ -36,25 +36,26 @@ class PMXI_Helper {
36
  $split = explode('/', str_replace('\\', '/', $pattern));
37
  $mask = array_pop($split);
38
  $path = implode('/', $split);
39
- if (($dir = opendir($path)) !== false) {
 
40
  $glob = array();
41
  while(($file = readdir($dir)) !== false) {
42
  // Recurse subdirectories (self::GLOB_RECURSE)
43
  if (($flags & self::GLOB_RECURSE) && is_dir($path . '/' . $file) && ( ! in_array($file, array('.', '..')))) {
44
  $glob = array_merge($glob, self::array_prepend(self::safe_glob($path . '/' . $file . '/' . $mask, $flags), ($flags & self::GLOB_PATH ? '' : $file . '/')));
45
  }
46
- // Match file mask
47
- if (self::fnmatch($mask, $file)) {
48
  if ((( ! ($flags & self::GLOB_ONLYDIR)) || is_dir("$path/$file"))
49
  && (( ! ($flags & self::GLOB_NODIR)) || ( ! is_dir($path . '/' . $file)))
50
  && (( ! ($flags & self::GLOB_NODOTS)) || ( ! in_array($file, array('.', '..'))))
51
  ) {
52
  $glob[] = ($flags & self::GLOB_PATH ? $path . '/' : '') . $file . ($flags & self::GLOB_MARK ? '/' : '');
53
  }
54
- }
55
  }
56
  closedir($dir);
57
- if ( ! ($flags & self::GLOB_NOSORT)) sort($glob);
58
  return $glob;
59
  } else {
60
  return false;
@@ -95,6 +96,7 @@ class PMXI_Helper {
95
  * non-POSIX complient remplacement for the fnmatch
96
  */
97
  public static function fnmatch($pattern, $string, $flags = 0) {
 
98
  $modifiers = null;
99
  $transforms = array(
100
  '\*' => '.*',
@@ -103,7 +105,8 @@ class PMXI_Helper {
103
  '\[' => '[',
104
  '\]' => ']',
105
  '\.' => '\.',
106
- '\\' => '\\\\'
 
107
  );
108
 
109
  // Forward slash in string must be in pattern:
@@ -130,7 +133,7 @@ class PMXI_Helper {
130
  .strtr(preg_quote($pattern, '#'), $transforms)
131
  .'$#'
132
  .$modifiers;
133
-
134
  return (boolean)preg_match($pattern, $string);
135
  }
136
  }
36
  $split = explode('/', str_replace('\\', '/', $pattern));
37
  $mask = array_pop($split);
38
  $path = implode('/', $split);
39
+
40
+ if (($dir = @opendir($path)) !== false or ($dir = @opendir($path . '/')) !== false) {
41
  $glob = array();
42
  while(($file = readdir($dir)) !== false) {
43
  // Recurse subdirectories (self::GLOB_RECURSE)
44
  if (($flags & self::GLOB_RECURSE) && is_dir($path . '/' . $file) && ( ! in_array($file, array('.', '..')))) {
45
  $glob = array_merge($glob, self::array_prepend(self::safe_glob($path . '/' . $file . '/' . $mask, $flags), ($flags & self::GLOB_PATH ? '' : $file . '/')));
46
  }
47
+ // Match file mask
48
+ if (self::fnmatch($mask, $file)) {
49
  if ((( ! ($flags & self::GLOB_ONLYDIR)) || is_dir("$path/$file"))
50
  && (( ! ($flags & self::GLOB_NODIR)) || ( ! is_dir($path . '/' . $file)))
51
  && (( ! ($flags & self::GLOB_NODOTS)) || ( ! in_array($file, array('.', '..'))))
52
  ) {
53
  $glob[] = ($flags & self::GLOB_PATH ? $path . '/' : '') . $file . ($flags & self::GLOB_MARK ? '/' : '');
54
  }
55
+ }
56
  }
57
  closedir($dir);
58
+ if ( ! ($flags & self::GLOB_NOSORT)) sort($glob);
59
  return $glob;
60
  } else {
61
  return false;
96
  * non-POSIX complient remplacement for the fnmatch
97
  */
98
  public static function fnmatch($pattern, $string, $flags = 0) {
99
+
100
  $modifiers = null;
101
  $transforms = array(
102
  '\*' => '.*',
105
  '\[' => '[',
106
  '\]' => ']',
107
  '\.' => '\.',
108
+ '\\' => '\\\\',
109
+ '\-' => '-',
110
  );
111
 
112
  // Forward slash in string must be in pattern:
133
  .strtr(preg_quote($pattern, '#'), $transforms)
134
  .'$#'
135
  .$modifiers;
136
+
137
  return (boolean)preg_match($pattern, $string);
138
  }
139
  }
config/options.php CHANGED
@@ -14,5 +14,6 @@ $config = array(
14
  "max_execution_time" => -1,
15
  "dismiss" => 0,
16
  "html_entities" => 0,
17
- "utf8_decode" => 0
 
18
  );
14
  "max_execution_time" => -1,
15
  "dismiss" => 0,
16
  "html_entities" => 0,
17
+ "utf8_decode" => 0,
18
+ "cron_job_key" => url_title(rand_char(12))
19
  );
controllers/admin/import.php CHANGED
@@ -12,22 +12,32 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
12
  protected function init() {
13
  parent::init();
14
 
 
 
 
 
 
 
 
 
 
 
15
  // enable sessions
16
  if ( ! session_id()) session_start();
17
 
18
  if ('PMXI_Admin_Manage' == PMXI_Plugin::getInstance()->getAdminCurrentScreen()->base) { // prereqisites are not checked when flow control is deligated
19
  $id = $this->input->get('id');
20
- $this->data['import'] = $import = new PMXI_Import_Record();
21
  if ( ! $id or $import->getById($id)->isEmpty()) { // specified import is not found
22
  wp_redirect(add_query_arg('page', 'pmxi-admin-manage', admin_url('admin.php'))); die();
23
  }
24
  $this->isWizard = false;
25
 
26
  } else {
27
- $action = PMXI_Plugin::getInstance()->getAdminCurrentScreen()->action;
28
  $this->_step_ready($action);
29
  $this->isInline = 'process' == $action;
30
- }
31
 
32
  XmlImportConfig::getInstance()->setCacheDirectory(sys_get_temp_dir());
33
 
@@ -42,34 +52,38 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
42
  public function get($var)
43
  {
44
  return $this->{$var};
45
- }
46
 
47
  /**
48
  * Checks whether corresponding step of wizard is complete
49
  * @param string $action
50
  */
51
- protected function _step_ready($action) {
52
  // step #1: xml selction - has no prerequisites
53
  if ('index' == $action) return true;
54
 
55
  // step #2: element selection
56
- $this->data['dom'] = $dom = new DOMDocument();
57
  $this->data['update_previous'] = $update_previous = new PMXI_Import_Record();
58
  $old = libxml_use_internal_errors(true);
 
59
  if (empty($_SESSION['pmxi_import'])
60
- or ! $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $_SESSION['pmxi_import']['xml'])) // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
61
- or empty($_SESSION['pmxi_import']['source'])
62
  or ! empty($_SESSION['pmxi_import']['update_previous']) and $update_previous->getById($_SESSION['pmxi_import']['update_previous'])->isEmpty()
63
  ) {
 
64
  wp_redirect_or_javascript($this->baseUrl); die();
65
  }
66
  libxml_use_internal_errors($old);
67
  if ('element' == $action) return true;
68
  if ('evaluate' == $action) return true;
69
-
70
  // step #3: template
71
  $xpath = new DOMXPath($dom);
 
72
  if (empty($_SESSION['pmxi_import']['xpath']) or ! ($this->data['elements'] = $elements = $xpath->query($_SESSION['pmxi_import']['xpath'])) or ! $elements->length) {
 
73
  wp_redirect_or_javascript(add_query_arg('action', 'element', $this->baseUrl)); die();
74
  }
75
  if ('template' == $action or 'preview' == $action or 'tag' == $action) return true;
@@ -90,7 +104,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
90
  */
91
  public function index() {
92
 
93
- $import = new PMXI_Import_Record();
94
  $this->data['id'] = $id = $this->input->get('id');
95
  if ($id and $import->getById($id)->isEmpty()) { // update requested but corresponding import is not found
96
  wp_redirect(remove_query_arg('id', $this->baseUrl)); die();
@@ -104,495 +118,283 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
104
  'reimport' => '',
105
  'is_update_previous' => $id ? 1 : 0,
106
  'update_previous' => $id,
 
 
 
 
107
  ));
108
-
109
- $this->data['imports'] = $imports = new PMXI_Import_List();
110
- $imports->setColumns('id', 'name', 'registered_on', 'path')->getBy(NULL, 'name ASC, registered_on DESC');
111
-
112
  $this->data['history'] = $history = new PMXI_File_List();
113
  $history->setColumns('id', 'name', 'registered_on', 'path')->getBy(NULL, 'id DESC');
114
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  if ($this->input->post('is_submitted_continue')) {
116
  if ( ! empty($_SESSION['pmxi_import']['xml'])) {
117
  wp_redirect(add_query_arg('action', 'element', $this->baseUrl)); die();
118
  }
119
- } elseif ('upload' == $this->input->post('type')) {
120
- if (empty($_FILES['upload']) or empty($_FILES['upload']['name'])) {
 
 
 
121
  $this->errors->add('form-validation', __('XML/CSV file must be specified', 'pmxi_plugin'));
122
- } elseif (empty($_FILES['upload']['size'])) {
123
  $this->errors->add('form-validation', __('Uploaded file is empty', 'pmxi_plugin'));
124
- } elseif ( ! preg_match('%\W(xml|gzip|zip|csv|gz)$%i', trim($_FILES['upload']['name'])) and !PMXI_Plugin::detect_csv($_FILES['upload']['type'])) {
125
  $this->errors->add('form-validation', __('Uploaded file must be XML, CSV or ZIP, GZIP', 'pmxi_plugin'));
126
- } elseif (preg_match('%\W(zip)$%i', trim($_FILES['upload']['name']))) {
127
-
128
- $zip = zip_open(trim($_FILES['upload']['tmp_name']));
129
- if (is_resource($zip)) {
130
- $uploads = wp_upload_dir();
131
- if($uploads['error']){
132
- $this->errors->add('form-validation', __('Can not create upload folder. Permision denied', 'pmxi_plugin'));
133
- }
134
- $filename = '';
135
- while ($zip_entry = zip_read($zip)) {
136
- $filename = zip_entry_name($zip_entry);
137
- $fp = fopen($uploads['path']."/".$filename, "w");
138
- if (zip_entry_open($zip, $zip_entry, "r")) {
139
- $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
140
- fwrite($fp,"$buf");
141
- zip_entry_close($zip_entry);
142
- fclose($fp);
143
- }
144
- break;
145
- }
146
- zip_close($zip);
147
-
148
- if (preg_match('%\W(csv)$%i', trim($filename))){
149
-
150
- $xml = PMXI_Plugin::csv_to_xml($uploads['path'] . '/' . trim($filename));
151
- if( is_array($xml) && isset($xml['error'])){
152
- $this->errors->add('form-validation', __($xml['error'], 'pmxi_plugin'));
153
- }
154
- else {
155
-
156
- // delete file in temporary folder
157
- unlink( $uploads['path'] .'/'. trim($filename));
158
- $fullfilename = $uploads['path']."/".$filename;
159
- // Let's make sure the file exists and is writable first.
160
-
161
- if (!$handle = fopen($fullfilename, 'w')) {
162
- $this->errors->add('form-validation', __('Cannot open file ' . $fullfilename, 'pmxi_plugin'));
163
- }
164
-
165
- // Write $somecontent to our opened file.
166
- if (fwrite($handle, $xml) === FALSE) {
167
- $this->errors->add('form-validation', __('Cannot write to file ' . $fullfilename, 'pmxi_plugin'));
168
- }
169
-
170
- fclose($handle);
171
-
172
-
173
- $filePath = $fullfilename;
174
- $source = array(
175
- 'name' => $filename,
176
- 'type' => 'upload',
177
- 'path' => '',
178
- );
179
- }
180
-
181
- }
182
- else
183
- {
184
- $filePath = $uploads['path']."/".$filename;
185
- $source = array(
186
- 'name' => $filename,
187
- 'type' => 'upload',
188
- 'path' => '',
189
- );
190
- }
191
-
192
- } else {
193
- $this->errors->add('form-validation', __('Failed to open uploaded ZIP archive', 'pmxi_plugin'));
194
- }
195
 
196
- } elseif ( preg_match('%\W(csv)$%i', trim($_FILES['upload']['name'])) or PMXI_Plugin::detect_csv($_FILES['upload']['type'])) {
197
- $uploads = wp_upload_dir();
198
- if($uploads['error']){
199
- $this->errors->add('form-validation', __('Can not create upload folder. Permision denied', 'pmxi_plugin'));
200
- }
201
- // copy file in temporary folder
202
- $fdata = file_get_contents($_FILES['upload']['tmp_name']);
203
- file_put_contents($uploads['path'] . '/' . trim(basename($_FILES['upload']['name'])), $fdata);
204
- chmod($uploads['path'] . '/'. trim(basename($_FILES['upload']['name'])), "0777");
205
- // end file convertion
206
- $xml = PMXI_Plugin::csv_to_xml($uploads['path'] . '/' . trim(basename($_FILES['upload']['name'])));
207
- if( is_array($xml) && isset($xml['error'])){
208
- $this->errors->add('form-validation', __($xml['error'], 'pmxi_plugin'));
209
- }
210
  else {
211
- // delete file in temporary folder
212
- unlink( $uploads['path'] .'/'. trim(basename($_FILES['upload']['name']) ));
213
- $filename = $_FILES['upload']['tmp_name'];
214
-
215
- // Let's make sure the file exists and is writable first.
216
- if (is_writable($filename)) {
217
 
218
- if (!$handle = fopen($filename, 'w')) {
219
- $this->errors->add('form-validation', __('Cannot open file ' . $filename, 'pmxi_plugin'));
220
- }
221
-
222
- // Write $somecontent to our opened file.
223
- if (fwrite($handle, $xml) === FALSE) {
224
- $this->errors->add('form-validation', __('Cannot write to file ' . $filename, 'pmxi_plugin'));
225
- }
226
-
227
- fclose($handle);
228
-
229
- } else {
230
- $this->errors->add('form-validation', __('The file' . $filename . 'is not writable', 'pmxi_plugin'));
231
- }
232
- $filePath = $_FILES['upload']['tmp_name'];
233
- $source = array(
234
- 'name' => $_FILES['upload']['name'],
235
- 'type' => 'upload',
236
- 'path' => '',
237
- );
238
- }
239
- } else {
240
- $filePath = $_FILES['upload']['tmp_name'];
241
- $source = array(
242
- 'name' => $_FILES['upload']['name'],
243
- 'type' => 'upload',
244
- 'path' => '',
245
- );
246
- }
247
- } elseif ('url' == $this->input->post('type')) {
248
- if (empty($post['url'])) {
249
- $this->errors->add('form-validation', __('XML/CSV file must be specified', 'pmxi_plugin'));
250
- } elseif ( ! preg_match('%^https?://%i', $post['url'])) {
251
- $this->errors->add('form-validation', __('Specified URL has wrong format'), 'pmxi_plugin');
252
- } elseif (preg_match('%\W(zip)$%i', trim($post['url']))) {
253
-
254
- $uploads = wp_upload_dir();
255
-
256
- $newfile = $uploads['path']."/".md5(time()).'.zip';
257
-
258
- if (!copy($post['url'], $newfile)) {
259
- $this->errors->add('form-validation', __('Failed upload ZIP archive', 'pmxi_plugin'));
260
- }
261
 
262
- $zip = zip_open($newfile);
263
- if (is_resource($zip)) {
264
- $uploads = wp_upload_dir();
 
 
265
  if($uploads['error']){
266
  $this->errors->add('form-validation', __('Can not create upload folder. Permision denied', 'pmxi_plugin'));
267
  }
268
- $filename = '';
269
- while ($zip_entry = zip_read($zip)) {
270
- $filename = zip_entry_name($zip_entry);
271
- $fp = fopen($uploads['path']."/".$filename, "w");
272
- if (zip_entry_open($zip, $zip_entry, "r")) {
273
- $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
274
- fwrite($fp,"$buf");
275
- zip_entry_close($zip_entry);
276
- fclose($fp);
277
- }
278
- break;
279
- }
280
- zip_close($zip);
281
- unlink($newfile);
282
- if (preg_match('%\W(csv)$%i', trim($filename))){
283
 
284
- $xml = PMXI_Plugin::csv_to_xml($uploads['path'] . '/' . trim($filename));
285
- if( is_array($xml) && isset($xml['error'])){
286
- $this->errors->add('form-validation', __($xml['error'], 'pmxi_plugin'));
287
- }
288
- else {
289
-
290
- // delete file in temporary folder
291
- unlink( $uploads['path'] .'/'. trim($filename));
292
- $fullfilename = $uploads['path']."/".$filename;
293
- // Let's make sure the file exists and is writable first.
294
-
295
- if (!$handle = fopen($fullfilename, 'w')) {
296
- $this->errors->add('form-validation', __('Cannot open file ' . $fullfilename, 'pmxi_plugin'));
297
- }
298
-
299
- // Write $somecontent to our opened file.
300
- if (fwrite($handle, $xml) === FALSE) {
301
- $this->errors->add('form-validation', __('Cannot write to file ' . $fullfilename, 'pmxi_plugin'));
302
- }
303
-
304
- fclose($handle);
305
-
306
-
307
- $filePath = $fullfilename;
308
- $source = array(
309
- 'name' => $filename,
310
- 'type' => 'url',
311
- 'path' => $post['url'],
312
- );
313
- }
314
 
315
- }
316
- else
317
- {
318
- $filePath = $uploads['path']."/".$filename;
319
- $source = array(
320
- 'name' => $filename,
321
- 'type' => 'url',
322
- 'path' => $post['url'],
323
- );
324
- }
325
 
326
- } else {
327
- $this->errors->add('form-validation', __('Failed to open uploaded ZIP archive', 'pmxi_plugin'));
328
- }
329
- } elseif ( preg_match('%\W(csv)$%i', trim($post['url'])) or $contents = get_headers($post['url'],1 ) and PMXI_Plugin::detect_csv($contents['Content-Type'])) {
330
- $uploads = wp_upload_dir();
331
- $fdata = file_get_contents($post['url']);
332
- $tmpname = md5(time()).'.csv';
333
- file_put_contents($uploads['path'] .'/'. $tmpname, $fdata);
334
- $xml = PMXI_Plugin::csv_to_xml($uploads['path'] .'/'. $tmpname);
335
- if( is_array($xml) && isset($xml['error'])){
336
- $this->errors->add('form-validation', __($xml['error'], 'pmxi_plugin'));
337
- }
338
- else {
339
- $filename = tempnam(XmlImportConfig::getInstance()->getCacheDirectory(), 'xim');
340
-
341
- // Let's make sure the file exists and is writable first.
342
- if (is_writable($filename)) {
343
-
344
- if (!$handle = fopen($filename, 'w')) {
345
- $this->errors->add('form-validation', __('Cannot open file ' . $filename, 'pmxi_plugin'));
346
- }
347
-
348
- // Write $somecontent to our opened file.
349
- if (fwrite($handle, $xml) === FALSE) {
350
- $this->errors->add('form-validation', __('Cannot write to file ' . $filename, 'pmxi_plugin'));
351
- }
352
-
353
- fclose($handle);
354
-
355
- } else {
356
- $this->errors->add('form-validation', __('The file' . $filename . 'is not writable', 'pmxi_plugin'));
357
- }
358
- $filePath = $filename;
359
  $source = array(
360
- 'name' => basename(parse_url($post['url'], PHP_URL_PATH)),
361
- 'type' => 'url',
362
- 'path' => $post['url'],
363
- );
364
- }
365
- }else {
366
- $filePath = $post['url'];
367
- $source = array(
368
- 'name' => basename(parse_url($filePath, PHP_URL_PATH)),
369
- 'type' => 'url',
370
- 'path' => $filePath,
371
- );
372
 
373
- }
374
- } elseif ('ftp' == $this->input->post('type')) {
375
- if (empty($post['ftp']['url'])) {
376
- $this->errors->add('form-validation', __('XML/CSV file must be specified', 'pmxi_plugin'));
377
- } elseif ( ! preg_match('%^ftps?://%i', $post['ftp']['url'])) {
378
- $this->errors->add('form-validation', __('Specified FTP resource has wrong format'), 'pmxi_plugin');
379
- } elseif ( preg_match('%\W(csv)$%i', trim($post['ftp']['url']))) {
380
- // path to remote file
381
- $remote_file = $post['ftp']['url'];
382
- $local_file = tempnam(XmlImportConfig::getInstance()->getCacheDirectory(), 'xim');
383
-
384
- // open some file to write to
385
- $handle = fopen($local_file, 'w');
386
-
387
- // set up basic connection
388
- $ftp_url = $post['ftp']['url'];
389
- $parsed_url = parse_url($ftp_url);
390
- $ftp_server = $parsed_url['host'] ;
391
- $conn_id = ftp_connect( $ftp_server );
392
- $is_ftp_ok = TRUE;
393
-
394
- // login with username and password
395
- $ftp_user_name = $post['ftp']['user'];
396
- $ftp_user_pass = $post['ftp']['pass'];
397
-
398
- // hide warning message
399
- echo '<span style="display:none">';
400
- if ( !ftp_login($conn_id, $ftp_user_name, $ftp_user_pass) ){
401
- $this->errors->add('form-validation', __('Login authentication failed', 'pmxi_plugin'));
402
- $is_ftp_ok = false;
403
- }
404
- echo '</span>';
405
-
406
 
407
- if ( $is_ftp_ok ){
408
- // try to download $remote_file and save it to $handle
409
- if (!ftp_fget($conn_id, $handle, $parsed_url['path'], FTP_ASCII, 0)) {
410
- $this->errors->add('form-validation', __('There was a problem while downloading' . $remote_file . 'to' . $local_file, 'pmxi_plugin'));
411
- }
412
-
413
- // close the connection and the file handler
414
- ftp_close($conn_id);
415
- fclose($handle);
416
-
417
- // copy file in temporary folder
418
- $uploads = wp_upload_dir();
419
  if($uploads['error']){
420
  $this->errors->add('form-validation', __('Can not create upload folder. Permision denied', 'pmxi_plugin'));
421
- }
422
- copy( $local_file, $uploads['path'] . basename($local_file));
423
- $url = $uploads['url'] . basename($local_file);
424
- // convert file to utf8
425
- chmod($uploads['path'] . basename($local_file), '0755');
426
- $fdata = file_get_contents($url);
427
- file_put_contents($uploads['path'] . basename($local_file), $fdata);
428
- // end file convertion
429
- $xml = PMXI_Plugin::csv_to_xml($uploads['path'] . basename($local_file));
430
- if( is_array($xml) && isset($xml['error'])){
431
- $this->errors->add('form-validation', __($xml['error'], 'pmxi_plugin'));
432
  }
433
- else {
434
- unlink( $uploads['path'] . basename($local_file) );
435
- $filename = $local_file;
436
-
437
- // Let's make sure the file exists and is writable first.
438
- if (is_writable($filename)) {
439
-
440
- if (!$handle = fopen($filename, 'w')) {
441
- $this->errors->add('form-validation', __('Cannot open file ' . $filename, 'pmxi_plugin'));
442
- }
443
-
444
- // Write $somecontent to our opened file.
445
- if (fwrite($handle, $xml) === FALSE) {
446
- $this->errors->add('form-validation', __('Cannot write to file ' . $filename, 'pmxi_plugin'));
447
- }
448
-
449
- fclose($handle);
450
-
451
- } else {
452
- $this->errors->add('form-validation', __('The file' . $filename . 'is not writable', 'pmxi_plugin'));
453
- }
454
- $filePath = $local_file;
455
- $source = array(
456
- 'name' => basename($local_file),
457
- 'type' => 'ftp',
458
- 'path' => $filePath,
459
- );
460
  }
461
- }
462
- } else {
463
- $filePath = $post['ftp']['url'];
464
- if (isset($post['ftp']['user']) and $post['ftp']['user'] !== '') {
465
- $filePath = preg_replace('%://([^@/]*@)?%', '://' . urlencode($post['ftp']['user']) . ':' . urlencode($post['ftp']['pass']) . '@', $filePath, 1);
466
  }
 
 
 
 
 
 
 
 
 
 
467
  $source = array(
468
- 'name' => basename(parse_url($filePath, PHP_URL_PATH)),
469
- 'type' => 'ftp',
470
  'path' => $filePath,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
471
  );
472
- }
473
- } elseif ('file' == $this->input->post('type')) {
474
- if (empty($post['file'])) {
475
- $this->errors->add('form-validation', __('XML/CSV file must be specified', 'pmxi_plugin'));
476
- } elseif (preg_match('%\W(csv)$%i', trim($post['file']))) {
477
- $uploads = PMXI_Plugin::ROOT_DIR . '/upload/';
478
- $wp_uploads = wp_upload_dir();
479
- if($wp_uploads['error']){
480
- $this->errors->add('form-validation', __('Can not create upload folder. Permision denied', 'pmxi_plugin'));
481
- }
482
- // copy file in temporary folder
483
- // hide warning message
484
- echo '<span style="display:none">';
485
- copy( $uploads . $post['file'], $wp_uploads['path'] . basename($post['file']));
486
- echo '</span>';
487
- $url = $wp_uploads['url'] . basename($post['file']);
488
- // convert file to utf8
489
- chmod($wp_uploads['path'] . basename($post['file']), '0755');
490
- $fdata = file_get_contents($url);
491
- file_put_contents($wp_uploads['path'] . basename($post['file']), $fdata);
492
- // end file convertion
493
- $xml = PMXI_Plugin::csv_to_xml($wp_uploads['path'] . basename($post['file']));
494
- if( is_array($xml) && isset($xml['error'])){
495
- $this->errors->add('form-validation', __($xml['error'], 'pmxi_plugin'));
496
- }
497
- else {
498
- $filename = $wp_uploads['path'] . basename($post['file']);
499
-
500
- // Let's make sure the file exists and is writable first.
501
- if (is_writable($filename)) {
502
-
503
- if (!$handle = fopen($filename, 'w')) {
504
- $this->errors->add('form-validation', __('Cannot open file ' . $filename, 'pmxi_plugin'));
505
- }
506
-
507
- // Write $somecontent to our opened file.
508
- if (fwrite($handle, $xml) === FALSE) {
509
- $this->errors->add('form-validation', __('Cannot write to file ' . $filename, 'pmxi_plugin'));
510
- }
511
-
512
- fclose($handle);
513
-
514
- } else {
515
- $this->errors->add('form-validation', __('The file ' . $filename . ' is not writable or you use wildcard for CSV file', 'pmxi_plugin'));
516
  }
517
- $filePath = $wp_uploads['path'] . basename($post['file']);
518
- $source = array(
519
- 'name' => basename(parse_url($filePath, PHP_URL_PATH)),
520
- 'type' => 'file',
521
- 'path' => $filePath,
522
- );
523
- }
524
  }
525
- else {
526
- $filePath = PMXI_Plugin::ROOT_DIR . '/upload/' . $post['file'];
 
 
 
 
527
  $source = array(
528
- 'name' => basename(parse_url($filePath, PHP_URL_PATH)),
529
- 'type' => 'file',
530
  'path' => $filePath,
531
  );
532
- }
533
- } elseif ('reimport' == $this->input->post('type')) {
534
- if (empty($post['reimport'])) {
535
- $this->errors->add('form-validation', __('XML/CSV file must be specified', 'pmxi_plugin'));
536
- }
537
  }
538
-
539
  if ($post['is_update_previous'] and empty($post['update_previous'])) {
540
- $this->errors->add('form-validation', __('Previous import for update must be selected or uncheck `Update Previous Import` option to proceed with a new one', 'pmxi_plugin'));
541
  }
542
 
543
  if ($this->input->post('is_submitted') and ! $this->errors->get_error_codes()) {
544
 
545
- check_admin_referer('choose-file', '_wpnonce_choose-file');
 
 
546
 
547
- if ('reimport' == $this->input->post('type')) { // get file content from database
548
- preg_match('%^#(\d+):%', $post['reimport'], $mtch) and $reimport_id = $mtch[1] or $reimport_id = 0;
549
- $file = new PMXI_File_Record();
550
- if ( ! $reimport_id or $file->getById($reimport_id)->isEmpty()) {
551
- $xml = FALSE;
552
- } else {
553
- $xml = @file_get_contents($file->path);
554
 
555
- if ($contents = get_headers($file->path,1 ) and PMXI_Plugin::detect_csv($contents['Content-Type'])) $xml = PMXI_Plugin::csv_to_xml($file->path);
 
 
 
 
556
 
557
- $source = array(
558
- 'name' => $file->name,
559
- 'type' => 'reimport',
560
- 'path' => $file->path,
561
- );
562
 
563
- }
564
- } else {
565
- if (in_array($this->input->post('type'), array('ftp', 'file'))) { // file may be specified by pattern
566
- $file_path_array = @PMXI_Helper::safe_glob($filePath, PMXI_Helper::GLOB_NODIR | PMXI_Helper::GLOB_PATH);
567
- if ($file_path_array) {
568
- $filePath = array_shift($file_path_array); // take only 1st matching one
569
- } else {
570
- $filePath = FALSE;
571
- }
572
- }
 
 
 
 
 
 
 
 
 
 
 
573
 
574
- ob_start();
575
- $filePath && @readgzfile($filePath);
576
-
577
- $xml = ob_get_clean();
578
-
579
- $wp_uploads = wp_upload_dir();
580
- $url = $wp_uploads['url'] .'/'. basename($filePath);
581
- file_put_contents($wp_uploads['path'] .'/'. basename($filePath), $xml);
582
- chmod($wp_uploads['path'] .'/'. basename($filePath), '0755');
583
-
584
- if ($contents = get_headers($url,1 ) and PMXI_Plugin::detect_csv($contents['Content-Type'])) $xml = PMXI_Plugin::csv_to_xml($wp_uploads['path']. basename($filePath));
585
 
586
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
587
 
588
- if (PMXI_Import_Record::validateXml($xml, $this->errors)) {
589
  // xml is valid
590
-
 
 
 
 
 
 
 
 
 
 
591
  $_SESSION['pmxi_import'] = array(
592
  'xml' => $xml,
593
- 'source' => $source,
594
- );
595
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
596
  $update_previous = new PMXI_Import_Record();
597
  if ($post['is_update_previous'] and ! $update_previous->getById($post['update_previous'])->isEmpty()) {
598
  $_SESSION['pmxi_import'] += array(
@@ -604,8 +406,9 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
604
  } else {
605
  $_SESSION['pmxi_import']['update_previous'] = '';
606
  }
607
-
608
  wp_redirect(add_query_arg('action', 'element', $this->baseUrl)); die();
 
609
  }
610
  }
611
 
@@ -617,11 +420,13 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
617
  */
618
  public function element()
619
  {
620
-
621
-
622
  $xpath = new DOMXPath($this->data['dom']);
623
  $post = $this->input->post(array('xpath' => ''));
624
  $this->data['post'] =& $post;
 
 
 
625
 
626
  if ($this->input->post('is_submitted')) {
627
  check_admin_referer('choose-elements', '_wpnonce_choose-elements');
@@ -643,23 +448,72 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
643
  }
644
  }
645
  }
 
646
  if ( ! $this->errors->get_error_codes()) {
647
  $_SESSION['pmxi_import']['xpath'] = $post['xpath'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
648
  wp_redirect(add_query_arg('action', 'template', $this->baseUrl)); die();
649
  }
650
  } else {
651
 
652
- $this->shrink_xml_element($this->data['dom']->documentElement);
653
 
654
  if (isset($_SESSION['pmxi_import']['xpath'])) {
655
  $post['xpath'] = $_SESSION['pmxi_import']['xpath'];
656
- if ( ! $xpath->query($post['xpath'])->length and ! empty($_SESSION['pmxi_import']['update_previous'])) {
 
657
  $_GET['pmxi_nt'] = __('<b>Warning</b>: No matching elements found for XPath expression from the import being updated. It probably means that new XML file has different format. Though you can update XPath, procceed only if you sure about update operation being valid.', 'pmxi_plugin');
658
  }
659
  } else {
660
  // suggest 1st repeating element as default selection
661
  $post['xpath'] = $this->xml_find_repeating($this->data['dom']->documentElement);
 
 
 
662
  }
 
663
  }
664
 
665
  // workaround to prevent rendered XML representation to eat memory since it has to be stored in momory when output is bufferred
@@ -681,33 +535,85 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
681
  }
682
 
683
  $xpath = new DOMXPath($this->data['dom']);
684
- $post = $this->input->post(array('xpath' => ''));
 
 
685
  if ('' == $post['xpath']) {
686
  $this->errors->add('form-validation', __('No elements selected', 'pmxi_plugin'));
687
- } else {
688
- $node_list = @ $xpath->query($post['xpath']); // prevent parsing warning to be displayed
689
- $this->data['node_list_count'] = $node_list->length;
690
- if (FALSE === $node_list) {
691
- $this->errors->add('form-validation', __('Invalid XPath expression', 'pmxi_plugin'));
692
- } elseif ( ! $node_list->length) {
693
- $this->errors->add('form-validation', __('No matching elements found for XPath expression specified', 'pmxi_plugin'));
694
- } else {
695
- foreach ($node_list as $el) {
696
- if ( ! $el instanceof DOMElement) {
697
- $this->errors->add('form-validation', __('XPath must match only elements', 'pmxi_plugin'));
698
- break;
699
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
700
  }
701
  }
702
  }
703
  if ( ! $this->errors->get_error_codes()) {
704
- $this->shrink_xml_element($this->data['dom']->documentElement);
 
705
  $xpath = new DOMXPath($this->data['dom']);
706
- $this->data['node_list'] = $node_list = @ $xpath->query($post['xpath']); // prevent parsing warning to be displayed
707
 
708
  $paths = array(); $this->data['paths'] =& $paths;
709
- if (PMXI_Plugin::getInstance()->getOption('highlight_limit') and $node_list->length <= PMXI_Plugin::getInstance()->getOption('highlight_limit')) {
710
- foreach ($node_list as $el) {
711
  if ( ! $el instanceof DOMElement) continue;
712
 
713
  $p = $this->get_xml_path($el, $xpath) and $paths[] = $p;
@@ -731,25 +637,27 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
731
  'content' => '',
732
  'name' => '',
733
  'is_keep_linebreaks' => 0,
734
- );
 
735
  if ($this->isWizard) {
736
  $this->data['post'] = $post = $this->input->post(
737
  (isset($_SESSION['pmxi_import']['template']) ? $_SESSION['pmxi_import']['template'] : array())
738
  + $default
739
  );
740
- } else {
741
  $this->data['post'] = $post = $this->input->post(
742
  $this->data['import']->template
743
  + $default
744
- );
745
- }
746
 
747
  if (($load_template = $this->input->post('load_template'))) { // init form with template selected
748
  if ( ! $template->getById($load_template)->isEmpty()) {
749
  $this->data['post'] = array(
750
  'title' => $template->title,
751
  'content' => $template->content,
752
- 'is_keep_linebreaks' => $template->is_keep_linebreaks,
 
753
  'name' => '', // template is always empty
754
  );
755
  $_SESSION['pmxi_import']['is_loaded_template'] = $load_template;
@@ -763,22 +671,22 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
763
  } else {
764
  $this->_validate_template($post['title'], 'Post title');
765
  }
 
766
  if (empty($post['content'])) {
767
  $this->errors->add('form-validation', __('Post content is empty', 'pmxi_plugin'));
768
  } else {
769
  $this->_validate_template($post['content'], 'Post content');
770
- }
771
-
772
 
773
- if ( ! $this->errors->get_error_codes()) {
774
  if ( ! empty($post['name'])) { // save template in database
775
  $template->getByName($post['name'])->set($post)->save();
776
- $_SESSION['pmxi_import']['saved_template'] = $template->id;
777
  }
778
  if ($this->isWizard) {
779
- $_SESSION['pmxi_import']['template'] = $post;
780
  wp_redirect(add_query_arg('action', 'options', $this->baseUrl)); die();
781
- } else {
782
  $this->data['import']->set('template', $post)->save();
783
  wp_redirect(add_query_arg(array('page' => 'pmxi-admin-manage', 'pmlc_nt' => urlencode(__('Template updated', 'pmxi_plugin'))) + array_intersect_key($_GET, array_flip($this->baseUrlParamNames)), admin_url('admin.php'))); die();
784
  }
@@ -795,6 +703,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
795
  wp_enqueue_script('quicktags');
796
  $this->render();
797
  }
 
798
  protected function _validate_template($text, $field_title)
799
  {
800
  try {
@@ -811,10 +720,12 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
811
  * Preview selected xml tag (called with ajax from `template` step)
812
  */
813
  public function tag()
814
- {
815
- if (empty($this->data['elements']))
816
- {
817
 
 
 
 
 
818
  $update_previous = new PMXI_Import_Record();
819
  if ($update_previous->getById($this->input->get('id'))) {
820
  $_SESSION['pmxi_import'] = array(
@@ -823,24 +734,65 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
823
  'template' => $update_previous->template,
824
  'options' => $update_previous->options,
825
  );
826
- $history_file = new PMXI_File_Record();
827
- $history_file->getBy('import_id', $update_previous->id);
828
- $history_file->__get('contents');
829
- $_SESSION['pmxi_import']['xml'] = $history_file->contents;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
830
  } else {
831
  $_SESSION['pmxi_import']['update_previous'] = '';
832
- }
833
- if (!empty($_SESSION['pmxi_import']['xml']))
834
- {
835
- $dom = new DOMDocument();
836
- $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $_SESSION['pmxi_import']['xml']));
837
- $xpath = new DOMXPath($dom);
838
-
839
- $this->data['elements'] = $elements = $xpath->query($_SESSION['pmxi_import']['xpath']);
840
- }
841
  }
842
 
843
- $this->data['tagno'] = min(max(intval($this->input->getpost('tagno', 1)), 1), $this->data['elements']->length);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
844
  $this->render();
845
  }
846
 
@@ -853,12 +805,43 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
853
  'title' => '',
854
  'content' => '',
855
  'is_keep_linebreaks' => 0,
856
- ));
857
- $tagno = min(max(intval($this->input->getpost('tagno', 1)), 1), $this->data['elements']->length);
858
- $xpath = "(" . $_SESSION['pmxi_import']['xpath'] . ")[$tagno]";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
859
  // validate
860
  try {
861
-
862
  if (empty($post['title'])) {
863
  $this->errors->add('form-validation', __('Post title is empty', 'pmxi_plugin'));
864
  } else {
@@ -866,11 +849,12 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
866
  if ( ! isset($this->data['title']) or '' == strval(trim(strip_tags($this->data['title'], '<img><input><textarea><iframe><object><embed>')))) {
867
  $this->errors->add('xml-parsing', __('<strong>Warning</strong>: resulting post title is empty', 'pmxi_plugin'));
868
  }
 
869
  }
870
  } catch (XmlImportException $e) {
871
  $this->errors->add('form-validation', sprintf(__('Error parsing title: %s', 'pmxi_plugin'), $e->getMessage()));
872
  }
873
- try {
874
  if (empty($post['content'])) {
875
  $this->errors->add('form-validation', __('Post content is empty', 'pmxi_plugin'));
876
  } else {
@@ -878,6 +862,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
878
  if ( ! isset($this->data['content']) or '' == strval(trim(strip_tags($this->data['content'], '<img><input><textarea><iframe><object><embed>')))) {
879
  $this->errors->add('xml-parsing', __('<strong>Warning</strong>: resulting post content is empty', 'pmxi_plugin'));
880
  }
 
881
  }
882
  } catch (XmlImportException $e) {
883
  $this->errors->add('form-validation', sprintf(__('Error parsing content: %s', 'pmxi_plugin'), $e->getMessage()));
@@ -898,16 +883,41 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
898
  if ($this->isWizard) {
899
  $this->data['source_type'] = $_SESSION['pmxi_import']['source']['type'];
900
  $default['unique_key'] = $_SESSION['pmxi_import']['template']['title'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
901
  $post = $this->input->post(
902
  (isset($_SESSION['pmxi_import']['options']) ? $_SESSION['pmxi_import']['options'] : array())
903
  + $default
904
  );
905
 
906
  $scheduled = $this->input->post(array(
907
- 'is_scheduled' => ! empty($post['scheduled']),
908
- 'scheduled_period' => ! empty($post['scheduled']) ? $post['scheduled'] : '0 0 * * *', // daily by default
909
  ));
910
-
911
  } else {
912
  $this->data['source_type'] = $this->data['import']->type;
913
  $post = $this->input->post(
@@ -919,15 +929,21 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
919
  'scheduled_period' => ! empty($this->data['import']->scheduled) ? $this->data['import']->scheduled : '0 0 * * *', // daily by default
920
  ));
921
  }
 
922
  $this->data['post'] =& $post;
923
  $this->data['scheduled'] =& $scheduled;
924
  $this->data['is_loaded_template'] = $_SESSION['pmxi_import']['is_loaded_template'];
925
 
 
 
 
 
 
926
  if (($load_options = $this->input->post('load_options'))) { // init form with template selected
927
  $this->data['load_options'] = true;
928
  $template = new PMXI_Template_Record();
929
- if ( ! $template->getById($this->data['is_loaded_template'])->isEmpty()) {
930
- $post = $template->options + $default;
931
  $scheduled = array(
932
  'is_scheduled' => ! empty($template->scheduled),
933
  'scheduled_period' => ! empty($template->scheduled) ? $template->scheduled : '0 0 * * *', // daily by default
@@ -938,25 +954,11 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
938
  $post = $default;
939
  $scheduled = $this->input->post(array(
940
  'is_scheduled' => ! empty($post['scheduled']),
941
- 'scheduled_period' => ! empty($post['scheduled']) ? $post['scheduled'] : '0 0 * * *', // daily by default
942
  ));
943
  } elseif ($this->input->post('is_submitted')) {
944
- check_admin_referer('options', '_wpnonce_options');
945
- // remove entires where both custom_name and custom_value are empty
946
- $not_empty = array_flip(array_values(array_merge(array_keys(array_filter($post['custom_name'])), array_keys(array_filter($post['custom_value'])))));
947
- $post['custom_name'] = array_intersect_key($post['custom_name'], $not_empty);
948
- $post['custom_value'] = array_intersect_key($post['custom_value'], $not_empty);
949
- // validate
950
- if (array_keys(array_filter($post['custom_name'])) != array_keys(array_filter($post['custom_value']))) {
951
- $this->errors->add('form-validation', __('Both name and value must be set for all custom parameters', 'pmxi_plugin'));
952
- } else {
953
- foreach ($post['custom_name'] as $custom_name) {
954
- $this->_validate_template($custom_name, __('Custom Field Name', 'pmxi_plugin'));
955
- }
956
- foreach ($post['custom_value'] as $custom_value) {
957
- $this->_validate_template($custom_value, __('Custom Field Value', 'pmxi_plugin'));
958
- }
959
- }
960
  if ('page' == $post['type'] and ! preg_match('%^(-?\d+)?$%', $post['order'])) {
961
  $this->errors->add('form-validation', __('Order must be an integer number', 'pmxi_plugin'));
962
  }
@@ -982,7 +984,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
982
  if ( ! preg_match('%^([1-9]\d*)( *- *([1-9]\d*))?$%', $chank, $mtch)) {
983
  $this->errors->add('form-validation', __('Wrong format of `Import only specified records` value', 'pmxi_plugin'));
984
  break;
985
- } elseif ($this->isWizard and (intval($mtch[1]) > $this->data['elements']->length or isset($mtch[3]) and intval($mtch[3]) > $this->data['elements']->length)) {
986
  $this->errors->add('form-validation', __('One of the numbers in `Import only specified records` value exceeds record quantity in XML file', 'pmxi_plugin'));
987
  break;
988
  }
@@ -994,6 +996,12 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
994
  } else {
995
  $this->_validate_template($post['unique_key'], __('Post Unique Key', 'pmxi_plugin'));
996
  }
 
 
 
 
 
 
997
 
998
  if ( ! $this->errors->get_error_codes()) { // no validation errors found
999
  // assign some defaults
@@ -1032,6 +1040,8 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
1032
  'template' => $_SESSION['pmxi_import']['template'],
1033
  'options' => $_SESSION['pmxi_import']['options'],
1034
  'scheduled' => $_SESSION['pmxi_import']['scheduled'],
 
 
1035
  )
1036
  )->save();
1037
 
@@ -1039,7 +1049,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
1039
  $history_file->set(array(
1040
  'name' => $import->name,
1041
  'import_id' => $import->id,
1042
- 'path' => $import->path,
1043
  'contents' => $_SESSION['pmxi_import']['xml'],
1044
  'registered_on' => date('Y-m-d H:i:s'),
1045
  ))->save();
@@ -1047,7 +1057,8 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
1047
  wp_redirect(add_query_arg(array('page' => 'pmxi-admin-manage', 'pmlc_nt' => urlencode($is_update ? __('Import updated', 'pmxi_plugin') : __('Import created', 'pmxi_plugin'))), admin_url('admin.php'))); die();
1048
  }
1049
  } else {
1050
- $this->data['import']->set('options', $post)->set('scheduled', $scheduled['is_scheduled'] ? $scheduled['scheduled_period'] : '')->save();
 
1051
  $template = new PMXI_Template_Record();
1052
 
1053
  if (!$template->getByName($this->data['import']->template['name'])->isEmpty()){
@@ -1058,9 +1069,7 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
1058
  wp_redirect(add_query_arg(array('page' => 'pmxi-admin-manage', 'pmlc_nt' => urlencode(__('Options updated', 'pmxi_plugin'))) + array_intersect_key($_GET, array_flip($this->baseUrlParamNames)), admin_url('admin.php'))); die();
1059
  }
1060
  }
1061
- }
1062
-
1063
- ! empty($post['custom_name']) or $post['custom_name'] = array('') and $post['custom_value'] = array('');
1064
 
1065
  $this->render();
1066
  }
@@ -1068,107 +1077,232 @@ class PMXI_Admin_Import extends PMXI_Controller_Admin {
1068
  /**
1069
  * Import processing step (status console)
1070
  */
1071
- public function process()
1072
  {
1073
- $this->render();
1074
- wp_ob_end_flush_all(); flush();
1075
-
1076
- set_time_limit(0);
1077
 
1078
- // store import info in database
1079
- $import = $this->data['update_previous'];
 
1080
  $import->set(
1081
- $_SESSION['pmxi_import']['source']
1082
  + array(
1083
  'xpath' => $_SESSION['pmxi_import']['xpath'],
1084
  'template' => $_SESSION['pmxi_import']['template'],
1085
- 'options' => $_SESSION['pmxi_import']['options'],
1086
- 'scheduled' => $_SESSION['pmxi_import']['scheduled']
 
 
1087
  )
1088
- )->save();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1089
 
1090
- $logger = create_function('$m', 'echo "<div class=\\"progress-msg\\">$m</div>\\n"; flush();');
 
 
1091
 
1092
- if (in_array($import->type, array('ftp', 'file'))) { // process files by patten
1093
- $import->execute($logger);
1094
- } else { // directly process XML
1095
- $import->process($_SESSION['pmxi_import']['xml'], $logger);
1096
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1097
 
1098
- unset($_SESSION['pmxi_import']); // clear session data (prevent from reimporting the same data on page refresh)
 
 
 
 
 
 
 
 
1099
 
1100
  // [indicate in header process is complete]
1101
- $msg = addcslashes(__('Complete', 'pmxi_plugin'), "'\n\r");
 
 
 
 
1102
  echo <<<COMPLETE
1103
  <script type="text/javascript">
1104
  //<![CDATA[
1105
  (function($){
 
 
 
 
 
 
1106
  $('#status').html('$msg');
1107
  window.onbeforeunload = false;
1108
  })(jQuery);
1109
  //]]>
1110
  </script>
1111
  COMPLETE;
1112
- // [/indicate in header process is complete]
1113
- }
1114
 
1115
- /**
1116
- * Remove xml document nodes by xpath expression
1117
- */
1118
- function removeNode($xml, $path)
1119
- {
1120
- $result = $xml->xpath($path);
1121
-
1122
- if (empty($result)) return false;
1123
- $errlevel = error_reporting(E_ALL & ~E_WARNING);
1124
- foreach ($result as $r) unset ($r[0]);
1125
- error_reporting($errlevel);
1126
-
1127
- return true;
1128
- }
1129
-
1130
- /*
1131
- *
1132
- * Get SimpleXML object by xpath extension
1133
- *
1134
- */
1135
- function get_chank(& $xml, $path){
1136
-
1137
- $result = $xml->xpath($path);
1138
-
1139
- $array = array();
1140
- foreach ($result as $el) {
1141
- array_push($array, $this->simplexml2array($el));
1142
- }
1143
-
1144
- if (empty($array)) return false;
1145
-
1146
- return new SimpleXMLElement(ArrayToXML::toXml($array));
1147
- }
1148
-
1149
- /*
1150
- *
1151
- * Convert SimpleXML object to array
1152
- *
1153
- */
1154
- function simplexml2array($xml) {
1155
- if (@get_class($xml) == 'SimpleXMLElement') {
1156
- $attributes = $xml->attributes();
1157
- foreach($attributes as $k=>$v) {
1158
- if ($v) $a[$k] = (string) $v;
1159
- }
1160
- $x = $xml;
1161
- $xml = get_object_vars($xml);
1162
- }
1163
- if (is_array($xml)) {
1164
- if (count($xml) == 0) return (string) $x; // for CDATA
1165
- foreach($xml as $key=>$value) {
1166
- $r[$key] = $this->simplexml2array($value);
1167
- }
1168
- if (isset($a)) $r['@attributes'] = $a; // Attributes
1169
- return $r;
1170
- }
1171
- return (string) $xml;
1172
  }
1173
 
1174
  protected $_sibling_limit = 20;
@@ -1227,10 +1361,10 @@ COMPLETE;
1227
  }
1228
  protected function render_xml_element(DOMElement $el, $shorten = false, $path = '/', $ind = 1, $lvl = 0)
1229
  {
1230
- $path .= $el->nodeName;
1231
  if ( ! $el->parentNode instanceof DOMDocument and $ind > 0) {
1232
  $path .= "[$ind]";
1233
- }
1234
 
1235
  echo '<div class="xml-element lvl-' . $lvl . ' lvl-mod4-' . ($lvl % 4) . '" title="' . $path . '">';
1236
  if ($el->hasChildNodes()) {
@@ -1265,6 +1399,19 @@ COMPLETE;
1265
  }
1266
  echo '</div>';
1267
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
1268
  protected function render_xml_text($text, $shorten = false, $is_render_collapsed = false)
1269
  {
1270
  if (empty($text)) {
@@ -1396,5 +1543,11 @@ COMPLETE;
1396
 
1397
  return NULL;
1398
  }
 
 
 
 
 
 
1399
 
1400
  }
12
  protected function init() {
13
  parent::init();
14
 
15
+ try{
16
+ $path = session_save_path();
17
+ if ( ! is_dir($path) or ! is_writable($path)){
18
+ @ini_set("session.save_handler", "files");
19
+ session_save_path(sys_get_temp_dir());
20
+ }
21
+ } catch (XmlImportException $e) {
22
+ $this->errors->add('form-validation', __('Can not create session.', 'pmxi_plugin'));
23
+ }
24
+
25
  // enable sessions
26
  if ( ! session_id()) session_start();
27
 
28
  if ('PMXI_Admin_Manage' == PMXI_Plugin::getInstance()->getAdminCurrentScreen()->base) { // prereqisites are not checked when flow control is deligated
29
  $id = $this->input->get('id');
30
+ $this->data['import'] = $import = new PMXI_Import_Record();
31
  if ( ! $id or $import->getById($id)->isEmpty()) { // specified import is not found
32
  wp_redirect(add_query_arg('page', 'pmxi-admin-manage', admin_url('admin.php'))); die();
33
  }
34
  $this->isWizard = false;
35
 
36
  } else {
37
+ $action = PMXI_Plugin::getInstance()->getAdminCurrentScreen()->action;
38
  $this->_step_ready($action);
39
  $this->isInline = 'process' == $action;
40
+ }
41
 
42
  XmlImportConfig::getInstance()->setCacheDirectory(sys_get_temp_dir());
43
 
52
  public function get($var)
53
  {
54
  return $this->{$var};
55
+ }
56
 
57
  /**
58
  * Checks whether corresponding step of wizard is complete
59
  * @param string $action
60
  */
61
+ protected function _step_ready($action) {
62
  // step #1: xml selction - has no prerequisites
63
  if ('index' == $action) return true;
64
 
65
  // step #2: element selection
66
+ $this->data['dom'] = $dom = new DOMDocument('1.0', 'UTF-8');
67
  $this->data['update_previous'] = $update_previous = new PMXI_Import_Record();
68
  $old = libxml_use_internal_errors(true);
69
+
70
  if (empty($_SESSION['pmxi_import'])
71
+ or ! $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $_SESSION['pmxi_import']['xml']))// FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
72
+ //or empty($_SESSION['pmxi_import']['source'])
73
  or ! empty($_SESSION['pmxi_import']['update_previous']) and $update_previous->getById($_SESSION['pmxi_import']['update_previous'])->isEmpty()
74
  ) {
75
+ $this->errors->add('form-validation', __('Can not create DOM object for provided feed.', 'pmxi_plugin'));
76
  wp_redirect_or_javascript($this->baseUrl); die();
77
  }
78
  libxml_use_internal_errors($old);
79
  if ('element' == $action) return true;
80
  if ('evaluate' == $action) return true;
81
+
82
  // step #3: template
83
  $xpath = new DOMXPath($dom);
84
+
85
  if (empty($_SESSION['pmxi_import']['xpath']) or ! ($this->data['elements'] = $elements = $xpath->query($_SESSION['pmxi_import']['xpath'])) or ! $elements->length) {
86
+ $this->errors->add('form-validation', __('No matching elements found.', 'pmxi_plugin'));
87
  wp_redirect_or_javascript(add_query_arg('action', 'element', $this->baseUrl)); die();
88
  }
89
  if ('template' == $action or 'preview' == $action or 'tag' == $action) return true;
104
  */
105
  public function index() {
106
 
107
+ $this->data['reimported_import'] = $import = new PMXI_Import_Record();
108
  $this->data['id'] = $id = $this->input->get('id');
109
  if ($id and $import->getById($id)->isEmpty()) { // update requested but corresponding import is not found
110
  wp_redirect(remove_query_arg('id', $this->baseUrl)); die();
118
  'reimport' => '',
119
  'is_update_previous' => $id ? 1 : 0,
120
  'update_previous' => $id,
121
+ 'xpath' => '/',
122
+ 'large_file' => '',
123
+ 'filepath' => '',
124
+ 'root_element' => ''
125
  ));
126
+
 
 
 
127
  $this->data['history'] = $history = new PMXI_File_List();
128
  $history->setColumns('id', 'name', 'registered_on', 'path')->getBy(NULL, 'id DESC');
129
 
130
+ if ($history->count())
131
+ {
132
+ $uploads = wp_upload_dir();
133
+ foreach ($history as $file){
134
+ if (file_exists(PMXI_Plugin::ROOT_DIR . '/history/' . $file['id']) and !file_exists($uploads['basedir'] . '/wpallimport_history/' . $file['id']))
135
+ {
136
+ $fdata = @file_get_contents(PMXI_Plugin::ROOT_DIR . '/history/' . $file['id']);
137
+ @file_put_contents($uploads['basedir'] . '/wpallimport_history/' . $file['id'], $fdata);
138
+ }
139
+ }
140
+ }
141
+
142
  if ($this->input->post('is_submitted_continue')) {
143
  if ( ! empty($_SESSION['pmxi_import']['xml'])) {
144
  wp_redirect(add_query_arg('action', 'element', $this->baseUrl)); die();
145
  }
146
+ } elseif ('upload' == $this->input->post('type')) {
147
+
148
+ $uploads = wp_upload_dir();
149
+
150
+ if (empty($post['filepath'])) {
151
  $this->errors->add('form-validation', __('XML/CSV file must be specified', 'pmxi_plugin'));
152
+ } elseif (!is_file($post['filepath'])) {
153
  $this->errors->add('form-validation', __('Uploaded file is empty', 'pmxi_plugin'));
154
+ } elseif ( ! preg_match('%\W(xml|gzip|zip|csv|gz)$%i', trim(basename($post['filepath'])))) {
155
  $this->errors->add('form-validation', __('Uploaded file must be XML, CSV or ZIP, GZIP', 'pmxi_plugin'));
156
+ } elseif (preg_match('%\W(zip)$%i', trim(basename($post['filepath'])))) {
157
+
158
+ include_once(PMXI_Plugin::ROOT_DIR.'/libraries/pclzip.lib.php');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
+ $archive = new PclZip($post['filepath']);
161
+ if (($v_result_list = $archive->extract(PCLZIP_OPT_PATH, $uploads['path'], PCLZIP_OPT_REPLACE_NEWER)) == 0) {
162
+ $this->errors->add('form-validation', 'Failed to open uploaded ZIP archive : '.$archive->errorInfo(true));
163
+ }
 
 
 
 
 
 
 
 
 
 
164
  else {
 
 
 
 
 
 
165
 
166
+ $filePath = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
 
168
+ if (!empty($v_result_list)){
169
+ foreach ($v_result_list as $unzipped_file) {
170
+ if ($unzipped_file['status'] == 'ok') $filePath = $unzipped_file['filename'];
171
+ }
172
+ }
173
  if($uploads['error']){
174
  $this->errors->add('form-validation', __('Can not create upload folder. Permision denied', 'pmxi_plugin'));
175
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
 
177
+ if(empty($filePath)){
178
+ $zip = zip_open(trim($post['filepath']));
179
+ if (is_resource($zip)) {
180
+ while ($zip_entry = zip_read($zip)) {
181
+ $filePath = zip_entry_name($zip_entry);
182
+ $fp = fopen($uploads['path']."/".$filePath, "w");
183
+ if (zip_entry_open($zip, $zip_entry, "r")) {
184
+ $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
185
+ fwrite($fp,"$buf");
186
+ zip_entry_close($zip_entry);
187
+ fclose($fp);
188
+ }
189
+ break;
190
+ }
191
+ zip_close($zip);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
 
193
+ } else {
194
+ $this->errors->add('form-validation', __('Failed to open uploaded ZIP archive. Can\'t extract files.', 'pmxi_plugin'));
195
+ }
196
+ }
 
 
 
 
 
 
197
 
198
+ // Detect if file is very large
199
+ $post['large_file'] = (filesize($filePath) > PMXI_Plugin::LARGE_SIZE) ? 'on' : false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  $source = array(
201
+ 'name' => basename($post['filepath']),
202
+ 'type' => 'upload',
203
+ 'path' => $post['filepath'],
204
+ );
 
 
 
 
 
 
 
 
205
 
206
+ if (preg_match('%\W(csv)$%i', trim($filePath))){ // If CSV file found in archieve
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  if($uploads['error']){
209
  $this->errors->add('form-validation', __('Can not create upload folder. Permision denied', 'pmxi_plugin'));
210
+ }
211
+ if (empty($post['large_file'])) {
212
+ $filePath = PMXI_Plugin::csv_to_xml($filePath);
 
 
 
 
 
 
 
 
213
  }
214
+ else{
215
+ include_once(PMXI_Plugin::ROOT_DIR.'/libraries/XmlImportCsvParse.php');
216
+ $csv = new PMXI_CsvParser($filePath, true); // create chunks
217
+ $filePath = $csv->xml_path;
218
+ $post['root_element'] = 'node';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  }
220
+ }
 
 
 
 
221
  }
222
+
223
+ } elseif ( preg_match('%\W(csv)$%i', trim($post['filepath']))) { // If CSV file uploaded
224
+
225
+ // Detect if file is very large
226
+ $post['large_file'] = (filesize($post['filepath']) > PMXI_Plugin::LARGE_SIZE) ? 'on' : false;
227
+
228
+ if($uploads['error']){
229
+ $this->errors->add('form-validation', __('Can not create upload folder. Permision denied', 'pmxi_plugin'));
230
+ }
231
+ $filePath = $post['filepath'];
232
  $source = array(
233
+ 'name' => basename($post['filepath']),
234
+ 'type' => 'upload',
235
  'path' => $filePath,
236
+ );
237
+ if (empty($post['large_file'])) {
238
+ $filePath = PMXI_Plugin::csv_to_xml($post['filepath']);
239
+ } else{
240
+ include_once(PMXI_Plugin::ROOT_DIR.'/libraries/XmlImportCsvParse.php');
241
+ $csv = new PMXI_CsvParser($post['filepath'], true);
242
+ $filePath = $csv->xml_path;
243
+ $post['root_element'] = 'node';
244
+ }
245
+ } elseif(preg_match('%\W(gz)$%i', trim($post['filepath']))){ // If gz file uploaded
246
+ $fileInfo = pmxi_gzfile_get_contents($post['filepath']);
247
+ $filePath = $fileInfo['localPath'];
248
+
249
+ // Detect if file is very large
250
+ $post['large_file'] = (filesize($filePath) > PMXI_Plugin::LARGE_SIZE) ? 'on' : false;
251
+
252
+ $source = array(
253
+ 'name' => basename($post['filepath']),
254
+ 'type' => 'upload',
255
+ 'path' => $post['filepath'],
256
  );
257
+
258
+ // detect CSV or XML
259
+ if ( $fileInfo['type'] == 'csv') { // it is CSV file
260
+ if (empty($post['large_file'])) {
261
+ $filePath = PMXI_Plugin::csv_to_xml($filePath); // convert CSV to XML
262
+ }
263
+ else{
264
+ include_once(PMXI_Plugin::ROOT_DIR.'/libraries/XmlImportCsvParse.php');
265
+ $csv = new PMXI_CsvParser($filePath, true); // create chunks
266
+ $filePath = $csv->xml_path;
267
+ $post['root_element'] = 'node';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  }
 
 
 
 
 
 
 
269
  }
270
+ } else { // If XML file uploaded
271
+
272
+ // Detect if file is very large
273
+ $post['large_file'] = (filesize($post['filepath']) > PMXI_Plugin::LARGE_SIZE) ? 'on' : false;
274
+
275
+ $filePath = $post['filepath'];
276
  $source = array(
277
+ 'name' => basename($post['filepath']),
278
+ 'type' => 'upload',
279
  'path' => $filePath,
280
  );
281
+ }
282
+ }
283
+ elseif ($this->input->post('is_submitted')){
284
+
285
+ $this->errors->add('form-validation', __('Upgrade to the paid edition of WP All Import to use this feature.', 'pmxi_plugin'));
286
  }
287
+
288
  if ($post['is_update_previous'] and empty($post['update_previous'])) {
289
+ $this->errors->add('form-validation', __('Previous import for update must be selected to proceed with a new one', 'pmxi_plugin'));
290
  }
291
 
292
  if ($this->input->post('is_submitted') and ! $this->errors->get_error_codes()) {
293
 
294
+ check_admin_referer('choose-file', '_wpnonce_choose-file');
295
+
296
+ $elements_cloud = array();
297
 
298
+ if (empty($xml)){
 
 
 
 
 
 
299
 
300
+ $wp_uploads = wp_upload_dir();
301
+
302
+ if (!empty($post['large_file'])){
303
+
304
+ set_time_limit(0);
305
 
306
+ $chunks = 0;
307
+
308
+ $chunk_path = '';
 
 
309
 
310
+ $local_paths = !empty($local_paths) ? $local_paths : array($filePath);
311
+
312
+ foreach ($local_paths as $key => $path) {
313
+
314
+ $file = new PMXI_Chunk($path, array('element' => $post['root_element'], 'path' => $wp_uploads['path']));
315
+
316
+ while ($chunk_xml = $file->read()) {
317
+
318
+ if (!empty($chunk_xml))
319
+ {
320
+ PMXI_Import_Record::preprocessXml($chunk_xml);
321
+ if ( ! $chunks ){ // save first chunk to the file
322
+ $chunk_path = $wp_uploads['path'] .'/'. wp_unique_filename($wp_uploads['path'], "chunk_".basename($path));
323
+ if (file_exists($chunk_path)) unlink($chunk_path);
324
+ file_put_contents($chunk_path, '<?xml version="1.0" encoding="utf-8"?>'."\n".$chunk_xml);
325
+ chmod($chunk_path, 0755);
326
+ }
327
+ $chunks++;
328
+ }
329
+ }
330
+ if ( ! $key ){
331
 
332
+ if ( ! empty($file->options['element'])) {
333
+
334
+ $post['root_element'] = $file->options['element'];
 
 
 
 
 
 
 
 
335
 
336
+ $xpath = "/".$post['root_element'];
337
+
338
+ $elements_cloud = $file->cloud;
339
+
340
+ if (empty($chunks)) { $this->errors->add('form-validation', __('No matching elements found for Root element and XPath expression specified', 'pmxi_plugin')); }
341
+
342
+ $filePath && $xml = @file_get_contents($chunk_path);
343
+ }
344
+ else $this->errors->add('form-validation', __('Unable to find root element for this feed. Please open the feed in your browser or a text editor and ensure it is a valid feed.', 'pmxi_plugin'));
345
+ }
346
+ }
347
+
348
+ } else {
349
+
350
+ ob_start();
351
+ $filePath && @readgzfile($filePath);
352
+ $xml = ob_get_clean();
353
+
354
+ if (empty($xml)){
355
+ $xml = @file_get_contents($filePath);
356
+ if (empty($xml)) get_file_curl($filePath, $wp_uploads['path'] .'/'. basename($filePath));
357
+ if (empty($xml)) $xml = @file_get_contents($wp_uploads['path'] .'/'. basename($filePath));
358
+ }
359
+ }
360
+ }
361
 
362
+ if ((empty($post['large_file']) and PMXI_Import_Record::validateXml($xml, $this->errors)) or (!empty($post['large_file']) and !empty($chunks))) {
363
  // xml is valid
364
+ if (!empty($post['large_file'])){
365
+ $source['large_import'] = 'Yes';
366
+ $source['root_element'] = $post['root_element'];
367
+ }
368
+ else {
369
+ $source['large_import'] = 'No';
370
+ $source['root_element'] = '';
371
+ }
372
+
373
+ $source['first_import'] = date("Y-m-d H:i:s");
374
+
375
  $_SESSION['pmxi_import'] = array(
376
  'xml' => $xml,
377
+ 'filePath' => $filePath,
378
+ 'source' => $source,
379
+ 'large_file' => (!empty($post['large_file'])) ? true : false,
380
+ 'chunk_number' => 1,
381
+ 'log' => '',
382
+ 'current_post_ids' => '',
383
+ 'processing' => 0,
384
+ 'queue_chunk_number' => 0,
385
+ 'count' => (isset($chunks)) ? $chunks : 0,
386
+ 'created_records' => 0,
387
+ 'updated_records' => 0,
388
+ 'skipped_records' => 0,
389
+ 'warnings' => 0,
390
+ 'errors' => 0,
391
+ 'start_time' => 0,
392
+ 'local_paths' => (!empty($local_paths)) ? $local_paths : array(), // ftp import local copies of remote files
393
+ 'action' => 'import',
394
+ 'elements_cloud' => (!empty($elements_cloud)) ? $elements_cloud : array()
395
+ );
396
+
397
+ unset($xml);
398
  $update_previous = new PMXI_Import_Record();
399
  if ($post['is_update_previous'] and ! $update_previous->getById($post['update_previous'])->isEmpty()) {
400
  $_SESSION['pmxi_import'] += array(
406
  } else {
407
  $_SESSION['pmxi_import']['update_previous'] = '';
408
  }
409
+
410
  wp_redirect(add_query_arg('action', 'element', $this->baseUrl)); die();
411
+
412
  }
413
  }
414
 
420
  */
421
  public function element()
422
  {
423
+
 
424
  $xpath = new DOMXPath($this->data['dom']);
425
  $post = $this->input->post(array('xpath' => ''));
426
  $this->data['post'] =& $post;
427
+ $this->data['elements_cloud'] = $_SESSION['pmxi_import']['elements_cloud'];
428
+
429
+ $wp_uploads = wp_upload_dir();
430
 
431
  if ($this->input->post('is_submitted')) {
432
  check_admin_referer('choose-elements', '_wpnonce_choose-elements');
448
  }
449
  }
450
  }
451
+
452
  if ( ! $this->errors->get_error_codes()) {
453
  $_SESSION['pmxi_import']['xpath'] = $post['xpath'];
454
+ // counting element selected by xPath
455
+ if ($_SESSION['pmxi_import']['large_file']){
456
+
457
+ $_SESSION['pmxi_import']['count'] = 0;
458
+
459
+ $this->data['node_list_count'] = 0;
460
+
461
+ // loop through the file until all lines are read
462
+ $first_loop = true;
463
+
464
+ foreach ($_SESSION['pmxi_import']['local_paths'] as $key => $path) {
465
+
466
+ $file = new PMXI_Chunk($path, array('element' => $_SESSION['pmxi_import']['source']['root_element'], 'path' => $wp_uploads['path'], 'type' => $this->input->post('type')));
467
+
468
+ while ($xml = $file->read()) {
469
+
470
+ if (!empty($xml))
471
+ {
472
+ PMXI_Import_Record::preprocessXml($xml);
473
+
474
+ $dom = new DOMDocument('1.0', 'UTF-8');
475
+ $old = libxml_use_internal_errors(true);
476
+ $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml)); // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
477
+ libxml_use_internal_errors($old);
478
+ $xpath = new DOMXPath($dom);
479
+ if (($this->data['elements'] = $elements = @$xpath->query($post['xpath'])) and $elements->length){
480
+ $_SESSION['pmxi_import']['count']++;
481
+ $this->data['node_list_count']++;
482
+ if ($first_loop){
483
+ $_SESSION['pmxi_import']['xml'] = $xml;
484
+ $first_loop = false;
485
+ }
486
+ }
487
+ unset($dom, $xpath, $elements);
488
+
489
+ }
490
+ }
491
+ }
492
+
493
+ if ( ! $this->data['node_list_count']) {
494
+ $this->errors->add('form-validation', __('No matching elements found for XPath expression specified', 'pmxi_plugin'));
495
+ }
496
+ }
497
  wp_redirect(add_query_arg('action', 'template', $this->baseUrl)); die();
498
  }
499
  } else {
500
 
501
+ //$this->shrink_xml_element($this->data['dom']->documentElement);
502
 
503
  if (isset($_SESSION['pmxi_import']['xpath'])) {
504
  $post['xpath'] = $_SESSION['pmxi_import']['xpath'];
505
+ $this->data['elements'] = $elements = $xpath->query($post['xpath']);
506
+ if ( ! $elements->length and ! empty($_SESSION['pmxi_import']['update_previous'])) {
507
  $_GET['pmxi_nt'] = __('<b>Warning</b>: No matching elements found for XPath expression from the import being updated. It probably means that new XML file has different format. Though you can update XPath, procceed only if you sure about update operation being valid.', 'pmxi_plugin');
508
  }
509
  } else {
510
  // suggest 1st repeating element as default selection
511
  $post['xpath'] = $this->xml_find_repeating($this->data['dom']->documentElement);
512
+ if (!empty($post['xpath'])){
513
+ $this->data['elements'] = $elements = $xpath->query($post['xpath']);
514
+ }
515
  }
516
+
517
  }
518
 
519
  // workaround to prevent rendered XML representation to eat memory since it has to be stored in momory when output is bufferred
535
  }
536
 
537
  $xpath = new DOMXPath($this->data['dom']);
538
+ $post = $this->input->post(array('xpath' => '', 'show_element' => 1, 'root_element' => $_SESSION['pmxi_import']['source']['root_element']));
539
+ $wp_uploads = wp_upload_dir();
540
+
541
  if ('' == $post['xpath']) {
542
  $this->errors->add('form-validation', __('No elements selected', 'pmxi_plugin'));
543
+ } else {
544
+ // counting selected elements
545
+ if ($_SESSION['pmxi_import']['large_file']){ // in large mode
546
+
547
+ $this->data['node_list_count'] = 0;
548
+
549
+ $_SESSION['pmxi_import']['count'] = 0;
550
+
551
+ $xpath_elements = explode('[', $post['xpath']);
552
+ $xpath_parts = explode('/', $xpath_elements[0]);
553
+
554
+ $_SESSION['pmxi_import']['source']['root_element'] = $xpath_parts[count($xpath_parts) - 1];
555
+
556
+ $loop = 1;
557
+
558
+ foreach ($_SESSION['pmxi_import']['local_paths'] as $key => $path) {
559
+
560
+ $file = new PMXI_Chunk($path, array('element' => $_SESSION['pmxi_import']['source']['root_element'], 'path' => $wp_uploads['path']));
561
+ // loop through the file until all lines are read
562
+ while ($xml = $file->read()) {
563
+
564
+ if (!empty($xml))
565
+ {
566
+ PMXI_Import_Record::preprocessXml($xml);
567
+
568
+ $dom = new DOMDocument('1.0', 'UTF-8');
569
+ $old = libxml_use_internal_errors(true);
570
+ $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml)); // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
571
+ libxml_use_internal_errors($old);
572
+ $xpath = new DOMXPath($dom);
573
+ if (($this->data['elements'] = $elements = @$xpath->query($post['xpath'])) and $elements->length){
574
+ $_SESSION['pmxi_import']['count']++;
575
+ $this->data['node_list_count']++;
576
+ if ($loop == $post['show_element'] ){
577
+ $_SESSION['pmxi_import']['xml'] = $xml;
578
+ $this->data['dom'] = $dom;
579
+ }
580
+ else unset($dom, $xpath, $elements);
581
+ $loop++;
582
+ }
583
+ }
584
+ }
585
+ unset($file);
586
+ }
587
+ if ( ! $this->data['node_list_count']) {
588
+ $this->errors->add('form-validation', __('No matching elements found for XPath expression specified', 'pmxi_plugin'));
589
+ }
590
+ }
591
+ else{ // in default mode
592
+ $this->data['elements'] = $elements = @ $xpath->query($post['xpath']); // prevent parsing warning to be displayed
593
+ $this->data['node_list_count'] = $elements->length;
594
+ if (FALSE === $elements) {
595
+ $this->errors->add('form-validation', __('Invalid XPath expression', 'pmxi_plugin'));
596
+ } elseif ( ! $elements->length) {
597
+ $this->errors->add('form-validation', __('No matching elements found for XPath expression specified', 'pmxi_plugin'));
598
+ } else {
599
+ foreach ($elements as $el) {
600
+ if ( ! $el instanceof DOMElement) {
601
+ $this->errors->add('form-validation', __('XPath must match only elements', 'pmxi_plugin'));
602
+ break;
603
+ };
604
+ }
605
  }
606
  }
607
  }
608
  if ( ! $this->errors->get_error_codes()) {
609
+
610
+ //$this->shrink_xml_element($this->data['dom']->documentElement);
611
  $xpath = new DOMXPath($this->data['dom']);
612
+ $this->data['elements'] = $elements = @ $xpath->query($post['xpath']); // prevent parsing warning to be displayed
613
 
614
  $paths = array(); $this->data['paths'] =& $paths;
615
+ if (PMXI_Plugin::getInstance()->getOption('highlight_limit') and $elements->length <= PMXI_Plugin::getInstance()->getOption('highlight_limit')) {
616
+ foreach ($elements as $el) {
617
  if ( ! $el instanceof DOMElement) continue;
618
 
619
  $p = $this->get_xml_path($el, $xpath) and $paths[] = $p;
637
  'content' => '',
638
  'name' => '',
639
  'is_keep_linebreaks' => 0,
640
+ 'is_leave_html' => 0
641
+ );
642
  if ($this->isWizard) {
643
  $this->data['post'] = $post = $this->input->post(
644
  (isset($_SESSION['pmxi_import']['template']) ? $_SESSION['pmxi_import']['template'] : array())
645
  + $default
646
  );
647
+ } else {
648
  $this->data['post'] = $post = $this->input->post(
649
  $this->data['import']->template
650
  + $default
651
+ );
652
+ }
653
 
654
  if (($load_template = $this->input->post('load_template'))) { // init form with template selected
655
  if ( ! $template->getById($load_template)->isEmpty()) {
656
  $this->data['post'] = array(
657
  'title' => $template->title,
658
  'content' => $template->content,
659
+ 'is_keep_linebreaks' => $template->is_keep_linebreaks,
660
+ 'is_leave_html' => $template->is_leave_html,
661
  'name' => '', // template is always empty
662
  );
663
  $_SESSION['pmxi_import']['is_loaded_template'] = $load_template;
671
  } else {
672
  $this->_validate_template($post['title'], 'Post title');
673
  }
674
+
675
  if (empty($post['content'])) {
676
  $this->errors->add('form-validation', __('Post content is empty', 'pmxi_plugin'));
677
  } else {
678
  $this->_validate_template($post['content'], 'Post content');
679
+ }
 
680
 
681
+ if ( ! $this->errors->get_error_codes()) {
682
  if ( ! empty($post['name'])) { // save template in database
683
  $template->getByName($post['name'])->set($post)->save();
684
+ $_SESSION['pmxi_import']['saved_template'] = $template->id;
685
  }
686
  if ($this->isWizard) {
687
+ $_SESSION['pmxi_import']['template'] = $post;
688
  wp_redirect(add_query_arg('action', 'options', $this->baseUrl)); die();
689
+ } else {
690
  $this->data['import']->set('template', $post)->save();
691
  wp_redirect(add_query_arg(array('page' => 'pmxi-admin-manage', 'pmlc_nt' => urlencode(__('Template updated', 'pmxi_plugin'))) + array_intersect_key($_GET, array_flip($this->baseUrlParamNames)), admin_url('admin.php'))); die();
692
  }
703
  wp_enqueue_script('quicktags');
704
  $this->render();
705
  }
706
+
707
  protected function _validate_template($text, $field_title)
708
  {
709
  try {
720
  * Preview selected xml tag (called with ajax from `template` step)
721
  */
722
  public function tag()
723
+ {
 
 
724
 
725
+ $wp_uploads = wp_upload_dir();
726
+
727
+ if (empty($this->data['elements']->length))
728
+ {
729
  $update_previous = new PMXI_Import_Record();
730
  if ($update_previous->getById($this->input->get('id'))) {
731
  $_SESSION['pmxi_import'] = array(
734
  'template' => $update_previous->template,
735
  'options' => $update_previous->options,
736
  );
737
+ $history = new PMXI_File_List();
738
+ $history->setColumns('id', 'name', 'registered_on', 'path')->getBy(array('import_id' => $update_previous->id), 'id DESC');
739
+ if ($history->count()){
740
+ $history_file = new PMXI_File_Record();
741
+ $history_file->getBy('id', $history[0]['id']);
742
+
743
+ if ($update_previous->large_import == 'Yes'){
744
+ $_SESSION['pmxi_import']['filePath'] = $history_file->path;
745
+ $_SESSION['pmxi_import']['source']['root_element'] = $update_previous->root_element;
746
+ $_SESSION['pmxi_import']['large_file'] = true;
747
+ $_SESSION['pmxi_import']['count'] = $update_previous->count;
748
+ }
749
+ else{
750
+ $_SESSION['pmxi_import']['xml'] = @file_get_contents($history_file->path);
751
+ $this->data['dom'] = $dom = new DOMDocument('1.0', 'UTF-8');
752
+ $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $_SESSION['pmxi_import']['xml']));
753
+ $xpath = new DOMXPath($dom);
754
+
755
+ $this->data['elements'] = $elements = $xpath->query($update_previous->xpath);
756
+ if ( !$elements->length ) $this->data['elements'] = $elements = $xpath->query('.');
757
+ }
758
+ }
759
+
760
  } else {
761
  $_SESSION['pmxi_import']['update_previous'] = '';
762
+ }
 
 
 
 
 
 
 
 
763
  }
764
 
765
+ $this->data['tagno'] = min(max(intval($this->input->getpost('tagno', 1)), 1), ( ! $_SESSION['pmxi_import']['large_file'] ) ? $this->data['elements']->length : $_SESSION['pmxi_import']['count']);
766
+
767
+ if ($_SESSION['pmxi_import']['large_file'] and $this->data['tagno']){
768
+ $loop = 1;
769
+ $_SESSION['pmxi_import']['local_paths'] = (!empty($_SESSION['pmxi_import']['local_paths'])) ? $_SESSION['pmxi_import']['local_paths'] : array($_SESSION['pmxi_import']['filePath']);
770
+ foreach ($_SESSION['pmxi_import']['local_paths'] as $key => $path) {
771
+ $file = new PMXI_Chunk($path, array('element' => $_SESSION['pmxi_import']['source']['root_element']));
772
+ // loop through the file until all lines are read
773
+ while ($xml = $file->read()) {
774
+ if (!empty($xml))
775
+ {
776
+ PMXI_Import_Record::preprocessXml($xml);
777
+
778
+ $dom = new DOMDocument('1.0', 'UTF-8');
779
+ $old = libxml_use_internal_errors(true);
780
+ $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml)); // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
781
+ libxml_use_internal_errors($old);
782
+ $xpath = new DOMXPath($dom);
783
+ if (($this->data['elements'] = $elements = @$xpath->query($_SESSION['pmxi_import']['xpath'])) and $elements->length){
784
+ if ($loop == $this->data['tagno']){
785
+ $_SESSION['pmxi_import']['xml'] = $xml;
786
+ break;
787
+ } else unset($dom, $xpath, $elements);
788
+ $loop++;
789
+ }
790
+ }
791
+ }
792
+ unset($file);
793
+ }
794
+ }
795
+
796
  $this->render();
797
  }
798
 
805
  'title' => '',
806
  'content' => '',
807
  'is_keep_linebreaks' => 0,
808
+ 'is_leave_html' => 0
809
+ ));
810
+ $wp_uploads = wp_upload_dir();
811
+
812
+ $tagno = min(max(intval($this->input->getpost('tagno', 1)), 1), ( ! $_SESSION['pmxi_import']['large_file']) ? $this->data['elements']->length : $_SESSION['pmxi_import']['count']);
813
+ if ($_SESSION['pmxi_import']['large_file']){
814
+ $loop = 1;
815
+ foreach ($_SESSION['pmxi_import']['local_paths'] as $key => $path) {
816
+ $file = new PMXI_Chunk($path, array('element' => $_SESSION['pmxi_import']['source']['root_element'], 'path' => $wp_uploads['path']));
817
+ // loop through the file until all lines are read
818
+ while ($xml = $file->read()) {
819
+ if (!empty($xml))
820
+ {
821
+ PMXI_Import_Record::preprocessXml($xml);
822
+
823
+ $dom = new DOMDocument('1.0', 'UTF-8');
824
+ $old = libxml_use_internal_errors(true);
825
+ $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml)); // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
826
+ libxml_use_internal_errors($old);
827
+ $xpath = new DOMXPath($dom);
828
+ if (($this->data['elements'] = $elements = @$xpath->query($_SESSION['pmxi_import']['xpath'])) and $elements->length){
829
+ if ( $loop == $tagno ) {
830
+ $_SESSION['pmxi_import']['xml'] = $xml;
831
+ break;
832
+ }
833
+ unset($dom, $xpath, $elements);
834
+ $loop++;
835
+ }
836
+ }
837
+ }
838
+ unset($file);
839
+ }
840
+ $tagno = 1;
841
+ }
842
+ $xpath = "(" . $_SESSION['pmxi_import']['xpath'] . ")[$tagno]";
843
  // validate
844
  try {
 
845
  if (empty($post['title'])) {
846
  $this->errors->add('form-validation', __('Post title is empty', 'pmxi_plugin'));
847
  } else {
849
  if ( ! isset($this->data['title']) or '' == strval(trim(strip_tags($this->data['title'], '<img><input><textarea><iframe><object><embed>')))) {
850
  $this->errors->add('xml-parsing', __('<strong>Warning</strong>: resulting post title is empty', 'pmxi_plugin'));
851
  }
852
+ else $this->data['title'] = ($post['is_leave_html']) ? utf8_encode(html_entity_decode($this->data['title'])) : $this->data['title'];
853
  }
854
  } catch (XmlImportException $e) {
855
  $this->errors->add('form-validation', sprintf(__('Error parsing title: %s', 'pmxi_plugin'), $e->getMessage()));
856
  }
857
+ try {
858
  if (empty($post['content'])) {
859
  $this->errors->add('form-validation', __('Post content is empty', 'pmxi_plugin'));
860
  } else {
862
  if ( ! isset($this->data['content']) or '' == strval(trim(strip_tags($this->data['content'], '<img><input><textarea><iframe><object><embed>')))) {
863
  $this->errors->add('xml-parsing', __('<strong>Warning</strong>: resulting post content is empty', 'pmxi_plugin'));
864
  }
865
+ else $this->data['content'] = ($post['is_leave_html']) ? utf8_encode(html_entity_decode($this->data['content'])) : $this->data['content'];
866
  }
867
  } catch (XmlImportException $e) {
868
  $this->errors->add('form-validation', sprintf(__('Error parsing content: %s', 'pmxi_plugin'), $e->getMessage()));
883
  if ($this->isWizard) {
884
  $this->data['source_type'] = $_SESSION['pmxi_import']['source']['type'];
885
  $default['unique_key'] = $_SESSION['pmxi_import']['template']['title'];
886
+
887
+ // auto searching ID element
888
+ if (!empty($this->data['dom'])){
889
+ $this->find_unique_key($this->data['dom']->documentElement);
890
+ if (!empty($this->_unique_key)){
891
+ $id_finded = false;
892
+ foreach ($this->_unique_key as $key) {
893
+ if (stripos($key, 'id') !== false) {
894
+ $default['unique_key'] .= ' - {'.$key.'[1]}';
895
+ $id_finded = true;
896
+ break;
897
+ }
898
+ }
899
+ if (!$id_finded){
900
+ foreach ($this->_unique_key as $key) {
901
+ if (stripos($key, 'url') !== false) {
902
+ $default['unique_key'] .= ' - {'.$key.'[1]}';
903
+ $id_finded = true;
904
+ break;
905
+ }
906
+ }
907
+ }
908
+ }
909
+ }
910
+
911
  $post = $this->input->post(
912
  (isset($_SESSION['pmxi_import']['options']) ? $_SESSION['pmxi_import']['options'] : array())
913
  + $default
914
  );
915
 
916
  $scheduled = $this->input->post(array(
917
+ 'is_scheduled' => ! empty($_SESSION['pmxi_import']['scheduled']),
918
+ 'scheduled_period' => ! empty($_SESSION['pmxi_import']['scheduled']) ? $_SESSION['pmxi_import']['scheduled'] : '0 0 * * *', // daily by default
919
  ));
920
+
921
  } else {
922
  $this->data['source_type'] = $this->data['import']->type;
923
  $post = $this->input->post(
929
  'scheduled_period' => ! empty($this->data['import']->scheduled) ? $this->data['import']->scheduled : '0 0 * * *', // daily by default
930
  ));
931
  }
932
+
933
  $this->data['post'] =& $post;
934
  $this->data['scheduled'] =& $scheduled;
935
  $this->data['is_loaded_template'] = $_SESSION['pmxi_import']['is_loaded_template'];
936
 
937
+ // Get All meta keys in the system
938
+ $this->data['meta_keys'] = $keys = new PMXI_Model_List();
939
+ $keys->setTable(PMXI_Plugin::getInstance()->getWPPrefix() . 'postmeta');
940
+ $keys->setColumns('meta_id', 'meta_key')->getBy(NULL, "meta_id", NULL, NULL, "meta_key");
941
+
942
  if (($load_options = $this->input->post('load_options'))) { // init form with template selected
943
  $this->data['load_options'] = true;
944
  $template = new PMXI_Template_Record();
945
+ if ( ! $template->getById($this->data['is_loaded_template'])->isEmpty()) {
946
+ $post = (!empty($template->options) ? $template->options : array()) + $default;
947
  $scheduled = array(
948
  'is_scheduled' => ! empty($template->scheduled),
949
  'scheduled_period' => ! empty($template->scheduled) ? $template->scheduled : '0 0 * * *', // daily by default
954
  $post = $default;
955
  $scheduled = $this->input->post(array(
956
  'is_scheduled' => ! empty($post['scheduled']),
957
+ 'scheduled_period' => ! empty($post['scheduled']) ? $post['scheduled_period'] : '0 0 * * *', // daily by default
958
  ));
959
  } elseif ($this->input->post('is_submitted')) {
960
+ check_admin_referer('options', '_wpnonce_options');
961
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
962
  if ('page' == $post['type'] and ! preg_match('%^(-?\d+)?$%', $post['order'])) {
963
  $this->errors->add('form-validation', __('Order must be an integer number', 'pmxi_plugin'));
964
  }
984
  if ( ! preg_match('%^([1-9]\d*)( *- *([1-9]\d*))?$%', $chank, $mtch)) {
985
  $this->errors->add('form-validation', __('Wrong format of `Import only specified records` value', 'pmxi_plugin'));
986
  break;
987
+ } elseif ($this->isWizard and empty($_SESSION['pmxi_import']['large_file']) and (intval($mtch[1]) > $this->data['elements']->length or isset($mtch[3]) and intval($mtch[3]) > $this->data['elements']->length)) {
988
  $this->errors->add('form-validation', __('One of the numbers in `Import only specified records` value exceeds record quantity in XML file', 'pmxi_plugin'));
989
  break;
990
  }
996
  } else {
997
  $this->_validate_template($post['unique_key'], __('Post Unique Key', 'pmxi_plugin'));
998
  }
999
+ if ( $post['is_duplicates'] and 'custom field' == $post['duplicate_indicator']){
1000
+ if ('' == $post['custom_duplicate_name'])
1001
+ $this->errors->add('form-validation', __('Custom field name must be specified.', 'pmxi_plugin'));
1002
+ if ('' == $post['custom_duplicate_value'])
1003
+ $this->errors->add('form-validation', __('Custom field value must be specified.', 'pmxi_plugin'));
1004
+ }
1005
 
1006
  if ( ! $this->errors->get_error_codes()) { // no validation errors found
1007
  // assign some defaults
1040
  'template' => $_SESSION['pmxi_import']['template'],
1041
  'options' => $_SESSION['pmxi_import']['options'],
1042
  'scheduled' => $_SESSION['pmxi_import']['scheduled'],
1043
+ 'count' => $_SESSION['pmxi_import']['count'],
1044
+ 'friendly_name' => $this->data['post']['friendly_name'],
1045
  )
1046
  )->save();
1047
 
1049
  $history_file->set(array(
1050
  'name' => $import->name,
1051
  'import_id' => $import->id,
1052
+ 'path' => $_SESSION['pmxi_import']['filePath'],
1053
  'contents' => $_SESSION['pmxi_import']['xml'],
1054
  'registered_on' => date('Y-m-d H:i:s'),
1055
  ))->save();
1057
  wp_redirect(add_query_arg(array('page' => 'pmxi-admin-manage', 'pmlc_nt' => urlencode($is_update ? __('Import updated', 'pmxi_plugin') : __('Import created', 'pmxi_plugin'))), admin_url('admin.php'))); die();
1058
  }
1059
  } else {
1060
+
1061
+ $this->data['import']->set('options', $post)->set( array( 'scheduled' => $scheduled['is_scheduled'] ? $scheduled['scheduled_period'] : '', 'friendly_name' => $this->data['post']['friendly_name'] ) )->save();
1062
  $template = new PMXI_Template_Record();
1063
 
1064
  if (!$template->getByName($this->data['import']->template['name'])->isEmpty()){
1069
  wp_redirect(add_query_arg(array('page' => 'pmxi-admin-manage', 'pmlc_nt' => urlencode(__('Options updated', 'pmxi_plugin'))) + array_intersect_key($_GET, array_flip($this->baseUrlParamNames)), admin_url('admin.php'))); die();
1070
  }
1071
  }
1072
+ }
 
 
1073
 
1074
  $this->render();
1075
  }
1077
  /**
1078
  * Import processing step (status console)
1079
  */
1080
+ public function process($save_history = true)
1081
  {
1082
+ $wp_uploads = wp_upload_dir();
 
 
 
1083
 
1084
+ set_time_limit(0);
1085
+
1086
+ $import = $this->data['update_previous'];
1087
  $import->set(
1088
+ (empty($_SESSION['pmxi_import']['source']) ? array() : $_SESSION['pmxi_import']['source'])
1089
  + array(
1090
  'xpath' => $_SESSION['pmxi_import']['xpath'],
1091
  'template' => $_SESSION['pmxi_import']['template'],
1092
+ 'options' => $_SESSION['pmxi_import']['options'],
1093
+ 'scheduled' => $_SESSION['pmxi_import']['scheduled'],
1094
+ 'count' => $_SESSION['pmxi_import']['count'],
1095
+ 'friendly_name' => $_SESSION['pmxi_import']['options']['friendly_name'],
1096
  )
1097
+ );
1098
+
1099
+ if ( ! PMXI_Plugin::is_ajax()) {
1100
+
1101
+ $this->render();
1102
+ wp_ob_end_flush_all(); flush();
1103
+
1104
+ // Save import history
1105
+ if ( $_SESSION['pmxi_import']['chunk_number'] === 1 ){
1106
+ // store import info in database
1107
+ $import->save();
1108
+
1109
+ if ($_SESSION['pmxi_import']['large_file']) $_SESSION['pmxi_import']['update_previous'] = $import->id;
1110
+
1111
+ if ($save_history){
1112
+ $history_file = new PMXI_File_Record();
1113
+ $history_file->set(array(
1114
+ 'name' => $import->name,
1115
+ 'import_id' => $import->id,
1116
+ 'path' => $_SESSION['pmxi_import']['filePath'],
1117
+ 'contents' => $_SESSION['pmxi_import']['xml'],
1118
+ 'registered_on' => date('Y-m-d H:i:s'),
1119
+ ))->save();
1120
+ }
1121
+ }
1122
+ }
1123
+
1124
+ // create chunks
1125
+ if ($_SESSION['pmxi_import']['large_file'] and $_SESSION['pmxi_import']['chunk_number'] === 1 and $_SESSION['pmxi_import']['options']['create_chunks'] and ! PMXI_Plugin::is_ajax()){
1126
+
1127
+ $_SESSION['pmxi_import']['chunks_files'] = array();
1128
+
1129
+ foreach ($_SESSION['pmxi_import']['local_paths'] as $key => $path) {
1130
+ $file = new PMXI_Chunk($path, array('element' => $_SESSION['pmxi_import']['source']['root_element'], 'path' => $wp_uploads['path']));
1131
+ $new_chunk = true;
1132
+ $loop = 0;
1133
+ $o = false;
1134
+
1135
+ // loop through the file until all lines are read
1136
+ while ($xml = $file->read()) {
1137
+
1138
+ if (!empty($xml))
1139
+ {
1140
+
1141
+ PMXI_Import_Record::preprocessXml($xml);
1142
+
1143
+ $dom = new DOMDocument('1.0', 'UTF-8');
1144
+ $old = libxml_use_internal_errors(true);
1145
+ $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml)); // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
1146
+ libxml_use_internal_errors($old);
1147
+ $xpath = new DOMXPath($dom);
1148
+ if (($elements = @$xpath->query($_SESSION['pmxi_import']['xpath'])) and $elements->length){
1149
+
1150
+ if ($new_chunk){
1151
+ $tmpname = $wp_uploads['path'] .'/'. wp_unique_filename($wp_uploads['path'], basename($path));
1152
+ $c = fopen($tmpname, 'w');
1153
+ fwrite($c, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<".$_SESSION['pmxi_import']['source']['root_element'] ."s>\n");
1154
+ }
1155
+
1156
+ fwrite($c, $xml . "\n");
1157
+
1158
+ if ($loop == $_SESSION['pmxi_import']['options']['records_per_request'] - 1) {
1159
+ fwrite($c, "</".$_SESSION['pmxi_import']['source']['root_element'] . "s>");
1160
+ fclose($c);
1161
+ $_SESSION['pmxi_import']['chunks_files'][] = $tmpname;
1162
+
1163
+ $loop = 0;
1164
+ $new_chunk = true;
1165
+ }
1166
+ else {
1167
+ $loop++;
1168
+ $new_chunk = false;
1169
+ }
1170
+ }
1171
+ }
1172
+ }
1173
+ if ($loop){
1174
+ fwrite($c, "</".$_SESSION['pmxi_import']['source']['root_element'] . "s>");
1175
+ fclose($c);
1176
+ $_SESSION['pmxi_import']['chunks_files'][] = $tmpname;
1177
+ }
1178
+ }
1179
+ $_SESSION['pmxi_import']['local_paths'] = $_SESSION['pmxi_import']['chunks_files'];
1180
+
1181
+ }
1182
+
1183
+ $logger = create_function('$m', 'echo "<div class=\\"progress-msg\\">$m</div>\\n"; if ( "" != strip_tags(pmxi_strip_tags_content($m))) { $_SESSION[\'pmxi_import\'][\'log\'] .= "<p>".strip_tags(pmxi_strip_tags_content($m))."</p>"; flush(); }');
1184
+
1185
+ $_SESSION['pmxi_import']['start_time'] = (empty($_SESSION['pmxi_import']['start_time'])) ? time() : $_SESSION['pmxi_import']['start_time'];
1186
 
1187
+ in_array($import->type, array('ftp')) and !PMXI_Plugin::is_ajax() and $logger and call_user_func($logger, __('Reading files for import...', 'pmxi_plugin'));
1188
+ in_array($import->type, array('ftp')) and !PMXI_Plugin::is_ajax() and $logger and call_user_func($logger, sprintf(_n('%s file found', '%s files found', count($_SESSION['pmxi_import']['local_paths']), 'pmxi_plugin'), count($_SESSION['pmxi_import']['local_paths'])));
1189
+ in_array($import->type, array('ftp')) and !PMXI_Plugin::is_ajax() and $logger and call_user_func($logger, sprintf(__('Importing %s (%s of %s)', 'pmxi_plugin'), $_SESSION['pmxi_import']['local_paths'][0], 1, count($_SESSION['pmxi_import']['local_paths'])));
1190
 
1191
+ if (empty($_SESSION['pmxi_import']['large_file'])){
1192
+ $import->process($_SESSION['pmxi_import']['xml'], $logger, false);
 
 
1193
  }
1194
+ elseif (PMXI_Plugin::is_ajax()) {
1195
+
1196
+ $_SESSION['pmxi_import']['current_post_ids'] = (empty($_SESSION['pmxi_import']['current_post_ids'])) ? array() : $_SESSION['pmxi_import']['current_post_ids'];
1197
+
1198
+ $_SESSION['pmxi_import']['pointer'] = (empty($_SESSION['pmxi_import']['pointer'])) ? 0 : $_SESSION['pmxi_import']['pointer'];
1199
+
1200
+ $loop = 0;
1201
+
1202
+ foreach ($_SESSION['pmxi_import']['local_paths'] as $key => $path) {
1203
+
1204
+ if ($_SESSION['pmxi_import']['options']['create_chunks'] and $_SESSION['pmxi_import']['action'] != 'continue'){
1205
+
1206
+ ob_start();
1207
+
1208
+ $xml = file_get_contents($path);
1209
+
1210
+ if (!empty($xml))
1211
+ {
1212
+ PMXI_Import_Record::preprocessXml($xml);
1213
+
1214
+ $import->set(array('xpath' => '/' . $_SESSION['pmxi_import']['source']['root_element'] . 's' . $_SESSION['pmxi_import']['xpath']))->save();
1215
+ $import->process($xml, $logger, $_SESSION['pmxi_import']['chunk_number']);
1216
+ $import->set(array('xpath' => $_SESSION['pmxi_import']['xpath']))->save();
1217
+
1218
+ array_shift($_SESSION['pmxi_import']['local_paths']);
1219
+ if (!empty($_SESSION['pmxi_import']['chunks_files'])) {
1220
+ $imported_file = array_shift($_SESSION['pmxi_import']['chunks_files']);
1221
+ @unlink($imported_file);
1222
+ }
1223
+ }
1224
+
1225
+ exit(ob_get_clean());
1226
+ }
1227
+ else{
1228
+
1229
+ $file = new PMXI_Chunk($path, array('element' => $_SESSION['pmxi_import']['source']['root_element'], 'path' => $wp_uploads['path']), $_SESSION['pmxi_import']['pointer']);
1230
+
1231
+ // loop through the file until all lines are read
1232
+ while ($xml = $file->read()) {
1233
+
1234
+ if (!empty($xml))
1235
+ {
1236
+ PMXI_Import_Record::preprocessXml($xml);
1237
+
1238
+ $dom = new DOMDocument('1.0', 'UTF-8');
1239
+ $old = libxml_use_internal_errors(true);
1240
+ $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml)); // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
1241
+ libxml_use_internal_errors($old);
1242
+ $xpath = new DOMXPath($dom);
1243
+ if (($this->data['elements'] = $elements = @$xpath->query($_SESSION['pmxi_import']['xpath'])) and $elements->length){
1244
+ $_SESSION['pmxi_import']['pointer'] = $file->pointer;
1245
+ $_SESSION['pmxi_import']['xml'] = $xml;
1246
+ if ( ! $loop ) ob_start();
1247
+ $import->process($_SESSION['pmxi_import']['xml'], $logger, $_SESSION['pmxi_import']['chunk_number']);
1248
+ if ( $loop == $_SESSION['pmxi_import']['options']['records_per_request'] - 1 ) exit(ob_get_clean());
1249
+ $loop++;
1250
+ }
1251
+ }
1252
+
1253
+ if ($_SESSION['pmxi_import']['created_records'] + $_SESSION['pmxi_import']['updated_records'] == $_SESSION['pmxi_import']['count']){
1254
+ array_shift($_SESSION['pmxi_import']['local_paths']);
1255
+ exit(ob_get_clean());
1256
+ }
1257
+
1258
+ $_SESSION['pmxi_import']['pointer'] = 0;
1259
+
1260
+ in_array($import->type,array('ftp')) and !empty($_SESSION['pmxi_import']['local_paths']) and $logger and call_user_func($logger, sprintf(__('Importing %s', 'pmxi_plugin'), $_SESSION['pmxi_import']['local_paths'][0]));
1261
+
1262
+ }
1263
+ }
1264
+ }
1265
+ }
1266
+
1267
+ do_action( 'pmxi_after_xml_import' );
1268
 
1269
+ if (! $_SESSION['pmxi_import']['large_file'] or PMXI_Plugin::is_ajax()){
1270
+
1271
+ // Save import process log
1272
+ $log_file = $wp_uploads['basedir'] . '/wpallimport_logs/' . $import->id . '.html';
1273
+ if (file_exists($log_file)) unlink($log_file);
1274
+ @file_put_contents($log_file, $_SESSION['pmxi_import']['log']);
1275
+
1276
+ // clear import session
1277
+ unset($_SESSION['pmxi_import']); // clear session data (prevent from reimporting the same data on page refresh)
1278
 
1279
  // [indicate in header process is complete]
1280
+ $msg = addcslashes(__('Complete', 'pmxi_plugin'), "'\n\r");
1281
+
1282
+ ob_start();
1283
+
1284
+ echo '<a id="download_pmxi_log" class="update" href="'.esc_url(add_query_arg(array('id' => $import->id, 'action' => 'log', 'page' => 'pmxi-admin-manage'), $this->baseUrl)).'">Download log</a>';
1285
  echo <<<COMPLETE
1286
  <script type="text/javascript">
1287
  //<![CDATA[
1288
  (function($){
1289
+ var percents = $('.import_percent:last').html();
1290
+ if (percents != null && percents != ''){
1291
+ $('#center_progress').html($('.import_process_bar:last').html());
1292
+ $('#right_progress').html(percents + '%');
1293
+ $('#progressbar div').css({'width': ((parseInt(percents) > 100) ? 100 : percents) + '%'});
1294
+ }
1295
  $('#status').html('$msg');
1296
  window.onbeforeunload = false;
1297
  })(jQuery);
1298
  //]]>
1299
  </script>
1300
  COMPLETE;
1301
+ // [/indicate in header process is complete]
 
1302
 
1303
+ echo ob_get_clean(); die;
1304
+
1305
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1306
  }
1307
 
1308
  protected $_sibling_limit = 20;
1361
  }
1362
  protected function render_xml_element(DOMElement $el, $shorten = false, $path = '/', $ind = 1, $lvl = 0)
1363
  {
1364
+ $path .= $el->nodeName;
1365
  if ( ! $el->parentNode instanceof DOMDocument and $ind > 0) {
1366
  $path .= "[$ind]";
1367
+ }
1368
 
1369
  echo '<div class="xml-element lvl-' . $lvl . ' lvl-mod4-' . ($lvl % 4) . '" title="' . $path . '">';
1370
  if ($el->hasChildNodes()) {
1399
  }
1400
  echo '</div>';
1401
  }
1402
+ protected $_unique_key = array();
1403
+ protected function find_unique_key(DOMElement $el){
1404
+ if ($el->hasChildNodes()) {
1405
+ if ($el->childNodes->length) {
1406
+ foreach ($el->childNodes as $child) {
1407
+ if ($child instanceof DOMElement) {
1408
+ if (!in_array($child->nodeName, $this->_unique_key)) $this->_unique_key[] = $child->nodeName;
1409
+ $this->find_unique_key($child);
1410
+ }
1411
+ }
1412
+ }
1413
+ }
1414
+ }
1415
  protected function render_xml_text($text, $shorten = false, $is_render_collapsed = false)
1416
  {
1417
  if (empty($text)) {
1543
 
1544
  return NULL;
1545
  }
1546
+
1547
+ protected function sxml_append(SimpleXMLElement $to, SimpleXMLElement $from) {
1548
+ $toDom = dom_import_simplexml($to);
1549
+ $fromDom = dom_import_simplexml($from);
1550
+ $toDom->appendChild($toDom->ownerDocument->importNode($fromDom, true));
1551
+ }
1552
 
1553
  }
controllers/admin/manage.php CHANGED
@@ -22,7 +22,7 @@ class PMXI_Admin_Manage extends PMXI_Controller_Admin {
22
 
23
  $get = $this->input->get(array(
24
  's' => '',
25
- 'order_by' => 'ID',
26
  'order' => 'DESC',
27
  'pagenum' => 1,
28
  'perPage' => 10,
@@ -55,96 +55,263 @@ class PMXI_Admin_Manage extends PMXI_Controller_Admin {
55
  'current' => $pagenum,
56
  ));
57
 
 
 
58
  $this->render();
59
  }
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  /**
62
  * Reimport
63
  */
64
  public function update() {
65
  $id = $this->input->get('id');
 
 
 
66
  $this->data['item'] = $item = new PMXI_Import_Record();
67
  if ( ! $id or $item->getById($id)->isEmpty()) {
68
  wp_redirect($this->baseUrl); die();
69
- }
70
 
 
 
71
  if ($this->input->post('is_confirmed')) {
72
- check_admin_referer('update-import', '_wpnonce_update-import');
73
-
74
- if (in_array($item->type, array('ftp', 'file'))) {
75
- $xml = '';
76
- } else {
77
 
78
- $contents = get_headers($item->path,1 );
79
-
80
- if (preg_match('%\W(zip)$%i', trim($item->path))){
81
 
82
- $uploads = wp_upload_dir();
83
 
84
- $newfile = $uploads['path']."/".md5(time()).'.zip';
85
 
86
- if (!copy($item->path, $newfile)) {
87
- $this->errors->add('form-validation', __('Failed upload ZIP archive', 'pmxi_plugin'));
88
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
- $zip = zip_open($newfile);
91
- if (is_resource($zip)) {
92
- $uploads = wp_upload_dir();
93
- if($uploads['error']){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  $this->errors->add('form-validation', __('Can not create upload folder. Permision denied', 'pmxi_plugin'));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  }
96
- $filename = '';
97
- while ($zip_entry = zip_read($zip)) {
98
- $filename = zip_entry_name($zip_entry);
99
- $fp = fopen($uploads['path']."/".$filename, "w");
100
- if (zip_entry_open($zip, $zip_entry, "r")) {
101
- $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
102
- fwrite($fp,"$buf");
103
- zip_entry_close($zip_entry);
104
- fclose($fp);
105
- }
106
- break;
107
- }
108
- zip_close($zip);
109
- unlink($newfile);
110
- if (preg_match('%\W(csv)$%i', trim($filename)) or PMXI_Plugin::detect_csv($contents['Content-Type']))
111
- $xml = PMXI_Plugin::csv_to_xml($uploads['path'] .'/'. $filename);
112
- else
113
- $xml = @file_get_contents($uploads['path'] .'/'. $filename);
114
  }
115
 
116
- } elseif (preg_match('%\W(csv)$%i', trim($item->path)) or PMXI_Plugin::detect_csv($contents['Content-Type'])) {
117
- $uploads = wp_upload_dir();
118
- $fdata = file_get_contents($item->path);
119
- $tmpname = md5(time()).'.csv';
120
- file_put_contents($uploads['path'] .'/'. $tmpname, $fdata);
121
- $xml = PMXI_Plugin::csv_to_xml($uploads['path'] .'/'. $tmpname);
122
  }
123
- else
124
- $xml = @file_get_contents($item->path);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  }
126
- if (in_array($item->type, array('ftp', 'file')) or PMXI_Import_Record::validateXml($xml, $this->errors)) { // xml is valid
 
 
 
 
 
 
 
 
 
 
127
  // compose data to look like result of wizard steps
128
- $_SESSION['pmxi_import'] = array(
129
- 'xml' => $xml,
 
130
  'source' => array(
131
  'name' => $item->name,
132
- 'type' => $item->type,
133
  'path' => $item->path,
 
134
  ),
135
  'update_previous' => $item->id,
136
  'xpath' => $item->xpath,
137
  'template' => $item->template,
138
  'options' => $item->options,
139
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  // deligate operation to other controller
141
  $controller = new PMXI_Admin_Import();
142
  $controller->data['update_previous'] = $item;
143
  $controller->process();
144
  return;
145
  }
146
-
147
- }
148
  $this->render();
149
  }
150
 
@@ -195,4 +362,18 @@ class PMXI_Admin_Manage extends PMXI_Controller_Admin {
195
 
196
  $this->render();
197
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  }
22
 
23
  $get = $this->input->get(array(
24
  's' => '',
25
+ 'order_by' => 'registered_on',
26
  'order' => 'DESC',
27
  'pagenum' => 1,
28
  'perPage' => 10,
55
  'current' => $pagenum,
56
  ));
57
 
58
+ unset($_SESSION['pmxi_import']);
59
+
60
  $this->render();
61
  }
62
 
63
+ /**
64
+ * Edit Template
65
+ */
66
+ public function edit() {
67
+ // deligate operation to other controller
68
+ $controller = new PMXI_Admin_Import();
69
+ $controller->set('isTemplateEdit', true);
70
+ $controller->template();
71
+ }
72
+
73
+ /**
74
+ * Edit Options
75
+ */
76
+ public function options() {
77
+ // deligate operation to other controller
78
+ $controller = new PMXI_Admin_Import();
79
+ $controller->set('isTemplateEdit', true);
80
+ $controller->options();
81
+ }
82
+
83
  /**
84
  * Reimport
85
  */
86
  public function update() {
87
  $id = $this->input->get('id');
88
+ $action_type = $this->input->get('type');
89
+ $pointer = 0;
90
+
91
  $this->data['item'] = $item = new PMXI_Import_Record();
92
  if ( ! $id or $item->getById($id)->isEmpty()) {
93
  wp_redirect($this->baseUrl); die();
94
+ }
95
 
96
+ unset($_SESSION['pmxi_import']);
97
+
98
  if ($this->input->post('is_confirmed')) {
 
 
 
 
 
99
 
100
+ check_admin_referer('update-import', '_wpnonce_update-import');
101
+
102
+ $uploads = wp_upload_dir();
103
 
104
+ if ($item->large_import == 'No' or ($item->large_import == 'Yes' and empty($_SESSION['pmxi_import']['chunk_number']))) {
105
 
106
+ if ( in_array($item->type, array('upload')) ) { // if import type NOT URL
107
 
108
+ if (preg_match('%\W(zip)$%i', trim(basename($item->path)))) {
109
+
110
+ include_once(PMXI_Plugin::ROOT_DIR.'/libraries/pclzip.lib.php');
111
+
112
+ $archive = new PclZip(trim($item->path));
113
+ if (($v_result_list = $archive->extract(PCLZIP_OPT_PATH, $uploads['path'], PCLZIP_OPT_REPLACE_NEWER)) == 0) {
114
+ $this->errors->add('form-validation', 'Failed to open uploaded ZIP archive : '.$archive->errorInfo(true));
115
+ }
116
+ else {
117
+
118
+ $filePath = '';
119
+
120
+ if (!empty($v_result_list)){
121
+ foreach ($v_result_list as $unzipped_file) {
122
+ if ($unzipped_file['status'] == 'ok') $filePath = $unzipped_file['filename'];
123
+ }
124
+ }
125
+ if($uploads['error']){
126
+ $this->errors->add('form-validation', __('Can not create upload folder. Permision denied', 'pmxi_plugin'));
127
+ }
128
+
129
+ if(empty($filePath)){
130
+ $zip = zip_open(trim($item->path));
131
+ if (is_resource($zip)) {
132
+ while ($zip_entry = zip_read($zip)) {
133
+ $filePath = zip_entry_name($zip_entry);
134
+ $fp = fopen($uploads['path']."/".$filePath, "w");
135
+ if (zip_entry_open($zip, $zip_entry, "r")) {
136
+ $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
137
+ fwrite($fp,"$buf");
138
+ zip_entry_close($zip_entry);
139
+ fclose($fp);
140
+ }
141
+ break;
142
+ }
143
+ zip_close($zip);
144
+
145
+ } else {
146
+ $this->errors->add('form-validation', __('Failed to open uploaded ZIP archive. Can\'t extract files.', 'pmxi_plugin'));
147
+ }
148
+ }
149
 
150
+ if (preg_match('%\W(csv)$%i', trim($filePath))){ // If CSV file found in archieve
151
+
152
+ if($uploads['error']){
153
+ $this->errors->add('form-validation', __('Can not create upload folder. Permision denied', 'pmxi_plugin'));
154
+ }
155
+ if (empty($item->large_import) or $item->large_import == 'No') {
156
+ $filePath = PMXI_Plugin::csv_to_xml($filePath);
157
+ }
158
+ else{
159
+ include_once(PMXI_Plugin::ROOT_DIR.'/libraries/XmlImportCsvParse.php');
160
+ $csv = new PMXI_CsvParser($filePath, true); // create chunks
161
+ $filePath = $csv->xml_path;
162
+ }
163
+ }
164
+ }
165
+
166
+ } elseif ( preg_match('%\W(csv)$%i', trim($item->path))) { // If CSV file uploaded
167
+ if($uploads['error']){
168
  $this->errors->add('form-validation', __('Can not create upload folder. Permision denied', 'pmxi_plugin'));
169
+ }
170
+ $filePath = $post['filepath'];
171
+ if (empty($item->large_import) or $item->large_import == 'No') {
172
+ $filePath = PMXI_Plugin::csv_to_xml($item->path);
173
+ } else{
174
+ include_once(PMXI_Plugin::ROOT_DIR.'/libraries/XmlImportCsvParse.php');
175
+ $csv = new PMXI_CsvParser($item->path, true);
176
+ $filePath = $csv->xml_path;
177
+ }
178
+ } elseif(preg_match('%\W(gz)$%i', trim($item->path))){ // If gz file uploaded
179
+ $fileInfo = pmxi_gzfile_get_contents($item->path);
180
+ $filePath = $fileInfo['localPath'];
181
+ // detect CSV or XML
182
+ if ( $fileInfo['type'] == 'csv') { // it is CSV file
183
+ if (empty($item->large_import) or $item->large_import == 'No') {
184
+ $filePath = PMXI_Plugin::csv_to_xml($filePath); // convert CSV to XML
185
+ }
186
+ else{
187
+ include_once(PMXI_Plugin::ROOT_DIR.'/libraries/XmlImportCsvParse.php');
188
+ $csv = new PMXI_CsvParser($filePath, true); // create chunks
189
+ $filePath = $csv->xml_path;
190
+ }
191
  }
192
+ } else { // If XML file uploaded
193
+
194
+ $filePath = $item->path;
195
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  }
197
 
 
 
 
 
 
 
198
  }
199
+
200
+ if (empty($xml)){
201
+
202
+ if ($item->large_import == 'Yes'){
203
+
204
+ set_time_limit(0);
205
+
206
+ $chunks = 0;
207
+
208
+ $chunk_path = '';
209
+
210
+ $local_paths = !empty($local_paths) ? $local_paths : array($filePath);
211
+
212
+ foreach ($local_paths as $key => $path) {
213
+
214
+ $file = new PMXI_Chunk($path, array('element' => $item->root_element, 'path' => $uploads['path']));
215
+
216
+ while ($xml = $file->read()) {
217
+
218
+ if (!empty($xml))
219
+ {
220
+ PMXI_Import_Record::preprocessXml($xml);
221
+
222
+ $dom = new DOMDocument('1.0', 'UTF-8');
223
+ $old = libxml_use_internal_errors(true);
224
+ $dom->loadXML(preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml)); // FIX: libxml xpath doesn't handle default namespace properly, so remove it upon XML load
225
+ libxml_use_internal_errors($old);
226
+ $xpath = new DOMXPath($dom);
227
+ if (($this->data['elements'] = $elements = @$xpath->query($item->xpath)) and $elements->length) {
228
+ if ( !$chunks) {
229
+ $chunk_path = $uploads['path'] .'/'. wp_unique_filename($uploads['path'], "chunk_".basename($path));
230
+ if (file_exists($chunk_path)) unlink($chunk_path);
231
+ file_put_contents($chunk_path, '<?xml version="1.0" encoding="utf-8"?>'."\n".$xml);
232
+ chmod($chunk_path, 0755);
233
+ }
234
+ $chunks++;
235
+
236
+ if (!empty($action_type) and $action_type == 'continue' and $chunks == $item->imported) $pointer = $file->pointer;
237
+
238
+ }
239
+ unset($dom, $xpath, $elements);
240
+ }
241
+ }
242
+ unset($file);
243
+
244
+ !$key and $filePath = $path;
245
+ }
246
+
247
+ if (empty($chunks))
248
+ $this->errors->add('form-validation', __('No matching elements found for Root element and XPath expression specified', 'pmxi_plugin'));
249
+ else
250
+ $xml = @file_get_contents($chunk_path);
251
+
252
+ } else {
253
+
254
+ ob_start();
255
+ $filePath && @readgzfile($filePath);
256
+ $xml = ob_get_clean();
257
+
258
+ if (empty($xml)){
259
+ $xml = @file_get_contents($filePath);
260
+ if (empty($xml)) get_file_curl($filePath, $uploads['path'] .'/'. basename($filePath));
261
+ if (empty($xml)) $xml = @file_get_contents($uploads['path'] .'/'. basename($filePath));
262
+ }
263
+ }
264
+ }
265
  }
266
+
267
+ if (!empty($_SESSION['pmxi_import']['xml'])) $xml = $_SESSION['pmxi_import']['xml'];
268
+
269
+ if ($item->large_import == 'Yes' or PMXI_Import_Record::validateXml($xml, $this->errors)) { // xml is valid
270
+
271
+ $item->set(array(
272
+ 'processing' => 0,
273
+ 'queue_chunk_number' => 0,
274
+ 'current_post_ids' => ''
275
+ ))->save();
276
+
277
  // compose data to look like result of wizard steps
278
+ $_SESSION['pmxi_import'] = (empty($_SESSION['pmxi_import']['chunk_number'])) ? array(
279
+ 'xml' => (isset($xml)) ? $xml : '',
280
+ 'filePath' => $filePath,
281
  'source' => array(
282
  'name' => $item->name,
283
+ 'type' => $item->type,
284
  'path' => $item->path,
285
+ 'root_element' => $item->root_element,
286
  ),
287
  'update_previous' => $item->id,
288
  'xpath' => $item->xpath,
289
  'template' => $item->template,
290
  'options' => $item->options,
291
+ 'scheduled' => $item->scheduled,
292
+ 'current_post_ids' => '',
293
+ 'large_file' => ($item->large_import == 'Yes') ? true : false,
294
+ 'chunk_number' => (!empty($action_type) and $action_type == 'continue') ? $item->imported : 1,
295
+ 'pointer' => $pointer,
296
+ 'log' => '',
297
+ 'created_records' => (!empty($action_type) and $action_type == 'continue') ? $item->created : 0,
298
+ 'updated_records' => (!empty($action_type) and $action_type == 'continue') ? $item->updated : 0,
299
+ 'skipped_records' => (!empty($action_type) and $action_type == 'continue') ? $item->skipped : 0,
300
+ 'warnings' => 0,
301
+ 'errors' => 0,
302
+ 'start_time' => 0,
303
+ 'count' => (isset($chunks)) ? $chunks : 0,
304
+ 'local_paths' => (!empty($local_paths)) ? $local_paths : array(), // ftp import local copies of remote files
305
+ 'action' => (!empty($action_type) and $action_type == 'continue') ? 'continue' : 'update',
306
+ ) : $_SESSION['pmxi_import'];
307
+
308
  // deligate operation to other controller
309
  $controller = new PMXI_Admin_Import();
310
  $controller->data['update_previous'] = $item;
311
  $controller->process();
312
  return;
313
  }
314
+ }
 
315
  $this->render();
316
  }
317
 
362
 
363
  $this->render();
364
  }
365
+
366
+ /*
367
+ * Download import log file
368
+ *
369
+ */
370
+ public function log(){
371
+
372
+ $id = $this->input->get('id');
373
+
374
+ $wp_uploads = wp_upload_dir();
375
+
376
+ PMXI_download::csv($wp_uploads['basedir'] . '/wpallimport_logs/' .$id.'.html');
377
+
378
+ }
379
  }
controllers/admin/settings.php CHANGED
@@ -46,12 +46,142 @@ class PMXI_Admin_Settings extends PMXI_Controller_Admin {
46
 
47
  $this->render();
48
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
- public function dismiss(){
 
 
51
 
52
- PMXI_Plugin::getInstance()->updateOption("dismiss", 1);
53
 
54
- exit('OK');
55
- }
56
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  }
46
 
47
  $this->render();
48
  }
49
+
50
+ /**
51
+ * upload.php
52
+ *
53
+ * Copyright 2009, Moxiecode Systems AB
54
+ * Released under GPL License.
55
+ *
56
+ * License: http://www.plupload.com/license
57
+ * Contributing: http://www.plupload.com/contributing
58
+ */
59
+ public function upload(){
60
+
61
+ // HTTP headers for no cache etc
62
+ header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
63
+ header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
64
+ header("Cache-Control: no-store, no-cache, must-revalidate");
65
+ header("Cache-Control: post-check=0, pre-check=0", false);
66
+ header("Pragma: no-cache");
67
 
68
+ // Settings
69
+ //$targetDir = ini_get("upload_tmp_dir") . DIRECTORY_SEPARATOR . "plupload";
70
+ $uploads = wp_upload_dir();
71
 
72
+ $targetDir = $uploads['path'];
73
 
74
+ $cleanupTargetDir = true; // Remove old files
75
+ $maxFileAge = 5 * 3600; // Temp file age in seconds
76
+
77
+ // 5 minutes execution time
78
+ @set_time_limit(5 * 60);
79
+
80
+ // Uncomment this one to fake upload time
81
+ // usleep(5000);
82
+
83
+ // Get parameters
84
+ $chunk = isset($_REQUEST["chunk"]) ? intval($_REQUEST["chunk"]) : 0;
85
+ $chunks = isset($_REQUEST["chunks"]) ? intval($_REQUEST["chunks"]) : 0;
86
+ $fileName = isset($_REQUEST["name"]) ? $_REQUEST["name"] : '';
87
+
88
+ // Clean the fileName for security reasons
89
+ $fileName = preg_replace('/[^\w\._]+/', '_', $fileName);
90
+
91
+ // Make sure the fileName is unique but only if chunking is disabled
92
+ if ($chunks < 2 && file_exists($targetDir . DIRECTORY_SEPARATOR . $fileName)) {
93
+ $ext = strrpos($fileName, '.');
94
+ $fileName_a = substr($fileName, 0, $ext);
95
+ $fileName_b = substr($fileName, $ext);
96
+
97
+ $count = 1;
98
+ while (file_exists($targetDir . DIRECTORY_SEPARATOR . $fileName_a . '_' . $count . $fileName_b))
99
+ $count++;
100
+
101
+ $fileName = $fileName_a . '_' . $count . $fileName_b;
102
+ }
103
+
104
+ $filePath = $targetDir . DIRECTORY_SEPARATOR . $fileName;
105
+
106
+ // Create target dir
107
+ if (!file_exists($targetDir))
108
+ @mkdir($targetDir);
109
+
110
+ // Remove old temp files
111
+ if ($cleanupTargetDir && is_dir($targetDir) && ($dir = opendir($targetDir))) {
112
+ while (($file = readdir($dir)) !== false) {
113
+ $tmpfilePath = $targetDir . DIRECTORY_SEPARATOR . $file;
114
+
115
+ // Remove temp file if it is older than the max age and is not the current file
116
+ if (preg_match('/\.part$/', $file) && (filemtime($tmpfilePath) < time() - $maxFileAge) && ($tmpfilePath != "{$filePath}.part")) {
117
+ @unlink($tmpfilePath);
118
+ }
119
+ }
120
+
121
+ closedir($dir);
122
+ } else
123
+ exit(json_encode(array("jsonrpc" => "2.0", "error" => array("code" => 100, "message" => "Failed to open temp directory."), "id" => "id")));
124
+
125
+
126
+ // Look for the content type header
127
+ if (isset($_SERVER["HTTP_CONTENT_TYPE"]))
128
+ $contentType = $_SERVER["HTTP_CONTENT_TYPE"];
129
+
130
+ if (isset($_SERVER["CONTENT_TYPE"]))
131
+ $contentType = $_SERVER["CONTENT_TYPE"];
132
+
133
+ // Handle non multipart uploads older WebKit versions didn't support multipart in HTML5
134
+ if (strpos($contentType, "multipart") !== false) {
135
+ if (isset($_FILES['file']['tmp_name']) && is_uploaded_file($_FILES['file']['tmp_name'])) {
136
+ // Open temp file
137
+ $out = fopen("{$filePath}.part", $chunk == 0 ? "wb" : "ab");
138
+ if ($out) {
139
+ // Read binary input stream and append it to temp file
140
+ $in = fopen($_FILES['file']['tmp_name'], "rb");
141
+
142
+ if ($in) {
143
+ while ($buff = fread($in, 4096))
144
+ fwrite($out, $buff);
145
+ } else
146
+ exit(json_encode(array("jsonrpc" => "2.0", "error" => array("code" => 101, "message" => "Failed to open input stream."), "id" => "id")));
147
+ fclose($in);
148
+ fclose($out);
149
+ @unlink($_FILES['file']['tmp_name']);
150
+ } else
151
+ die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
152
+ } else
153
+ exit(json_encode(array("jsonrpc" => "2.0", "error" => array("code" => 103, "message" => "Failed to move uploaded file."), "id" => "id")));
154
+ } else {
155
+ // Open temp file
156
+ $out = fopen("{$filePath}.part", $chunk == 0 ? "wb" : "ab");
157
+ if ($out) {
158
+ // Read binary input stream and append it to temp file
159
+ $in = fopen("php://input", "rb");
160
+
161
+ if ($in) {
162
+ while ($buff = fread($in, 4096))
163
+ fwrite($out, $buff);
164
+ } else
165
+ exit(json_encode(array("jsonrpc" => "2.0", "error" => array("code" => 101, "message" => "Failed to open input stream."), "id" => "id")));
166
+
167
+ fclose($in);
168
+ fclose($out);
169
+ } else
170
+ exit(json_encode(array("jsonrpc" => "2.0", "error" => array("code" => 102, "message" => "Failed to open output stream."), "id" => "id")));
171
+ }
172
+
173
+ // Check if file has been uploaded
174
+ if (!$chunks || $chunk == $chunks - 1) {
175
+ // Strip the temp .part suffix off
176
+ rename("{$filePath}.part", $filePath); chmod($filePath, 0755);
177
+ }
178
+
179
+ // Return JSON-RPC response
180
+ exit(json_encode(array("jsonrpc" => "2.0", "result" => null, "id" => "id", "name" => $filePath)));
181
+
182
+ }
183
+
184
+ public function download(){
185
+ PMXI_download::csv(PMXI_Plugin::ROOT_DIR.'/logs/'.$_GET['file'].'.txt');
186
+ }
187
  }
controllers/controller/admin.php CHANGED
@@ -40,25 +40,36 @@ abstract class PMXI_Controller_Admin extends PMXI_Controller {
40
  if ( ! is_a($wp_styles, 'WP_Styles'))
41
  $wp_styles = new WP_Styles();
42
 
43
- wp_enqueue_style('jquery-ui', PMXI_Plugin::getInstance()->getRelativePath() . '/static/js/jquery/css/smoothness/jquery-ui.css');
44
- wp_enqueue_style('jquery-tipsy', PMXI_Plugin::getInstance()->getRelativePath() . '/static/js/jquery/css/smoothness/jquery.tipsy.css');
45
- wp_enqueue_style('pmxi-admin-style', PMXI_Plugin::getInstance()->getRelativePath() . '/static/css/admin.css');
46
- wp_enqueue_style('pmxi-admin-style-ie', PMXI_Plugin::getInstance()->getRelativePath() . '/static/css/admin-ie.css');
47
  $wp_styles->add_data('pmxi-admin-style-ie', 'conditional', 'lte IE 7');
48
 
49
  $scheme_color = get_user_option('admin_color') and is_file(PMXI_Plugin::ROOT_DIR . '/static/css/admin-colors-' . $scheme_color . '.css') or $scheme_color = 'fresh';
50
  if (is_file(PMXI_Plugin::ROOT_DIR . '/static/css/admin-colors-' . $scheme_color . '.css')) {
51
- wp_enqueue_style('pmxi-admin-style-color', PMXI_Plugin::getInstance()->getRelativePath() . '/static/css/admin-colors-' . $scheme_color . '.css');
52
  }
53
 
54
- wp_enqueue_script('jquery-ui-datepicker', PMXI_Plugin::getInstance()->getRelativePath() . '/static/js/jquery/ui.datepicker.js', 'jquery-ui-core');
55
- wp_enqueue_script('jquery-ui-autocomplete', PMXI_Plugin::getInstance()->getRelativePath() . '/static/js/jquery/ui.autocomplete.js', array('jquery-ui-core', 'jquery-ui-widget', 'jquery-ui-position'));
56
- wp_enqueue_script('jquery-tipsy', PMXI_Plugin::getInstance()->getRelativePath() . '/static/js/jquery/jquery.tipsy.js', 'jquery');
57
- wp_enqueue_script('jquery-nestable', PMXI_Plugin::getInstance()->getRelativePath() . '/static/js/jquery/jquery.mjs.nestedSortable.js', array('jquery', 'jquery-ui-dialog', 'jquery-ui-sortable', 'jquery-ui-draggable', 'jquery-ui-droppable'));
58
-
59
- wp_enqueue_script('pmxi-admin-script', PMXI_Plugin::getInstance()->getRelativePath() . '/static/js/admin.js', array('jquery', 'jquery-ui-dialog', 'jquery-ui-datepicker', 'jquery-ui-draggable', 'jquery-ui-droppable'));
60
-
61
- }
 
 
 
 
 
 
 
 
 
 
 
62
 
63
  /**
64
  * @see Controller::render()
40
  if ( ! is_a($wp_styles, 'WP_Styles'))
41
  $wp_styles = new WP_Styles();
42
 
43
+ wp_enqueue_style('jquery-ui', PMXI_ROOT_URL . '/static/js/jquery/css/redmond/jquery-ui.css');
44
+ wp_enqueue_style('jquery-tipsy', PMXI_ROOT_URL . '/static/js/jquery/css/smoothness/jquery.tipsy.css');
45
+ wp_enqueue_style('pmxi-admin-style', PMXI_ROOT_URL . '/static/css/admin.css');
46
+ wp_enqueue_style('pmxi-admin-style-ie', PMXI_ROOT_URL . '/static/css/admin-ie.css');
47
  $wp_styles->add_data('pmxi-admin-style-ie', 'conditional', 'lte IE 7');
48
 
49
  $scheme_color = get_user_option('admin_color') and is_file(PMXI_Plugin::ROOT_DIR . '/static/css/admin-colors-' . $scheme_color . '.css') or $scheme_color = 'fresh';
50
  if (is_file(PMXI_Plugin::ROOT_DIR . '/static/css/admin-colors-' . $scheme_color . '.css')) {
51
+ wp_enqueue_style('pmxi-admin-style-color', PMXI_ROOT_URL . '/static/css/admin-colors-' . $scheme_color . '.css');
52
  }
53
 
54
+ wp_enqueue_script('jquery-ui-datepicker', PMXI_ROOT_URL . '/static/js/jquery/ui.datepicker.js', 'jquery-ui-core');
55
+ wp_enqueue_script('jquery-ui-autocomplete', PMXI_ROOT_URL . '/static/js/jquery/ui.autocomplete.js', array('jquery-ui-core', 'jquery-ui-widget', 'jquery-ui-position'));
56
+ wp_enqueue_script('jquery-tipsy', PMXI_ROOT_URL . '/static/js/jquery/jquery.tipsy.js', 'jquery');
57
+ wp_enqueue_script('jquery-nestable', PMXI_ROOT_URL . '/static/js/jquery/jquery.mjs.nestedSortable.js', array('jquery', 'jquery-ui-dialog', 'jquery-ui-sortable', 'jquery-ui-draggable', 'jquery-ui-droppable', 'jquery-ui-tabs', 'jquery-ui-progressbar'));
58
+ wp_enqueue_script('jquery-moment', PMXI_ROOT_URL . '/static/js/jquery/moment.js', 'jquery');
59
+
60
+ /* load plupload scripts */
61
+ wp_deregister_script('swfupload-all');
62
+ wp_deregister_script('swfupload-handlers');
63
+ wp_enqueue_script('swfupload-handlers', get_option('siteurl') . "/wp-includes/js/swfupload/handlers.js", array('jquery'), '2201-20100523');
64
+
65
+ wp_enqueue_script('jquery-browserplus-min', 'http://bp.yahooapis.com/2.4.21/browserplus-min.js', array('jquery'));
66
+ wp_enqueue_script('full-plupload', PMXI_ROOT_URL . '/static/js/plupload/plupload.full.js', array('jquery-browserplus-min'));
67
+ wp_enqueue_script('jquery-plupload', PMXI_ROOT_URL . '/static/js/plupload/wplupload.js', array('full-plupload', 'jquery'));
68
+
69
+ wp_enqueue_script('pmxi-script', PMXI_ROOT_URL . '/static/js/pmxi.js', array('jquery'));
70
+ wp_enqueue_script('pmxi-admin-script', PMXI_ROOT_URL . '/static/js/admin.js', array('jquery', 'jquery-ui-dialog', 'jquery-ui-datepicker', 'jquery-ui-draggable', 'jquery-ui-droppable'));
71
+
72
+ }
73
 
74
  /**
75
  * @see Controller::render()
helpers/get_file_curl.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! function_exists('get_file_curl')):
3
+
4
+ function get_file_curl($url, $fullpath, $to_variable = false) {
5
+
6
+ $ch = curl_init($url);
7
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
8
+ $rawdata = curl_exec_follow($ch);
9
+
10
+ $result = curl_getinfo($ch, CURLINFO_HTTP_CODE);
11
+
12
+ curl_close ($ch);
13
+
14
+ if(file_exists($fullpath)) unlink($fullpath);
15
+
16
+ $fp = fopen($fullpath,'w');
17
+ fwrite($fp, $rawdata);
18
+ fclose($fp);
19
+
20
+ return ($result == 200) ? (($to_variable) ? $rawdata : true) : false;
21
+ }
22
+
23
+ endif;
24
+
25
+ if (!function_exists('curl_exec_follow')):
26
+ function curl_exec_follow($ch, &$maxredirect = null) {
27
+
28
+ $mr = $maxredirect === null ? 5 : intval($maxredirect);
29
+
30
+ if (ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) {
31
+
32
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $mr > 0);
33
+ curl_setopt($ch, CURLOPT_MAXREDIRS, $mr);
34
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
35
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
36
+
37
+ } else {
38
+
39
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
40
+
41
+ if ($mr > 0)
42
+ {
43
+ $original_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
44
+ $newurl = $original_url;
45
+
46
+ $rch = curl_copy_handle($ch);
47
+
48
+ curl_setopt($rch, CURLOPT_HEADER, true);
49
+ curl_setopt($rch, CURLOPT_NOBODY, true);
50
+ curl_setopt($rch, CURLOPT_FORBID_REUSE, false);
51
+ do
52
+ {
53
+ curl_setopt($rch, CURLOPT_URL, $newurl);
54
+ $header = curl_exec($rch);
55
+ if (curl_errno($rch)) {
56
+ $code = 0;
57
+ } else {
58
+ $code = curl_getinfo($rch, CURLINFO_HTTP_CODE);
59
+ if ($code == 301 || $code == 302) {
60
+ preg_match('/Location:(.*?)\n/', $header, $matches);
61
+ $newurl = trim(array_pop($matches));
62
+
63
+ // if no scheme is present then the new url is a
64
+ // relative path and thus needs some extra care
65
+ if(!preg_match("/^https?:/i", $newurl)){
66
+ $newurl = $original_url . $newurl;
67
+ }
68
+ } else {
69
+ $code = 0;
70
+ }
71
+ }
72
+ } while ($code && --$mr);
73
+
74
+ curl_close($rch);
75
+
76
+ if (!$mr)
77
+ {
78
+ if ($maxredirect === null)
79
+ trigger_error('Too many redirects.', E_USER_WARNING);
80
+ else
81
+ $maxredirect = 0;
82
+
83
+ return false;
84
+ }
85
+ curl_setopt($ch, CURLOPT_URL, $newurl);
86
+ }
87
+ }
88
+ return curl_exec($ch);
89
+ }
90
+ endif;
helpers/import_custom_meta_box.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!function_exists('import_custom_meta_box')){
3
+ function import_custom_meta_box($edit_post) {
4
+ ?>
5
+ <div id="postcustomstuff">
6
+ <table id="list-table">
7
+ <tbody class="list:meta" id="the-list">
8
+ <?php if (!empty($_SESSION['pmxi_import']['options']['custom_name'])): foreach ($_SESSION['pmxi_import']['options']['custom_name'] as $i => $name): ?>
9
+ <tr>
10
+ <td class="left">
11
+ <label class="screen-reader-text">Key</label>
12
+ <input type="text" value="<?php echo esc_attr($name) ?>" name="custom_name[]" size="20">
13
+ <div class="submit"><input type="submit" class="delete deletemeta" value="Delete"></div>
14
+ </td>
15
+ <td>
16
+ <label class="screen-reader-text">Value</label>
17
+ <textarea name="custom_value[]" rows="2" cols="30" class="widefat"><?php echo esc_html($_SESSION['pmxi_import']['options']['custom_value'][$i]) ?></textarea>
18
+ </td>
19
+ </tr>
20
+ <?php endforeach; endif; ?>
21
+ </tbody>
22
+ </table>
23
+ <?php meta_form(); ?>
24
+ </div>
25
+ <p><?php _e('Custom fields can be used to add extra metadata to a post that you can <a href="http://codex.wordpress.org/Using_Custom_Fields" target="_blank">use in your theme</a>.'); ?></p>
26
+ <?php
27
+ }
28
+ }
29
+ ?>
helpers/pmxi_functions.php ADDED
@@ -0,0 +1,285 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IF statement
4
+ *
5
+ * @access public
6
+ * @param string
7
+ * @param string
8
+ * @param string
9
+ * @param string
10
+ * @param string
11
+ * @return string
12
+ */
13
+ if (!function_exists('pmxi_if')){
14
+ function pmxi_if($left_condition, $operand = '', $right_condition = '', $then, $else = ''){
15
+ $str = trim(implode(' ', array($left_condition, html_entity_decode($operand), $right_condition)));
16
+ return (eval ("return ($str);")) ? $then : $else;
17
+ }
18
+ }
19
+
20
+ function is_empty($var)
21
+ {
22
+ return empty($var);
23
+ }
24
+
25
+
26
+ /**
27
+ * Word Limiter
28
+ *
29
+ * Limits a string to X number of words.
30
+ *
31
+ * @access public
32
+ * @param string
33
+ * @param string
34
+ * @param string the end character. Usually an ellipsis
35
+ * @return string
36
+ */
37
+ if ( ! function_exists('pmxi_word_limiter'))
38
+ {
39
+ function pmxi_word_limiter($str, $limit = 100, $end_char = '&#8230;')
40
+ {
41
+ if (trim($str) == '')
42
+ {
43
+ return $str;
44
+ }
45
+
46
+ preg_match('/^\s*+(?:\S++\s*+){1,'.(int) $limit.'}/', $str, $matches);
47
+
48
+ if (strlen($str) == strlen($matches[0]))
49
+ {
50
+ $end_char = '';
51
+ }
52
+
53
+ return rtrim($matches[0]).$end_char;
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Character Limiter
59
+ *
60
+ * Limits the string based on the character count. Preserves complete words
61
+ * so the character count may not be exactly as specified.
62
+ *
63
+ * @access public
64
+ * @param string
65
+ * @param string
66
+ * @param string the end character. Usually an ellipsis
67
+ * @return string
68
+ */
69
+ if ( ! function_exists('pmxi_character_limiter'))
70
+ {
71
+ function pmxi_character_limiter($str, $n = 500, $end_char = '&#8230;')
72
+ {
73
+ if (strlen($str) < $n)
74
+ {
75
+ return $str;
76
+ }
77
+
78
+ $str = preg_replace("/\s+/", ' ', str_replace(array("\r\n", "\r", "\n"), ' ', $str));
79
+
80
+ if (strlen($str) <= $n)
81
+ {
82
+ return $str;
83
+ }
84
+
85
+ $out = "";
86
+ foreach (explode(' ', trim($str)) as $val)
87
+ {
88
+ $out .= $val.' ';
89
+
90
+ if (strlen($out) >= $n)
91
+ {
92
+ $out = trim($out);
93
+ return (strlen($out) == strlen($str)) ? $out : $out.$end_char;
94
+ }
95
+ }
96
+ }
97
+ }
98
+
99
+ function url_title($str, $separator = 'dash', $lowercase = FALSE)
100
+ {
101
+ if ($separator == 'dash')
102
+ {
103
+ $search = '_';
104
+ $replace = '-';
105
+ }
106
+ else
107
+ {
108
+ $search = '-';
109
+ $replace = '_';
110
+ }
111
+
112
+ $trans = array(
113
+ '&\#\d+?;' => '',
114
+ '&\S+?;' => '',
115
+ '\s+' => $replace,
116
+ '[^a-z0-9\-\._]' => '',
117
+ $replace.'+' => $replace,
118
+ $replace.'$' => $replace,
119
+ '^'.$replace => $replace,
120
+ '\.+$' => ''
121
+ );
122
+
123
+ $str = strip_tags($str);
124
+
125
+ foreach ($trans as $key => $val)
126
+ {
127
+ $str = preg_replace("#".$key."#i", $val, $str);
128
+ }
129
+
130
+ if ($lowercase === TRUE)
131
+ {
132
+ $str = strtolower($str);
133
+ }
134
+
135
+ return trim(stripslashes($str));
136
+ }
137
+
138
+
139
+ function rand_char($length) {
140
+ $random = '';
141
+ for ($i = 0; $i < $length; $i++) {
142
+ $random .= chr(mt_rand(33, 126));
143
+ }
144
+ return $random;
145
+ }
146
+
147
+ /**
148
+ * Reading large files from remote server
149
+ * @ $filePath - file URL
150
+ * return local path of copied file
151
+ */
152
+ function pmxi_copy_url_file($filePath, $detect = false){
153
+ /*$ctx = stream_context_create();
154
+ stream_context_set_params($ctx, array("notification" => "stream_notification_callback"));*/
155
+
156
+ $type = (preg_match('%\W(csv)$%i', basename($filePath))) ? 'csv' : false;
157
+ $type = (preg_match('%\W(xml)$%i', basename($filePath))) ? 'xml' : false;
158
+
159
+ $uploads = wp_upload_dir();
160
+ $tmpname = wp_unique_filename($uploads['path'], basename($filePath));
161
+ $localPath = $uploads['path'] .'/'. $tmpname;
162
+
163
+ get_file_curl($filePath, $localPath);
164
+
165
+ if (file_exists($localPath)) {
166
+
167
+ if (!$type){
168
+ $file = @fopen($localPath, "rb");
169
+ while (!feof($file)) {
170
+ $chunk = @fread($file, 1024);
171
+ if (strpos($chunk, "<") !== false) $type = 'xml'; else $type = 'csv'; // if it's a 1st chunk, then chunk <? symbols to detect XML file
172
+ break;
173
+ }
174
+ @fclose($file);
175
+ }
176
+
177
+ } else {
178
+ $file = @fopen($filePath, "rb");
179
+ $fp = @fopen($localPath, 'w');
180
+ $first_chunk = true;
181
+ while (!feof($file)) {
182
+ $chunk = @fread($file, 1024);
183
+ if (!$type and $first_chunk and strpos($chunk, "<") !== false) $type = 'xml'; elseif (!$type and $first_chunk) $type = 'csv'; // if it's a 1st chunk, then chunk <? symbols to detect XML file
184
+ $first_chunk = false;
185
+ @fwrite($fp, $chunk);
186
+ }
187
+ @fclose($file);
188
+ @fclose($fp);
189
+ }
190
+
191
+ return ($detect) ? array('type' => $type, 'localPath' => $localPath) : $localPath;
192
+ }
193
+
194
+ function pmxi_gzfile_get_contents($filename, $use_include_path = 0) {
195
+
196
+ $type = 'csv';
197
+ $uploads = wp_upload_dir();
198
+ $tmpname = wp_unique_filename($uploads['path'], basename($filename));
199
+ $fp = @fopen($uploads['path'] .'/'. $tmpname, 'w');
200
+
201
+ $file = @gzopen($filename, 'rb', $use_include_path);
202
+ if ($file) {
203
+ $first_chunk = true;
204
+ while (!gzeof($file)) {
205
+ $chunk = gzread($file, 1024);
206
+ if ($first_chunk and strpos($chunk, "<") !== false) { $type = 'xml'; $first_chunk = false; } // if it's a 1st chunk, then chunk <? symbols to detect XML file
207
+ @fwrite($fp, $chunk);
208
+ }
209
+ gzclose($file);
210
+ }
211
+ @fclose($fp);
212
+ $localPath = $uploads['path'] .'/'. $tmpname;
213
+ return array('type' => $type, 'localPath' => $localPath);
214
+ }
215
+
216
+ function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
217
+ static $filesize = null;
218
+
219
+ $msg = '';
220
+ switch($notification_code) {
221
+ case STREAM_NOTIFY_RESOLVE:
222
+ case STREAM_NOTIFY_AUTH_REQUIRED:
223
+ case STREAM_NOTIFY_COMPLETED:
224
+ case STREAM_NOTIFY_FAILURE:
225
+ case STREAM_NOTIFY_AUTH_RESULT:
226
+ /* Ignore */
227
+ break;
228
+
229
+ case STREAM_NOTIFY_REDIRECTED:
230
+ //$msg = "Being redirected to: ". $message;
231
+ break;
232
+
233
+ case STREAM_NOTIFY_CONNECT:
234
+ //$msg = "Connected...";
235
+ break;
236
+
237
+ case STREAM_NOTIFY_FILE_SIZE_IS:
238
+ $filesize = $bytes_max;
239
+ //$msg = "Filesize: ". $filesize;
240
+ break;
241
+
242
+ case STREAM_NOTIFY_MIME_TYPE_IS:
243
+ //$msg = "Mime-type: ". $message;
244
+ break;
245
+
246
+ case STREAM_NOTIFY_PROGRESS:
247
+ if ($bytes_transferred > 0) {
248
+ echo "<script type='text/javascript'>";
249
+ if (!isset($filesize)) {
250
+ printf("document.getElementById('url_progressbar').innerHTML('Unknown filesize.. %2d kb done..');", $bytes_transferred/1024);
251
+ } else {
252
+ $length = (int)(($bytes_transferred/$filesize)*100);
253
+ echo "document.getElementById('url_upload_value').style.width = ".$length."%";
254
+ printf("document.getElementById('url_progressbar').innerHTML('%02d%% (%0".strlen($filesize/1024)."d/%2d kb)');", $length, ($bytes_transferred/1024), $filesize/1024);
255
+ }
256
+ echo "</script>";
257
+ echo(str_repeat(' ', 256));
258
+ if (@ob_get_contents()) {
259
+ @ob_end_flush();
260
+ }
261
+ flush();
262
+ }
263
+ break;
264
+ }
265
+ }
266
+
267
+ function pmxi_strip_tags_content($text, $tags = '', $invert = FALSE) {
268
+
269
+ preg_match_all('/<(.+?)[\s]*\/?[\s]*>/si', trim($tags), $tags);
270
+ $tags = array_unique($tags[1]);
271
+
272
+ if(is_array($tags) AND count($tags) > 0) {
273
+ if($invert == FALSE) {
274
+ return preg_replace('@<(?!(?:'. implode('|', $tags) .')\b)(\w+)\b.*?>.*?</\1>@si', '', $text);
275
+ }
276
+ else {
277
+ return preg_replace('@<('. implode('|', $tags) .')\b.*?>.*?</\1>@si', '', $text);
278
+ }
279
+ }
280
+ elseif($invert == FALSE) {
281
+ return preg_replace('@<(\w+)\b.*?>.*?</\1>@si', '', $text);
282
+ }
283
+ return $text;
284
+ }
285
+
libraries/XmlImportCsvParse.php CHANGED
@@ -71,7 +71,15 @@ class PMXI_CsvParser
71
  'eol' => '',
72
  'length' => 999999,
73
  'escape' => '"'
74
- );
 
 
 
 
 
 
 
 
75
 
76
  protected
77
 
@@ -108,11 +116,14 @@ class PMXI_CsvParser
108
  * @see load()
109
  * @return void
110
  */
111
- public function __construct($filename = null)
112
  {
 
 
 
113
 
114
  ini_set( "display_errors", 0);
115
- ini_set('auto_detect_line_endings', true);
116
 
117
  $file_params = self::analyse_file($filename, 10);
118
 
@@ -128,36 +139,6 @@ class PMXI_CsvParser
128
  *
129
  * indicates the object which file is to be loaded
130
  *
131
- * <code>
132
- *
133
- * require_once 'File/CSV/DataSource.php';
134
- *
135
- * $csv = new File_CSV_DataSource;
136
- * $csv->load('my_cool.csv');
137
- * var_export($csv->connect());
138
- *
139
- * array (
140
- * 0 =>
141
- * array (
142
- * 'name' => 'john',
143
- * 'age' => '13',
144
- * 'skill' => 'knows magic',
145
- * ),
146
- * 1 =>
147
- * array (
148
- * 'name' => 'tanaka',
149
- * 'age' => '8',
150
- * 'skill' => 'makes sushi',
151
- * ),
152
- * 2 =>
153
- * array (
154
- * 'name' => 'jose',
155
- * 'age' => '5',
156
- * 'skill' => 'dances salsa',
157
- * ),
158
- * )
159
- *
160
- * </code>
161
  *
162
  * @param string $filename the csv filename to load
163
  *
@@ -177,16 +158,6 @@ class PMXI_CsvParser
177
  *
178
  * lets you define different settings for scanning
179
  *
180
- * Given array will override the internal settings
181
- *
182
- * <code>
183
- * $settings = array(
184
- * 'delimiter' => ',',
185
- * 'eol' => ";",
186
- * 'length' => 999999,
187
- * 'escape' => '"'
188
- * );
189
- * </code>
190
  *
191
  * @param mixed $array containing settings to use
192
  *
@@ -204,18 +175,6 @@ class PMXI_CsvParser
204
  *
205
  * gets csv headers into an array
206
  *
207
- * <code>
208
- *
209
- * var_export($csv->getHeaders());
210
- *
211
- * array (
212
- * 0 => 'name',
213
- * 1 => 'age',
214
- * 2 => 'skill',
215
- * )
216
- *
217
- * </code>
218
- *
219
  * @access public
220
  * @return array
221
  */
@@ -242,78 +201,7 @@ class PMXI_CsvParser
242
  *
243
  * Attempts to create a relationship for every single cell that
244
  * was captured and its corresponding header. The sample below shows
245
- * how a connection/relationship is built.
246
- *
247
- * sample of a csv file "my_cool.csv"
248
- *
249
- * <code>
250
- * name,age,skill
251
- * john,13,knows magic
252
- * tanaka,8,makes sushi
253
- * jose,5,dances salsa
254
- * </code>
255
- *
256
- * php implementation
257
- *
258
- * <code>
259
- *
260
- * $csv = new File_CSV_DataSource;
261
- * $csv->load('my_cool.csv');
262
- *
263
- * if (!$csv->isSymmetric()) {
264
- * die('file has headers and rows with different lengths
265
- * cannot connect');
266
- * }
267
- *
268
- * var_export($csv->connect());
269
- *
270
- * array (
271
- * 0 =>
272
- * array (
273
- * 'name' => 'john',
274
- * 'age' => '13',
275
- * 'skill' => 'knows magic',
276
- * ),
277
- * 1 =>
278
- * array (
279
- * 'name' => 'tanaka',
280
- * 'age' => '8',
281
- * 'skill' => 'makes sushi',
282
- * ),
283
- * 2 =>
284
- * array (
285
- * 'name' => 'jose',
286
- * 'age' => '5',
287
- * 'skill' => 'dances salsa',
288
- * ),
289
- * )
290
- *
291
- * </code>
292
- *
293
- *
294
- * You can pass a collection of headers in an array to build
295
- * a connection for those columns only!
296
- *
297
- * <code>
298
- *
299
- * var_export($csv->connect(array('age')));
300
- *
301
- * array (
302
- * 0 =>
303
- * array (
304
- * 'age' => '13',
305
- * ),
306
- * 1 =>
307
- * array (
308
- * 'age' => '8',
309
- * ),
310
- * 2 =>
311
- * array (
312
- * 'age' => '5',
313
- * ),
314
- * )
315
- *
316
- * </code>
317
  *
318
  * @param array $columns the columns to connect, if nothing
319
  * is given all headers will be used to create a connection
@@ -385,35 +273,6 @@ class PMXI_CsvParser
385
  * lets assume that we add one more row to our csv file.
386
  * that has only two values. Something like
387
  *
388
- * <code>
389
- * name,age,skill
390
- * john,13,knows magic
391
- * tanaka,8,makes sushi
392
- * jose,5,dances salsa
393
- * niki,6
394
- * </code>
395
- *
396
- * Then in our php code
397
- *
398
- * <code>
399
- * $csv->load('my_cool.csv');
400
- * var_export($csv->getAsymmetricRows());
401
- * </code>
402
- *
403
- * The result
404
- *
405
- * <code>
406
- *
407
- * array (
408
- * 0 =>
409
- * array (
410
- * 0 => 'niki',
411
- * 1 => '6',
412
- * ),
413
- * )
414
- *
415
- * </code>
416
- *
417
  * @access public
418
  * @return array filled with rows that do not match headers
419
  * @see getHeaders(), symmetrize(), isSymmetric(),
@@ -500,35 +359,6 @@ class PMXI_CsvParser
500
  *
501
  * Note $name is the same as the items returned by getHeaders()
502
  *
503
- * sample of a csv file "my_cool.csv"
504
- *
505
- * <code>
506
- * name,age,skill
507
- * john,13,knows magic
508
- * tanaka,8,makes sushi
509
- * jose,5,dances salsa
510
- * </code>
511
- *
512
- * php implementation
513
- *
514
- * <code>
515
- * $csv = new File_CSV_DataSource;
516
- * $csv->load('my_cool.csv');
517
- * var_export($csv->getColumn('name'));
518
- * </code>
519
- *
520
- * the above example outputs something like
521
- *
522
- * <code>
523
- *
524
- * array (
525
- * 0 => 'john',
526
- * 1 => 'tanaka',
527
- * 2 => 'jose',
528
- * )
529
- *
530
- * </code>
531
- *
532
  * @param string $name the name of the column to fetch
533
  *
534
  * @access public
@@ -555,31 +385,6 @@ class PMXI_CsvParser
555
  * checks if a column exists, columns are identified by their
556
  * header name.
557
  *
558
- * sample of a csv file "my_cool.csv"
559
- *
560
- * <code>
561
- * name,age,skill
562
- * john,13,knows magic
563
- * tanaka,8,makes sushi
564
- * jose,5,dances salsa
565
- * </code>
566
- *
567
- * php implementation
568
- *
569
- * <code>
570
- * $csv = new File_CSV_DataSource;
571
- * $csv->load('my_cool.csv');
572
- * $headers = $csv->getHeaders();
573
- * </code>
574
- *
575
- * now lets check if the columns exist
576
- *
577
- * <code>
578
- * var_export($csv->hasColumn($headers[0])); // true
579
- * var_export($csv->hasColumn('age')); // true
580
- * var_export($csv->hasColumn('I dont exist')); // false
581
- * </code>
582
- *
583
  * @param string $string an item returned by getHeaders()
584
  *
585
  * @access public
@@ -595,49 +400,6 @@ class PMXI_CsvParser
595
  * column appender
596
  *
597
  * Appends a column and each or all values in it can be
598
- * dinamically filled. Only when the $values argument is given.
599
- * <code>
600
- *
601
- *
602
- * var_export($csv->fillColumn('age', 99));
603
- * true
604
- *
605
- * var_export($csv->appendColumn('candy_ownership', array(99, 44, 65)));
606
- * true
607
- *
608
- * var_export($csv->appendColumn('import_id', 111111111));
609
- * true
610
- *
611
- * var_export($csv->connect());
612
- *
613
- * array (
614
- * 0 =>
615
- * array (
616
- * 'name' => 'john',
617
- * 'age' => 99,
618
- * 'skill' => 'knows magic',
619
- * 'candy_ownership' => 99,
620
- * 'import_id' => 111111111,
621
- * ),
622
- * 1 =>
623
- * array (
624
- * 'name' => 'tanaka',
625
- * 'age' => 99,
626
- * 'skill' => 'makes sushi',
627
- * 'candy_ownership' => 44,
628
- * 'import_id' => 111111111,
629
- * ),
630
- * 2 =>
631
- * array (
632
- * 'name' => 'jose',
633
- * 'age' => 99,
634
- * 'skill' => 'dances salsa',
635
- * 'candy_ownership' => 65,
636
- * 'import_id' => 111111111,
637
- * ),
638
- * )
639
- *
640
- * </code>
641
  *
642
  * @param string $column an item returned by getHeaders()
643
  * @param mixed $values same as fillColumn()
@@ -674,71 +436,6 @@ class PMXI_CsvParser
674
  *
675
  * fills alll the data in the given column with $values
676
  *
677
- * sample of a csv file "my_cool.csv"
678
- *
679
- * <code>
680
- * name,age,skill
681
- * john,13,knows magic
682
- * tanaka,8,makes sushi
683
- * jose,5,dances salsa
684
- * </code>
685
- *
686
- * php implementation
687
- *
688
- * <code>
689
- * $csv = new File_CSV_DataSource;
690
- * $csv->load('my_cool.csv');
691
- *
692
- * // if the csv file loads
693
- * if ($csv->load('my_cool.csv')) {
694
- *
695
- * // grab all data within the age column
696
- * var_export($csv->getColumn('age'));
697
- *
698
- * // rename all values in it with the number 99
699
- * var_export($csv->fillColumn('age', 99));
700
- *
701
- * // grab all data within the age column
702
- * var_export($csv->getColumn('age'));
703
- *
704
- * // rename each value in a column independently
705
- * $data = array(1, 2, 3);
706
- * $csv->fillColumn('age', $data);
707
- *
708
- * var_export($csv->getColumn('age'));
709
- * }
710
- * </code>
711
- *
712
- * standard output
713
- *
714
- * <code>
715
- * array (
716
- * 0 => '13',
717
- * 1 => '8',
718
- * 2 => '5',
719
- * )
720
- * </code>
721
- *
722
- * <code>
723
- * true
724
- * </code>
725
- *
726
- * <code>
727
- * array (
728
- * 0 => 99,
729
- * 1 => 99,
730
- * 2 => 99,
731
- * )
732
- * </code>
733
- *
734
- * <code>
735
- * array (
736
- * 0 => 1,
737
- * 1 => 2,
738
- * 2 => 3,
739
- * )
740
- * </code>
741
- *
742
  * @param mixed $column the column identified by a string
743
  * @param mixed $values ither one of the following
744
  * - (Number) will fill the whole column with the value of number
@@ -790,89 +487,7 @@ class PMXI_CsvParser
790
  /**
791
  * column remover
792
  *
793
- * Completly removes a whole column identified by $name
794
- * Note: that this function will only work if data is symmetric.
795
- *
796
- * sample of a csv file "my_cool.csv"
797
- *
798
- * <code>
799
- * name,age,skill
800
- * john,13,knows magic
801
- * tanaka,8,makes sushi
802
- * jose,5,dances salsa
803
- * </code>
804
- *
805
- * load the library and csv file
806
- *
807
- * <code>
808
- * require_once 'File/CSV/DataSource.php';
809
- * $csv = new File_CSV_DataSource;
810
- * $csv->load('my_cool.csv');
811
- * </code>
812
- *
813
- * lets dump currently loaded data
814
- * <code>
815
- * var_export($csv->connect());
816
- * </code>
817
- *
818
- * output
819
- *
820
- * <code>
821
- * array (
822
- * 0 =>
823
- * array (
824
- * 'name' => 'john',
825
- * 'age' => '13',
826
- * 'skill' => 'knows magic',
827
- * ),
828
- * 1 =>
829
- * array (
830
- * 'name' => 'tanaka',
831
- * 'age' => '8',
832
- * 'skill' => 'makes sushi',
833
- * ),
834
- * 2 =>
835
- * array (
836
- * 'name' => 'jose',
837
- * 'age' => '5',
838
- * 'skill' => 'dances salsa',
839
- * ),
840
- * )
841
- * </code>
842
- *
843
- * and now let's remove the second column
844
- *
845
- * <code>
846
- * var_export($csv->removeColumn('age'));
847
- * </code>
848
- *
849
- * output
850
- *
851
- * <code>
852
- * true
853
- * </code>
854
- *
855
- * those changes made let's dump the data again and see what we got
856
- *
857
- * <code>
858
- * array (
859
- * 0 =>
860
- * array (
861
- * 'name' => 'john',
862
- * 'skill' => 'knows magic',
863
- * ),
864
- * 1 =>
865
- * array (
866
- * 'name' => 'tanaka',
867
- * 'skill' => 'makes sushi',
868
- * ),
869
- * 2 =>
870
- * array (
871
- * 'name' => 'jose',
872
- * 'skill' => 'dances salsa',
873
- * ),
874
- * )
875
- * </code>
876
  *
877
  * @param string $name same as the ones returned by getHeaders();
878
  *
@@ -945,30 +560,7 @@ class PMXI_CsvParser
945
  /**
946
  * cell fetcher
947
  *
948
- * gets the value of a specific cell by given coordinates
949
- *
950
- * Note: That indexes start with zero, and headers are not
951
- * searched!
952
- *
953
- * For example if we are trying to grab the cell that is in the
954
- * second row and the third column
955
- *
956
- * <code>
957
- * name,age,skill
958
- * john,13,knows magic
959
- * tanaka,8,makes sushi
960
- * jose,5,dances salsa
961
- * </code>
962
- *
963
- * we would do something like
964
- * <code>
965
- * var_export($csv->getCell(1, 2));
966
- * </code>
967
- *
968
- * and get the following results
969
- * <code>
970
- * 'makes sushi'
971
- * </code>
972
  *
973
  * @param integer $x the row to fetch
974
  * @param integer $y the column to fetch
@@ -990,57 +582,7 @@ class PMXI_CsvParser
990
  /**
991
  * cell value filler
992
  *
993
- * replaces the value of a specific cell
994
- *
995
- * sample of a csv file "my_cool.csv"
996
- *
997
- * <code>
998
- * name,age,skill
999
- * john,13,knows magic
1000
- * tanaka,8,makes sushi
1001
- * jose,5,dances salsa
1002
- * </code>
1003
- *
1004
- * php implementation
1005
- *
1006
- * <code>
1007
- *
1008
- * $csv = new File_CSV_DataSource;
1009
- *
1010
- * // load the csv file
1011
- * $csv->load('my_cool.csv');
1012
- *
1013
- * // find out if the given coordinate is valid
1014
- * if($csv->hasCell(1, 1)) {
1015
- *
1016
- * // if so grab that cell and dump it
1017
- * var_export($csv->getCell(1, 1)); // '8'
1018
- *
1019
- * // replace the value of that cell
1020
- * $csv->fillCell(1, 1, 'new value'); // true
1021
- *
1022
- * // output the new value of the cell
1023
- * var_export($csv->getCell(1, 1)); // 'new value'
1024
- *
1025
- * }
1026
- * </code>
1027
- *
1028
- * now lets try to grab the whole row
1029
- *
1030
- * <code>
1031
- * // show the whole row
1032
- * var_export($csv->getRow(1));
1033
- * </code>
1034
- *
1035
- * standard output
1036
- *
1037
- * <code>
1038
- * array (
1039
- * 0 => 'tanaka',
1040
- * 1 => 'new value',
1041
- * 2 => 'makes sushi',
1042
- * )
1043
- * </code>
1044
  *
1045
  * @param integer $x the row to fetch
1046
  * @param integer $y the column to fetch
@@ -1062,37 +604,7 @@ class PMXI_CsvParser
1062
  }
1063
 
1064
  /**
1065
- * checks if a coordinate is valid
1066
- *
1067
- * sample of a csv file "my_cool.csv"
1068
- *
1069
- * <code>
1070
- * name,age,skill
1071
- * john,13,knows magic
1072
- * tanaka,8,makes sushi
1073
- * jose,5,dances salsa
1074
- * </code>
1075
- *
1076
- * load the csv file
1077
- *
1078
- * <code>
1079
- * $csv = new File_CSV_DataSource;
1080
- * var_export($csv->load('my_cool.csv')); // true if file is
1081
- * // loaded
1082
- * </code>
1083
- *
1084
- * find out if a coordinate is valid
1085
- *
1086
- * <code>
1087
- * var_export($csv->hasCell(99, 3)); // false
1088
- * </code>
1089
- *
1090
- * check again for a know valid coordinate and grab that cell
1091
- *
1092
- * <code>
1093
- * var_export($csv->hasCell(1, 1)); // true
1094
- * var_export($csv->getCell(1, 1)); // '8'
1095
- * </code>
1096
  *
1097
  * @param mixed $x the row to fetch
1098
  * @param mixed $y the column to fetch
@@ -1110,70 +622,7 @@ class PMXI_CsvParser
1110
  /**
1111
  * row fetcher
1112
  *
1113
- * Note: first row is zero
1114
- *
1115
- * sample of a csv file "my_cool.csv"
1116
- *
1117
- * <code>
1118
- * name,age,skill
1119
- * john,13,knows magic
1120
- * tanaka,8,makes sushi
1121
- * jose,5,dances salsa
1122
- * </code>
1123
- *
1124
- * load the library and csv file
1125
- *
1126
- * <code>
1127
- * require_once 'File/CSV/DataSource.php';
1128
- * $csv = new File_CSV_DataSource;
1129
- * $csv->load('my_cool.csv');
1130
- * </code>
1131
- *
1132
- * lets dump currently loaded data
1133
- * <code>
1134
- * var_export($csv->connect());
1135
- * </code>
1136
- *
1137
- * output
1138
- *
1139
- * <code>
1140
- * array (
1141
- * 0 =>
1142
- * array (
1143
- * 'name' => 'john',
1144
- * 'age' => '13',
1145
- * 'skill' => 'knows magic',
1146
- * ),
1147
- * 1 =>
1148
- * array (
1149
- * 'name' => 'tanaka',
1150
- * 'age' => '8',
1151
- * 'skill' => 'makes sushi',
1152
- * ),
1153
- * 2 =>
1154
- * array (
1155
- * 'name' => 'jose',
1156
- * 'age' => '5',
1157
- * 'skill' => 'dances salsa',
1158
- * ),
1159
- * )
1160
- * </code>
1161
- *
1162
- * Now let's fetch the second row
1163
- *
1164
- * <code>
1165
- * var_export($csv->getRow(1));
1166
- * </code>
1167
- *
1168
- * output
1169
- *
1170
- * <code>
1171
- * array (
1172
- * 0 => 'tanaka',
1173
- * 1 => '8',
1174
- * 2 => 'makes sushi',
1175
- * )
1176
- * </code>
1177
  *
1178
  * @param integer $number the row number to fetch
1179
  *
@@ -1197,98 +646,7 @@ class PMXI_CsvParser
1197
  * - all rows if no $range argument is given
1198
  * - a range of rows identified by their key
1199
  * - if rows in range are not found nothing is retrived instead
1200
- * - if no rows were found an empty array is returned
1201
- *
1202
- * sample of a csv file "my_cool.csv"
1203
- *
1204
- * <code>
1205
- * name,age,skill
1206
- * john,13,knows magic
1207
- * tanaka,8,makes sushi
1208
- * jose,5,dances salsa
1209
- * </code>
1210
- *
1211
- * load the library and csv file
1212
- *
1213
- * <code>
1214
- * require_once 'File/CSV/DataSource.php';
1215
- * $csv = new File_CSV_DataSource;
1216
- * $csv->load('my_cool.csv');
1217
- * </code>
1218
- *
1219
- * lets dump currently loaded data
1220
- * <code>
1221
- * var_export($csv->connect());
1222
- * </code>
1223
- *
1224
- * output
1225
- *
1226
- * <code>
1227
- * array (
1228
- * 0 =>
1229
- * array (
1230
- * 'name' => 'john',
1231
- * 'age' => '13',
1232
- * 'skill' => 'knows magic',
1233
- * ),
1234
- * 1 =>
1235
- * array (
1236
- * 'name' => 'tanaka',
1237
- * 'age' => '8',
1238
- * 'skill' => 'makes sushi',
1239
- * ),
1240
- * 2 =>
1241
- * array (
1242
- * 'name' => 'jose',
1243
- * 'age' => '5',
1244
- * 'skill' => 'dances salsa',
1245
- * ),
1246
- * )
1247
- * </code>
1248
- *
1249
- * now get the second and thirdh row
1250
- *
1251
- * <code>
1252
- * var_export($csv->getRows(array(1, 2)));
1253
- * </code>
1254
- *
1255
- * output
1256
- *
1257
- * <code>
1258
- * array (
1259
- * 0 =>
1260
- * array (
1261
- * 0 => 'tanaka',
1262
- * 1 => '8',
1263
- * 2 => 'makes sushi',
1264
- * ),
1265
- * 1 =>
1266
- * array (
1267
- * 0 => 'jose',
1268
- * 1 => '5',
1269
- * 2 => 'dances salsa',
1270
- * ),
1271
- * )
1272
- * </code>
1273
- *
1274
- * now lets try something odd and the goodie third row
1275
- *
1276
- * <code>
1277
- * var_export($csv->getRows(array(9, 2)));
1278
- * </code>
1279
- *
1280
- * output
1281
- *
1282
- * <code>
1283
- * array (
1284
- * 0 =>
1285
- * array (
1286
- * 0 => 'jose',
1287
- * 1 => '5',
1288
- * 2 => 'dances salsa',
1289
- * ),
1290
- * )
1291
- * </code>
1292
  *
1293
  * @param array $range a list of rows to retrive
1294
  *
@@ -1319,23 +677,6 @@ class PMXI_CsvParser
1319
  *
1320
  * This function will exclude the headers
1321
  *
1322
- * sample of a csv file "my_cool.csv"
1323
- *
1324
- * <code>
1325
- * name,age,skill
1326
- * john,13,knows magic
1327
- * tanaka,8,makes sushi
1328
- * jose,5,dances salsa
1329
- * </code>
1330
- *
1331
- * php implementation
1332
- *
1333
- * <code>
1334
- * $csv = new File_CSV_DataSource;
1335
- * $csv->load('my_cool.csv');
1336
- * var_export($csv->countRows()); // returns 3
1337
- * </code>
1338
- *
1339
  * @access public
1340
  * @return integer
1341
  */
@@ -1349,116 +690,6 @@ class PMXI_CsvParser
1349
  *
1350
  * Aggregates one more row to the currently loaded dataset
1351
  *
1352
- * sample of a csv file "my_cool.csv"
1353
- *
1354
- * <code>
1355
- * name,age,skill
1356
- * john,13,knows magic
1357
- * tanaka,8,makes sushi
1358
- * jose,5,dances salsa
1359
- * </code>
1360
- *
1361
- *
1362
- * first let's load the file and output whatever was retrived.
1363
- *
1364
- * <code>
1365
- * require_once 'File/CSV/DataSource.php';
1366
- * $csv = new File_CSV_DataSource;
1367
- * $csv->load('my_cool.csv');
1368
- * var_export($csv->connect());
1369
- * </code>
1370
- *
1371
- * output
1372
- *
1373
- * <code>
1374
- *
1375
- * array (
1376
- * 0 =>
1377
- * array (
1378
- * 'name' => 'john',
1379
- * 'age' => '13',
1380
- * 'skill' => 'knows magic',
1381
- * ),
1382
- * 1 =>
1383
- * array (
1384
- * 'name' => 'tanaka',
1385
- * 'age' => '8',
1386
- * 'skill' => 'makes sushi',
1387
- * ),
1388
- * 2 =>
1389
- * array (
1390
- * 'name' => 'jose',
1391
- * 'age' => '5',
1392
- * 'skill' => 'dances salsa',
1393
- * ),
1394
- * )
1395
- * </code>
1396
- *
1397
- * now lets do some modifications, let's try adding three rows.
1398
- *
1399
- * <code>
1400
- * var_export($csv->appendRow(1));
1401
- * var_export($csv->appendRow('2'));
1402
- * var_export($csv->appendRow(array(3, 3, 3)));
1403
- * </code>
1404
- *
1405
- * output
1406
- *
1407
- * <code>
1408
- * true
1409
- * true
1410
- * true
1411
- * </code>
1412
- *
1413
- * and now let's try to see what has changed
1414
- *
1415
- * <code>
1416
- * var_export($csv->connect());
1417
- * </code>
1418
- *
1419
- * output
1420
- *
1421
- * <code>
1422
- * array (
1423
- * 0 =>
1424
- * array (
1425
- * 'name' => 'john',
1426
- * 'age' => '13',
1427
- * 'skill' => 'knows magic',
1428
- * ),
1429
- * 1 =>
1430
- * array (
1431
- * 'name' => 'tanaka',
1432
- * 'age' => '8',
1433
- * 'skill' => 'makes sushi',
1434
- * ),
1435
- * 2 =>
1436
- * array (
1437
- * 'name' => 'jose',
1438
- * 'age' => '5',
1439
- * 'skill' => 'dances salsa',
1440
- * ),
1441
- * 3 =>
1442
- * array (
1443
- * 'name' => 1,
1444
- * 'age' => 1,
1445
- * 'skill' => 1,
1446
- * ),
1447
- * 4 =>
1448
- * array (
1449
- * 'name' => '2',
1450
- * 'age' => '2',
1451
- * 'skill' => '2',
1452
- * ),
1453
- * 5 =>
1454
- * array (
1455
- * 'name' => 3,
1456
- * 'age' => 3,
1457
- * 'skill' => 3,
1458
- * ),
1459
- * )
1460
- * </code>
1461
- *
1462
  * @param array $values the values to be appended to the row
1463
  *
1464
  * @access public
@@ -1474,111 +705,7 @@ class PMXI_CsvParser
1474
  /**
1475
  * fillRow
1476
  *
1477
- * Replaces the contents of cells in one given row with $values.
1478
- *
1479
- * sample of a csv file "my_cool.csv"
1480
- *
1481
- * <code>
1482
- * name,age,skill
1483
- * john,13,knows magic
1484
- * tanaka,8,makes sushi
1485
- * jose,5,dances salsa
1486
- * </code>
1487
- *
1488
- * if we load the csv file and fill the second row with new data?
1489
- *
1490
- * <code>
1491
- * // load the library
1492
- * require_once 'File/CSV/DataSource.php';
1493
- * $csv = new File_CSV_DataSource;
1494
- *
1495
- * // load csv file
1496
- * $csv->load('my_cool.csv');
1497
- *
1498
- * // fill exitent row
1499
- * var_export($csv->fillRow(1, 'x'));
1500
- * </code>
1501
- *
1502
- * output
1503
- *
1504
- * <code>
1505
- * true
1506
- * </code>
1507
- *
1508
- * now let's dump whatever we have changed
1509
- *
1510
- * <code>
1511
- * var_export($csv->connect());
1512
- * </code>
1513
- *
1514
- * output
1515
- *
1516
- * <code>
1517
- * array (
1518
- * 0 =>
1519
- * array (
1520
- * 'name' => 'john',
1521
- * 'age' => '13',
1522
- * 'skill' => 'knows magic',
1523
- * ),
1524
- * 1 =>
1525
- * array (
1526
- * 'name' => 'x',
1527
- * 'age' => 'x',
1528
- * 'skill' => 'x',
1529
- * ),
1530
- * 2 =>
1531
- * array (
1532
- * 'name' => 'jose',
1533
- * 'age' => '5',
1534
- * 'skill' => 'dances salsa',
1535
- * ),
1536
- * )
1537
- * </code>
1538
- *
1539
- * now lets try to fill the row with specific data for each cell
1540
- *
1541
- * <code>
1542
- * var_export($csv->fillRow(1, array(1, 2, 3)));
1543
- * </code>
1544
- *
1545
- * output
1546
- *
1547
- * <code>
1548
- * true
1549
- * </code>
1550
- *
1551
- * and dump the results
1552
- *
1553
- * <code>
1554
- * var_export($csv->connect());
1555
- * </code>
1556
- *
1557
- * output
1558
- *
1559
- * <code>
1560
- *
1561
- * array (
1562
- * 0 =>
1563
- * array (
1564
- * 'name' => 'john',
1565
- * 'age' => '13',
1566
- * 'skill' => 'knows magic',
1567
- * ),
1568
- * 1 =>
1569
- * array (
1570
- * 'name' => 1,
1571
- * 'age' => 2,
1572
- * 'skill' => 3,
1573
- * ),
1574
- * 2 =>
1575
- * array (
1576
- * 'name' => 'jose',
1577
- * 'age' => '5',
1578
- * 'skill' => 'dances salsa',
1579
- * ),
1580
- * )
1581
- * </code>
1582
  *
1583
  * @param integer $row the row to fill identified by its key
1584
  * @param mixed $values the value to use, if a string or number
@@ -1617,72 +744,7 @@ class PMXI_CsvParser
1617
  * row existance checker
1618
  *
1619
  * Scans currently loaded dataset and
1620
- * checks if a given row identified by $number exists
1621
- *
1622
- * sample of a csv file "my_cool.csv"
1623
- *
1624
- * <code>
1625
- * name,age,skill
1626
- * john,13,knows magic
1627
- * tanaka,8,makes sushi
1628
- * jose,5,dances salsa
1629
- * </code>
1630
- *
1631
- * load library and csv file
1632
- *
1633
- * <code>
1634
- * require_once 'File/CSV/DataSource.php';
1635
- * $csv = new File_CSV_DataSource;
1636
- * $csv->load('my_cool.csv');
1637
- * </code>
1638
- *
1639
- * build a relationship and dump it so we can see the rows we will
1640
- * be working with
1641
- *
1642
- * <code>
1643
- * var_export($csv->connect());
1644
- * </code>
1645
- *
1646
- * output
1647
- *
1648
- * <code>
1649
- * array (
1650
- * 0 =>
1651
- * array (
1652
- * 'name' => 'john',
1653
- * 'age' => '13',
1654
- * 'skill' => 'knows magic',
1655
- * ),
1656
- * 1 => // THIS ROW EXISTS!!!
1657
- * array (
1658
- * 'name' => 'tanaka',
1659
- * 'age' => '8',
1660
- * 'skill' => 'makes sushi',
1661
- * ),
1662
- * 2 =>
1663
- * array (
1664
- * 'name' => 'jose',
1665
- * 'age' => '5',
1666
- * 'skill' => 'dances salsa',
1667
- * ),
1668
- * )
1669
- * </code>
1670
- *
1671
- * now lets check for row existance
1672
- *
1673
- * <code>
1674
- * var_export($csv->hasRow(1));
1675
- * var_export($csv->hasRow(-1));
1676
- * var_export($csv->hasRow(9999));
1677
- * </code>
1678
- *
1679
- * output
1680
- *
1681
- * <code>
1682
- * true
1683
- * false
1684
- * false
1685
- * </code>
1686
  *
1687
  * @param mixed $number a numeric value that identifies the row
1688
  * you are trying to fetch.
@@ -1700,88 +762,7 @@ class PMXI_CsvParser
1700
  * row remover
1701
  *
1702
  * removes one row from the current data set.
1703
- *
1704
- * sample of a csv file "my_cool.csv"
1705
- *
1706
- * <code>
1707
- * name,age,skill
1708
- * john,13,knows magic
1709
- * tanaka,8,makes sushi
1710
- * jose,5,dances salsa
1711
- * </code>
1712
- *
1713
- * first let's load the file and output whatever was retrived.
1714
- *
1715
- * <code>
1716
- * require_once 'File/CSV/DataSource.php';
1717
- * $csv = new File_CSV_DataSource;
1718
- * $csv->load('my_cool.csv');
1719
- * var_export($csv->connect());
1720
- * </code>
1721
- *
1722
- * output
1723
- *
1724
- * <code>
1725
- *
1726
- * array (
1727
- * 0 =>
1728
- * array (
1729
- * 'name' => 'john',
1730
- * 'age' => '13',
1731
- * 'skill' => 'knows magic',
1732
- * ),
1733
- * 1 =>
1734
- * array (
1735
- * 'name' => 'tanaka',
1736
- * 'age' => '8',
1737
- * 'skill' => 'makes sushi',
1738
- * ),
1739
- * 2 =>
1740
- * array (
1741
- * 'name' => 'jose',
1742
- * 'age' => '5',
1743
- * 'skill' => 'dances salsa',
1744
- * ),
1745
- * )
1746
- * </code>
1747
- *
1748
- * now lets remove the second row
1749
- *
1750
- * <code>
1751
- * var_export($csv->removeRow(1));
1752
- * </code>
1753
- *
1754
- * output
1755
- *
1756
- * <code>
1757
- * true
1758
- * </code>
1759
- *
1760
- * now lets dump again the data and see what changes have been
1761
- * made
1762
- *
1763
- * <code>
1764
- * var_export($csv->connect());
1765
- * </code>
1766
- *
1767
- * output
1768
- *
1769
- * <code>
1770
- * array (
1771
- * 0 =>
1772
- * array (
1773
- * 'name' => 'john',
1774
- * 'age' => '13',
1775
- * 'skill' => 'knows magic',
1776
- * ),
1777
- * 1 =>
1778
- * array (
1779
- * 'name' => 'jose',
1780
- * 'age' => '5',
1781
- * 'skill' => 'dances salsa',
1782
- * ),
1783
- * )
1784
- * </code>
1785
  *
1786
  * @param mixed $number the key that identifies that row
1787
  *
@@ -1859,116 +840,29 @@ class PMXI_CsvParser
1859
  foreach ($this->rows as $key => $row) {
1860
  $item = array();
1861
  foreach ($this->headers as $col => $value) {
1862
- $item[$value] = $row[$col];
1863
  }
1864
  array_push($ret_arr, $item);
1865
  unset($item);
1866
  }
1867
  return $ret_arr;
1868
- }
 
 
 
 
 
 
 
 
 
 
1869
 
1870
  /**
1871
  * header creator
1872
  *
1873
  * uses prefix and creates a header for each column suffixed by a
1874
- * numeric value
1875
- *
1876
- * by default the first row is interpreted as headers but if we
1877
- * have a csv file with data only and no headers it becomes really
1878
- * annoying to work with the current loaded data.
1879
- *
1880
- * this function will create a set dinamically generated headers
1881
- * and make the current headers accessable with the row handling
1882
- * functions
1883
- *
1884
- * Note: that the csv file contains only data but no headers
1885
- * sample of a csv file "my_cool.csv"
1886
- *
1887
- * <code>
1888
- * john,13,knows magic
1889
- * tanaka,8,makes sushi
1890
- * jose,5,dances salsa
1891
- * </code>
1892
- *
1893
- * checks if the csv file was loaded
1894
- *
1895
- * <code>
1896
- * $csv = new File_CSV_DataSource;
1897
- * if (!$csv->load('my_cool.csv')) {
1898
- * die('can not load csv file');
1899
- * }
1900
- * </code>
1901
- *
1902
- * dump current headers
1903
- *
1904
- * <code>
1905
- * var_export($csv->getHeaders());
1906
- * </code>
1907
- *
1908
- * standard output
1909
- *
1910
- * <code>
1911
- * array (
1912
- * 0 => 'john',
1913
- * 1 => '13',
1914
- * 2 => 'knows magic',
1915
- * )
1916
- * </code>
1917
- *
1918
- * generate headers named 'column' suffixed by a number and interpret
1919
- * the previous headers as rows.
1920
- *
1921
- * <code>
1922
- * $csv->createHeaders('column')
1923
- * </code>
1924
- *
1925
- * dump current headers
1926
- *
1927
- * <code>
1928
- * var_export($csv->getHeaders());
1929
- * </code>
1930
- *
1931
- * standard output
1932
- *
1933
- * <code>
1934
- * array (
1935
- * 0 => 'column_1',
1936
- * 1 => 'column_2',
1937
- * 2 => 'column_3',
1938
- * )
1939
- * </code>
1940
- *
1941
- * build a relationship and dump it
1942
- *
1943
- * <code>
1944
- * var_export($csv->connect());
1945
- * </code>
1946
- *
1947
- * output
1948
- *
1949
- * <code>
1950
- *
1951
- * array (
1952
- * 0 =>
1953
- * array (
1954
- * 'column_1' => 'john',
1955
- * 'column_2' => '13',
1956
- * 'column_3' => 'knows magic',
1957
- * ),
1958
- * 1 =>
1959
- * array (
1960
- * 'column_1' => 'tanaka',
1961
- * 'column_2' => '8',
1962
- * 'column_3' => 'makes sushi',
1963
- * ),
1964
- * 2 =>
1965
- * array (
1966
- * 'column_1' => 'jose',
1967
- * 'column_2' => '5',
1968
- * 'column_3' => 'dances salsa',
1969
- * ),
1970
- * )
1971
- * </code>
1972
  *
1973
  * @param string $prefix string to use as prefix for each
1974
  * independent header
@@ -2000,123 +894,6 @@ class PMXI_CsvParser
2000
  * uses a $list of values which wil be used to replace current
2001
  * headers.
2002
  *
2003
- * Note: that given $list must match the length of all rows.
2004
- * known as symmetric. see isSymmetric() and getAsymmetricRows() methods
2005
- *
2006
- * Also, that current headers will be used as first row of data
2007
- * and consecuently all rows order will change with this action.
2008
- *
2009
- * sample of a csv file "my_cool.csv"
2010
- *
2011
- * <code>
2012
- * name,age,skill
2013
- * john,13,knows magic
2014
- * tanaka,8,makes sushi
2015
- * jose,5,dances salsa
2016
- * </code>
2017
- *
2018
- * load the library and csv file
2019
- *
2020
- * <code>
2021
- * require_once 'File/CSV/DataSource.php';
2022
- * $csv = new File_CSV_DataSource;
2023
- * $csv->load('my_cool.csv');
2024
- * </code>
2025
- *
2026
- * lets dump currently loaded data
2027
- * <code>
2028
- * var_export($csv->connect());
2029
- * </code>
2030
- *
2031
- * output
2032
- *
2033
- * <code>
2034
- * array (
2035
- * 0 =>
2036
- * array (
2037
- * 'name' => 'john',
2038
- * 'age' => '13',
2039
- * 'skill' => 'knows magic',
2040
- * ),
2041
- * 1 =>
2042
- * array (
2043
- * 'name' => 'tanaka',
2044
- * 'age' => '8',
2045
- * 'skill' => 'makes sushi',
2046
- * ),
2047
- * 2 =>
2048
- * array (
2049
- * 'name' => 'jose',
2050
- * 'age' => '5',
2051
- * 'skill' => 'dances salsa',
2052
- * ),
2053
- * )
2054
- * </code>
2055
- *
2056
- * And now lets create a new set of headers and attempt to inject
2057
- * them into the current loaded dataset
2058
- *
2059
- * <code>
2060
- * $new_headers = array('a', 'b', 'c');
2061
- * var_export($csv->setHeaders($new_headers));
2062
- * </code>
2063
- *
2064
- * output
2065
- *
2066
- * <code>
2067
- * true
2068
- * </code>
2069
- *
2070
- * Now lets try the same with some headers that do not match the
2071
- * current headers length. (this should fail)
2072
- *
2073
- * <code>
2074
- * $new_headers = array('a', 'b');
2075
- * var_export($csv->setHeaders($new_headers));
2076
- * </code>
2077
- *
2078
- * output
2079
- *
2080
- * <code>
2081
- * false
2082
- * </code>
2083
- *
2084
- * now let's dump whatever we have changed
2085
- *
2086
- * <code>
2087
- * var_export($csv->connect());
2088
- * </code>
2089
- *
2090
- * output
2091
- *
2092
- * <code>
2093
- * array (
2094
- * 0 =>
2095
- * array (
2096
- * 'a' => 'name',
2097
- * 'b' => 'age',
2098
- * 'c' => 'skill',
2099
- * ),
2100
- * 1 =>
2101
- * array (
2102
- * 'a' => 'john',
2103
- * 'b' => '13',
2104
- * 'c' => 'knows magic',
2105
- * ),
2106
- * 2 =>
2107
- * array (
2108
- * 'a' => 'tanaka',
2109
- * 'b' => '8',
2110
- * 'c' => 'makes sushi',
2111
- * ),
2112
- * 3 =>
2113
- * array (
2114
- * 'a' => 'jose',
2115
- * 'b' => '5',
2116
- * 'c' => 'dances salsa',
2117
- * ),
2118
- * )
2119
- * </code>
2120
  *
2121
  * @param array $list a collection of names to use as headers,
2122
  *
@@ -2157,33 +934,62 @@ class PMXI_CsvParser
2157
  $c = 0;
2158
  $d = $this->settings['delimiter'];
2159
  $e = $this->settings['escape'];
2160
- $l = $this->settings['length'];
2161
-
2162
- $res = fopen($this->_filename, 'r');
2163
 
 
 
 
 
 
 
 
 
 
2164
  $create_new_headers = false;
2165
 
2166
  while ($keys = fgetcsv($res, $l, $d, $e)) {
2167
 
2168
  if ($c == 0) {
2169
- foreach ($keys as $key => $value) {
 
 
2170
  if (preg_match('%\W(http:|https:|ftp:)$%i', $value) or is_numeric($value)) {
2171
  $create_new_headers = true;
2172
  break;
2173
  }
2174
  }
2175
  $this->headers = $keys;
2176
- } else {
2177
- array_push($this->rows, $keys);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2178
  }
2179
 
2180
  $c ++;
2181
  }
2182
-
 
2183
  fclose($res);
2184
- $this->removeEmpty();
2185
-
2186
- if ($create_new_headers) $this->createHeaders('column');
2187
 
2188
  return true;
2189
  }
@@ -2306,10 +1112,8 @@ class PMXI_CsvParser
2306
  // specify allowed field delimiters
2307
  $delimiters = array(
2308
  'comma' => ',',
2309
- 'semicolon' => ';',
2310
- 'tab' => "\t",
2311
- 'pipe' => '|',
2312
- 'colon' => ':'
2313
  );
2314
 
2315
  // specify allowed line endings
@@ -2329,9 +1133,9 @@ class PMXI_CsvParser
2329
  asort($line_result);
2330
 
2331
  // log to output array
2332
- $output['line_ending']['results'] = $line_result;
2333
  $output['line_ending']['count'] = end($line_result);
2334
- $output['line_ending']['key'] = key($line_result);
2335
  $output['line_ending']['value'] = $line_endings[$output['line_ending']['key']];
2336
  $lines = explode($output['line_ending']['value'], $contents);
2337
 
@@ -2378,7 +1182,7 @@ class ArrayToXML
2378
  * @return string XML
2379
  */
2380
  public static function toXml($data, $rootNodeName = 'data', $xml=null)
2381
- {
2382
  // turn off compatibility mode as simple xml throws a wobbly if you don't.
2383
  if (ini_get('zend.ze1_compatibility_mode') == 1)
2384
  {
@@ -2399,7 +1203,7 @@ class ArrayToXML
2399
  // make string key...
2400
  $key = "node";
2401
  }
2402
-
2403
  // replace anything not alpha numeric
2404
  $key = preg_replace('/[^a-z0-9_]/i', '', $key);
2405
 
@@ -2413,11 +1217,10 @@ class ArrayToXML
2413
  else
2414
  {
2415
  // add single node.
2416
- $value = htmlspecialchars($value);
2417
  $xml->addChild($key,$value);
2418
  }
2419
-
2420
-
2421
  }
2422
  // pass back as string. or simple xml object if you want!
2423
  return $xml->asXML();
71
  'eol' => '',
72
  'length' => 999999,
73
  'escape' => '"'
74
+ ),
75
+
76
+ $tmp_files = array(),
77
+
78
+ $xpath = '',
79
+
80
+ $large_import = false,
81
+
82
+ $xml_path = '';
83
 
84
  protected
85
 
116
  * @see load()
117
  * @return void
118
  */
119
+ public function __construct($filename = null, $large_import = false, $xpath = '')
120
  {
121
+
122
+ $this->large_import = $large_import;
123
+ $this->xpath = (!empty($xpath) ? $xpath : ((!empty($_POST['xpath'])) ? $_POST['xpath'] : '/node'));
124
 
125
  ini_set( "display_errors", 0);
126
+ ini_set('auto_detect_line_endings', true);
127
 
128
  $file_params = self::analyse_file($filename, 10);
129
 
139
  *
140
  * indicates the object which file is to be loaded
141
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  *
143
  * @param string $filename the csv filename to load
144
  *
158
  *
159
  * lets you define different settings for scanning
160
  *
 
 
 
 
 
 
 
 
 
 
161
  *
162
  * @param mixed $array containing settings to use
163
  *
175
  *
176
  * gets csv headers into an array
177
  *
 
 
 
 
 
 
 
 
 
 
 
 
178
  * @access public
179
  * @return array
180
  */
201
  *
202
  * Attempts to create a relationship for every single cell that
203
  * was captured and its corresponding header. The sample below shows
204
+ * how a connection/relationship is built.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  *
206
  * @param array $columns the columns to connect, if nothing
207
  * is given all headers will be used to create a connection
273
  * lets assume that we add one more row to our csv file.
274
  * that has only two values. Something like
275
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
  * @access public
277
  * @return array filled with rows that do not match headers
278
  * @see getHeaders(), symmetrize(), isSymmetric(),
359
  *
360
  * Note $name is the same as the items returned by getHeaders()
361
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362
  * @param string $name the name of the column to fetch
363
  *
364
  * @access public
385
  * checks if a column exists, columns are identified by their
386
  * header name.
387
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
388
  * @param string $string an item returned by getHeaders()
389
  *
390
  * @access public
400
  * column appender
401
  *
402
  * Appends a column and each or all values in it can be
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
403
  *
404
  * @param string $column an item returned by getHeaders()
405
  * @param mixed $values same as fillColumn()
436
  *
437
  * fills alll the data in the given column with $values
438
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
439
  * @param mixed $column the column identified by a string
440
  * @param mixed $values ither one of the following
441
  * - (Number) will fill the whole column with the value of number
487
  /**
488
  * column remover
489
  *
490
+ * Completly removes a whole column identified by $name
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
491
  *
492
  * @param string $name same as the ones returned by getHeaders();
493
  *
560
  /**
561
  * cell fetcher
562
  *
563
+ * gets the value of a specific cell by given coordinates
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
564
  *
565
  * @param integer $x the row to fetch
566
  * @param integer $y the column to fetch
582
  /**
583
  * cell value filler
584
  *
585
+ * replaces the value of a specific cell
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
586
  *
587
  * @param integer $x the row to fetch
588
  * @param integer $y the column to fetch
604
  }
605
 
606
  /**
607
+ * checks if a coordinate is valid
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
608
  *
609
  * @param mixed $x the row to fetch
610
  * @param mixed $y the column to fetch
622
  /**
623
  * row fetcher
624
  *
625
+ * Note: first row is zero
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
626
  *
627
  * @param integer $number the row number to fetch
628
  *
646
  * - all rows if no $range argument is given
647
  * - a range of rows identified by their key
648
  * - if rows in range are not found nothing is retrived instead
649
+ * - if no rows were found an empty array is returned
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
650
  *
651
  * @param array $range a list of rows to retrive
652
  *
677
  *
678
  * This function will exclude the headers
679
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
680
  * @access public
681
  * @return integer
682
  */
690
  *
691
  * Aggregates one more row to the currently loaded dataset
692
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
693
  * @param array $values the values to be appended to the row
694
  *
695
  * @access public
705
  /**
706
  * fillRow
707
  *
708
+ * Replaces the contents of cells in one given row with $values.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
709
  *
710
  * @param integer $row the row to fill identified by its key
711
  * @param mixed $values the value to use, if a string or number
744
  * row existance checker
745
  *
746
  * Scans currently loaded dataset and
747
+ * checks if a given row identified by $number exists
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
748
  *
749
  * @param mixed $number a numeric value that identifies the row
750
  * you are trying to fetch.
762
  * row remover
763
  *
764
  * removes one row from the current data set.
765
+ *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
766
  *
767
  * @param mixed $number the key that identifies that row
768
  *
840
  foreach ($this->rows as $key => $row) {
841
  $item = array();
842
  foreach ($this->headers as $col => $value) {
843
+ $item[$value] = $this->fixEncoding($row[$col]);
844
  }
845
  array_push($ret_arr, $item);
846
  unset($item);
847
  }
848
  return $ret_arr;
849
+ }
850
+
851
+ // Fixes the encoding to uf8
852
+ function fixEncoding($in_str)
853
+ {
854
+ $cur_encoding = mb_detect_encoding($in_str) ;
855
+ if($cur_encoding == "UTF-8" && mb_check_encoding($in_str,"UTF-8"))
856
+ return $in_str;
857
+ else
858
+ return utf8_encode($in_str);
859
+ } // fixEncoding
860
 
861
  /**
862
  * header creator
863
  *
864
  * uses prefix and creates a header for each column suffixed by a
865
+ * numeric value
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
866
  *
867
  * @param string $prefix string to use as prefix for each
868
  * independent header
894
  * uses a $list of values which wil be used to replace current
895
  * headers.
896
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
897
  *
898
  * @param array $list a collection of names to use as headers,
899
  *
934
  $c = 0;
935
  $d = $this->settings['delimiter'];
936
  $e = $this->settings['escape'];
937
+ $l = $this->settings['length'];
 
 
938
 
939
+ $res = fopen($this->_filename, 'rb');
940
+
941
+ $wp_uploads = wp_upload_dir();
942
+ if ($this->large_import){
943
+ $tmpname = wp_unique_filename($wp_uploads['path'], str_replace("csv", "xml", basename($this->_filename)));
944
+ $this->xml_path = $wp_uploads['path'] .'/'. $tmpname;
945
+ $fp = fopen($this->xml_path, 'w');
946
+ fwrite($fp, '<?xml version="1.0" encoding="utf-8"?><data>');
947
+ }
948
  $create_new_headers = false;
949
 
950
  while ($keys = fgetcsv($res, $l, $d, $e)) {
951
 
952
  if ($c == 0) {
953
+ foreach ($keys as $key => $value) {
954
+ $value = trim(strtolower(preg_replace('/^[0-9]{1}/','el_', preg_replace('/[^a-z0-9_]/i', '', $value))));
955
+ $keys[$key] = (!empty($value)) ? $value : 'undefined'.$key;
956
  if (preg_match('%\W(http:|https:|ftp:)$%i', $value) or is_numeric($value)) {
957
  $create_new_headers = true;
958
  break;
959
  }
960
  }
961
  $this->headers = $keys;
962
+
963
+ if ($create_new_headers) $this->createHeaders('column');
964
+
965
+ } else {
966
+
967
+ if (!$this->large_import and empty($_POST['large_file'])) {
968
+ array_push($this->rows, $keys);
969
+ }
970
+ else if (!empty($keys[0])){
971
+
972
+ $chunk = array();
973
+
974
+ foreach ($this->headers as $key => $header) {
975
+ $chunk[$header] = $this->fixEncoding($keys[$key]);
976
+ }
977
+
978
+ if (!empty($chunk))
979
+ {
980
+ fwrite($fp, "<node>");
981
+ foreach ($chunk as $header => $value) fwrite($fp, "<".$header.">".$value."</".$header.">");
982
+ fwrite($fp, "</node>");
983
+ }
984
+ }
985
  }
986
 
987
  $c ++;
988
  }
989
+ fwrite($fp, '</data>');
990
+ fclose($fp);
991
  fclose($res);
992
+ $this->removeEmpty();
 
 
993
 
994
  return true;
995
  }
1112
  // specify allowed field delimiters
1113
  $delimiters = array(
1114
  'comma' => ',',
1115
+ 'semicolon' => ';',
1116
+ 'pipe' => '|'
 
 
1117
  );
1118
 
1119
  // specify allowed line endings
1133
  asort($line_result);
1134
 
1135
  // log to output array
1136
+ $output['line_ending']['results'] = $line_result;
1137
  $output['line_ending']['count'] = end($line_result);
1138
+ $output['line_ending']['key'] = key($line_result);
1139
  $output['line_ending']['value'] = $line_endings[$output['line_ending']['key']];
1140
  $lines = explode($output['line_ending']['value'], $contents);
1141
 
1182
  * @return string XML
1183
  */
1184
  public static function toXml($data, $rootNodeName = 'data', $xml=null)
1185
+ {
1186
  // turn off compatibility mode as simple xml throws a wobbly if you don't.
1187
  if (ini_get('zend.ze1_compatibility_mode') == 1)
1188
  {
1203
  // make string key...
1204
  $key = "node";
1205
  }
1206
+
1207
  // replace anything not alpha numeric
1208
  $key = preg_replace('/[^a-z0-9_]/i', '', $key);
1209
 
1217
  else
1218
  {
1219
  // add single node.
1220
+ $value = htmlspecialchars($value);
1221
  $xml->addChild($key,$value);
1222
  }
1223
+
 
1224
  }
1225
  // pass back as string. or simple xml object if you want!
1226
  return $xml->asXML();
libraries/XmlImportParser.php CHANGED
@@ -49,7 +49,17 @@ class XmlImportParser {
49
  // FIX: remove default namespace because libxml xpath implementation doesn't handle it properly
50
  $xml and $xml = preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml);
51
 
52
- $this->xml = new SimpleXMLElement($xml);
 
 
 
 
 
 
 
 
 
 
53
  $this->rootNodeXPath = $rootNodeXPath;
54
  $this->cachedTemplate = $cachedTemplate;
55
  }
@@ -62,7 +72,7 @@ class XmlImportParser {
62
  * @return array
63
  */
64
  public function parse($records = array())
65
- {
66
  empty($records) or is_array($records) or $records = array($records);
67
 
68
  $result = array();
@@ -70,7 +80,7 @@ class XmlImportParser {
70
  $rootNodes = $this->xml->xpath($this->rootNodeXPath);
71
  if ($rootNodes === false)
72
  throw new XmlImportException('Invalid root node XPath \'' . $this->rootNodeXPath . '\' specified');
73
-
74
  for ($i = 0; $i < count($rootNodes); $i++) {
75
  if (empty($records) or in_array($i + 1, $records)) {
76
  $rootNode = $rootNodes[$i];
49
  // FIX: remove default namespace because libxml xpath implementation doesn't handle it properly
50
  $xml and $xml = preg_replace('%xmlns\s*=\s*([\'"]).*\1%sU', '', $xml);
51
 
52
+ libxml_use_internal_errors(true);
53
+ try{
54
+ $this->xml = new SimpleXMLElement($xml);
55
+ } catch (Exception $e){
56
+ try{
57
+ $this->xml = new SimpleXMLElement(utf8_encode($xml));
58
+ } catch (Exception $e){
59
+ throw new XmlImportException($e->getMessage());
60
+ }
61
+ }
62
+
63
  $this->rootNodeXPath = $rootNodeXPath;
64
  $this->cachedTemplate = $cachedTemplate;
65
  }
72
  * @return array
73
  */
74
  public function parse($records = array())
75
+ {
76
  empty($records) or is_array($records) or $records = array($records);
77
 
78
  $result = array();
80
  $rootNodes = $this->xml->xpath($this->rootNodeXPath);
81
  if ($rootNodes === false)
82
  throw new XmlImportException('Invalid root node XPath \'' . $this->rootNodeXPath . '\' specified');
83
+
84
  for ($i = 0; $i < count($rootNodes); $i++) {
85
  if (empty($records) or in_array($i + 1, $records)) {
86
  $rootNode = $rootNodes[$i];
libraries/XmlImportTemplateCodeGenerator.php CHANGED
@@ -12,7 +12,6 @@ require_once dirname(__FILE__) . '/ast/XmlImportAstInteger.php';
12
  require_once dirname(__FILE__) . '/ast/XmlImportAstFloat.php';
13
  require_once dirname(__FILE__) . '/ast/XmlImportAstString.php';
14
  require_once dirname(__FILE__) . '/ast/XmlImportAstXPath.php';
15
- require_once dirname(__FILE__) . '/ast/XmlImportAstFunction.php';
16
  require_once dirname(__FILE__) . '/ast/XmlImportAstWith.php';
17
  require_once dirname(__FILE__) . '/ast/XmlImportAstForeach.php';
18
  require_once dirname(__FILE__) . '/ast/XmlImportAstIf.php';
@@ -92,11 +91,11 @@ class XmlImportTemplateCodeGenerator
92
  $var = '$x' . $this->xmlVariableNumber++;
93
  array_push($this->xmlStack, $var);
94
  $result .= $this->openPhpTag() . $var . ' = $this->xml;' ;
95
- }
96
  $result .= $this->generateForSequence($this->sequence);
97
-
98
  if (count($this->sequence->getVariables()))
99
- {
100
  array_pop($this->xmlStack);
101
  }
102
  if (is_null($filename))
@@ -122,7 +121,7 @@ class XmlImportTemplateCodeGenerator
122
  {
123
  $result .= $this->openPhpTag();
124
  foreach ($sequence->getVariableDefinitions() as $xpath)
125
- {
126
  $result .= PHP_EOL . str_replace('{{XML}}', $this->xmlStack[count($this->xmlStack) - 1], $xpath);
127
  }
128
  $result .= PHP_EOL;
@@ -132,6 +131,7 @@ class XmlImportTemplateCodeGenerator
132
  $result .= $this->generateForStatement($statement);
133
  }
134
  array_pop($this->sequenceStack);
 
135
  return $result;
136
  }
137
 
@@ -186,7 +186,7 @@ class XmlImportTemplateCodeGenerator
186
  array_pop($this->xmlStack);
187
  }
188
  elseif ($statement instanceof XmlImportAstIf)
189
- {
190
  $result .= PHP_EOL . 'if (' . $this->generateForExpression($statement->getCondition()) . ') :' . PHP_EOL;
191
  $result .= $this->generateForSequence($statement->getIfBody());
192
  foreach ($statement->getElseIfs() as $elseif)
@@ -228,22 +228,18 @@ class XmlImportTemplateCodeGenerator
228
  $result = $expression->getValue();
229
  break;
230
 
231
- case 'XmlImportAstXPath':
232
  if ($inPrint)
233
  {
234
- $variables = $this->sequenceStack[count($this->sequenceStack) - 1]->getVariables();
235
- $result = '$this->getValue(' . $variables[$expression->getValue()] . ')';
236
  }
237
  else
238
- {
239
- $variables = $this->sequenceStack[count($this->sequenceStack) - 1]->getVariables();
240
- $result = $variables[$expression->getValue()];
241
  }
242
  break;
243
-
244
- case 'XmlImportAstFunction':
245
- $result = $this->generateForFunction($expression);
246
- break;
247
 
248
  case 'XmlImportAstMath':
249
  $result = $this->generateForMath($expression);
@@ -255,28 +251,7 @@ class XmlImportTemplateCodeGenerator
255
  }
256
  return $result;
257
  }
258
-
259
- /**
260
- * Generates code for a function
261
- *
262
- * @param XmlImportAstFunction $function
263
- * @return string
264
- */
265
- private function generateForFunction(XmlImportAstFunction $function)
266
- {
267
- $result = $function->getName() . '(';
268
- $arguments = $function->getArguments();
269
- for($i = 0; $i < count($arguments); $i++)
270
- {
271
- $result .= $this->generateForExpression($arguments[$i], true);
272
- if ($i < (count($arguments) - 1))
273
- $result .= ', ';
274
- }
275
- $result .= ')';
276
-
277
- return $result;
278
- }
279
-
280
  /**
281
  * Generates code for a function
282
  *
@@ -303,36 +278,59 @@ class XmlImportTemplateCodeGenerator
303
  */
304
  private function generateForSpintax(XmlImportAstSpintax $spintax)
305
  {
306
- $result = '';
307
  $arguments = $spintax->getArguments();
 
 
308
 
309
- $spintax_begin = array();
310
- $spintax_end = array();
311
- $context = '';
312
- $first_arg = true;
313
- for ($i = 0; $i < count($arguments); $i++) {
314
- if ($first_arg and $arguments[$i]['type'] == 'xpath') {
315
- $spintax_begin[] = $this->generateForExpression($arguments[$i]['argument'], true);
316
- }
317
- elseif ($arguments[$i]['type'] == 'context')
318
- {
319
- $first_arg = false;
320
- $context = $this->generateForExpression($arguments[$i]['argument'], true);
 
 
 
321
  }
322
- else
323
- $spintax_end[] = $this->generateForExpression($arguments[$i]['argument'], true);
324
- }
325
-
326
- for($i = 0; $i < count($spintax_begin); $i++)
327
- {
328
- for ($j = 0; $j < count($spintax_end); $j++) {
329
- $result .= '"<p>".'.$spintax_begin[$i].'."&nbsp;".'.$context.'."&nbsp;".'.$spintax_end[$j].'."</p>".';
330
- }
331
  }
332
 
333
- return substr_replace($result ,"",-1);
334
  }
335
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336
  /**
337
  * Add PHP open tag if needed
338
  *
12
  require_once dirname(__FILE__) . '/ast/XmlImportAstFloat.php';
13
  require_once dirname(__FILE__) . '/ast/XmlImportAstString.php';
14
  require_once dirname(__FILE__) . '/ast/XmlImportAstXPath.php';
 
15
  require_once dirname(__FILE__) . '/ast/XmlImportAstWith.php';
16
  require_once dirname(__FILE__) . '/ast/XmlImportAstForeach.php';
17
  require_once dirname(__FILE__) . '/ast/XmlImportAstIf.php';
91
  $var = '$x' . $this->xmlVariableNumber++;
92
  array_push($this->xmlStack, $var);
93
  $result .= $this->openPhpTag() . $var . ' = $this->xml;' ;
94
+ }
95
  $result .= $this->generateForSequence($this->sequence);
96
+
97
  if (count($this->sequence->getVariables()))
98
+ {
99
  array_pop($this->xmlStack);
100
  }
101
  if (is_null($filename))
121
  {
122
  $result .= $this->openPhpTag();
123
  foreach ($sequence->getVariableDefinitions() as $xpath)
124
+ {
125
  $result .= PHP_EOL . str_replace('{{XML}}', $this->xmlStack[count($this->xmlStack) - 1], $xpath);
126
  }
127
  $result .= PHP_EOL;
131
  $result .= $this->generateForStatement($statement);
132
  }
133
  array_pop($this->sequenceStack);
134
+
135
  return $result;
136
  }
137
 
186
  array_pop($this->xmlStack);
187
  }
188
  elseif ($statement instanceof XmlImportAstIf)
189
+ {
190
  $result .= PHP_EOL . 'if (' . $this->generateForExpression($statement->getCondition()) . ') :' . PHP_EOL;
191
  $result .= $this->generateForSequence($statement->getIfBody());
192
  foreach ($statement->getElseIfs() as $elseif)
228
  $result = $expression->getValue();
229
  break;
230
 
231
+ case 'XmlImportAstXPath':
232
  if ($inPrint)
233
  {
234
+ $variables = $this->sequenceStack[count($this->sequenceStack) - 1]->getVariables();
235
+ $result = '$this->getValue(' . $variables[$expression->getValue()] . ')';
236
  }
237
  else
238
+ {
239
+ $variables = $this->sequenceStack[count($this->sequenceStack) - 1]->getVariables();
240
+ $result = $variables[$expression->getValue()];
241
  }
242
  break;
 
 
 
 
243
 
244
  case 'XmlImportAstMath':
245
  $result = $this->generateForMath($expression);
251
  }
252
  return $result;
253
  }
254
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
  /**
256
  * Generates code for a function
257
  *
278
  */
279
  private function generateForSpintax(XmlImportAstSpintax $spintax)
280
  {
281
+ $result = '';
282
  $arguments = $spintax->getArguments();
283
+ $elements = array();
284
+ $buf = array();
285
 
286
+ for($i = 0; $i < count($arguments); $i++)
287
+ {
288
+
289
+ if ($arguments[$i]->getValue() != '|') array_push($buf, $this->generateForExpression($arguments[$i], true)); else { array_push($elements, $buf); $buf = array();}
290
+
291
+ }
292
+
293
+ array_push($elements, $buf);
294
+
295
+ if (!empty($elements) and is_array($elements)){
296
+
297
+ $spintax_arr = $this->generateVariation($elements);
298
+
299
+ foreach ($spintax_arr as $key => $value) {
300
+ $result .= "\"<p>\".".implode(".", $value).".\"</p>\""; if ($key != count($spintax_arr) - 1) $result .= ".";
301
  }
302
+
 
 
 
 
 
 
 
 
303
  }
304
 
305
+ return $result;
306
  }
307
 
308
+ function generateVariation($A, $i = 0)
309
+ {
310
+ $result = array();
311
+
312
+ if ($i < count($A))
313
+ {
314
+ $variations = $this->generateVariation($A, $i + 1);
315
+
316
+ for ($j = 0; $j < count($A[$i]); $j++)
317
+ {
318
+ if ($variations)
319
+ {
320
+ foreach ($variations as $variation)
321
+ {
322
+ $result[] = array_merge(array($A[$i][$j]), $variation);
323
+ }
324
+ }
325
+ else
326
+ {
327
+ $result[] = array($A[$i][$j]);
328
+ }
329
+ }
330
+ }
331
+
332
+ return $result;
333
+ }
334
  /**
335
  * Add PHP open tag if needed
336
  *
libraries/XmlImportTemplateParser.php CHANGED
@@ -17,7 +17,6 @@ require_once dirname(__FILE__) . '/ast/XmlImportAstXPath.php';
17
  require_once dirname(__FILE__) . '/ast/XmlImportAstString.php';
18
  require_once dirname(__FILE__) . '/ast/XmlImportAstInteger.php';
19
  require_once dirname(__FILE__) . '/ast/XmlImportAstFloat.php';
20
- require_once dirname(__FILE__) . '/ast/XmlImportAstFunction.php';
21
 
22
  /**
23
  * Parses a list of nodes into AST (Abstract Syntax Tree)
@@ -161,7 +160,7 @@ class XmlImportTemplateParser
161
  }
162
  elseif($this->clauseStack[count($this->clauseStack) - 1] == XmlImportToken::KIND_ENDIF &&
163
  in_array($this->tokens[$this->index + 1]->getKind(), array(XmlImportToken::KIND_ELSE, XmlImportToken::KIND_ELSEIF)))
164
- {
165
  if ($this->elseAllowed)
166
  {
167
  if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_ELSE)
@@ -186,11 +185,8 @@ class XmlImportTemplateParser
186
  {
187
  if ($this->index + 1 == count($this->tokens))
188
  throw new XmlImportException("Reached end of template but expression was expected");
189
- if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_FUNCTION)
190
- {
191
- return $this->parseFunction();
192
- }
193
- elseif($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_MATH)
194
  {
195
  return $this->parseMath();
196
  }
@@ -200,7 +196,7 @@ class XmlImportTemplateParser
200
  }
201
  elseif ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_XPATH)
202
  {
203
- $xpath = new XmlImportAstXPath($this->tokens[++$this->index]->getValue());
204
  $this->sequenceStack[count($this->sequenceStack) - 1]->addVariable($xpath);
205
  return $xpath;
206
  }
@@ -218,43 +214,7 @@ class XmlImportTemplateParser
218
  }
219
  else
220
  throw new XmlImportException("Unexpected token " . $this->tokens[$this->index + 1]->getKind());
221
- }
222
-
223
- /**
224
- * Parses function
225
- *
226
- * @return XmlImportAstFunction
227
- */
228
- private function parseFunction()
229
- {
230
- $function = new XmlImportAstFunction($this->tokens[++$this->index]->getValue());
231
- if ($this->tokens[$this->index + 1]->getKind() != XmlImportToken::KIND_OPEN)
232
- throw new XmlImportException ("Open brace expected instead of " . $this->tokens[$this->index + 1]->getKind());
233
- $this->index++;
234
- if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_CLOSE)
235
- {
236
- $this->index++;
237
- return $function;
238
- }
239
- else
240
- {
241
- while ($this->index < count($this->tokens) - 2)
242
- {
243
- $function->addArgument($this->parseExpression());
244
- if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_CLOSE)
245
- {
246
- $this->index++;
247
- return $function;
248
- break;
249
- }
250
- elseif ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_COMMA)
251
- $this->index++;
252
- else
253
- throw new XmlImportException("Comma or closing brace expected instead of " . $this->tokens[$this->index + 1]->getKind());
254
- }
255
- throw new XmlImportException("Unexpected end of {$function->getName()} function argument list");
256
- }
257
- }
258
 
259
  /**
260
  * Parses function
@@ -309,20 +269,10 @@ class XmlImportTemplateParser
309
  return $spintax;
310
  }
311
  else
312
- {
313
  while ($this->index < count($this->tokens) - 2)
314
- {
315
- if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_XPATH)
316
- {
317
- $xpath_parts = explode('|', str_replace(array('{', '}'), '', $this->tokens[++$this->index]->getValue()));
318
- for ($i = 0; $i < count($xpath_parts); $i++) {
319
- $xpath = new XmlImportAstXPath($xpath_parts[$i]);
320
- $this->sequenceStack[count($this->sequenceStack) - 1]->addVariable($xpath);
321
- $spintax->addArgument($xpath, 'xpath');
322
- }
323
- }
324
- else $spintax->addArgument($this->parseExpression(), 'context');
325
-
326
  if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_CLOSE)
327
  {
328
  $this->index++;
@@ -330,11 +280,11 @@ class XmlImportTemplateParser
330
  break;
331
  }
332
  elseif ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_COMMA)
333
- $this->index++;
334
  else
335
  throw new XmlImportException("Comma or closing brace expected instead of " . $this->tokens[$this->index + 1]->getKind());
336
  }
337
- throw new XmlImportException("Unexpected end of MATH argument list");
338
  }
339
  }
340
 
@@ -439,10 +389,11 @@ class XmlImportTemplateParser
439
  }
440
  if ($this->index + 1 < count($this->tokens) && $this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_ELSE)
441
  {
442
- $this->index++;
443
  $if->addElseBody($this->parseSequence());
444
  }
445
  }
 
446
  return $if;
447
  }
448
  }
17
  require_once dirname(__FILE__) . '/ast/XmlImportAstString.php';
18
  require_once dirname(__FILE__) . '/ast/XmlImportAstInteger.php';
19
  require_once dirname(__FILE__) . '/ast/XmlImportAstFloat.php';
 
20
 
21
  /**
22
  * Parses a list of nodes into AST (Abstract Syntax Tree)
160
  }
161
  elseif($this->clauseStack[count($this->clauseStack) - 1] == XmlImportToken::KIND_ENDIF &&
162
  in_array($this->tokens[$this->index + 1]->getKind(), array(XmlImportToken::KIND_ELSE, XmlImportToken::KIND_ELSEIF)))
163
+ {
164
  if ($this->elseAllowed)
165
  {
166
  if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_ELSE)
185
  {
186
  if ($this->index + 1 == count($this->tokens))
187
  throw new XmlImportException("Reached end of template but expression was expected");
188
+
189
+ if($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_MATH)
 
 
 
190
  {
191
  return $this->parseMath();
192
  }
196
  }
197
  elseif ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_XPATH)
198
  {
199
+ $xpath = new XmlImportAstXPath($this->tokens[++$this->index]->getValue());
200
  $this->sequenceStack[count($this->sequenceStack) - 1]->addVariable($xpath);
201
  return $xpath;
202
  }
214
  }
215
  else
216
  throw new XmlImportException("Unexpected token " . $this->tokens[$this->index + 1]->getKind());
217
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
 
219
  /**
220
  * Parses function
269
  return $spintax;
270
  }
271
  else
272
+ {
273
  while ($this->index < count($this->tokens) - 2)
274
+ {
275
+ $spintax->addArgument($this->parseExpression());
 
 
 
 
 
 
 
 
 
 
276
  if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_CLOSE)
277
  {
278
  $this->index++;
280
  break;
281
  }
282
  elseif ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_COMMA)
283
+ $this->index++;
284
  else
285
  throw new XmlImportException("Comma or closing brace expected instead of " . $this->tokens[$this->index + 1]->getKind());
286
  }
287
+ throw new XmlImportException("Unexpected end of {$function->getName()} function argument list");
288
  }
289
  }
290
 
389
  }
390
  if ($this->index + 1 < count($this->tokens) && $this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_ELSE)
391
  {
392
+ $this->index++;
393
  $if->addElseBody($this->parseSequence());
394
  }
395
  }
396
+
397
  return $if;
398
  }
399
  }
libraries/ast/XmlImportAstSpintax.php CHANGED
@@ -33,12 +33,9 @@ class XmlImportAstSpintax extends XmlImportAstExpression
33
  *
34
  * @param XmlImportAstExpression $argument
35
  */
36
- public function addArgument(XmlImportAstExpression $argument, $type = false)
37
  {
38
- $this->arguments[] = array(
39
- 'argument' => $argument,
40
- 'type' => $type
41
- );
42
  }
43
 
44
  /**
33
  *
34
  * @param XmlImportAstExpression $argument
35
  */
36
+ public function addArgument(XmlImportAstExpression $argument)
37
  {
38
+ $this->arguments[] = $argument;
 
 
 
39
  }
40
 
41
  /**
libraries/pclzip.lib.php ADDED
@@ -0,0 +1,5697 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // --------------------------------------------------------------------------------
3
+ // PhpConcept Library - Zip Module 2.8.2
4
+ // --------------------------------------------------------------------------------
5
+ // License GNU/LGPL - Vincent Blavet - August 2009
6
+ // http://www.phpconcept.net
7
+ // --------------------------------------------------------------------------------
8
+ //
9
+ // Presentation :
10
+ // PclZip is a PHP library that manage ZIP archives.
11
+ // So far tests show that archives generated by PclZip are readable by
12
+ // WinZip application and other tools.
13
+ //
14
+ // Description :
15
+ // See readme.txt and http://www.phpconcept.net
16
+ //
17
+ // Warning :
18
+ // This library and the associated files are non commercial, non professional
19
+ // work.
20
+ // It should not have unexpected results. However if any damage is caused by
21
+ // this software the author can not be responsible.
22
+ // The use of this software is at the risk of the user.
23
+ //
24
+ // --------------------------------------------------------------------------------
25
+ // $Id: pclzip.lib.php,v 1.60 2009/09/30 21:01:04 vblavet Exp $
26
+ // --------------------------------------------------------------------------------
27
+
28
+ // ----- Constants
29
+ if (!defined('PCLZIP_READ_BLOCK_SIZE')) {
30
+ define( 'PCLZIP_READ_BLOCK_SIZE', 2048 );
31
+ }
32
+
33
+ // ----- File list separator
34
+ // In version 1.x of PclZip, the separator for file list is a space
35
+ // (which is not a very smart choice, specifically for windows paths !).
36
+ // A better separator should be a comma (,). This constant gives you the
37
+ // abilty to change that.
38
+ // However notice that changing this value, may have impact on existing
39
+ // scripts, using space separated filenames.
40
+ // Recommanded values for compatibility with older versions :
41
+ //define( 'PCLZIP_SEPARATOR', ' ' );
42
+ // Recommanded values for smart separation of filenames.
43
+ if (!defined('PCLZIP_SEPARATOR')) {
44
+ define( 'PCLZIP_SEPARATOR', ',' );
45
+ }
46
+
47
+ // ----- Error configuration
48
+ // 0 : PclZip Class integrated error handling
49
+ // 1 : PclError external library error handling. By enabling this
50
+ // you must ensure that you have included PclError library.
51
+ // [2,...] : reserved for futur use
52
+ if (!defined('PCLZIP_ERROR_EXTERNAL')) {
53
+ define( 'PCLZIP_ERROR_EXTERNAL', 0 );
54
+ }
55
+
56
+ // ----- Optional static temporary directory
57
+ // By default temporary files are generated in the script current
58
+ // path.
59
+ // If defined :
60
+ // - MUST BE terminated by a '/'.
61
+ // - MUST be a valid, already created directory
62
+ // Samples :
63
+ // define( 'PCLZIP_TEMPORARY_DIR', '/temp/' );
64
+ // define( 'PCLZIP_TEMPORARY_DIR', 'C:/Temp/' );
65
+
66
+ $wp_uploads = wp_upload_dir();
67
+
68
+ if (!defined('PCLZIP_TEMPORARY_DIR')) {
69
+ define( 'PCLZIP_TEMPORARY_DIR', $wp_uploads['path'] );
70
+ }
71
+
72
+ // ----- Optional threshold ratio for use of temporary files
73
+ // Pclzip sense the size of the file to add/extract and decide to
74
+ // use or not temporary file. The algorythm is looking for
75
+ // memory_limit of PHP and apply a ratio.
76
+ // threshold = memory_limit * ratio.
77
+ // Recommended values are under 0.5. Default 0.47.
78
+ // Samples :
79
+ // define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.5 );
80
+ if (!defined('PCLZIP_TEMPORARY_FILE_RATIO')) {
81
+ define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.47 );
82
+ }
83
+
84
+ // --------------------------------------------------------------------------------
85
+ // ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED *****
86
+ // --------------------------------------------------------------------------------
87
+
88
+ // ----- Global variables
89
+ $g_pclzip_version = "2.8.2";
90
+
91
+ // ----- Error codes
92
+ // -1 : Unable to open file in binary write mode
93
+ // -2 : Unable to open file in binary read mode
94
+ // -3 : Invalid parameters
95
+ // -4 : File does not exist
96
+ // -5 : Filename is too long (max. 255)
97
+ // -6 : Not a valid zip file
98
+ // -7 : Invalid extracted file size
99
+ // -8 : Unable to create directory
100
+ // -9 : Invalid archive extension
101
+ // -10 : Invalid archive format
102
+ // -11 : Unable to delete file (unlink)
103
+ // -12 : Unable to rename file (rename)
104
+ // -13 : Invalid header checksum
105
+ // -14 : Invalid archive size
106
+ define( 'PCLZIP_ERR_USER_ABORTED', 2 );
107
+ define( 'PCLZIP_ERR_NO_ERROR', 0 );
108
+ define( 'PCLZIP_ERR_WRITE_OPEN_FAIL', -1 );
109
+ define( 'PCLZIP_ERR_READ_OPEN_FAIL', -2 );
110
+ define( 'PCLZIP_ERR_INVALID_PARAMETER', -3 );
111
+ define( 'PCLZIP_ERR_MISSING_FILE', -4 );
112
+ define( 'PCLZIP_ERR_FILENAME_TOO_LONG', -5 );
113
+ define( 'PCLZIP_ERR_INVALID_ZIP', -6 );
114
+ define( 'PCLZIP_ERR_BAD_EXTRACTED_FILE', -7 );
115
+ define( 'PCLZIP_ERR_DIR_CREATE_FAIL', -8 );
116
+ define( 'PCLZIP_ERR_BAD_EXTENSION', -9 );
117
+ define( 'PCLZIP_ERR_BAD_FORMAT', -10 );
118
+ define( 'PCLZIP_ERR_DELETE_FILE_FAIL', -11 );
119
+ define( 'PCLZIP_ERR_RENAME_FILE_FAIL', -12 );
120
+ define( 'PCLZIP_ERR_BAD_CHECKSUM', -13 );
121
+ define( 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', -14 );
122
+ define( 'PCLZIP_ERR_MISSING_OPTION_VALUE', -15 );
123
+ define( 'PCLZIP_ERR_INVALID_OPTION_VALUE', -16 );
124
+ define( 'PCLZIP_ERR_ALREADY_A_DIRECTORY', -17 );
125
+ define( 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', -18 );
126
+ define( 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION', -19 );
127
+ define( 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE', -20 );
128
+ define( 'PCLZIP_ERR_DIRECTORY_RESTRICTION', -21 );
129
+
130
+ // ----- Options values
131
+ define( 'PCLZIP_OPT_PATH', 77001 );
132
+ define( 'PCLZIP_OPT_ADD_PATH', 77002 );
133
+ define( 'PCLZIP_OPT_REMOVE_PATH', 77003 );
134
+ define( 'PCLZIP_OPT_REMOVE_ALL_PATH', 77004 );
135
+ define( 'PCLZIP_OPT_SET_CHMOD', 77005 );
136
+ define( 'PCLZIP_OPT_EXTRACT_AS_STRING', 77006 );
137
+ define( 'PCLZIP_OPT_NO_COMPRESSION', 77007 );
138
+ define( 'PCLZIP_OPT_BY_NAME', 77008 );
139
+ define( 'PCLZIP_OPT_BY_INDEX', 77009 );
140
+ define( 'PCLZIP_OPT_BY_EREG', 77010 );
141
+ define( 'PCLZIP_OPT_BY_PREG', 77011 );
142
+ define( 'PCLZIP_OPT_COMMENT', 77012 );
143
+ define( 'PCLZIP_OPT_ADD_COMMENT', 77013 );
144
+ define( 'PCLZIP_OPT_PREPEND_COMMENT', 77014 );
145
+ define( 'PCLZIP_OPT_EXTRACT_IN_OUTPUT', 77015 );
146
+ define( 'PCLZIP_OPT_REPLACE_NEWER', 77016 );
147
+ define( 'PCLZIP_OPT_STOP_ON_ERROR', 77017 );
148
+ // Having big trouble with crypt. Need to multiply 2 long int
149
+ // which is not correctly supported by PHP ...
150
+ //define( 'PCLZIP_OPT_CRYPT', 77018 );
151
+ define( 'PCLZIP_OPT_EXTRACT_DIR_RESTRICTION', 77019 );
152
+ define( 'PCLZIP_OPT_TEMP_FILE_THRESHOLD', 77020 );
153
+ define( 'PCLZIP_OPT_ADD_TEMP_FILE_THRESHOLD', 77020 ); // alias
154
+ define( 'PCLZIP_OPT_TEMP_FILE_ON', 77021 );
155
+ define( 'PCLZIP_OPT_ADD_TEMP_FILE_ON', 77021 ); // alias
156
+ define( 'PCLZIP_OPT_TEMP_FILE_OFF', 77022 );
157
+ define( 'PCLZIP_OPT_ADD_TEMP_FILE_OFF', 77022 ); // alias
158
+
159
+ // ----- File description attributes
160
+ define( 'PCLZIP_ATT_FILE_NAME', 79001 );
161
+ define( 'PCLZIP_ATT_FILE_NEW_SHORT_NAME', 79002 );
162
+ define( 'PCLZIP_ATT_FILE_NEW_FULL_NAME', 79003 );
163
+ define( 'PCLZIP_ATT_FILE_MTIME', 79004 );
164
+ define( 'PCLZIP_ATT_FILE_CONTENT', 79005 );
165
+ define( 'PCLZIP_ATT_FILE_COMMENT', 79006 );
166
+
167
+ // ----- Call backs values
168
+ define( 'PCLZIP_CB_PRE_EXTRACT', 78001 );
169
+ define( 'PCLZIP_CB_POST_EXTRACT', 78002 );
170
+ define( 'PCLZIP_CB_PRE_ADD', 78003 );
171
+ define( 'PCLZIP_CB_POST_ADD', 78004 );
172
+ /* For futur use
173
+ define( 'PCLZIP_CB_PRE_LIST', 78005 );
174
+ define( 'PCLZIP_CB_POST_LIST', 78006 );
175
+ define( 'PCLZIP_CB_PRE_DELETE', 78007 );
176
+ define( 'PCLZIP_CB_POST_DELETE', 78008 );
177
+ */
178
+
179
+ // --------------------------------------------------------------------------------
180
+ // Class : PclZip
181
+ // Description :
182
+ // PclZip is the class that represent a Zip archive.
183
+ // The public methods allow the manipulation of the archive.
184
+ // Attributes :
185
+ // Attributes must not be accessed directly.
186
+ // Methods :
187
+ // PclZip() : Object creator
188
+ // create() : Creates the Zip archive
189
+ // listContent() : List the content of the Zip archive
190
+ // extract() : Extract the content of the archive
191
+ // properties() : List the properties of the archive
192
+ // --------------------------------------------------------------------------------
193
+ class PclZip
194
+ {
195
+ // ----- Filename of the zip file
196
+ var $zipname = '';
197
+
198
+ // ----- File descriptor of the zip file
199
+ var $zip_fd = 0;
200
+
201
+ // ----- Internal error handling
202
+ var $error_code = 1;
203
+ var $error_string = '';
204
+
205
+ // ----- Current status of the magic_quotes_runtime
206
+ // This value store the php configuration for magic_quotes
207
+ // The class can then disable the magic_quotes and reset it after
208
+ var $magic_quotes_status;
209
+
210
+ // --------------------------------------------------------------------------------
211
+ // Function : PclZip()
212
+ // Description :
213
+ // Creates a PclZip object and set the name of the associated Zip archive
214
+ // filename.
215
+ // Note that no real action is taken, if the archive does not exist it is not
216
+ // created. Use create() for that.
217
+ // --------------------------------------------------------------------------------
218
+ function PclZip($p_zipname)
219
+ {
220
+
221
+ // ----- Tests the zlib
222
+ if (!function_exists('gzopen'))
223
+ {
224
+ die('Abort '.basename(__FILE__).' : Missing zlib extensions');
225
+ }
226
+
227
+ // ----- Set the attributes
228
+ $this->zipname = $p_zipname;
229
+ $this->zip_fd = 0;
230
+ $this->magic_quotes_status = -1;
231
+
232
+ // ----- Return
233
+ return;
234
+ }
235
+ // --------------------------------------------------------------------------------
236
+
237
+ // --------------------------------------------------------------------------------
238
+ // Function :
239
+ // create($p_filelist, $p_add_dir="", $p_remove_dir="")
240
+ // create($p_filelist, $p_option, $p_option_value, ...)
241
+ // Description :
242
+ // This method supports two different synopsis. The first one is historical.
243
+ // This method creates a Zip Archive. The Zip file is created in the
244
+ // filesystem. The files and directories indicated in $p_filelist
245
+ // are added in the archive. See the parameters description for the
246
+ // supported format of $p_filelist.
247
+ // When a directory is in the list, the directory and its content is added
248
+ // in the archive.
249
+ // In this synopsis, the function takes an optional variable list of
250
+ // options. See bellow the supported options.
251
+ // Parameters :
252
+ // $p_filelist : An array containing file or directory names, or
253
+ // a string containing one filename or one directory name, or
254
+ // a string containing a list of filenames and/or directory
255
+ // names separated by spaces.
256
+ // $p_add_dir : A path to add before the real path of the archived file,
257
+ // in order to have it memorized in the archive.
258
+ // $p_remove_dir : A path to remove from the real path of the file to archive,
259
+ // in order to have a shorter path memorized in the archive.
260
+ // When $p_add_dir and $p_remove_dir are set, $p_remove_dir
261
+ // is removed first, before $p_add_dir is added.
262
+ // Options :
263
+ // PCLZIP_OPT_ADD_PATH :
264
+ // PCLZIP_OPT_REMOVE_PATH :
265
+ // PCLZIP_OPT_REMOVE_ALL_PATH :
266
+ // PCLZIP_OPT_COMMENT :
267
+ // PCLZIP_CB_PRE_ADD :
268
+ // PCLZIP_CB_POST_ADD :
269
+ // Return Values :
270
+ // 0 on failure,
271
+ // The list of the added files, with a status of the add action.
272
+ // (see PclZip::listContent() for list entry format)
273
+ // --------------------------------------------------------------------------------
274
+ function create($p_filelist)
275
+ {
276
+ $v_result=1;
277
+
278
+ // ----- Reset the error handler
279
+ $this->privErrorReset();
280
+
281
+ // ----- Set default values
282
+ $v_options = array();
283
+ $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
284
+
285
+ // ----- Look for variable options arguments
286
+ $v_size = func_num_args();
287
+
288
+ // ----- Look for arguments
289
+ if ($v_size > 1) {
290
+ // ----- Get the arguments
291
+ $v_arg_list = func_get_args();
292
+
293
+ // ----- Remove from the options list the first argument
294
+ array_shift($v_arg_list);
295
+ $v_size--;
296
+
297
+ // ----- Look for first arg
298
+ if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
299
+
300
+ // ----- Parse the options
301
+ $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
302
+ array (PCLZIP_OPT_REMOVE_PATH => 'optional',
303
+ PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
304
+ PCLZIP_OPT_ADD_PATH => 'optional',
305
+ PCLZIP_CB_PRE_ADD => 'optional',
306
+ PCLZIP_CB_POST_ADD => 'optional',
307
+ PCLZIP_OPT_NO_COMPRESSION => 'optional',
308
+ PCLZIP_OPT_COMMENT => 'optional',
309
+ PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
310
+ PCLZIP_OPT_TEMP_FILE_ON => 'optional',
311
+ PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
312
+ //, PCLZIP_OPT_CRYPT => 'optional'
313
+ ));
314
+ if ($v_result != 1) {
315
+ return 0;
316
+ }
317
+ }
318
+
319
+ // ----- Look for 2 args
320
+ // Here we need to support the first historic synopsis of the
321
+ // method.
322
+ else {
323
+
324
+ // ----- Get the first argument
325
+ $v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0];
326
+
327
+ // ----- Look for the optional second argument
328
+ if ($v_size == 2) {
329
+ $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
330
+ }
331
+ else if ($v_size > 2) {
332
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
333
+ "Invalid number / type of arguments");
334
+ return 0;
335
+ }
336
+ }
337
+ }
338
+
339
+ // ----- Look for default option values
340
+ $this->privOptionDefaultThreshold($v_options);
341
+
342
+ // ----- Init
343
+ $v_string_list = array();
344
+ $v_att_list = array();
345
+ $v_filedescr_list = array();
346
+ $p_result_list = array();
347
+
348
+ // ----- Look if the $p_filelist is really an array
349
+ if (is_array($p_filelist)) {
350
+
351
+ // ----- Look if the first element is also an array
352
+ // This will mean that this is a file description entry
353
+ if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
354
+ $v_att_list = $p_filelist;
355
+ }
356
+
357
+ // ----- The list is a list of string names
358
+ else {
359
+ $v_string_list = $p_filelist;
360
+ }
361
+ }
362
+
363
+ // ----- Look if the $p_filelist is a string
364
+ else if (is_string($p_filelist)) {
365
+ // ----- Create a list from the string
366
+ $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
367
+ }
368
+
369
+ // ----- Invalid variable type for $p_filelist
370
+ else {
371
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
372
+ return 0;
373
+ }
374
+
375
+ // ----- Reformat the string list
376
+ if (sizeof($v_string_list) != 0) {
377
+ foreach ($v_string_list as $v_string) {
378
+ if ($v_string != '') {
379
+ $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
380
+ }
381
+ else {
382
+ }
383
+ }
384
+ }
385
+
386
+ // ----- For each file in the list check the attributes
387
+ $v_supported_attributes
388
+ = array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
389
+ ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
390
+ ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
391
+ ,PCLZIP_ATT_FILE_MTIME => 'optional'
392
+ ,PCLZIP_ATT_FILE_CONTENT => 'optional'
393
+ ,PCLZIP_ATT_FILE_COMMENT => 'optional'
394
+ );
395
+ foreach ($v_att_list as $v_entry) {
396
+ $v_result = $this->privFileDescrParseAtt($v_entry,
397
+ $v_filedescr_list[],
398
+ $v_options,
399
+ $v_supported_attributes);
400
+ if ($v_result != 1) {
401
+ return 0;
402
+ }
403
+ }
404
+
405
+ // ----- Expand the filelist (expand directories)
406
+ $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
407
+ if ($v_result != 1) {
408
+ return 0;
409
+ }
410
+
411
+ // ----- Call the create fct
412
+ $v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options);
413
+ if ($v_result != 1) {
414
+ return 0;
415
+ }
416
+
417
+ // ----- Return
418
+ return $p_result_list;
419
+ }
420
+ // --------------------------------------------------------------------------------
421
+
422
+ // --------------------------------------------------------------------------------
423
+ // Function :
424
+ // add($p_filelist, $p_add_dir="", $p_remove_dir="")
425
+ // add($p_filelist, $p_option, $p_option_value, ...)
426
+ // Description :
427
+ // This method supports two synopsis. The first one is historical.
428
+ // This methods add the list of files in an existing archive.
429
+ // If a file with the same name already exists, it is added at the end of the
430
+ // archive, the first one is still present.
431
+ // If the archive does not exist, it is created.
432
+ // Parameters :
433
+ // $p_filelist : An array containing file or directory names, or
434
+ // a string containing one filename or one directory name, or
435
+ // a string containing a list of filenames and/or directory
436
+ // names separated by spaces.
437
+ // $p_add_dir : A path to add before the real path of the archived file,
438
+ // in order to have it memorized in the archive.
439
+ // $p_remove_dir : A path to remove from the real path of the file to archive,
440
+ // in order to have a shorter path memorized in the archive.
441
+ // When $p_add_dir and $p_remove_dir are set, $p_remove_dir
442
+ // is removed first, before $p_add_dir is added.
443
+ // Options :
444
+ // PCLZIP_OPT_ADD_PATH :
445
+ // PCLZIP_OPT_REMOVE_PATH :
446
+ // PCLZIP_OPT_REMOVE_ALL_PATH :
447
+ // PCLZIP_OPT_COMMENT :
448
+ // PCLZIP_OPT_ADD_COMMENT :
449
+ // PCLZIP_OPT_PREPEND_COMMENT :
450
+ // PCLZIP_CB_PRE_ADD :
451
+ // PCLZIP_CB_POST_ADD :
452
+ // Return Values :
453
+ // 0 on failure,
454
+ // The list of the added files, with a status of the add action.
455
+ // (see PclZip::listContent() for list entry format)
456
+ // --------------------------------------------------------------------------------
457
+ function add($p_filelist)
458
+ {
459
+ $v_result=1;
460
+
461
+ // ----- Reset the error handler
462
+ $this->privErrorReset();
463
+
464
+ // ----- Set default values
465
+ $v_options = array();
466
+ $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;
467
+
468
+ // ----- Look for variable options arguments
469
+ $v_size = func_num_args();
470
+
471
+ // ----- Look for arguments
472
+ if ($v_size > 1) {
473
+ // ----- Get the arguments
474
+ $v_arg_list = func_get_args();
475
+
476
+ // ----- Remove form the options list the first argument
477
+ array_shift($v_arg_list);
478
+ $v_size--;
479
+
480
+ // ----- Look for first arg
481
+ if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
482
+
483
+ // ----- Parse the options
484
+ $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
485
+ array (PCLZIP_OPT_REMOVE_PATH => 'optional',
486
+ PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
487
+ PCLZIP_OPT_ADD_PATH => 'optional',
488
+ PCLZIP_CB_PRE_ADD => 'optional',
489
+ PCLZIP_CB_POST_ADD => 'optional',
490
+ PCLZIP_OPT_NO_COMPRESSION => 'optional',
491
+ PCLZIP_OPT_COMMENT => 'optional',
492
+ PCLZIP_OPT_ADD_COMMENT => 'optional',
493
+ PCLZIP_OPT_PREPEND_COMMENT => 'optional',
494
+ PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
495
+ PCLZIP_OPT_TEMP_FILE_ON => 'optional',
496
+ PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
497
+ //, PCLZIP_OPT_CRYPT => 'optional'
498
+ ));
499
+ if ($v_result != 1) {
500
+ return 0;
501
+ }
502
+ }
503
+
504
+ // ----- Look for 2 args
505
+ // Here we need to support the first historic synopsis of the
506
+ // method.
507
+ else {
508
+
509
+ // ----- Get the first argument
510
+ $v_options[PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0];
511
+
512
+ // ----- Look for the optional second argument
513
+ if ($v_size == 2) {
514
+ $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
515
+ }
516
+ else if ($v_size > 2) {
517
+ // ----- Error log
518
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
519
+
520
+ // ----- Return
521
+ return 0;
522
+ }
523
+ }
524
+ }
525
+
526
+ // ----- Look for default option values
527
+ $this->privOptionDefaultThreshold($v_options);
528
+
529
+ // ----- Init
530
+ $v_string_list = array();
531
+ $v_att_list = array();
532
+ $v_filedescr_list = array();
533
+ $p_result_list = array();
534
+
535
+ // ----- Look if the $p_filelist is really an array
536
+ if (is_array($p_filelist)) {
537
+
538
+ // ----- Look if the first element is also an array
539
+ // This will mean that this is a file description entry
540
+ if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
541
+ $v_att_list = $p_filelist;
542
+ }
543
+
544
+ // ----- The list is a list of string names
545
+ else {
546
+ $v_string_list = $p_filelist;
547
+ }
548
+ }
549
+
550
+ // ----- Look if the $p_filelist is a string
551
+ else if (is_string($p_filelist)) {
552
+ // ----- Create a list from the string
553
+ $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
554
+ }
555
+
556
+ // ----- Invalid variable type for $p_filelist
557
+ else {
558
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist");
559
+ return 0;
560
+ }
561
+
562
+ // ----- Reformat the string list
563
+ if (sizeof($v_string_list) != 0) {
564
+ foreach ($v_string_list as $v_string) {
565
+ $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
566
+ }
567
+ }
568
+
569
+ // ----- For each file in the list check the attributes
570
+ $v_supported_attributes
571
+ = array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
572
+ ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
573
+ ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
574
+ ,PCLZIP_ATT_FILE_MTIME => 'optional'
575
+ ,PCLZIP_ATT_FILE_CONTENT => 'optional'
576
+ ,PCLZIP_ATT_FILE_COMMENT => 'optional'
577
+ );
578
+ foreach ($v_att_list as $v_entry) {
579
+ $v_result = $this->privFileDescrParseAtt($v_entry,
580
+ $v_filedescr_list[],
581
+ $v_options,
582
+ $v_supported_attributes);
583
+ if ($v_result != 1) {
584
+ return 0;
585
+ }
586
+ }
587
+
588
+ // ----- Expand the filelist (expand directories)
589
+ $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
590
+ if ($v_result != 1) {
591
+ return 0;
592
+ }
593
+
594
+ // ----- Call the create fct
595
+ $v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options);
596
+ if ($v_result != 1) {
597
+ return 0;
598
+ }
599
+
600
+ // ----- Return
601
+ return $p_result_list;
602
+ }
603
+ // --------------------------------------------------------------------------------
604
+
605
+ // --------------------------------------------------------------------------------
606
+ // Function : listContent()
607
+ // Description :
608
+ // This public method, gives the list of the files and directories, with their
609
+ // properties.
610
+ // The properties of each entries in the list are (used also in other functions) :
611
+ // filename : Name of the file. For a create or add action it is the filename
612
+ // given by the user. For an extract function it is the filename
613
+ // of the extracted file.
614
+ // stored_filename : Name of the file / directory stored in the archive.
615
+ // size : Size of the stored file.
616
+ // compressed_size : Size of the file's data compressed in the archive
617
+ // (without the headers overhead)
618
+ // mtime : Last known modification date of the file (UNIX timestamp)
619
+ // comment : Comment associated with the file
620
+ // folder : true | false
621
+ // index : index of the file in the archive
622
+ // status : status of the action (depending of the action) :
623
+ // Values are :
624
+ // ok : OK !
625
+ // filtered : the file / dir is not extracted (filtered by user)
626
+ // already_a_directory : the file can not be extracted because a
627
+ // directory with the same name already exists
628
+ // write_protected : the file can not be extracted because a file
629
+ // with the same name already exists and is
630
+ // write protected
631
+ // newer_exist : the file was not extracted because a newer file exists
632
+ // path_creation_fail : the file is not extracted because the folder
633
+ // does not exist and can not be created
634
+ // write_error : the file was not extracted because there was a
635
+ // error while writing the file
636
+ // read_error : the file was not extracted because there was a error
637
+ // while reading the file
638
+ // invalid_header : the file was not extracted because of an archive
639
+ // format error (bad file header)
640
+ // Note that each time a method can continue operating when there
641
+ // is an action error on a file, the error is only logged in the file status.
642
+ // Return Values :
643
+ // 0 on an unrecoverable failure,
644
+ // The list of the files in the archive.
645
+ // --------------------------------------------------------------------------------
646
+ function listContent()
647
+ {
648
+ $v_result=1;
649
+
650
+ // ----- Reset the error handler
651
+ $this->privErrorReset();
652
+
653
+ // ----- Check archive
654
+ if (!$this->privCheckFormat()) {
655
+ return(0);
656
+ }
657
+
658
+ // ----- Call the extracting fct
659
+ $p_list = array();
660
+ if (($v_result = $this->privList($p_list)) != 1)
661
+ {
662
+ unset($p_list);
663
+ return(0);
664
+ }
665
+
666
+ // ----- Return
667
+ return $p_list;
668
+ }
669
+ // --------------------------------------------------------------------------------
670
+
671
+ // --------------------------------------------------------------------------------
672
+ // Function :
673
+ // extract($p_path="./", $p_remove_path="")
674
+ // extract([$p_option, $p_option_value, ...])
675
+ // Description :
676
+ // This method supports two synopsis. The first one is historical.
677
+ // This method extract all the files / directories from the archive to the
678
+ // folder indicated in $p_path.
679
+ // If you want to ignore the 'root' part of path of the memorized files
680
+ // you can indicate this in the optional $p_remove_path parameter.
681
+ // By default, if a newer file with the same name already exists, the
682
+ // file is not extracted.
683
+ //
684
+ // If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions
685
+ // are used, the path indicated in PCLZIP_OPT_ADD_PATH is append
686
+ // at the end of the path value of PCLZIP_OPT_PATH.
687
+ // Parameters :
688
+ // $p_path : Path where the files and directories are to be extracted
689
+ // $p_remove_path : First part ('root' part) of the memorized path
690
+ // (if any similar) to remove while extracting.
691
+ // Options :
692
+ // PCLZIP_OPT_PATH :
693
+ // PCLZIP_OPT_ADD_PATH :
694
+ // PCLZIP_OPT_REMOVE_PATH :
695
+ // PCLZIP_OPT_REMOVE_ALL_PATH :
696
+ // PCLZIP_CB_PRE_EXTRACT :
697
+ // PCLZIP_CB_POST_EXTRACT :
698
+ // Return Values :
699
+ // 0 or a negative value on failure,
700
+ // The list of the extracted files, with a status of the action.
701
+ // (see PclZip::listContent() for list entry format)
702
+ // --------------------------------------------------------------------------------
703
+ function extract()
704
+ {
705
+ $v_result=1;
706
+
707
+ // ----- Reset the error handler
708
+ $this->privErrorReset();
709
+
710
+ // ----- Check archive
711
+ if (!$this->privCheckFormat()) {
712
+ return(0);
713
+ }
714
+
715
+ // ----- Set default values
716
+ $v_options = array();
717
+ // $v_path = "./";
718
+ $v_path = '';
719
+ $v_remove_path = "";
720
+ $v_remove_all_path = false;
721
+
722
+ // ----- Look for variable options arguments
723
+ $v_size = func_num_args();
724
+
725
+ // ----- Default values for option
726
+ $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
727
+
728
+ // ----- Look for arguments
729
+ if ($v_size > 0) {
730
+ // ----- Get the arguments
731
+ $v_arg_list = func_get_args();
732
+
733
+ // ----- Look for first arg
734
+ if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
735
+
736
+ // ----- Parse the options
737
+ $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
738
+ array (PCLZIP_OPT_PATH => 'optional',
739
+ PCLZIP_OPT_REMOVE_PATH => 'optional',
740
+ PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
741
+ PCLZIP_OPT_ADD_PATH => 'optional',
742
+ PCLZIP_CB_PRE_EXTRACT => 'optional',
743
+ PCLZIP_CB_POST_EXTRACT => 'optional',
744
+ PCLZIP_OPT_SET_CHMOD => 'optional',
745
+ PCLZIP_OPT_BY_NAME => 'optional',
746
+ PCLZIP_OPT_BY_EREG => 'optional',
747
+ PCLZIP_OPT_BY_PREG => 'optional',
748
+ PCLZIP_OPT_BY_INDEX => 'optional',
749
+ PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
750
+ PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional',
751
+ PCLZIP_OPT_REPLACE_NEWER => 'optional'
752
+ ,PCLZIP_OPT_STOP_ON_ERROR => 'optional'
753
+ ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
754
+ PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
755
+ PCLZIP_OPT_TEMP_FILE_ON => 'optional',
756
+ PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
757
+ ));
758
+ if ($v_result != 1) {
759
+ return 0;
760
+ }
761
+
762
+ // ----- Set the arguments
763
+ if (isset($v_options[PCLZIP_OPT_PATH])) {
764
+ $v_path = $v_options[PCLZIP_OPT_PATH];
765
+ }
766
+ if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
767
+ $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
768
+ }
769
+ if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
770
+ $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
771
+ }
772
+ if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
773
+ // ----- Check for '/' in last path char
774
+ if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
775
+ $v_path .= '/';
776
+ }
777
+ $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
778
+ }
779
+ }
780
+
781
+ // ----- Look for 2 args
782
+ // Here we need to support the first historic synopsis of the
783
+ // method.
784
+ else {
785
+
786
+ // ----- Get the first argument
787
+ $v_path = $v_arg_list[0];
788
+
789
+ // ----- Look for the optional second argument
790
+ if ($v_size == 2) {
791
+ $v_remove_path = $v_arg_list[1];
792
+ }
793
+ else if ($v_size > 2) {
794
+ // ----- Error log
795
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
796
+
797
+ // ----- Return
798
+ return 0;
799
+ }
800
+ }
801
+ }
802
+
803
+ // ----- Look for default option values
804
+ $this->privOptionDefaultThreshold($v_options);
805
+
806
+ // ----- Trace
807
+
808
+ // ----- Call the extracting fct
809
+ $p_list = array();
810
+ $v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path,
811
+ $v_remove_all_path, $v_options);
812
+ if ($v_result < 1) {
813
+ unset($p_list);
814
+ return(0);
815
+ }
816
+
817
+ // ----- Return
818
+ return $p_list;
819
+ }
820
+ // --------------------------------------------------------------------------------
821
+
822
+
823
+ // --------------------------------------------------------------------------------
824
+ // Function :
825
+ // extractByIndex($p_index, $p_path="./", $p_remove_path="")
826
+ // extractByIndex($p_index, [$p_option, $p_option_value, ...])
827
+ // Description :
828
+ // This method supports two synopsis. The first one is historical.
829
+ // This method is doing a partial extract of the archive.
830
+ // The extracted files or folders are identified by their index in the
831
+ // archive (from 0 to n).
832
+ // Note that if the index identify a folder, only the folder entry is
833
+ // extracted, not all the files included in the archive.
834
+ // Parameters :
835
+ // $p_index : A single index (integer) or a string of indexes of files to
836
+ // extract. The form of the string is "0,4-6,8-12" with only numbers
837
+ // and '-' for range or ',' to separate ranges. No spaces or ';'
838
+ // are allowed.
839
+ // $p_path : Path where the files and directories are to be extracted
840
+ // $p_remove_path : First part ('root' part) of the memorized path
841
+ // (if any similar) to remove while extracting.
842
+ // Options :
843
+ // PCLZIP_OPT_PATH :
844
+ // PCLZIP_OPT_ADD_PATH :
845
+ // PCLZIP_OPT_REMOVE_PATH :
846
+ // PCLZIP_OPT_REMOVE_ALL_PATH :
847
+ // PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and
848
+ // not as files.
849
+ // The resulting content is in a new field 'content' in the file
850
+ // structure.
851
+ // This option must be used alone (any other options are ignored).
852
+ // PCLZIP_CB_PRE_EXTRACT :
853
+ // PCLZIP_CB_POST_EXTRACT :
854
+ // Return Values :
855
+ // 0 on failure,
856
+ // The list of the extracted files, with a status of the action.
857
+ // (see PclZip::listContent() for list entry format)
858
+ // --------------------------------------------------------------------------------
859
+ //function extractByIndex($p_index, options...)
860
+ function extractByIndex($p_index)
861
+ {
862
+ $v_result=1;
863
+
864
+ // ----- Reset the error handler
865
+ $this->privErrorReset();
866
+
867
+ // ----- Check archive
868
+ if (!$this->privCheckFormat()) {
869
+ return(0);
870
+ }
871
+
872
+ // ----- Set default values
873
+ $v_options = array();
874
+ // $v_path = "./";
875
+ $v_path = '';
876
+ $v_remove_path = "";
877
+ $v_remove_all_path = false;
878
+
879
+ // ----- Look for variable options arguments
880
+ $v_size = func_num_args();
881
+
882
+ // ----- Default values for option
883
+ $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
884
+
885
+ // ----- Look for arguments
886
+ if ($v_size > 1) {
887
+ // ----- Get the arguments
888
+ $v_arg_list = func_get_args();
889
+
890
+ // ----- Remove form the options list the first argument
891
+ array_shift($v_arg_list);
892
+ $v_size--;
893
+
894
+ // ----- Look for first arg
895
+ if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
896
+
897
+ // ----- Parse the options
898
+ $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
899
+ array (PCLZIP_OPT_PATH => 'optional',
900
+ PCLZIP_OPT_REMOVE_PATH => 'optional',
901
+ PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
902
+ PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
903
+ PCLZIP_OPT_ADD_PATH => 'optional',
904
+ PCLZIP_CB_PRE_EXTRACT => 'optional',
905
+ PCLZIP_CB_POST_EXTRACT => 'optional',
906
+ PCLZIP_OPT_SET_CHMOD => 'optional',
907
+ PCLZIP_OPT_REPLACE_NEWER => 'optional'
908
+ ,PCLZIP_OPT_STOP_ON_ERROR => 'optional'
909
+ ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
910
+ PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
911
+ PCLZIP_OPT_TEMP_FILE_ON => 'optional',
912
+ PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
913
+ ));
914
+ if ($v_result != 1) {
915
+ return 0;
916
+ }
917
+
918
+ // ----- Set the arguments
919
+ if (isset($v_options[PCLZIP_OPT_PATH])) {
920
+ $v_path = $v_options[PCLZIP_OPT_PATH];
921
+ }
922
+ if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
923
+ $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
924
+ }
925
+ if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
926
+ $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
927
+ }
928
+ if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
929
+ // ----- Check for '/' in last path char
930
+ if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
931
+ $v_path .= '/';
932
+ }
933
+ $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
934
+ }
935
+ if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) {
936
+ $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
937
+ }
938
+ else {
939
+ }
940
+ }
941
+
942
+ // ----- Look for 2 args
943
+ // Here we need to support the first historic synopsis of the
944
+ // method.
945
+ else {
946
+
947
+ // ----- Get the first argument
948
+ $v_path = $v_arg_list[0];
949
+
950
+ // ----- Look for the optional second argument
951
+ if ($v_size == 2) {
952
+ $v_remove_path = $v_arg_list[1];
953
+ }
954
+ else if ($v_size > 2) {
955
+ // ----- Error log
956
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
957
+
958
+ // ----- Return
959
+ return 0;
960
+ }
961
+ }
962
+ }
963
+
964
+ // ----- Trace
965
+
966
+ // ----- Trick
967
+ // Here I want to reuse extractByRule(), so I need to parse the $p_index
968
+ // with privParseOptions()
969
+ $v_arg_trick = array (PCLZIP_OPT_BY_INDEX, $p_index);
970
+ $v_options_trick = array();
971
+ $v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick,
972
+ array (PCLZIP_OPT_BY_INDEX => 'optional' ));
973
+ if ($v_result != 1) {
974
+ return 0;
975
+ }
976
+ $v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX];
977
+
978
+ // ----- Look for default option values
979
+ $this->privOptionDefaultThreshold($v_options);
980
+
981
+ // ----- Call the extracting fct
982
+ if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) {
983
+ return(0);
984
+ }
985
+
986
+ // ----- Return
987
+ return $p_list;
988
+ }
989
+ // --------------------------------------------------------------------------------
990
+
991
+ // --------------------------------------------------------------------------------
992
+ // Function :
993
+ // delete([$p_option, $p_option_value, ...])
994
+ // Description :
995
+ // This method removes files from the archive.
996
+ // If no parameters are given, then all the archive is emptied.
997
+ // Parameters :
998
+ // None or optional arguments.
999
+ // Options :
1000
+ // PCLZIP_OPT_BY_INDEX :
1001
+ // PCLZIP_OPT_BY_NAME :
1002
+ // PCLZIP_OPT_BY_EREG :
1003
+ // PCLZIP_OPT_BY_PREG :
1004
+ // Return Values :
1005
+ // 0 on failure,
1006
+ // The list of the files which are still present in the archive.
1007
+ // (see PclZip::listContent() for list entry format)
1008
+ // --------------------------------------------------------------------------------
1009
+ function delete()
1010
+ {
1011
+ $v_result=1;
1012
+
1013
+ // ----- Reset the error handler
1014
+ $this->privErrorReset();
1015
+
1016
+ // ----- Check archive
1017
+ if (!$this->privCheckFormat()) {
1018
+ return(0);
1019
+ }
1020
+
1021
+ // ----- Set default values
1022
+ $v_options = array();
1023
+
1024
+ // ----- Look for variable options arguments
1025
+ $v_size = func_num_args();
1026
+
1027
+ // ----- Look for arguments
1028
+ if ($v_size > 0) {
1029
+ // ----- Get the arguments
1030
+ $v_arg_list = func_get_args();
1031
+
1032
+ // ----- Parse the options
1033
+ $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
1034
+ array (PCLZIP_OPT_BY_NAME => 'optional',
1035
+ PCLZIP_OPT_BY_EREG => 'optional',
1036
+ PCLZIP_OPT_BY_PREG => 'optional',
1037
+ PCLZIP_OPT_BY_INDEX => 'optional' ));
1038
+ if ($v_result != 1) {
1039
+ return 0;
1040
+ }
1041
+ }
1042
+
1043
+ // ----- Magic quotes trick
1044
+ $this->privDisableMagicQuotes();
1045
+
1046
+ // ----- Call the delete fct
1047
+ $v_list = array();
1048
+ if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) {
1049
+ $this->privSwapBackMagicQuotes();
1050
+ unset($v_list);
1051
+ return(0);
1052
+ }
1053
+
1054
+ // ----- Magic quotes trick
1055
+ $this->privSwapBackMagicQuotes();
1056
+
1057
+ // ----- Return
1058
+ return $v_list;
1059
+ }
1060
+ // --------------------------------------------------------------------------------
1061
+
1062
+ // --------------------------------------------------------------------------------
1063
+ // Function : deleteByIndex()
1064
+ // Description :
1065
+ // ***** Deprecated *****
1066
+ // delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered.
1067
+ // --------------------------------------------------------------------------------
1068
+ function deleteByIndex($p_index)
1069
+ {
1070
+
1071
+ $p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index);
1072
+
1073
+ // ----- Return
1074
+ return $p_list;
1075
+ }
1076
+ // --------------------------------------------------------------------------------
1077
+
1078
+ // --------------------------------------------------------------------------------
1079
+ // Function : properties()
1080
+ // Description :
1081
+ // This method gives the properties of the archive.
1082
+ // The properties are :
1083
+ // nb : Number of files in the archive
1084
+ // comment : Comment associated with the archive file
1085
+ // status : not_exist, ok
1086
+ // Parameters :
1087
+ // None
1088
+ // Return Values :
1089
+ // 0 on failure,
1090
+ // An array with the archive properties.
1091
+ // --------------------------------------------------------------------------------
1092
+ function properties()
1093
+ {
1094
+
1095
+ // ----- Reset the error handler
1096
+ $this->privErrorReset();
1097
+
1098
+ // ----- Magic quotes trick
1099
+ $this->privDisableMagicQuotes();
1100
+
1101
+ // ----- Check archive
1102
+ if (!$this->privCheckFormat()) {
1103
+ $this->privSwapBackMagicQuotes();
1104
+ return(0);
1105
+ }
1106
+
1107
+ // ----- Default properties
1108
+ $v_prop = array();
1109
+ $v_prop['comment'] = '';
1110
+ $v_prop['nb'] = 0;
1111
+ $v_prop['status'] = 'not_exist';
1112
+
1113
+ // ----- Look if file exists
1114
+ if (@is_file($this->zipname))
1115
+ {
1116
+ // ----- Open the zip file
1117
+ if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
1118
+ {
1119
+ $this->privSwapBackMagicQuotes();
1120
+
1121
+ // ----- Error log
1122
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
1123
+
1124
+ // ----- Return
1125
+ return 0;
1126
+ }
1127
+
1128
+ // ----- Read the central directory informations
1129
+ $v_central_dir = array();
1130
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
1131
+ {
1132
+ $this->privSwapBackMagicQuotes();
1133
+ return 0;
1134
+ }
1135
+
1136
+ // ----- Close the zip file
1137
+ $this->privCloseFd();
1138
+
1139
+ // ----- Set the user attributes
1140
+ $v_prop['comment'] = $v_central_dir['comment'];
1141
+ $v_prop['nb'] = $v_central_dir['entries'];
1142
+ $v_prop['status'] = 'ok';
1143
+ }
1144
+
1145
+ // ----- Magic quotes trick
1146
+ $this->privSwapBackMagicQuotes();
1147
+
1148
+ // ----- Return
1149
+ return $v_prop;
1150
+ }
1151
+ // --------------------------------------------------------------------------------
1152
+
1153
+ // --------------------------------------------------------------------------------
1154
+ // Function : duplicate()
1155
+ // Description :
1156
+ // This method creates an archive by copying the content of an other one. If
1157
+ // the archive already exist, it is replaced by the new one without any warning.
1158
+ // Parameters :
1159
+ // $p_archive : The filename of a valid archive, or
1160
+ // a valid PclZip object.
1161
+ // Return Values :
1162
+ // 1 on success.
1163
+ // 0 or a negative value on error (error code).
1164
+ // --------------------------------------------------------------------------------
1165
+ function duplicate($p_archive)
1166
+ {
1167
+ $v_result = 1;
1168
+
1169
+ // ----- Reset the error handler
1170
+ $this->privErrorReset();
1171
+
1172
+ // ----- Look if the $p_archive is a PclZip object
1173
+ if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip'))
1174
+ {
1175
+
1176
+ // ----- Duplicate the archive
1177
+ $v_result = $this->privDuplicate($p_archive->zipname);
1178
+ }
1179
+
1180
+ // ----- Look if the $p_archive is a string (so a filename)
1181
+ else if (is_string($p_archive))
1182
+ {
1183
+
1184
+ // ----- Check that $p_archive is a valid zip file
1185
+ // TBC : Should also check the archive format
1186
+ if (!is_file($p_archive)) {
1187
+ // ----- Error log
1188
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'");
1189
+ $v_result = PCLZIP_ERR_MISSING_FILE;
1190
+ }
1191
+ else {
1192
+ // ----- Duplicate the archive
1193
+ $v_result = $this->privDuplicate($p_archive);
1194
+ }
1195
+ }
1196
+
1197
+ // ----- Invalid variable
1198
+ else
1199
+ {
1200
+ // ----- Error log
1201
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
1202
+ $v_result = PCLZIP_ERR_INVALID_PARAMETER;
1203
+ }
1204
+
1205
+ // ----- Return
1206
+ return $v_result;
1207
+ }
1208
+ // --------------------------------------------------------------------------------
1209
+
1210
+ // --------------------------------------------------------------------------------
1211
+ // Function : merge()
1212
+ // Description :
1213
+ // This method merge the $p_archive_to_add archive at the end of the current
1214
+ // one ($this).
1215
+ // If the archive ($this) does not exist, the merge becomes a duplicate.
1216
+ // If the $p_archive_to_add archive does not exist, the merge is a success.
1217
+ // Parameters :
1218
+ // $p_archive_to_add : It can be directly the filename of a valid zip archive,
1219
+ // or a PclZip object archive.
1220
+ // Return Values :
1221
+ // 1 on success,
1222
+ // 0 or negative values on error (see below).
1223
+ // --------------------------------------------------------------------------------
1224
+ function merge($p_archive_to_add)
1225
+ {
1226
+ $v_result = 1;
1227
+
1228
+ // ----- Reset the error handler
1229
+ $this->privErrorReset();
1230
+
1231
+ // ----- Check archive
1232
+ if (!$this->privCheckFormat()) {
1233
+ return(0);
1234
+ }
1235
+
1236
+ // ----- Look if the $p_archive_to_add is a PclZip object
1237
+ if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip'))
1238
+ {
1239
+
1240
+ // ----- Merge the archive
1241
+ $v_result = $this->privMerge($p_archive_to_add);
1242
+ }
1243
+
1244
+ // ----- Look if the $p_archive_to_add is a string (so a filename)
1245
+ else if (is_string($p_archive_to_add))
1246
+ {
1247
+
1248
+ // ----- Create a temporary archive
1249
+ $v_object_archive = new PclZip($p_archive_to_add);
1250
+
1251
+ // ----- Merge the archive
1252
+ $v_result = $this->privMerge($v_object_archive);
1253
+ }
1254
+
1255
+ // ----- Invalid variable
1256
+ else
1257
+ {
1258
+ // ----- Error log
1259
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
1260
+ $v_result = PCLZIP_ERR_INVALID_PARAMETER;
1261
+ }
1262
+
1263
+ // ----- Return
1264
+ return $v_result;
1265
+ }
1266
+ // --------------------------------------------------------------------------------
1267
+
1268
+
1269
+
1270
+ // --------------------------------------------------------------------------------
1271
+ // Function : errorCode()
1272
+ // Description :
1273
+ // Parameters :
1274
+ // --------------------------------------------------------------------------------
1275
+ function errorCode()
1276
+ {
1277
+ if (PCLZIP_ERROR_EXTERNAL == 1) {
1278
+ return(PclErrorCode());
1279
+ }
1280
+ else {
1281
+ return($this->error_code);
1282
+ }
1283
+ }
1284
+ // --------------------------------------------------------------------------------
1285
+
1286
+ // --------------------------------------------------------------------------------
1287
+ // Function : errorName()
1288
+ // Description :
1289
+ // Parameters :
1290
+ // --------------------------------------------------------------------------------
1291
+ function errorName($p_with_code=false)
1292
+ {
1293
+ $v_name = array ( PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR',
1294
+ PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL',
1295
+ PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL',
1296
+ PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER',
1297
+ PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE',
1298
+ PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG',
1299
+ PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP',
1300
+ PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE',
1301
+ PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL',
1302
+ PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION',
1303
+ PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT',
1304
+ PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL',
1305
+ PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL',
1306
+ PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM',
1307
+ PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP',
1308
+ PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE',
1309
+ PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE',
1310
+ PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION',
1311
+ PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION'
1312
+ ,PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE'
1313
+ ,PCLZIP_ERR_DIRECTORY_RESTRICTION => 'PCLZIP_ERR_DIRECTORY_RESTRICTION'
1314
+ );
1315
+
1316
+ if (isset($v_name[$this->error_code])) {
1317
+ $v_value = $v_name[$this->error_code];
1318
+ }
1319
+ else {
1320
+ $v_value = 'NoName';
1321
+ }
1322
+
1323
+ if ($p_with_code) {
1324
+ return($v_value.' ('.$this->error_code.')');
1325
+ }
1326
+ else {
1327
+ return($v_value);
1328
+ }
1329
+ }
1330
+ // --------------------------------------------------------------------------------
1331
+
1332
+ // --------------------------------------------------------------------------------
1333
+ // Function : errorInfo()
1334
+ // Description :
1335
+ // Parameters :
1336
+ // --------------------------------------------------------------------------------
1337
+ function errorInfo($p_full=false)
1338
+ {
1339
+ if (PCLZIP_ERROR_EXTERNAL == 1) {
1340
+ return(PclErrorString());
1341
+ }
1342
+ else {
1343
+ if ($p_full) {
1344
+ return($this->errorName(true)." : ".$this->error_string);
1345
+ }
1346
+ else {
1347
+ return($this->error_string." [code ".$this->error_code."]");
1348
+ }
1349
+ }
1350
+ }
1351
+ // --------------------------------------------------------------------------------
1352
+
1353
+
1354
+ // --------------------------------------------------------------------------------
1355
+ // ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
1356
+ // ***** *****
1357
+ // ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY *****
1358
+ // --------------------------------------------------------------------------------
1359
+
1360
+
1361
+
1362
+ // --------------------------------------------------------------------------------
1363
+ // Function : privCheckFormat()
1364
+ // Description :
1365
+ // This method check that the archive exists and is a valid zip archive.
1366
+ // Several level of check exists. (futur)
1367
+ // Parameters :
1368
+ // $p_level : Level of check. Default 0.
1369
+ // 0 : Check the first bytes (magic codes) (default value))
1370
+ // 1 : 0 + Check the central directory (futur)
1371
+ // 2 : 1 + Check each file header (futur)
1372
+ // Return Values :
1373
+ // true on success,
1374
+ // false on error, the error code is set.
1375
+ // --------------------------------------------------------------------------------
1376
+ function privCheckFormat($p_level=0)
1377
+ {
1378
+ $v_result = true;
1379
+
1380
+ // ----- Reset the file system cache
1381
+ clearstatcache();
1382
+
1383
+ // ----- Reset the error handler
1384
+ $this->privErrorReset();
1385
+
1386
+ // ----- Look if the file exits
1387
+ if (!is_file($this->zipname)) {
1388
+ // ----- Error log
1389
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'");
1390
+ return(false);
1391
+ }
1392
+
1393
+ // ----- Check that the file is readeable
1394
+ if (!is_readable($this->zipname)) {
1395
+ // ----- Error log
1396
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'");
1397
+ return(false);
1398
+ }
1399
+
1400
+ // ----- Check the magic code
1401
+ // TBC
1402
+
1403
+ // ----- Check the central header
1404
+ // TBC
1405
+
1406
+ // ----- Check each file header
1407
+ // TBC
1408
+
1409
+ // ----- Return
1410
+ return $v_result;
1411
+ }
1412
+ // --------------------------------------------------------------------------------
1413
+
1414
+ // --------------------------------------------------------------------------------
1415
+ // Function : privParseOptions()
1416
+ // Description :
1417
+ // This internal methods reads the variable list of arguments ($p_options_list,
1418
+ // $p_size) and generate an array with the options and values ($v_result_list).
1419
+ // $v_requested_options contains the options that can be present and those that
1420
+ // must be present.
1421
+ // $v_requested_options is an array, with the option value as key, and 'optional',
1422
+ // or 'mandatory' as value.
1423
+ // Parameters :
1424
+ // See above.
1425
+ // Return Values :
1426
+ // 1 on success.
1427
+ // 0 on failure.
1428
+ // --------------------------------------------------------------------------------
1429
+ function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false)
1430
+ {
1431
+ $v_result=1;
1432
+
1433
+ // ----- Read the options
1434
+ $i=0;
1435
+ while ($i<$p_size) {
1436
+
1437
+ // ----- Check if the option is supported
1438
+ if (!isset($v_requested_options[$p_options_list[$i]])) {
1439
+ // ----- Error log
1440
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method");
1441
+
1442
+ // ----- Return
1443
+ return PclZip::errorCode();
1444
+ }
1445
+
1446
+ // ----- Look for next option
1447
+ switch ($p_options_list[$i]) {
1448
+ // ----- Look for options that request a path value
1449
+ case PCLZIP_OPT_PATH :
1450
+ case PCLZIP_OPT_REMOVE_PATH :
1451
+ case PCLZIP_OPT_ADD_PATH :
1452
+ // ----- Check the number of parameters
1453
+ if (($i+1) >= $p_size) {
1454
+ // ----- Error log
1455
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1456
+
1457
+ // ----- Return
1458
+ return PclZip::errorCode();
1459
+ }
1460
+
1461
+ // ----- Get the value
1462
+ $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE);
1463
+ $i++;
1464
+ break;
1465
+
1466
+ case PCLZIP_OPT_TEMP_FILE_THRESHOLD :
1467
+ // ----- Check the number of parameters
1468
+ if (($i+1) >= $p_size) {
1469
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1470
+ return PclZip::errorCode();
1471
+ }
1472
+
1473
+ // ----- Check for incompatible options
1474
+ if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
1475
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
1476
+ return PclZip::errorCode();
1477
+ }
1478
+
1479
+ // ----- Check the value
1480
+ $v_value = $p_options_list[$i+1];
1481
+ if ((!is_integer($v_value)) || ($v_value<0)) {
1482
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Integer expected for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1483
+ return PclZip::errorCode();
1484
+ }
1485
+
1486
+ // ----- Get the value (and convert it in bytes)
1487
+ $v_result_list[$p_options_list[$i]] = $v_value*1048576;
1488
+ $i++;
1489
+ break;
1490
+
1491
+ case PCLZIP_OPT_TEMP_FILE_ON :
1492
+ // ----- Check for incompatible options
1493
+ if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
1494
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
1495
+ return PclZip::errorCode();
1496
+ }
1497
+
1498
+ $v_result_list[$p_options_list[$i]] = true;
1499
+ break;
1500
+
1501
+ case PCLZIP_OPT_TEMP_FILE_OFF :
1502
+ // ----- Check for incompatible options
1503
+ if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_ON])) {
1504
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_ON'");
1505
+ return PclZip::errorCode();
1506
+ }
1507
+ // ----- Check for incompatible options
1508
+ if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
1509
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_THRESHOLD'");
1510
+ return PclZip::errorCode();
1511
+ }
1512
+
1513
+ $v_result_list[$p_options_list[$i]] = true;
1514
+ break;
1515
+
1516
+ case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION :
1517
+ // ----- Check the number of parameters
1518
+ if (($i+1) >= $p_size) {
1519
+ // ----- Error log
1520
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1521
+
1522
+ // ----- Return
1523
+ return PclZip::errorCode();
1524
+ }
1525
+
1526
+ // ----- Get the value
1527
+ if ( is_string($p_options_list[$i+1])
1528
+ && ($p_options_list[$i+1] != '')) {
1529
+ $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE);
1530
+ $i++;
1531
+ }
1532
+ else {
1533
+ }
1534
+ break;
1535
+
1536
+ // ----- Look for options that request an array of string for value
1537
+ case PCLZIP_OPT_BY_NAME :
1538
+ // ----- Check the number of parameters
1539
+ if (($i+1) >= $p_size) {
1540
+ // ----- Error log
1541
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1542
+
1543
+ // ----- Return
1544
+ return PclZip::errorCode();
1545
+ }
1546
+
1547
+ // ----- Get the value
1548
+ if (is_string($p_options_list[$i+1])) {
1549
+ $v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1];
1550
+ }
1551
+ else if (is_array($p_options_list[$i+1])) {
1552
+ $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1553
+ }
1554
+ else {
1555
+ // ----- Error log
1556
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1557
+
1558
+ // ----- Return
1559
+ return PclZip::errorCode();
1560
+ }
1561
+ $i++;
1562
+ break;
1563
+
1564
+ // ----- Look for options that request an EREG or PREG expression
1565
+ case PCLZIP_OPT_BY_EREG :
1566
+ // ereg() is deprecated starting with PHP 5.3. Move PCLZIP_OPT_BY_EREG
1567
+ // to PCLZIP_OPT_BY_PREG
1568
+ $p_options_list[$i] = PCLZIP_OPT_BY_PREG;
1569
+ case PCLZIP_OPT_BY_PREG :
1570
+ //case PCLZIP_OPT_CRYPT :
1571
+ // ----- Check the number of parameters
1572
+ if (($i+1) >= $p_size) {
1573
+ // ----- Error log
1574
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1575
+
1576
+ // ----- Return
1577
+ return PclZip::errorCode();
1578
+ }
1579
+
1580
+ // ----- Get the value
1581
+ if (is_string($p_options_list[$i+1])) {
1582
+ $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1583
+ }
1584
+ else {
1585
+ // ----- Error log
1586
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1587
+
1588
+ // ----- Return
1589
+ return PclZip::errorCode();
1590
+ }
1591
+ $i++;
1592
+ break;
1593
+
1594
+ // ----- Look for options that takes a string
1595
+ case PCLZIP_OPT_COMMENT :
1596
+ case PCLZIP_OPT_ADD_COMMENT :
1597
+ case PCLZIP_OPT_PREPEND_COMMENT :
1598
+ // ----- Check the number of parameters
1599
+ if (($i+1) >= $p_size) {
1600
+ // ----- Error log
1601
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
1602
+ "Missing parameter value for option '"
1603
+ .PclZipUtilOptionText($p_options_list[$i])
1604
+ ."'");
1605
+
1606
+ // ----- Return
1607
+ return PclZip::errorCode();
1608
+ }
1609
+
1610
+ // ----- Get the value
1611
+ if (is_string($p_options_list[$i+1])) {
1612
+ $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1613
+ }
1614
+ else {
1615
+ // ----- Error log
1616
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
1617
+ "Wrong parameter value for option '"
1618
+ .PclZipUtilOptionText($p_options_list[$i])
1619
+ ."'");
1620
+
1621
+ // ----- Return
1622
+ return PclZip::errorCode();
1623
+ }
1624
+ $i++;
1625
+ break;
1626
+
1627
+ // ----- Look for options that request an array of index
1628
+ case PCLZIP_OPT_BY_INDEX :
1629
+ // ----- Check the number of parameters
1630
+ if (($i+1) >= $p_size) {
1631
+ // ----- Error log
1632
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1633
+
1634
+ // ----- Return
1635
+ return PclZip::errorCode();
1636
+ }
1637
+
1638
+ // ----- Get the value
1639
+ $v_work_list = array();
1640
+ if (is_string($p_options_list[$i+1])) {
1641
+
1642
+ // ----- Remove spaces
1643
+ $p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', '');
1644
+
1645
+ // ----- Parse items
1646
+ $v_work_list = explode(",", $p_options_list[$i+1]);
1647
+ }
1648
+ else if (is_integer($p_options_list[$i+1])) {
1649
+ $v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1];
1650
+ }
1651
+ else if (is_array($p_options_list[$i+1])) {
1652
+ $v_work_list = $p_options_list[$i+1];
1653
+ }
1654
+ else {
1655
+ // ----- Error log
1656
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1657
+
1658
+ // ----- Return
1659
+ return PclZip::errorCode();
1660
+ }
1661
+
1662
+ // ----- Reduce the index list
1663
+ // each index item in the list must be a couple with a start and
1664
+ // an end value : [0,3], [5-5], [8-10], ...
1665
+ // ----- Check the format of each item
1666
+ $v_sort_flag=false;
1667
+ $v_sort_value=0;
1668
+ for ($j=0; $j<sizeof($v_work_list); $j++) {
1669
+ // ----- Explode the item
1670
+ $v_item_list = explode("-", $v_work_list[$j]);
1671
+ $v_size_item_list = sizeof($v_item_list);
1672
+
1673
+ // ----- TBC : Here we might check that each item is a
1674
+ // real integer ...
1675
+
1676
+ // ----- Look for single value
1677
+ if ($v_size_item_list == 1) {
1678
+ // ----- Set the option value
1679
+ $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1680
+ $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[0];
1681
+ }
1682
+ elseif ($v_size_item_list == 2) {
1683
+ // ----- Set the option value
1684
+ $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
1685
+ $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[1];
1686
+ }
1687
+ else {
1688
+ // ----- Error log
1689
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Too many values in index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1690
+
1691
+ // ----- Return
1692
+ return PclZip::errorCode();
1693
+ }
1694
+
1695
+
1696
+ // ----- Look for list sort
1697
+ if ($v_result_list[$p_options_list[$i]][$j]['start'] < $v_sort_value) {
1698
+ $v_sort_flag=true;
1699
+
1700
+ // ----- TBC : An automatic sort should be writen ...
1701
+ // ----- Error log
1702
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Invalid order of index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1703
+
1704
+ // ----- Return
1705
+ return PclZip::errorCode();
1706
+ }
1707
+ $v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start'];
1708
+ }
1709
+
1710
+ // ----- Sort the items
1711
+ if ($v_sort_flag) {
1712
+ // TBC : To Be Completed
1713
+ }
1714
+
1715
+ // ----- Next option
1716
+ $i++;
1717
+ break;
1718
+
1719
+ // ----- Look for options that request no value
1720
+ case PCLZIP_OPT_REMOVE_ALL_PATH :
1721
+ case PCLZIP_OPT_EXTRACT_AS_STRING :
1722
+ case PCLZIP_OPT_NO_COMPRESSION :
1723
+ case PCLZIP_OPT_EXTRACT_IN_OUTPUT :
1724
+ case PCLZIP_OPT_REPLACE_NEWER :
1725
+ case PCLZIP_OPT_STOP_ON_ERROR :
1726
+ $v_result_list[$p_options_list[$i]] = true;
1727
+ break;
1728
+
1729
+ // ----- Look for options that request an octal value
1730
+ case PCLZIP_OPT_SET_CHMOD :
1731
+ // ----- Check the number of parameters
1732
+ if (($i+1) >= $p_size) {
1733
+ // ----- Error log
1734
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1735
+
1736
+ // ----- Return
1737
+ return PclZip::errorCode();
1738
+ }
1739
+
1740
+ // ----- Get the value
1741
+ $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
1742
+ $i++;
1743
+ break;
1744
+
1745
+ // ----- Look for options that request a call-back
1746
+ case PCLZIP_CB_PRE_EXTRACT :
1747
+ case PCLZIP_CB_POST_EXTRACT :
1748
+ case PCLZIP_CB_PRE_ADD :
1749
+ case PCLZIP_CB_POST_ADD :
1750
+ /* for futur use
1751
+ case PCLZIP_CB_PRE_DELETE :
1752
+ case PCLZIP_CB_POST_DELETE :
1753
+ case PCLZIP_CB_PRE_LIST :
1754
+ case PCLZIP_CB_POST_LIST :
1755
+ */
1756
+ // ----- Check the number of parameters
1757
+ if (($i+1) >= $p_size) {
1758
+ // ----- Error log
1759
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1760
+
1761
+ // ----- Return
1762
+ return PclZip::errorCode();
1763
+ }
1764
+
1765
+ // ----- Get the value
1766
+ $v_function_name = $p_options_list[$i+1];
1767
+
1768
+ // ----- Check that the value is a valid existing function
1769
+ if (!function_exists($v_function_name)) {
1770
+ // ----- Error log
1771
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText($p_options_list[$i])."'");
1772
+
1773
+ // ----- Return
1774
+ return PclZip::errorCode();
1775
+ }
1776
+
1777
+ // ----- Set the attribute
1778
+ $v_result_list[$p_options_list[$i]] = $v_function_name;
1779
+ $i++;
1780
+ break;
1781
+
1782
+ default :
1783
+ // ----- Error log
1784
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
1785
+ "Unknown parameter '"
1786
+ .$p_options_list[$i]."'");
1787
+
1788
+ // ----- Return
1789
+ return PclZip::errorCode();
1790
+ }
1791
+
1792
+ // ----- Next options
1793
+ $i++;
1794
+ }
1795
+
1796
+ // ----- Look for mandatory options
1797
+ if ($v_requested_options !== false) {
1798
+ for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
1799
+ // ----- Look for mandatory option
1800
+ if ($v_requested_options[$key] == 'mandatory') {
1801
+ // ----- Look if present
1802
+ if (!isset($v_result_list[$key])) {
1803
+ // ----- Error log
1804
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
1805
+
1806
+ // ----- Return
1807
+ return PclZip::errorCode();
1808
+ }
1809
+ }
1810
+ }
1811
+ }
1812
+
1813
+ // ----- Look for default values
1814
+ if (!isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
1815
+
1816
+ }
1817
+
1818
+ // ----- Return
1819
+ return $v_result;
1820
+ }
1821
+ // --------------------------------------------------------------------------------
1822
+
1823
+ // --------------------------------------------------------------------------------
1824
+ // Function : privOptionDefaultThreshold()
1825
+ // Description :
1826
+ // Parameters :
1827
+ // Return Values :
1828
+ // --------------------------------------------------------------------------------
1829
+ function privOptionDefaultThreshold(&$p_options)
1830
+ {
1831
+ $v_result=1;
1832
+
1833
+ if (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
1834
+ || isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) {
1835
+ return $v_result;
1836
+ }
1837
+
1838
+ // ----- Get 'memory_limit' configuration value
1839
+ $v_memory_limit = ini_get('memory_limit');
1840
+ $v_memory_limit = trim($v_memory_limit);
1841
+ $last = strtolower(substr($v_memory_limit, -1));
1842
+
1843
+ if($last == 'g')
1844
+ //$v_memory_limit = $v_memory_limit*1024*1024*1024;
1845
+ $v_memory_limit = $v_memory_limit*1073741824;
1846
+ if($last == 'm')
1847
+ //$v_memory_limit = $v_memory_limit*1024*1024;
1848
+ $v_memory_limit = $v_memory_limit*1048576;
1849
+ if($last == 'k')
1850
+ $v_memory_limit = $v_memory_limit*1024;
1851
+
1852
+ $p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit*PCLZIP_TEMPORARY_FILE_RATIO);
1853
+
1854
+
1855
+ // ----- Sanity check : No threshold if value lower than 1M
1856
+ if ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] < 1048576) {
1857
+ unset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]);
1858
+ }
1859
+
1860
+ // ----- Return
1861
+ return $v_result;
1862
+ }
1863
+ // --------------------------------------------------------------------------------
1864
+
1865
+ // --------------------------------------------------------------------------------
1866
+ // Function : privFileDescrParseAtt()
1867
+ // Description :
1868
+ // Parameters :
1869
+ // Return Values :
1870
+ // 1 on success.
1871
+ // 0 on failure.
1872
+ // --------------------------------------------------------------------------------
1873
+ function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options=false)
1874
+ {
1875
+ $v_result=1;
1876
+
1877
+ // ----- For each file in the list check the attributes
1878
+ foreach ($p_file_list as $v_key => $v_value) {
1879
+
1880
+ // ----- Check if the option is supported
1881
+ if (!isset($v_requested_options[$v_key])) {
1882
+ // ----- Error log
1883
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '".$v_key."' for this file");
1884
+
1885
+ // ----- Return
1886
+ return PclZip::errorCode();
1887
+ }
1888
+
1889
+ // ----- Look for attribute
1890
+ switch ($v_key) {
1891
+ case PCLZIP_ATT_FILE_NAME :
1892
+ if (!is_string($v_value)) {
1893
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1894
+ return PclZip::errorCode();
1895
+ }
1896
+
1897
+ $p_filedescr['filename'] = PclZipUtilPathReduction($v_value);
1898
+
1899
+ if ($p_filedescr['filename'] == '') {
1900
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '".PclZipUtilOptionText($v_key)."'");
1901
+ return PclZip::errorCode();
1902
+ }
1903
+
1904
+ break;
1905
+
1906
+ case PCLZIP_ATT_FILE_NEW_SHORT_NAME :
1907
+ if (!is_string($v_value)) {
1908
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1909
+ return PclZip::errorCode();
1910
+ }
1911
+
1912
+ $p_filedescr['new_short_name'] = PclZipUtilPathReduction($v_value);
1913
+
1914
+ if ($p_filedescr['new_short_name'] == '') {
1915
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty short filename for attribute '".PclZipUtilOptionText($v_key)."'");
1916
+ return PclZip::errorCode();
1917
+ }
1918
+ break;
1919
+
1920
+ case PCLZIP_ATT_FILE_NEW_FULL_NAME :
1921
+ if (!is_string($v_value)) {
1922
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1923
+ return PclZip::errorCode();
1924
+ }
1925
+
1926
+ $p_filedescr['new_full_name'] = PclZipUtilPathReduction($v_value);
1927
+
1928
+ if ($p_filedescr['new_full_name'] == '') {
1929
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty full filename for attribute '".PclZipUtilOptionText($v_key)."'");
1930
+ return PclZip::errorCode();
1931
+ }
1932
+ break;
1933
+
1934
+ // ----- Look for options that takes a string
1935
+ case PCLZIP_ATT_FILE_COMMENT :
1936
+ if (!is_string($v_value)) {
1937
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
1938
+ return PclZip::errorCode();
1939
+ }
1940
+
1941
+ $p_filedescr['comment'] = $v_value;
1942
+ break;
1943
+
1944
+ case PCLZIP_ATT_FILE_MTIME :
1945
+ if (!is_integer($v_value)) {
1946
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". Integer expected for attribute '".PclZipUtilOptionText($v_key)."'");
1947
+ return PclZip::errorCode();
1948
+ }
1949
+
1950
+ $p_filedescr['mtime'] = $v_value;
1951
+ break;
1952
+
1953
+ case PCLZIP_ATT_FILE_CONTENT :
1954
+ $p_filedescr['content'] = $v_value;
1955
+ break;
1956
+
1957
+ default :
1958
+ // ----- Error log
1959
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
1960
+ "Unknown parameter '".$v_key."'");
1961
+
1962
+ // ----- Return
1963
+ return PclZip::errorCode();
1964
+ }
1965
+
1966
+ // ----- Look for mandatory options
1967
+ if ($v_requested_options !== false) {
1968
+ for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
1969
+ // ----- Look for mandatory option
1970
+ if ($v_requested_options[$key] == 'mandatory') {
1971
+ // ----- Look if present
1972
+ if (!isset($p_file_list[$key])) {
1973
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
1974
+ return PclZip::errorCode();
1975
+ }
1976
+ }
1977
+ }
1978
+ }
1979
+
1980
+ // end foreach
1981
+ }
1982
+
1983
+ // ----- Return
1984
+ return $v_result;
1985
+ }
1986
+ // --------------------------------------------------------------------------------
1987
+
1988
+ // --------------------------------------------------------------------------------
1989
+ // Function : privFileDescrExpand()
1990
+ // Description :
1991
+ // This method look for each item of the list to see if its a file, a folder
1992
+ // or a string to be added as file. For any other type of files (link, other)
1993
+ // just ignore the item.
1994
+ // Then prepare the information that will be stored for that file.
1995
+ // When its a folder, expand the folder with all the files that are in that
1996
+ // folder (recursively).
1997
+ // Parameters :
1998
+ // Return Values :
1999
+ // 1 on success.
2000
+ // 0 on failure.
2001
+ // --------------------------------------------------------------------------------
2002
+ function privFileDescrExpand(&$p_filedescr_list, &$p_options)
2003
+ {
2004
+ $v_result=1;
2005
+
2006
+ // ----- Create a result list
2007
+ $v_result_list = array();
2008
+
2009
+ // ----- Look each entry
2010
+ for ($i=0; $i<sizeof($p_filedescr_list); $i++) {
2011
+
2012
+ // ----- Get filedescr
2013
+ $v_descr = $p_filedescr_list[$i];
2014
+
2015
+ // ----- Reduce the filename
2016
+ $v_descr['filename'] = PclZipUtilTranslateWinPath($v_descr['filename'], false);
2017
+ $v_descr['filename'] = PclZipUtilPathReduction($v_descr['filename']);
2018
+
2019
+ // ----- Look for real file or folder
2020
+ if (file_exists($v_descr['filename'])) {
2021
+ if (@is_file($v_descr['filename'])) {
2022
+ $v_descr['type'] = 'file';
2023
+ }
2024
+ else if (@is_dir($v_descr['filename'])) {
2025
+ $v_descr['type'] = 'folder';
2026
+ }
2027
+ else if (@is_link($v_descr['filename'])) {
2028
+ // skip
2029
+ continue;
2030
+ }
2031
+ else {
2032
+ // skip
2033
+ continue;
2034
+ }
2035
+ }
2036
+
2037
+ // ----- Look for string added as file
2038
+ else if (isset($v_descr['content'])) {
2039
+ $v_descr['type'] = 'virtual_file';
2040
+ }
2041
+
2042
+ // ----- Missing file
2043
+ else {
2044
+ // ----- Error log
2045
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$v_descr['filename']."' does not exist");
2046
+
2047
+ // ----- Return
2048
+ return PclZip::errorCode();
2049
+ }
2050
+
2051
+ // ----- Calculate the stored filename
2052
+ $this->privCalculateStoredFilename($v_descr, $p_options);
2053
+
2054
+ // ----- Add the descriptor in result list
2055
+ $v_result_list[sizeof($v_result_list)] = $v_descr;
2056
+
2057
+ // ----- Look for folder
2058
+ if ($v_descr['type'] == 'folder') {
2059
+ // ----- List of items in folder
2060
+ $v_dirlist_descr = array();
2061
+ $v_dirlist_nb = 0;
2062
+ if ($v_folder_handler = @opendir($v_descr['filename'])) {
2063
+ while (($v_item_handler = @readdir($v_folder_handler)) !== false) {
2064
+
2065
+ // ----- Skip '.' and '..'
2066
+ if (($v_item_handler == '.') || ($v_item_handler == '..')) {
2067
+ continue;
2068
+ }
2069
+
2070
+ // ----- Compose the full filename
2071
+ $v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler;
2072
+
2073
+ // ----- Look for different stored filename
2074
+ // Because the name of the folder was changed, the name of the
2075
+ // files/sub-folders also change
2076
+ if (($v_descr['stored_filename'] != $v_descr['filename'])
2077
+ && (!isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))) {
2078
+ if ($v_descr['stored_filename'] != '') {
2079
+ $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler;
2080
+ }
2081
+ else {
2082
+ $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler;
2083
+ }
2084
+ }
2085
+
2086
+ $v_dirlist_nb++;
2087
+ }
2088
+
2089
+ @closedir($v_folder_handler);
2090
+ }
2091
+ else {
2092
+ // TBC : unable to open folder in read mode
2093
+ }
2094
+
2095
+ // ----- Expand each element of the list
2096
+ if ($v_dirlist_nb != 0) {
2097
+ // ----- Expand
2098
+ if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) {
2099
+ return $v_result;
2100
+ }
2101
+
2102
+ // ----- Concat the resulting list
2103
+ $v_result_list = array_merge($v_result_list, $v_dirlist_descr);
2104
+ }
2105
+ else {
2106
+ }
2107
+
2108
+ // ----- Free local array
2109
+ unset($v_dirlist_descr);
2110
+ }
2111
+ }
2112
+
2113
+ // ----- Get the result list
2114
+ $p_filedescr_list = $v_result_list;
2115
+
2116
+ // ----- Return
2117
+ return $v_result;
2118
+ }
2119
+ // --------------------------------------------------------------------------------
2120
+
2121
+ // --------------------------------------------------------------------------------
2122
+ // Function : privCreate()
2123
+ // Description :
2124
+ // Parameters :
2125
+ // Return Values :
2126
+ // --------------------------------------------------------------------------------
2127
+ function privCreate($p_filedescr_list, &$p_result_list, &$p_options)
2128
+ {
2129
+ $v_result=1;
2130
+ $v_list_detail = array();
2131
+
2132
+ // ----- Magic quotes trick
2133
+ $this->privDisableMagicQuotes();
2134
+
2135
+ // ----- Open the file in write mode
2136
+ if (($v_result = $this->privOpenFd('wb')) != 1)
2137
+ {
2138
+ // ----- Return
2139
+ return $v_result;
2140
+ }
2141
+
2142
+ // ----- Add the list of files
2143
+ $v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options);
2144
+
2145
+ // ----- Close
2146
+ $this->privCloseFd();
2147
+
2148
+ // ----- Magic quotes trick
2149
+ $this->privSwapBackMagicQuotes();
2150
+
2151
+ // ----- Return
2152
+ return $v_result;
2153
+ }
2154
+ // --------------------------------------------------------------------------------
2155
+
2156
+ // --------------------------------------------------------------------------------
2157
+ // Function : privAdd()
2158
+ // Description :
2159
+ // Parameters :
2160
+ // Return Values :
2161
+ // --------------------------------------------------------------------------------
2162
+ function privAdd($p_filedescr_list, &$p_result_list, &$p_options)
2163
+ {
2164
+ $v_result=1;
2165
+ $v_list_detail = array();
2166
+
2167
+ // ----- Look if the archive exists or is empty
2168
+ if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0))
2169
+ {
2170
+
2171
+ // ----- Do a create
2172
+ $v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options);
2173
+
2174
+ // ----- Return
2175
+ return $v_result;
2176
+ }
2177
+ // ----- Magic quotes trick
2178
+ $this->privDisableMagicQuotes();
2179
+
2180
+ // ----- Open the zip file
2181
+ if (($v_result=$this->privOpenFd('rb')) != 1)
2182
+ {
2183
+ // ----- Magic quotes trick
2184
+ $this->privSwapBackMagicQuotes();
2185
+
2186
+ // ----- Return
2187
+ return $v_result;
2188
+ }
2189
+
2190
+ // ----- Read the central directory informations
2191
+ $v_central_dir = array();
2192
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
2193
+ {
2194
+ $this->privCloseFd();
2195
+ $this->privSwapBackMagicQuotes();
2196
+ return $v_result;
2197
+ }
2198
+
2199
+ // ----- Go to beginning of File
2200
+ @rewind($this->zip_fd);
2201
+
2202
+ // ----- Creates a temporay file
2203
+ $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
2204
+
2205
+ // ----- Open the temporary file in write mode
2206
+ if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
2207
+ {
2208
+ $this->privCloseFd();
2209
+ $this->privSwapBackMagicQuotes();
2210
+
2211
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
2212
+
2213
+ // ----- Return
2214
+ return PclZip::errorCode();
2215
+ }
2216
+
2217
+ // ----- Copy the files from the archive to the temporary file
2218
+ // TBC : Here I should better append the file and go back to erase the central dir
2219
+ $v_size = $v_central_dir['offset'];
2220
+ while ($v_size != 0)
2221
+ {
2222
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2223
+ $v_buffer = fread($this->zip_fd, $v_read_size);
2224
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
2225
+ $v_size -= $v_read_size;
2226
+ }
2227
+
2228
+ // ----- Swap the file descriptor
2229
+ // Here is a trick : I swap the temporary fd with the zip fd, in order to use
2230
+ // the following methods on the temporary fil and not the real archive
2231
+ $v_swap = $this->zip_fd;
2232
+ $this->zip_fd = $v_zip_temp_fd;
2233
+ $v_zip_temp_fd = $v_swap;
2234
+
2235
+ // ----- Add the files
2236
+ $v_header_list = array();
2237
+ if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
2238
+ {
2239
+ fclose($v_zip_temp_fd);
2240
+ $this->privCloseFd();
2241
+ @unlink($v_zip_temp_name);
2242
+ $this->privSwapBackMagicQuotes();
2243
+
2244
+ // ----- Return
2245
+ return $v_result;
2246
+ }
2247
+
2248
+ // ----- Store the offset of the central dir
2249
+ $v_offset = @ftell($this->zip_fd);
2250
+
2251
+ // ----- Copy the block of file headers from the old archive
2252
+ $v_size = $v_central_dir['size'];
2253
+ while ($v_size != 0)
2254
+ {
2255
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2256
+ $v_buffer = @fread($v_zip_temp_fd, $v_read_size);
2257
+ @fwrite($this->zip_fd, $v_buffer, $v_read_size);
2258
+ $v_size -= $v_read_size;
2259
+ }
2260
+
2261
+ // ----- Create the Central Dir files header
2262
+ for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++)
2263
+ {
2264
+ // ----- Create the file header
2265
+ if ($v_header_list[$i]['status'] == 'ok') {
2266
+ if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
2267
+ fclose($v_zip_temp_fd);
2268
+ $this->privCloseFd();
2269
+ @unlink($v_zip_temp_name);
2270
+ $this->privSwapBackMagicQuotes();
2271
+
2272
+ // ----- Return
2273
+ return $v_result;
2274
+ }
2275
+ $v_count++;
2276
+ }
2277
+
2278
+ // ----- Transform the header to a 'usable' info
2279
+ $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
2280
+ }
2281
+
2282
+ // ----- Zip file comment
2283
+ $v_comment = $v_central_dir['comment'];
2284
+ if (isset($p_options[PCLZIP_OPT_COMMENT])) {
2285
+ $v_comment = $p_options[PCLZIP_OPT_COMMENT];
2286
+ }
2287
+ if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) {
2288
+ $v_comment = $v_comment.$p_options[PCLZIP_OPT_ADD_COMMENT];
2289
+ }
2290
+ if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) {
2291
+ $v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT].$v_comment;
2292
+ }
2293
+
2294
+ // ----- Calculate the size of the central header
2295
+ $v_size = @ftell($this->zip_fd)-$v_offset;
2296
+
2297
+ // ----- Create the central dir footer
2298
+ if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1)
2299
+ {
2300
+ // ----- Reset the file list
2301
+ unset($v_header_list);
2302
+ $this->privSwapBackMagicQuotes();
2303
+
2304
+ // ----- Return
2305
+ return $v_result;
2306
+ }
2307
+
2308
+ // ----- Swap back the file descriptor
2309
+ $v_swap = $this->zip_fd;
2310
+ $this->zip_fd = $v_zip_temp_fd;
2311
+ $v_zip_temp_fd = $v_swap;
2312
+
2313
+ // ----- Close
2314
+ $this->privCloseFd();
2315
+
2316
+ // ----- Close the temporary file
2317
+ @fclose($v_zip_temp_fd);
2318
+
2319
+ // ----- Magic quotes trick
2320
+ $this->privSwapBackMagicQuotes();
2321
+
2322
+ // ----- Delete the zip file
2323
+ // TBC : I should test the result ...
2324
+ @unlink($this->zipname);
2325
+
2326
+ // ----- Rename the temporary file
2327
+ // TBC : I should test the result ...
2328
+ //@rename($v_zip_temp_name, $this->zipname);
2329
+ PclZipUtilRename($v_zip_temp_name, $this->zipname);
2330
+
2331
+ // ----- Return
2332
+ return $v_result;
2333
+ }
2334
+ // --------------------------------------------------------------------------------
2335
+
2336
+ // --------------------------------------------------------------------------------
2337
+ // Function : privOpenFd()
2338
+ // Description :
2339
+ // Parameters :
2340
+ // --------------------------------------------------------------------------------
2341
+ function privOpenFd($p_mode)
2342
+ {
2343
+ $v_result=1;
2344
+
2345
+ // ----- Look if already open
2346
+ if ($this->zip_fd != 0)
2347
+ {
2348
+ // ----- Error log
2349
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open');
2350
+
2351
+ // ----- Return
2352
+ return PclZip::errorCode();
2353
+ }
2354
+
2355
+ // ----- Open the zip file
2356
+ if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0)
2357
+ {
2358
+ // ----- Error log
2359
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode');
2360
+
2361
+ // ----- Return
2362
+ return PclZip::errorCode();
2363
+ }
2364
+
2365
+ // ----- Return
2366
+ return $v_result;
2367
+ }
2368
+ // --------------------------------------------------------------------------------
2369
+
2370
+ // --------------------------------------------------------------------------------
2371
+ // Function : privCloseFd()
2372
+ // Description :
2373
+ // Parameters :
2374
+ // --------------------------------------------------------------------------------
2375
+ function privCloseFd()
2376
+ {
2377
+ $v_result=1;
2378
+
2379
+ if ($this->zip_fd != 0)
2380
+ @fclose($this->zip_fd);
2381
+ $this->zip_fd = 0;
2382
+
2383
+ // ----- Return
2384
+ return $v_result;
2385
+ }
2386
+ // --------------------------------------------------------------------------------
2387
+
2388
+ // --------------------------------------------------------------------------------
2389
+ // Function : privAddList()
2390
+ // Description :
2391
+ // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
2392
+ // different from the real path of the file. This is usefull if you want to have PclTar
2393
+ // running in any directory, and memorize relative path from an other directory.
2394
+ // Parameters :
2395
+ // $p_list : An array containing the file or directory names to add in the tar
2396
+ // $p_result_list : list of added files with their properties (specially the status field)
2397
+ // $p_add_dir : Path to add in the filename path archived
2398
+ // $p_remove_dir : Path to remove in the filename path archived
2399
+ // Return Values :
2400
+ // --------------------------------------------------------------------------------
2401
+ // function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
2402
+ function privAddList($p_filedescr_list, &$p_result_list, &$p_options)
2403
+ {
2404
+ $v_result=1;
2405
+
2406
+ // ----- Add the files
2407
+ $v_header_list = array();
2408
+ if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
2409
+ {
2410
+ // ----- Return
2411
+ return $v_result;
2412
+ }
2413
+
2414
+ // ----- Store the offset of the central dir
2415
+ $v_offset = @ftell($this->zip_fd);
2416
+
2417
+ // ----- Create the Central Dir files header
2418
+ for ($i=0,$v_count=0; $i<sizeof($v_header_list); $i++)
2419
+ {
2420
+ // ----- Create the file header
2421
+ if ($v_header_list[$i]['status'] == 'ok') {
2422
+ if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
2423
+ // ----- Return
2424
+ return $v_result;
2425
+ }
2426
+ $v_count++;
2427
+ }
2428
+
2429
+ // ----- Transform the header to a 'usable' info
2430
+ $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
2431
+ }
2432
+
2433
+ // ----- Zip file comment
2434
+ $v_comment = '';
2435
+ if (isset($p_options[PCLZIP_OPT_COMMENT])) {
2436
+ $v_comment = $p_options[PCLZIP_OPT_COMMENT];
2437
+ }
2438
+
2439
+ // ----- Calculate the size of the central header
2440
+ $v_size = @ftell($this->zip_fd)-$v_offset;
2441
+
2442
+ // ----- Create the central dir footer
2443
+ if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1)
2444
+ {
2445
+ // ----- Reset the file list
2446
+ unset($v_header_list);
2447
+
2448
+ // ----- Return
2449
+ return $v_result;
2450
+ }
2451
+
2452
+ // ----- Return
2453
+ return $v_result;
2454
+ }
2455
+ // --------------------------------------------------------------------------------
2456
+
2457
+ // --------------------------------------------------------------------------------
2458
+ // Function : privAddFileList()
2459
+ // Description :
2460
+ // Parameters :
2461
+ // $p_filedescr_list : An array containing the file description
2462
+ // or directory names to add in the zip
2463
+ // $p_result_list : list of added files with their properties (specially the status field)
2464
+ // Return Values :
2465
+ // --------------------------------------------------------------------------------
2466
+ function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options)
2467
+ {
2468
+ $v_result=1;
2469
+ $v_header = array();
2470
+
2471
+ // ----- Recuperate the current number of elt in list
2472
+ $v_nb = sizeof($p_result_list);
2473
+
2474
+ // ----- Loop on the files
2475
+ for ($j=0; ($j<sizeof($p_filedescr_list)) && ($v_result==1); $j++) {
2476
+ // ----- Format the filename
2477
+ $p_filedescr_list[$j]['filename']
2478
+ = PclZipUtilTranslateWinPath($p_filedescr_list[$j]['filename'], false);
2479
+
2480
+
2481
+ // ----- Skip empty file names
2482
+ // TBC : Can this be possible ? not checked in DescrParseAtt ?
2483
+ if ($p_filedescr_list[$j]['filename'] == "") {
2484
+ continue;
2485
+ }
2486
+
2487
+ // ----- Check the filename
2488
+ if ( ($p_filedescr_list[$j]['type'] != 'virtual_file')
2489
+ && (!file_exists($p_filedescr_list[$j]['filename']))) {
2490
+ PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$p_filedescr_list[$j]['filename']."' does not exist");
2491
+ return PclZip::errorCode();
2492
+ }
2493
+
2494
+ // ----- Look if it is a file or a dir with no all path remove option
2495
+ // or a dir with all its path removed
2496
+ // if ( (is_file($p_filedescr_list[$j]['filename']))
2497
+ // || ( is_dir($p_filedescr_list[$j]['filename'])
2498
+ if ( ($p_filedescr_list[$j]['type'] == 'file')
2499
+ || ($p_filedescr_list[$j]['type'] == 'virtual_file')
2500
+ || ( ($p_filedescr_list[$j]['type'] == 'folder')
2501
+ && ( !isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])
2502
+ || !$p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))
2503
+ ) {
2504
+
2505
+ // ----- Add the file
2506
+ $v_result = $this->privAddFile($p_filedescr_list[$j], $v_header,
2507
+ $p_options);
2508
+ if ($v_result != 1) {
2509
+ return $v_result;
2510
+ }
2511
+
2512
+ // ----- Store the file infos
2513
+ $p_result_list[$v_nb++] = $v_header;
2514
+ }
2515
+ }
2516
+
2517
+ // ----- Return
2518
+ return $v_result;
2519
+ }
2520
+ // --------------------------------------------------------------------------------
2521
+
2522
+ // --------------------------------------------------------------------------------
2523
+ // Function : privAddFile()
2524
+ // Description :
2525
+ // Parameters :
2526
+ // Return Values :
2527
+ // --------------------------------------------------------------------------------
2528
+ function privAddFile($p_filedescr, &$p_header, &$p_options)
2529
+ {
2530
+ $v_result=1;
2531
+
2532
+ // ----- Working variable
2533
+ $p_filename = $p_filedescr['filename'];
2534
+
2535
+ // TBC : Already done in the fileAtt check ... ?
2536
+ if ($p_filename == "") {
2537
+ // ----- Error log
2538
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");
2539
+
2540
+ // ----- Return
2541
+ return PclZip::errorCode();
2542
+ }
2543
+
2544
+ // ----- Look for a stored different filename
2545
+ /* TBC : Removed
2546
+ if (isset($p_filedescr['stored_filename'])) {
2547
+ $v_stored_filename = $p_filedescr['stored_filename'];
2548
+ }
2549
+ else {
2550
+ $v_stored_filename = $p_filedescr['stored_filename'];
2551
+ }
2552
+ */
2553
+
2554
+ // ----- Set the file properties
2555
+ clearstatcache();
2556
+ $p_header['version'] = 20;
2557
+ $p_header['version_extracted'] = 10;
2558
+ $p_header['flag'] = 0;
2559
+ $p_header['compression'] = 0;
2560
+ $p_header['crc'] = 0;
2561
+ $p_header['compressed_size'] = 0;
2562
+ $p_header['filename_len'] = strlen($p_filename);
2563
+ $p_header['extra_len'] = 0;
2564
+ $p_header['disk'] = 0;
2565
+ $p_header['internal'] = 0;
2566
+ $p_header['offset'] = 0;
2567
+ $p_header['filename'] = $p_filename;
2568
+ // TBC : Removed $p_header['stored_filename'] = $v_stored_filename;
2569
+ $p_header['stored_filename'] = $p_filedescr['stored_filename'];
2570
+ $p_header['extra'] = '';
2571
+ $p_header['status'] = 'ok';
2572
+ $p_header['index'] = -1;
2573
+
2574
+ // ----- Look for regular file
2575
+ if ($p_filedescr['type']=='file') {
2576
+ $p_header['external'] = 0x00000000;
2577
+ $p_header['size'] = filesize($p_filename);
2578
+ }
2579
+
2580
+ // ----- Look for regular folder
2581
+ else if ($p_filedescr['type']=='folder') {
2582
+ $p_header['external'] = 0x00000010;
2583
+ $p_header['mtime'] = filemtime($p_filename);
2584
+ $p_header['size'] = filesize($p_filename);
2585
+ }
2586
+
2587
+ // ----- Look for virtual file
2588
+ else if ($p_filedescr['type'] == 'virtual_file') {
2589
+ $p_header['external'] = 0x00000000;
2590
+ $p_header['size'] = strlen($p_filedescr['content']);
2591
+ }
2592
+
2593
+
2594
+ // ----- Look for filetime
2595
+ if (isset($p_filedescr['mtime'])) {
2596
+ $p_header['mtime'] = $p_filedescr['mtime'];
2597
+ }
2598
+ else if ($p_filedescr['type'] == 'virtual_file') {
2599
+ $p_header['mtime'] = time();
2600
+ }
2601
+ else {
2602
+ $p_header['mtime'] = filemtime($p_filename);
2603
+ }
2604
+
2605
+ // ------ Look for file comment
2606
+ if (isset($p_filedescr['comment'])) {
2607
+ $p_header['comment_len'] = strlen($p_filedescr['comment']);
2608
+ $p_header['comment'] = $p_filedescr['comment'];
2609
+ }
2610
+ else {
2611
+ $p_header['comment_len'] = 0;
2612
+ $p_header['comment'] = '';
2613
+ }
2614
+
2615
+ // ----- Look for pre-add callback
2616
+ if (isset($p_options[PCLZIP_CB_PRE_ADD])) {
2617
+
2618
+ // ----- Generate a local information
2619
+ $v_local_header = array();
2620
+ $this->privConvertHeader2FileInfo($p_header, $v_local_header);
2621
+
2622
+ // ----- Call the callback
2623
+ // Here I do not use call_user_func() because I need to send a reference to the
2624
+ // header.
2625
+ // eval('$v_result = '.$p_options[PCLZIP_CB_PRE_ADD].'(PCLZIP_CB_PRE_ADD, $v_local_header);');
2626
+ $v_result = $p_options[PCLZIP_CB_PRE_ADD](PCLZIP_CB_PRE_ADD, $v_local_header);
2627
+ if ($v_result == 0) {
2628
+ // ----- Change the file status
2629
+ $p_header['status'] = "skipped";
2630
+ $v_result = 1;
2631
+ }
2632
+
2633
+ // ----- Update the informations
2634
+ // Only some fields can be modified
2635
+ if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
2636
+ $p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']);
2637
+ }
2638
+ }
2639
+
2640
+ // ----- Look for empty stored filename
2641
+ if ($p_header['stored_filename'] == "") {
2642
+ $p_header['status'] = "filtered";
2643
+ }
2644
+
2645
+ // ----- Check the path length
2646
+ if (strlen($p_header['stored_filename']) > 0xFF) {
2647
+ $p_header['status'] = 'filename_too_long';
2648
+ }
2649
+
2650
+ // ----- Look if no error, or file not skipped
2651
+ if ($p_header['status'] == 'ok') {
2652
+
2653
+ // ----- Look for a file
2654
+ if ($p_filedescr['type'] == 'file') {
2655
+ // ----- Look for using temporary file to zip
2656
+ if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
2657
+ && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON])
2658
+ || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
2659
+ && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_header['size'])) ) ) {
2660
+ $v_result = $this->privAddFileUsingTempFile($p_filedescr, $p_header, $p_options);
2661
+ if ($v_result < PCLZIP_ERR_NO_ERROR) {
2662
+ return $v_result;
2663
+ }
2664
+ }
2665
+
2666
+ // ----- Use "in memory" zip algo
2667
+ else {
2668
+
2669
+ // ----- Open the source file
2670
+ if (($v_file = @fopen($p_filename, "rb")) == 0) {
2671
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
2672
+ return PclZip::errorCode();
2673
+ }
2674
+
2675
+ // ----- Read the file content
2676
+ $v_content = @fread($v_file, $p_header['size']);
2677
+
2678
+ // ----- Close the file
2679
+ @fclose($v_file);
2680
+
2681
+ // ----- Calculate the CRC
2682
+ $p_header['crc'] = @crc32($v_content);
2683
+
2684
+ // ----- Look for no compression
2685
+ if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
2686
+ // ----- Set header parameters
2687
+ $p_header['compressed_size'] = $p_header['size'];
2688
+ $p_header['compression'] = 0;
2689
+ }
2690
+
2691
+ // ----- Look for normal compression
2692
+ else {
2693
+ // ----- Compress the content
2694
+ $v_content = @gzdeflate($v_content);
2695
+
2696
+ // ----- Set header parameters
2697
+ $p_header['compressed_size'] = strlen($v_content);
2698
+ $p_header['compression'] = 8;
2699
+ }
2700
+
2701
+ // ----- Call the header generation
2702
+ if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2703
+ @fclose($v_file);
2704
+ return $v_result;
2705
+ }
2706
+
2707
+ // ----- Write the compressed (or not) content
2708
+ @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
2709
+
2710
+ }
2711
+
2712
+ }
2713
+
2714
+ // ----- Look for a virtual file (a file from string)
2715
+ else if ($p_filedescr['type'] == 'virtual_file') {
2716
+
2717
+ $v_content = $p_filedescr['content'];
2718
+
2719
+ // ----- Calculate the CRC
2720
+ $p_header['crc'] = @crc32($v_content);
2721
+
2722
+ // ----- Look for no compression
2723
+ if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
2724
+ // ----- Set header parameters
2725
+ $p_header['compressed_size'] = $p_header['size'];
2726
+ $p_header['compression'] = 0;
2727
+ }
2728
+
2729
+ // ----- Look for normal compression
2730
+ else {
2731
+ // ----- Compress the content
2732
+ $v_content = @gzdeflate($v_content);
2733
+
2734
+ // ----- Set header parameters
2735
+ $p_header['compressed_size'] = strlen($v_content);
2736
+ $p_header['compression'] = 8;
2737
+ }
2738
+
2739
+ // ----- Call the header generation
2740
+ if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2741
+ @fclose($v_file);
2742
+ return $v_result;
2743
+ }
2744
+
2745
+ // ----- Write the compressed (or not) content
2746
+ @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
2747
+ }
2748
+
2749
+ // ----- Look for a directory
2750
+ else if ($p_filedescr['type'] == 'folder') {
2751
+ // ----- Look for directory last '/'
2752
+ if (@substr($p_header['stored_filename'], -1) != '/') {
2753
+ $p_header['stored_filename'] .= '/';
2754
+ }
2755
+
2756
+ // ----- Set the file properties
2757
+ $p_header['size'] = 0;
2758
+ //$p_header['external'] = 0x41FF0010; // Value for a folder : to be checked
2759
+ $p_header['external'] = 0x00000010; // Value for a folder : to be checked
2760
+
2761
+ // ----- Call the header generation
2762
+ if (($v_result = $this->privWriteFileHeader($p_header)) != 1)
2763
+ {
2764
+ return $v_result;
2765
+ }
2766
+ }
2767
+ }
2768
+
2769
+ // ----- Look for post-add callback
2770
+ if (isset($p_options[PCLZIP_CB_POST_ADD])) {
2771
+
2772
+ // ----- Generate a local information
2773
+ $v_local_header = array();
2774
+ $this->privConvertHeader2FileInfo($p_header, $v_local_header);
2775
+
2776
+ // ----- Call the callback
2777
+ // Here I do not use call_user_func() because I need to send a reference to the
2778
+ // header.
2779
+ // eval('$v_result = '.$p_options[PCLZIP_CB_POST_ADD].'(PCLZIP_CB_POST_ADD, $v_local_header);');
2780
+ $v_result = $p_options[PCLZIP_CB_POST_ADD](PCLZIP_CB_POST_ADD, $v_local_header);
2781
+ if ($v_result == 0) {
2782
+ // ----- Ignored
2783
+ $v_result = 1;
2784
+ }
2785
+
2786
+ // ----- Update the informations
2787
+ // Nothing can be modified
2788
+ }
2789
+
2790
+ // ----- Return
2791
+ return $v_result;
2792
+ }
2793
+ // --------------------------------------------------------------------------------
2794
+
2795
+ // --------------------------------------------------------------------------------
2796
+ // Function : privAddFileUsingTempFile()
2797
+ // Description :
2798
+ // Parameters :
2799
+ // Return Values :
2800
+ // --------------------------------------------------------------------------------
2801
+ function privAddFileUsingTempFile($p_filedescr, &$p_header, &$p_options)
2802
+ {
2803
+ $v_result=PCLZIP_ERR_NO_ERROR;
2804
+
2805
+ // ----- Working variable
2806
+ $p_filename = $p_filedescr['filename'];
2807
+
2808
+
2809
+ // ----- Open the source file
2810
+ if (($v_file = @fopen($p_filename, "rb")) == 0) {
2811
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
2812
+ return PclZip::errorCode();
2813
+ }
2814
+
2815
+ // ----- Creates a compressed temporary file
2816
+ $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz';
2817
+ if (($v_file_compressed = @gzopen($v_gzip_temp_name, "wb")) == 0) {
2818
+ fclose($v_file);
2819
+ PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
2820
+ return PclZip::errorCode();
2821
+ }
2822
+
2823
+ // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
2824
+ $v_size = filesize($p_filename);
2825
+ while ($v_size != 0) {
2826
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2827
+ $v_buffer = @fread($v_file, $v_read_size);
2828
+ //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
2829
+ @gzputs($v_file_compressed, $v_buffer, $v_read_size);
2830
+ $v_size -= $v_read_size;
2831
+ }
2832
+
2833
+ // ----- Close the file
2834
+ @fclose($v_file);
2835
+ @gzclose($v_file_compressed);
2836
+
2837
+ // ----- Check the minimum file size
2838
+ if (filesize($v_gzip_temp_name) < 18) {
2839
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'gzip temporary file \''.$v_gzip_temp_name.'\' has invalid filesize - should be minimum 18 bytes');
2840
+ return PclZip::errorCode();
2841
+ }
2842
+
2843
+ // ----- Extract the compressed attributes
2844
+ if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) {
2845
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
2846
+ return PclZip::errorCode();
2847
+ }
2848
+
2849
+ // ----- Read the gzip file header
2850
+ $v_binary_data = @fread($v_file_compressed, 10);
2851
+ $v_data_header = unpack('a1id1/a1id2/a1cm/a1flag/Vmtime/a1xfl/a1os', $v_binary_data);
2852
+
2853
+ // ----- Check some parameters
2854
+ $v_data_header['os'] = bin2hex($v_data_header['os']);
2855
+
2856
+ // ----- Read the gzip file footer
2857
+ @fseek($v_file_compressed, filesize($v_gzip_temp_name)-8);
2858
+ $v_binary_data = @fread($v_file_compressed, 8);
2859
+ $v_data_footer = unpack('Vcrc/Vcompressed_size', $v_binary_data);
2860
+
2861
+ // ----- Set the attributes
2862
+ $p_header['compression'] = ord($v_data_header['cm']);
2863
+ //$p_header['mtime'] = $v_data_header['mtime'];
2864
+ $p_header['crc'] = $v_data_footer['crc'];
2865
+ $p_header['compressed_size'] = filesize($v_gzip_temp_name)-18;
2866
+
2867
+ // ----- Close the file
2868
+ @fclose($v_file_compressed);
2869
+
2870
+ // ----- Call the header generation
2871
+ if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
2872
+ return $v_result;
2873
+ }
2874
+
2875
+ // ----- Add the compressed data
2876
+ if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0)
2877
+ {
2878
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
2879
+ return PclZip::errorCode();
2880
+ }
2881
+
2882
+ // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
2883
+ fseek($v_file_compressed, 10);
2884
+ $v_size = $p_header['compressed_size'];
2885
+ while ($v_size != 0)
2886
+ {
2887
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
2888
+ $v_buffer = @fread($v_file_compressed, $v_read_size);
2889
+ //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
2890
+ @fwrite($this->zip_fd, $v_buffer, $v_read_size);
2891
+ $v_size -= $v_read_size;
2892
+ }
2893
+
2894
+ // ----- Close the file
2895
+ @fclose($v_file_compressed);
2896
+
2897
+ // ----- Unlink the temporary file
2898
+ @unlink($v_gzip_temp_name);
2899
+
2900
+ // ----- Return
2901
+ return $v_result;
2902
+ }
2903
+ // --------------------------------------------------------------------------------
2904
+
2905
+ // --------------------------------------------------------------------------------
2906
+ // Function : privCalculateStoredFilename()
2907
+ // Description :
2908
+ // Based on file descriptor properties and global options, this method
2909
+ // calculate the filename that will be stored in the archive.
2910
+ // Parameters :
2911
+ // Return Values :
2912
+ // --------------------------------------------------------------------------------
2913
+ function privCalculateStoredFilename(&$p_filedescr, &$p_options)
2914
+ {
2915
+ $v_result=1;
2916
+
2917
+ // ----- Working variables
2918
+ $p_filename = $p_filedescr['filename'];
2919
+ if (isset($p_options[PCLZIP_OPT_ADD_PATH])) {
2920
+ $p_add_dir = $p_options[PCLZIP_OPT_ADD_PATH];
2921
+ }
2922
+ else {
2923
+ $p_add_dir = '';
2924
+ }
2925
+ if (isset($p_options[PCLZIP_OPT_REMOVE_PATH])) {
2926
+ $p_remove_dir = $p_options[PCLZIP_OPT_REMOVE_PATH];
2927
+ }
2928
+ else {
2929
+ $p_remove_dir = '';
2930
+ }
2931
+ if (isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
2932
+ $p_remove_all_dir = $p_options[PCLZIP_OPT_REMOVE_ALL_PATH];
2933
+ }
2934
+ else {
2935
+ $p_remove_all_dir = 0;
2936
+ }
2937
+
2938
+
2939
+ // ----- Look for full name change
2940
+ if (isset($p_filedescr['new_full_name'])) {
2941
+ // ----- Remove drive letter if any
2942
+ $v_stored_filename = PclZipUtilTranslateWinPath($p_filedescr['new_full_name']);
2943
+ }
2944
+
2945
+ // ----- Look for path and/or short name change
2946
+ else {
2947
+
2948
+ // ----- Look for short name change
2949
+ // Its when we cahnge just the filename but not the path
2950
+ if (isset($p_filedescr['new_short_name'])) {
2951
+ $v_path_info = pathinfo($p_filename);
2952
+ $v_dir = '';
2953
+ if ($v_path_info['dirname'] != '') {
2954
+ $v_dir = $v_path_info['dirname'].'/';
2955
+ }
2956
+ $v_stored_filename = $v_dir.$p_filedescr['new_short_name'];
2957
+ }
2958
+ else {
2959
+ // ----- Calculate the stored filename
2960
+ $v_stored_filename = $p_filename;
2961
+ }
2962
+
2963
+ // ----- Look for all path to remove
2964
+ if ($p_remove_all_dir) {
2965
+ $v_stored_filename = basename($p_filename);
2966
+ }
2967
+ // ----- Look for partial path remove
2968
+ else if ($p_remove_dir != "") {
2969
+ if (substr($p_remove_dir, -1) != '/')
2970
+ $p_remove_dir .= "/";
2971
+
2972
+ if ( (substr($p_filename, 0, 2) == "./")
2973
+ || (substr($p_remove_dir, 0, 2) == "./")) {
2974
+
2975
+ if ( (substr($p_filename, 0, 2) == "./")
2976
+ && (substr($p_remove_dir, 0, 2) != "./")) {
2977
+ $p_remove_dir = "./".$p_remove_dir;
2978
+ }
2979
+ if ( (substr($p_filename, 0, 2) != "./")
2980
+ && (substr($p_remove_dir, 0, 2) == "./")) {
2981
+ $p_remove_dir = substr($p_remove_dir, 2);
2982
+ }
2983
+ }
2984
+
2985
+ $v_compare = PclZipUtilPathInclusion($p_remove_dir,
2986
+ $v_stored_filename);
2987
+ if ($v_compare > 0) {
2988
+ if ($v_compare == 2) {
2989
+ $v_stored_filename = "";
2990
+ }
2991
+ else {
2992
+ $v_stored_filename = substr($v_stored_filename,
2993
+ strlen($p_remove_dir));
2994
+ }
2995
+ }
2996
+ }
2997
+
2998
+ // ----- Remove drive letter if any
2999
+ $v_stored_filename = PclZipUtilTranslateWinPath($v_stored_filename);
3000
+
3001
+ // ----- Look for path to add
3002
+ if ($p_add_dir != "") {
3003
+ if (substr($p_add_dir, -1) == "/")
3004
+ $v_stored_filename = $p_add_dir.$v_stored_filename;
3005
+ else
3006
+ $v_stored_filename = $p_add_dir."/".$v_stored_filename;
3007
+ }
3008
+ }
3009
+
3010
+ // ----- Filename (reduce the path of stored name)
3011
+ $v_stored_filename = PclZipUtilPathReduction($v_stored_filename);
3012
+ $p_filedescr['stored_filename'] = $v_stored_filename;
3013
+
3014
+ // ----- Return
3015
+ return $v_result;
3016
+ }
3017
+ // --------------------------------------------------------------------------------
3018
+
3019
+ // --------------------------------------------------------------------------------
3020
+ // Function : privWriteFileHeader()
3021
+ // Description :
3022
+ // Parameters :
3023
+ // Return Values :
3024
+ // --------------------------------------------------------------------------------
3025
+ function privWriteFileHeader(&$p_header)
3026
+ {
3027
+ $v_result=1;
3028
+
3029
+ // ----- Store the offset position of the file
3030
+ $p_header['offset'] = ftell($this->zip_fd);
3031
+
3032
+ // ----- Transform UNIX mtime to DOS format mdate/mtime
3033
+ $v_date = getdate($p_header['mtime']);
3034
+ $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
3035
+ $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
3036
+
3037
+ // ----- Packed data
3038
+ $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50,
3039
+ $p_header['version_extracted'], $p_header['flag'],
3040
+ $p_header['compression'], $v_mtime, $v_mdate,
3041
+ $p_header['crc'], $p_header['compressed_size'],
3042
+ $p_header['size'],
3043
+ strlen($p_header['stored_filename']),
3044
+ $p_header['extra_len']);
3045
+
3046
+ // ----- Write the first 148 bytes of the header in the archive
3047
+ fputs($this->zip_fd, $v_binary_data, 30);
3048
+
3049
+ // ----- Write the variable fields
3050
+ if (strlen($p_header['stored_filename']) != 0)
3051
+ {
3052
+ fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
3053
+ }
3054
+ if ($p_header['extra_len'] != 0)
3055
+ {
3056
+ fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
3057
+ }
3058
+
3059
+ // ----- Return
3060
+ return $v_result;
3061
+ }
3062
+ // --------------------------------------------------------------------------------
3063
+
3064
+ // --------------------------------------------------------------------------------
3065
+ // Function : privWriteCentralFileHeader()
3066
+ // Description :
3067
+ // Parameters :
3068
+ // Return Values :
3069
+ // --------------------------------------------------------------------------------
3070
+ function privWriteCentralFileHeader(&$p_header)
3071
+ {
3072
+ $v_result=1;
3073
+
3074
+ // TBC
3075
+ //for(reset($p_header); $key = key($p_header); next($p_header)) {
3076
+ //}
3077
+
3078
+ // ----- Transform UNIX mtime to DOS format mdate/mtime
3079
+ $v_date = getdate($p_header['mtime']);
3080
+ $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
3081
+ $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
3082
+
3083
+
3084
+ // ----- Packed data
3085
+ $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50,
3086
+ $p_header['version'], $p_header['version_extracted'],
3087
+ $p_header['flag'], $p_header['compression'],
3088
+ $v_mtime, $v_mdate, $p_header['crc'],
3089
+ $p_header['compressed_size'], $p_header['size'],
3090
+ strlen($p_header['stored_filename']),
3091
+ $p_header['extra_len'], $p_header['comment_len'],
3092
+ $p_header['disk'], $p_header['internal'],
3093
+ $p_header['external'], $p_header['offset']);
3094
+
3095
+ // ----- Write the 42 bytes of the header in the zip file
3096
+ fputs($this->zip_fd, $v_binary_data, 46);
3097
+
3098
+ // ----- Write the variable fields
3099
+ if (strlen($p_header['stored_filename']) != 0)
3100
+ {
3101
+ fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
3102
+ }
3103
+ if ($p_header['extra_len'] != 0)
3104
+ {
3105
+ fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
3106
+ }
3107
+ if ($p_header['comment_len'] != 0)
3108
+ {
3109
+ fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']);
3110
+ }
3111
+
3112
+ // ----- Return
3113
+ return $v_result;
3114
+ }
3115
+ // --------------------------------------------------------------------------------
3116
+
3117
+ // --------------------------------------------------------------------------------
3118
+ // Function : privWriteCentralHeader()
3119
+ // Description :
3120
+ // Parameters :
3121
+ // Return Values :
3122
+ // --------------------------------------------------------------------------------
3123
+ function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment)
3124
+ {
3125
+ $v_result=1;
3126
+
3127
+ // ----- Packed data
3128
+ $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries,
3129
+ $p_nb_entries, $p_size,
3130
+ $p_offset, strlen($p_comment));
3131
+
3132
+ // ----- Write the 22 bytes of the header in the zip file
3133
+ fputs($this->zip_fd, $v_binary_data, 22);
3134
+
3135
+ // ----- Write the variable fields
3136
+ if (strlen($p_comment) != 0)
3137
+ {
3138
+ fputs($this->zip_fd, $p_comment, strlen($p_comment));
3139
+ }
3140
+
3141
+ // ----- Return
3142
+ return $v_result;
3143
+ }
3144
+ // --------------------------------------------------------------------------------
3145
+
3146
+ // --------------------------------------------------------------------------------
3147
+ // Function : privList()
3148
+ // Description :
3149
+ // Parameters :
3150
+ // Return Values :
3151
+ // --------------------------------------------------------------------------------
3152
+ function privList(&$p_list)
3153
+ {
3154
+ $v_result=1;
3155
+
3156
+ // ----- Magic quotes trick
3157
+ $this->privDisableMagicQuotes();
3158
+
3159
+ // ----- Open the zip file
3160
+ if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
3161
+ {
3162
+ // ----- Magic quotes trick
3163
+ $this->privSwapBackMagicQuotes();
3164
+
3165
+ // ----- Error log
3166
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
3167
+
3168
+ // ----- Return
3169
+ return PclZip::errorCode();
3170
+ }
3171
+
3172
+ // ----- Read the central directory informations
3173
+ $v_central_dir = array();
3174
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
3175
+ {
3176
+ $this->privSwapBackMagicQuotes();
3177
+ return $v_result;
3178
+ }
3179
+
3180
+ // ----- Go to beginning of Central Dir
3181
+ @rewind($this->zip_fd);
3182
+ if (@fseek($this->zip_fd, $v_central_dir['offset']))
3183
+ {
3184
+ $this->privSwapBackMagicQuotes();
3185
+
3186
+ // ----- Error log
3187
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3188
+
3189
+ // ----- Return
3190
+ return PclZip::errorCode();
3191
+ }
3192
+
3193
+ // ----- Read each entry
3194
+ for ($i=0; $i<$v_central_dir['entries']; $i++)
3195
+ {
3196
+ // ----- Read the file header
3197
+ if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
3198
+ {
3199
+ $this->privSwapBackMagicQuotes();
3200
+ return $v_result;
3201
+ }
3202
+ $v_header['index'] = $i;
3203
+
3204
+ // ----- Get the only interesting attributes
3205
+ $this->privConvertHeader2FileInfo($v_header, $p_list[$i]);
3206
+ unset($v_header);
3207
+ }
3208
+
3209
+ // ----- Close the zip file
3210
+ $this->privCloseFd();
3211
+
3212
+ // ----- Magic quotes trick
3213
+ $this->privSwapBackMagicQuotes();
3214
+
3215
+ // ----- Return
3216
+ return $v_result;
3217
+ }
3218
+ // --------------------------------------------------------------------------------
3219
+
3220
+ // --------------------------------------------------------------------------------
3221
+ // Function : privConvertHeader2FileInfo()
3222
+ // Description :
3223
+ // This function takes the file informations from the central directory
3224
+ // entries and extract the interesting parameters that will be given back.
3225
+ // The resulting file infos are set in the array $p_info
3226
+ // $p_info['filename'] : Filename with full path. Given by user (add),
3227
+ // extracted in the filesystem (extract).
3228
+ // $p_info['stored_filename'] : Stored filename in the archive.
3229
+ // $p_info['size'] = Size of the file.
3230
+ // $p_info['compressed_size'] = Compressed size of the file.
3231
+ // $p_info['mtime'] = Last modification date of the file.
3232
+ // $p_info['comment'] = Comment associated with the file.
3233
+ // $p_info['folder'] = true/false : indicates if the entry is a folder or not.
3234
+ // $p_info['status'] = status of the action on the file.
3235
+ // $p_info['crc'] = CRC of the file content.
3236
+ // Parameters :
3237
+ // Return Values :
3238
+ // --------------------------------------------------------------------------------
3239
+ function privConvertHeader2FileInfo($p_header, &$p_info)
3240
+ {
3241
+ $v_result=1;
3242
+
3243
+ // ----- Get the interesting attributes
3244
+ $v_temp_path = PclZipUtilPathReduction($p_header['filename']);
3245
+ $p_info['filename'] = $v_temp_path;
3246
+ $v_temp_path = PclZipUtilPathReduction($p_header['stored_filename']);
3247
+ $p_info['stored_filename'] = $v_temp_path;
3248
+ $p_info['size'] = $p_header['size'];
3249
+ $p_info['compressed_size'] = $p_header['compressed_size'];
3250
+ $p_info['mtime'] = $p_header['mtime'];
3251
+ $p_info['comment'] = $p_header['comment'];
3252
+ $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010);
3253
+ $p_info['index'] = $p_header['index'];
3254
+ $p_info['status'] = $p_header['status'];
3255
+ $p_info['crc'] = $p_header['crc'];
3256
+
3257
+ // ----- Return
3258
+ return $v_result;
3259
+ }
3260
+ // --------------------------------------------------------------------------------
3261
+
3262
+ // --------------------------------------------------------------------------------
3263
+ // Function : privExtractByRule()
3264
+ // Description :
3265
+ // Extract a file or directory depending of rules (by index, by name, ...)
3266
+ // Parameters :
3267
+ // $p_file_list : An array where will be placed the properties of each
3268
+ // extracted file
3269
+ // $p_path : Path to add while writing the extracted files
3270
+ // $p_remove_path : Path to remove (from the file memorized path) while writing the
3271
+ // extracted files. If the path does not match the file path,
3272
+ // the file is extracted with its memorized path.
3273
+ // $p_remove_path does not apply to 'list' mode.
3274
+ // $p_path and $p_remove_path are commulative.
3275
+ // Return Values :
3276
+ // 1 on success,0 or less on error (see error code list)
3277
+ // --------------------------------------------------------------------------------
3278
+ function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
3279
+ {
3280
+ $v_result=1;
3281
+
3282
+ // ----- Magic quotes trick
3283
+ $this->privDisableMagicQuotes();
3284
+
3285
+ // ----- Check the path
3286
+ if ( ($p_path == "")
3287
+ || ( (substr($p_path, 0, 1) != "/")
3288
+ && (substr($p_path, 0, 3) != "../")
3289
+ && (substr($p_path,1,2)!=":/")))
3290
+ $p_path = "./".$p_path;
3291
+
3292
+ // ----- Reduce the path last (and duplicated) '/'
3293
+ if (($p_path != "./") && ($p_path != "/"))
3294
+ {
3295
+ // ----- Look for the path end '/'
3296
+ while (substr($p_path, -1) == "/")
3297
+ {
3298
+ $p_path = substr($p_path, 0, strlen($p_path)-1);
3299
+ }
3300
+ }
3301
+
3302
+ // ----- Look for path to remove format (should end by /)
3303
+ if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/'))
3304
+ {
3305
+ $p_remove_path .= '/';
3306
+ }
3307
+ $p_remove_path_size = strlen($p_remove_path);
3308
+
3309
+ // ----- Open the zip file
3310
+ if (($v_result = $this->privOpenFd('rb')) != 1)
3311
+ {
3312
+ $this->privSwapBackMagicQuotes();
3313
+ return $v_result;
3314
+ }
3315
+
3316
+ // ----- Read the central directory informations
3317
+ $v_central_dir = array();
3318
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
3319
+ {
3320
+ // ----- Close the zip file
3321
+ $this->privCloseFd();
3322
+ $this->privSwapBackMagicQuotes();
3323
+
3324
+ return $v_result;
3325
+ }
3326
+
3327
+ // ----- Start at beginning of Central Dir
3328
+ $v_pos_entry = $v_central_dir['offset'];
3329
+
3330
+ // ----- Read each entry
3331
+ $j_start = 0;
3332
+ for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
3333
+ {
3334
+
3335
+ // ----- Read next Central dir entry
3336
+ @rewind($this->zip_fd);
3337
+ if (@fseek($this->zip_fd, $v_pos_entry))
3338
+ {
3339
+ // ----- Close the zip file
3340
+ $this->privCloseFd();
3341
+ $this->privSwapBackMagicQuotes();
3342
+
3343
+ // ----- Error log
3344
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3345
+
3346
+ // ----- Return
3347
+ return PclZip::errorCode();
3348
+ }
3349
+
3350
+ // ----- Read the file header
3351
+ $v_header = array();
3352
+ if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
3353
+ {
3354
+ // ----- Close the zip file
3355
+ $this->privCloseFd();
3356
+ $this->privSwapBackMagicQuotes();
3357
+
3358
+ return $v_result;
3359
+ }
3360
+
3361
+ // ----- Store the index
3362
+ $v_header['index'] = $i;
3363
+
3364
+ // ----- Store the file position
3365
+ $v_pos_entry = ftell($this->zip_fd);
3366
+
3367
+ // ----- Look for the specific extract rules
3368
+ $v_extract = false;
3369
+
3370
+ // ----- Look for extract by name rule
3371
+ if ( (isset($p_options[PCLZIP_OPT_BY_NAME]))
3372
+ && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
3373
+
3374
+ // ----- Look if the filename is in the list
3375
+ for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_extract); $j++) {
3376
+
3377
+ // ----- Look for a directory
3378
+ if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
3379
+
3380
+ // ----- Look if the directory is in the filename path
3381
+ if ( (strlen($v_header['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
3382
+ && (substr($v_header['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
3383
+ $v_extract = true;
3384
+ }
3385
+ }
3386
+ // ----- Look for a filename
3387
+ elseif ($v_header['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
3388
+ $v_extract = true;
3389
+ }
3390
+ }
3391
+ }
3392
+
3393
+ // ----- Look for extract by ereg rule
3394
+ // ereg() is deprecated with PHP 5.3
3395
+ /*
3396
+ else if ( (isset($p_options[PCLZIP_OPT_BY_EREG]))
3397
+ && ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
3398
+
3399
+ if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) {
3400
+ $v_extract = true;
3401
+ }
3402
+ }
3403
+ */
3404
+
3405
+ // ----- Look for extract by preg rule
3406
+ else if ( (isset($p_options[PCLZIP_OPT_BY_PREG]))
3407
+ && ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
3408
+
3409
+ if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) {
3410
+ $v_extract = true;
3411
+ }
3412
+ }
3413
+
3414
+ // ----- Look for extract by index rule
3415
+ else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX]))
3416
+ && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
3417
+
3418
+ // ----- Look if the index is in the list
3419
+ for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_extract); $j++) {
3420
+
3421
+ if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
3422
+ $v_extract = true;
3423
+ }
3424
+ if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
3425
+ $j_start = $j+1;
3426
+ }
3427
+
3428
+ if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
3429
+ break;
3430
+ }
3431
+ }
3432
+ }
3433
+
3434
+ // ----- Look for no rule, which means extract all the archive
3435
+ else {
3436
+ $v_extract = true;
3437
+ }
3438
+
3439
+ // ----- Check compression method
3440
+ if ( ($v_extract)
3441
+ && ( ($v_header['compression'] != 8)
3442
+ && ($v_header['compression'] != 0))) {
3443
+ $v_header['status'] = 'unsupported_compression';
3444
+
3445
+ // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3446
+ if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3447
+ && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3448
+
3449
+ $this->privSwapBackMagicQuotes();
3450
+
3451
+ PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_COMPRESSION,
3452
+ "Filename '".$v_header['stored_filename']."' is "
3453
+ ."compressed by an unsupported compression "
3454
+ ."method (".$v_header['compression'].") ");
3455
+
3456
+ return PclZip::errorCode();
3457
+ }
3458
+ }
3459
+
3460
+ // ----- Check encrypted files
3461
+ if (($v_extract) && (($v_header['flag'] & 1) == 1)) {
3462
+ $v_header['status'] = 'unsupported_encryption';
3463
+
3464
+ // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3465
+ if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3466
+ && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3467
+
3468
+ $this->privSwapBackMagicQuotes();
3469
+
3470
+ PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION,
3471
+ "Unsupported encryption for "
3472
+ ." filename '".$v_header['stored_filename']
3473
+ ."'");
3474
+
3475
+ return PclZip::errorCode();
3476
+ }
3477
+ }
3478
+
3479
+ // ----- Look for real extraction
3480
+ if (($v_extract) && ($v_header['status'] != 'ok')) {
3481
+ $v_result = $this->privConvertHeader2FileInfo($v_header,
3482
+ $p_file_list[$v_nb_extracted++]);
3483
+ if ($v_result != 1) {
3484
+ $this->privCloseFd();
3485
+ $this->privSwapBackMagicQuotes();
3486
+ return $v_result;
3487
+ }
3488
+
3489
+ $v_extract = false;
3490
+ }
3491
+
3492
+ // ----- Look for real extraction
3493
+ if ($v_extract)
3494
+ {
3495
+
3496
+ // ----- Go to the file position
3497
+ @rewind($this->zip_fd);
3498
+ if (@fseek($this->zip_fd, $v_header['offset']))
3499
+ {
3500
+ // ----- Close the zip file
3501
+ $this->privCloseFd();
3502
+
3503
+ $this->privSwapBackMagicQuotes();
3504
+
3505
+ // ----- Error log
3506
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
3507
+
3508
+ // ----- Return
3509
+ return PclZip::errorCode();
3510
+ }
3511
+
3512
+ // ----- Look for extraction as string
3513
+ if ($p_options[PCLZIP_OPT_EXTRACT_AS_STRING]) {
3514
+
3515
+ $v_string = '';
3516
+
3517
+ // ----- Extracting the file
3518
+ $v_result1 = $this->privExtractFileAsString($v_header, $v_string, $p_options);
3519
+ if ($v_result1 < 1) {
3520
+ $this->privCloseFd();
3521
+ $this->privSwapBackMagicQuotes();
3522
+ return $v_result1;
3523
+ }
3524
+
3525
+ // ----- Get the only interesting attributes
3526
+ if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1)
3527
+ {
3528
+ // ----- Close the zip file
3529
+ $this->privCloseFd();
3530
+ $this->privSwapBackMagicQuotes();
3531
+
3532
+ return $v_result;
3533
+ }
3534
+
3535
+ // ----- Set the file content
3536
+ $p_file_list[$v_nb_extracted]['content'] = $v_string;
3537
+
3538
+ // ----- Next extracted file
3539
+ $v_nb_extracted++;
3540
+
3541
+ // ----- Look for user callback abort
3542
+ if ($v_result1 == 2) {
3543
+ break;
3544
+ }
3545
+ }
3546
+ // ----- Look for extraction in standard output
3547
+ elseif ( (isset($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT]))
3548
+ && ($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) {
3549
+ // ----- Extracting the file in standard output
3550
+ $v_result1 = $this->privExtractFileInOutput($v_header, $p_options);
3551
+ if ($v_result1 < 1) {
3552
+ $this->privCloseFd();
3553
+ $this->privSwapBackMagicQuotes();
3554
+ return $v_result1;
3555
+ }
3556
+
3557
+ // ----- Get the only interesting attributes
3558
+ if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) {
3559
+ $this->privCloseFd();
3560
+ $this->privSwapBackMagicQuotes();
3561
+ return $v_result;
3562
+ }
3563
+
3564
+ // ----- Look for user callback abort
3565
+ if ($v_result1 == 2) {
3566
+ break;
3567
+ }
3568
+ }
3569
+ // ----- Look for normal extraction
3570
+ else {
3571
+ // ----- Extracting the file
3572
+ $v_result1 = $this->privExtractFile($v_header,
3573
+ $p_path, $p_remove_path,
3574
+ $p_remove_all_path,
3575
+ $p_options);
3576
+ if ($v_result1 < 1) {
3577
+ $this->privCloseFd();
3578
+ $this->privSwapBackMagicQuotes();
3579
+ return $v_result1;
3580
+ }
3581
+
3582
+ // ----- Get the only interesting attributes
3583
+ if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1)
3584
+ {
3585
+ // ----- Close the zip file
3586
+ $this->privCloseFd();
3587
+ $this->privSwapBackMagicQuotes();
3588
+
3589
+ return $v_result;
3590
+ }
3591
+
3592
+ // ----- Look for user callback abort
3593
+ if ($v_result1 == 2) {
3594
+ break;
3595
+ }
3596
+ }
3597
+ }
3598
+ }
3599
+
3600
+ // ----- Close the zip file
3601
+ $this->privCloseFd();
3602
+ $this->privSwapBackMagicQuotes();
3603
+
3604
+ // ----- Return
3605
+ return $v_result;
3606
+ }
3607
+ // --------------------------------------------------------------------------------
3608
+
3609
+ // --------------------------------------------------------------------------------
3610
+ // Function : privExtractFile()
3611
+ // Description :
3612
+ // Parameters :
3613
+ // Return Values :
3614
+ //
3615
+ // 1 : ... ?
3616
+ // PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback
3617
+ // --------------------------------------------------------------------------------
3618
+ function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
3619
+ {
3620
+ $v_result=1;
3621
+
3622
+ // ----- Read the file header
3623
+ if (($v_result = $this->privReadFileHeader($v_header)) != 1)
3624
+ {
3625
+ // ----- Return
3626
+ return $v_result;
3627
+ }
3628
+
3629
+
3630
+ // ----- Check that the file header is coherent with $p_entry info
3631
+ if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
3632
+ // TBC
3633
+ }
3634
+
3635
+ // ----- Look for all path to remove
3636
+ if ($p_remove_all_path == true) {
3637
+ // ----- Look for folder entry that not need to be extracted
3638
+ if (($p_entry['external']&0x00000010)==0x00000010) {
3639
+
3640
+ $p_entry['status'] = "filtered";
3641
+
3642
+ return $v_result;
3643
+ }
3644
+
3645
+ // ----- Get the basename of the path
3646
+ $p_entry['filename'] = basename($p_entry['filename']);
3647
+ }
3648
+
3649
+ // ----- Look for path to remove
3650
+ else if ($p_remove_path != "")
3651
+ {
3652
+ if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2)
3653
+ {
3654
+
3655
+ // ----- Change the file status
3656
+ $p_entry['status'] = "filtered";
3657
+
3658
+ // ----- Return
3659
+ return $v_result;
3660
+ }
3661
+
3662
+ $p_remove_path_size = strlen($p_remove_path);
3663
+ if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path)
3664
+ {
3665
+
3666
+ // ----- Remove the path
3667
+ $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);
3668
+
3669
+ }
3670
+ }
3671
+
3672
+ // ----- Add the path
3673
+ if ($p_path != '') {
3674
+ $p_entry['filename'] = $p_path."/".$p_entry['filename'];
3675
+ }
3676
+
3677
+ // ----- Check a base_dir_restriction
3678
+ if (isset($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) {
3679
+ $v_inclusion
3680
+ = PclZipUtilPathInclusion($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION],
3681
+ $p_entry['filename']);
3682
+ if ($v_inclusion == 0) {
3683
+
3684
+ PclZip::privErrorLog(PCLZIP_ERR_DIRECTORY_RESTRICTION,
3685
+ "Filename '".$p_entry['filename']."' is "
3686
+ ."outside PCLZIP_OPT_EXTRACT_DIR_RESTRICTION");
3687
+
3688
+ return PclZip::errorCode();
3689
+ }
3690
+ }
3691
+
3692
+ // ----- Look for pre-extract callback
3693
+ if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
3694
+
3695
+ // ----- Generate a local information
3696
+ $v_local_header = array();
3697
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3698
+
3699
+ // ----- Call the callback
3700
+ // Here I do not use call_user_func() because I need to send a reference to the
3701
+ // header.
3702
+ // eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
3703
+ $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
3704
+ if ($v_result == 0) {
3705
+ // ----- Change the file status
3706
+ $p_entry['status'] = "skipped";
3707
+ $v_result = 1;
3708
+ }
3709
+
3710
+ // ----- Look for abort result
3711
+ if ($v_result == 2) {
3712
+ // ----- This status is internal and will be changed in 'skipped'
3713
+ $p_entry['status'] = "aborted";
3714
+ $v_result = PCLZIP_ERR_USER_ABORTED;
3715
+ }
3716
+
3717
+ // ----- Update the informations
3718
+ // Only some fields can be modified
3719
+ $p_entry['filename'] = $v_local_header['filename'];
3720
+ }
3721
+
3722
+
3723
+ // ----- Look if extraction should be done
3724
+ if ($p_entry['status'] == 'ok') {
3725
+
3726
+ // ----- Look for specific actions while the file exist
3727
+ if (file_exists($p_entry['filename']))
3728
+ {
3729
+
3730
+ // ----- Look if file is a directory
3731
+ if (is_dir($p_entry['filename']))
3732
+ {
3733
+
3734
+ // ----- Change the file status
3735
+ $p_entry['status'] = "already_a_directory";
3736
+
3737
+ // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3738
+ // For historical reason first PclZip implementation does not stop
3739
+ // when this kind of error occurs.
3740
+ if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3741
+ && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3742
+
3743
+ PclZip::privErrorLog(PCLZIP_ERR_ALREADY_A_DIRECTORY,
3744
+ "Filename '".$p_entry['filename']."' is "
3745
+ ."already used by an existing directory");
3746
+
3747
+ return PclZip::errorCode();
3748
+ }
3749
+ }
3750
+ // ----- Look if file is write protected
3751
+ else if (!is_writeable($p_entry['filename']))
3752
+ {
3753
+
3754
+ // ----- Change the file status
3755
+ $p_entry['status'] = "write_protected";
3756
+
3757
+ // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3758
+ // For historical reason first PclZip implementation does not stop
3759
+ // when this kind of error occurs.
3760
+ if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3761
+ && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3762
+
3763
+ PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
3764
+ "Filename '".$p_entry['filename']."' exists "
3765
+ ."and is write protected");
3766
+
3767
+ return PclZip::errorCode();
3768
+ }
3769
+ }
3770
+
3771
+ // ----- Look if the extracted file is older
3772
+ else if (filemtime($p_entry['filename']) > $p_entry['mtime'])
3773
+ {
3774
+ // ----- Change the file status
3775
+ if ( (isset($p_options[PCLZIP_OPT_REPLACE_NEWER]))
3776
+ && ($p_options[PCLZIP_OPT_REPLACE_NEWER]===true)) {
3777
+ }
3778
+ else {
3779
+ $p_entry['status'] = "newer_exist";
3780
+
3781
+ // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
3782
+ // For historical reason first PclZip implementation does not stop
3783
+ // when this kind of error occurs.
3784
+ if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
3785
+ && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
3786
+
3787
+ PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
3788
+ "Newer version of '".$p_entry['filename']."' exists "
3789
+ ."and option PCLZIP_OPT_REPLACE_NEWER is not selected");
3790
+
3791
+ return PclZip::errorCode();
3792
+ }
3793
+ }
3794
+ }
3795
+ else {
3796
+ }
3797
+ }
3798
+
3799
+ // ----- Check the directory availability and create it if necessary
3800
+ else {
3801
+ if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/'))
3802
+ $v_dir_to_check = $p_entry['filename'];
3803
+ else if (!strstr($p_entry['filename'], "/"))
3804
+ $v_dir_to_check = "";
3805
+ else
3806
+ $v_dir_to_check = dirname($p_entry['filename']);
3807
+
3808
+ if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) {
3809
+
3810
+ // ----- Change the file status
3811
+ $p_entry['status'] = "path_creation_fail";
3812
+
3813
+ // ----- Return
3814
+ //return $v_result;
3815
+ $v_result = 1;
3816
+ }
3817
+ }
3818
+ }
3819
+
3820
+ // ----- Look if extraction should be done
3821
+ if ($p_entry['status'] == 'ok') {
3822
+
3823
+ // ----- Do the extraction (if not a folder)
3824
+ if (!(($p_entry['external']&0x00000010)==0x00000010))
3825
+ {
3826
+ // ----- Look for not compressed file
3827
+ if ($p_entry['compression'] == 0) {
3828
+
3829
+ // ----- Opening destination file
3830
+ if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0)
3831
+ {
3832
+
3833
+ // ----- Change the file status
3834
+ $p_entry['status'] = "write_error";
3835
+
3836
+ // ----- Return
3837
+ return $v_result;
3838
+ }
3839
+
3840
+
3841
+ // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
3842
+ $v_size = $p_entry['compressed_size'];
3843
+ while ($v_size != 0)
3844
+ {
3845
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
3846
+ $v_buffer = @fread($this->zip_fd, $v_read_size);
3847
+ /* Try to speed up the code
3848
+ $v_binary_data = pack('a'.$v_read_size, $v_buffer);
3849
+ @fwrite($v_dest_file, $v_binary_data, $v_read_size);
3850
+ */
3851
+ @fwrite($v_dest_file, $v_buffer, $v_read_size);
3852
+ $v_size -= $v_read_size;
3853
+ }
3854
+
3855
+ // ----- Closing the destination file
3856
+ fclose($v_dest_file);
3857
+
3858
+ // ----- Change the file mtime
3859
+ touch($p_entry['filename'], $p_entry['mtime']);
3860
+
3861
+
3862
+ }
3863
+ else {
3864
+ // ----- TBC
3865
+ // Need to be finished
3866
+ if (($p_entry['flag'] & 1) == 1) {
3867
+ PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, 'File \''.$p_entry['filename'].'\' is encrypted. Encrypted files are not supported.');
3868
+ return PclZip::errorCode();
3869
+ }
3870
+
3871
+
3872
+ // ----- Look for using temporary file to unzip
3873
+ if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
3874
+ && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON])
3875
+ || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
3876
+ && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_entry['size'])) ) ) {
3877
+ $v_result = $this->privExtractFileUsingTempFile($p_entry, $p_options);
3878
+ if ($v_result < PCLZIP_ERR_NO_ERROR) {
3879
+ return $v_result;
3880
+ }
3881
+ }
3882
+
3883
+ // ----- Look for extract in memory
3884
+ else {
3885
+
3886
+
3887
+ // ----- Read the compressed file in a buffer (one shot)
3888
+ $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
3889
+
3890
+ // ----- Decompress the file
3891
+ $v_file_content = @gzinflate($v_buffer);
3892
+ unset($v_buffer);
3893
+ if ($v_file_content === FALSE) {
3894
+
3895
+ // ----- Change the file status
3896
+ // TBC
3897
+ $p_entry['status'] = "error";
3898
+
3899
+ return $v_result;
3900
+ }
3901
+
3902
+ // ----- Opening destination file
3903
+ if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
3904
+
3905
+ // ----- Change the file status
3906
+ $p_entry['status'] = "write_error";
3907
+
3908
+ return $v_result;
3909
+ }
3910
+
3911
+ // ----- Write the uncompressed data
3912
+ @fwrite($v_dest_file, $v_file_content, $p_entry['size']);
3913
+ unset($v_file_content);
3914
+
3915
+ // ----- Closing the destination file
3916
+ @fclose($v_dest_file);
3917
+
3918
+ }
3919
+
3920
+ // ----- Change the file mtime
3921
+ @touch($p_entry['filename'], $p_entry['mtime']);
3922
+ }
3923
+
3924
+ // ----- Look for chmod option
3925
+ if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) {
3926
+
3927
+ // ----- Change the mode of the file
3928
+ @chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]);
3929
+ }
3930
+
3931
+ }
3932
+ }
3933
+
3934
+ // ----- Change abort status
3935
+ if ($p_entry['status'] == "aborted") {
3936
+ $p_entry['status'] = "skipped";
3937
+ }
3938
+
3939
+ // ----- Look for post-extract callback
3940
+ elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
3941
+
3942
+ // ----- Generate a local information
3943
+ $v_local_header = array();
3944
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
3945
+
3946
+ // ----- Call the callback
3947
+ // Here I do not use call_user_func() because I need to send a reference to the
3948
+ // header.
3949
+ // eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
3950
+ $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);
3951
+
3952
+ // ----- Look for abort result
3953
+ if ($v_result == 2) {
3954
+ $v_result = PCLZIP_ERR_USER_ABORTED;
3955
+ }
3956
+ }
3957
+
3958
+ // ----- Return
3959
+ return $v_result;
3960
+ }
3961
+ // --------------------------------------------------------------------------------
3962
+
3963
+ // --------------------------------------------------------------------------------
3964
+ // Function : privExtractFileUsingTempFile()
3965
+ // Description :
3966
+ // Parameters :
3967
+ // Return Values :
3968
+ // --------------------------------------------------------------------------------
3969
+ function privExtractFileUsingTempFile(&$p_entry, &$p_options)
3970
+ {
3971
+ $v_result=1;
3972
+
3973
+ // ----- Creates a temporary file
3974
+ $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz';
3975
+ if (($v_dest_file = @fopen($v_gzip_temp_name, "wb")) == 0) {
3976
+ fclose($v_file);
3977
+ PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
3978
+ return PclZip::errorCode();
3979
+ }
3980
+
3981
+
3982
+ // ----- Write gz file format header
3983
+ $v_binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($p_entry['compression']), Chr(0x00), time(), Chr(0x00), Chr(3));
3984
+ @fwrite($v_dest_file, $v_binary_data, 10);
3985
+
3986
+ // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
3987
+ $v_size = $p_entry['compressed_size'];
3988
+ while ($v_size != 0)
3989
+ {
3990
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
3991
+ $v_buffer = @fread($this->zip_fd, $v_read_size);
3992
+ //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
3993
+ @fwrite($v_dest_file, $v_buffer, $v_read_size);
3994
+ $v_size -= $v_read_size;
3995
+ }
3996
+
3997
+ // ----- Write gz file format footer
3998
+ $v_binary_data = pack('VV', $p_entry['crc'], $p_entry['size']);
3999
+ @fwrite($v_dest_file, $v_binary_data, 8);
4000
+
4001
+ // ----- Close the temporary file
4002
+ @fclose($v_dest_file);
4003
+
4004
+ // ----- Opening destination file
4005
+ if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
4006
+ $p_entry['status'] = "write_error";
4007
+ return $v_result;
4008
+ }
4009
+
4010
+ // ----- Open the temporary gz file
4011
+ if (($v_src_file = @gzopen($v_gzip_temp_name, 'rb')) == 0) {
4012
+ @fclose($v_dest_file);
4013
+ $p_entry['status'] = "read_error";
4014
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
4015
+ return PclZip::errorCode();
4016
+ }
4017
+
4018
+
4019
+ // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
4020
+ $v_size = $p_entry['size'];
4021
+ while ($v_size != 0) {
4022
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
4023
+ $v_buffer = @gzread($v_src_file, $v_read_size);
4024
+ //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
4025
+ @fwrite($v_dest_file, $v_buffer, $v_read_size);
4026
+ $v_size -= $v_read_size;
4027
+ }
4028
+ @fclose($v_dest_file);
4029
+ @gzclose($v_src_file);
4030
+
4031
+ // ----- Delete the temporary file
4032
+ @unlink($v_gzip_temp_name);
4033
+
4034
+ // ----- Return
4035
+ return $v_result;
4036
+ }
4037
+ // --------------------------------------------------------------------------------
4038
+
4039
+ // --------------------------------------------------------------------------------
4040
+ // Function : privExtractFileInOutput()
4041
+ // Description :
4042
+ // Parameters :
4043
+ // Return Values :
4044
+ // --------------------------------------------------------------------------------
4045
+ function privExtractFileInOutput(&$p_entry, &$p_options)
4046
+ {
4047
+ $v_result=1;
4048
+
4049
+ // ----- Read the file header
4050
+ if (($v_result = $this->privReadFileHeader($v_header)) != 1) {
4051
+ return $v_result;
4052
+ }
4053
+
4054
+
4055
+ // ----- Check that the file header is coherent with $p_entry info
4056
+ if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
4057
+ // TBC
4058
+ }
4059
+
4060
+ // ----- Look for pre-extract callback
4061
+ if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
4062
+
4063
+ // ----- Generate a local information
4064
+ $v_local_header = array();
4065
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4066
+
4067
+ // ----- Call the callback
4068
+ // Here I do not use call_user_func() because I need to send a reference to the
4069
+ // header.
4070
+ // eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
4071
+ $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
4072
+ if ($v_result == 0) {
4073
+ // ----- Change the file status
4074
+ $p_entry['status'] = "skipped";
4075
+ $v_result = 1;
4076
+ }
4077
+
4078
+ // ----- Look for abort result
4079
+ if ($v_result == 2) {
4080
+ // ----- This status is internal and will be changed in 'skipped'
4081
+ $p_entry['status'] = "aborted";
4082
+ $v_result = PCLZIP_ERR_USER_ABORTED;
4083
+ }
4084
+
4085
+ // ----- Update the informations
4086
+ // Only some fields can be modified
4087
+ $p_entry['filename'] = $v_local_header['filename'];
4088
+ }
4089
+
4090
+ // ----- Trace
4091
+
4092
+ // ----- Look if extraction should be done
4093
+ if ($p_entry['status'] == 'ok') {
4094
+
4095
+ // ----- Do the extraction (if not a folder)
4096
+ if (!(($p_entry['external']&0x00000010)==0x00000010)) {
4097
+ // ----- Look for not compressed file
4098
+ if ($p_entry['compressed_size'] == $p_entry['size']) {
4099
+
4100
+ // ----- Read the file in a buffer (one shot)
4101
+ $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
4102
+
4103
+ // ----- Send the file to the output
4104
+ echo $v_buffer;
4105
+ unset($v_buffer);
4106
+ }
4107
+ else {
4108
+
4109
+ // ----- Read the compressed file in a buffer (one shot)
4110
+ $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
4111
+
4112
+ // ----- Decompress the file
4113
+ $v_file_content = gzinflate($v_buffer);
4114
+ unset($v_buffer);
4115
+
4116
+ // ----- Send the file to the output
4117
+ echo $v_file_content;
4118
+ unset($v_file_content);
4119
+ }
4120
+ }
4121
+ }
4122
+
4123
+ // ----- Change abort status
4124
+ if ($p_entry['status'] == "aborted") {
4125
+ $p_entry['status'] = "skipped";
4126
+ }
4127
+
4128
+ // ----- Look for post-extract callback
4129
+ elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
4130
+
4131
+ // ----- Generate a local information
4132
+ $v_local_header = array();
4133
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4134
+
4135
+ // ----- Call the callback
4136
+ // Here I do not use call_user_func() because I need to send a reference to the
4137
+ // header.
4138
+ // eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
4139
+ $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);
4140
+
4141
+ // ----- Look for abort result
4142
+ if ($v_result == 2) {
4143
+ $v_result = PCLZIP_ERR_USER_ABORTED;
4144
+ }
4145
+ }
4146
+
4147
+ return $v_result;
4148
+ }
4149
+ // --------------------------------------------------------------------------------
4150
+
4151
+ // --------------------------------------------------------------------------------
4152
+ // Function : privExtractFileAsString()
4153
+ // Description :
4154
+ // Parameters :
4155
+ // Return Values :
4156
+ // --------------------------------------------------------------------------------
4157
+ function privExtractFileAsString(&$p_entry, &$p_string, &$p_options)
4158
+ {
4159
+ $v_result=1;
4160
+
4161
+ // ----- Read the file header
4162
+ $v_header = array();
4163
+ if (($v_result = $this->privReadFileHeader($v_header)) != 1)
4164
+ {
4165
+ // ----- Return
4166
+ return $v_result;
4167
+ }
4168
+
4169
+
4170
+ // ----- Check that the file header is coherent with $p_entry info
4171
+ if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
4172
+ // TBC
4173
+ }
4174
+
4175
+ // ----- Look for pre-extract callback
4176
+ if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
4177
+
4178
+ // ----- Generate a local information
4179
+ $v_local_header = array();
4180
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4181
+
4182
+ // ----- Call the callback
4183
+ // Here I do not use call_user_func() because I need to send a reference to the
4184
+ // header.
4185
+ // eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
4186
+ $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
4187
+ if ($v_result == 0) {
4188
+ // ----- Change the file status
4189
+ $p_entry['status'] = "skipped";
4190
+ $v_result = 1;
4191
+ }
4192
+
4193
+ // ----- Look for abort result
4194
+ if ($v_result == 2) {
4195
+ // ----- This status is internal and will be changed in 'skipped'
4196
+ $p_entry['status'] = "aborted";
4197
+ $v_result = PCLZIP_ERR_USER_ABORTED;
4198
+ }
4199
+
4200
+ // ----- Update the informations
4201
+ // Only some fields can be modified
4202
+ $p_entry['filename'] = $v_local_header['filename'];
4203
+ }
4204
+
4205
+
4206
+ // ----- Look if extraction should be done
4207
+ if ($p_entry['status'] == 'ok') {
4208
+
4209
+ // ----- Do the extraction (if not a folder)
4210
+ if (!(($p_entry['external']&0x00000010)==0x00000010)) {
4211
+ // ----- Look for not compressed file
4212
+ // if ($p_entry['compressed_size'] == $p_entry['size'])
4213
+ if ($p_entry['compression'] == 0) {
4214
+
4215
+ // ----- Reading the file
4216
+ $p_string = @fread($this->zip_fd, $p_entry['compressed_size']);
4217
+ }
4218
+ else {
4219
+
4220
+ // ----- Reading the file
4221
+ $v_data = @fread($this->zip_fd, $p_entry['compressed_size']);
4222
+
4223
+ // ----- Decompress the file
4224
+ if (($p_string = @gzinflate($v_data)) === FALSE) {
4225
+ // TBC
4226
+ }
4227
+ }
4228
+
4229
+ // ----- Trace
4230
+ }
4231
+ else {
4232
+ // TBC : error : can not extract a folder in a string
4233
+ }
4234
+
4235
+ }
4236
+
4237
+ // ----- Change abort status
4238
+ if ($p_entry['status'] == "aborted") {
4239
+ $p_entry['status'] = "skipped";
4240
+ }
4241
+
4242
+ // ----- Look for post-extract callback
4243
+ elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
4244
+
4245
+ // ----- Generate a local information
4246
+ $v_local_header = array();
4247
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
4248
+
4249
+ // ----- Swap the content to header
4250
+ $v_local_header['content'] = $p_string;
4251
+ $p_string = '';
4252
+
4253
+ // ----- Call the callback
4254
+ // Here I do not use call_user_func() because I need to send a reference to the
4255
+ // header.
4256
+ // eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
4257
+ $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);
4258
+
4259
+ // ----- Swap back the content to header
4260
+ $p_string = $v_local_header['content'];
4261
+ unset($v_local_header['content']);
4262
+
4263
+ // ----- Look for abort result
4264
+ if ($v_result == 2) {
4265
+ $v_result = PCLZIP_ERR_USER_ABORTED;
4266
+ }
4267
+ }
4268
+
4269
+ // ----- Return
4270
+ return $v_result;
4271
+ }
4272
+ // --------------------------------------------------------------------------------
4273
+
4274
+ // --------------------------------------------------------------------------------
4275
+ // Function : privReadFileHeader()
4276
+ // Description :
4277
+ // Parameters :
4278
+ // Return Values :
4279
+ // --------------------------------------------------------------------------------
4280
+ function privReadFileHeader(&$p_header)
4281
+ {
4282
+ $v_result=1;
4283
+
4284
+ // ----- Read the 4 bytes signature
4285
+ $v_binary_data = @fread($this->zip_fd, 4);
4286
+ $v_data = unpack('Vid', $v_binary_data);
4287
+
4288
+ // ----- Check signature
4289
+ if ($v_data['id'] != 0x04034b50)
4290
+ {
4291
+
4292
+ // ----- Error log
4293
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
4294
+
4295
+ // ----- Return
4296
+ return PclZip::errorCode();
4297
+ }
4298
+
4299
+ // ----- Read the first 42 bytes of the header
4300
+ $v_binary_data = fread($this->zip_fd, 26);
4301
+
4302
+ // ----- Look for invalid block size
4303
+ if (strlen($v_binary_data) != 26)
4304
+ {
4305
+ $p_header['filename'] = "";
4306
+ $p_header['status'] = "invalid_header";
4307
+
4308
+ // ----- Error log
4309
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
4310
+
4311
+ // ----- Return
4312
+ return PclZip::errorCode();
4313
+ }
4314
+
4315
+ // ----- Extract the values
4316
+ $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);
4317
+
4318
+ // ----- Get filename
4319
+ $p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']);
4320
+
4321
+ // ----- Get extra_fields
4322
+ if ($v_data['extra_len'] != 0) {
4323
+ $p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']);
4324
+ }
4325
+ else {
4326
+ $p_header['extra'] = '';
4327
+ }
4328
+
4329
+ // ----- Extract properties
4330
+ $p_header['version_extracted'] = $v_data['version'];
4331
+ $p_header['compression'] = $v_data['compression'];
4332
+ $p_header['size'] = $v_data['size'];
4333
+ $p_header['compressed_size'] = $v_data['compressed_size'];
4334
+ $p_header['crc'] = $v_data['crc'];
4335
+ $p_header['flag'] = $v_data['flag'];
4336
+ $p_header['filename_len'] = $v_data['filename_len'];
4337
+
4338
+ // ----- Recuperate date in UNIX format
4339
+ $p_header['mdate'] = $v_data['mdate'];
4340
+ $p_header['mtime'] = $v_data['mtime'];
4341
+ if ($p_header['mdate'] && $p_header['mtime'])
4342
+ {
4343
+ // ----- Extract time
4344
+ $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
4345
+ $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
4346
+ $v_seconde = ($p_header['mtime'] & 0x001F)*2;
4347
+
4348
+ // ----- Extract date
4349
+ $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
4350
+ $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
4351
+ $v_day = $p_header['mdate'] & 0x001F;
4352
+
4353
+ // ----- Get UNIX date format
4354
+ $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
4355
+
4356
+ }
4357
+ else
4358
+ {
4359
+ $p_header['mtime'] = time();
4360
+ }
4361
+
4362
+ // TBC
4363
+ //for(reset($v_data); $key = key($v_data); next($v_data)) {
4364
+ //}
4365
+
4366
+ // ----- Set the stored filename
4367
+ $p_header['stored_filename'] = $p_header['filename'];
4368
+
4369
+ // ----- Set the status field
4370
+ $p_header['status'] = "ok";
4371
+
4372
+ // ----- Return
4373
+ return $v_result;
4374
+ }
4375
+ // --------------------------------------------------------------------------------
4376
+
4377
+ // --------------------------------------------------------------------------------
4378
+ // Function : privReadCentralFileHeader()
4379
+ // Description :
4380
+ // Parameters :
4381
+ // Return Values :
4382
+ // --------------------------------------------------------------------------------
4383
+ function privReadCentralFileHeader(&$p_header)
4384
+ {
4385
+ $v_result=1;
4386
+
4387
+ // ----- Read the 4 bytes signature
4388
+ $v_binary_data = @fread($this->zip_fd, 4);
4389
+ $v_data = unpack('Vid', $v_binary_data);
4390
+
4391
+ // ----- Check signature
4392
+ if ($v_data['id'] != 0x02014b50)
4393
+ {
4394
+
4395
+ // ----- Error log
4396
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
4397
+
4398
+ // ----- Return
4399
+ return PclZip::errorCode();
4400
+ }
4401
+
4402
+ // ----- Read the first 42 bytes of the header
4403
+ $v_binary_data = fread($this->zip_fd, 42);
4404
+
4405
+ // ----- Look for invalid block size
4406
+ if (strlen($v_binary_data) != 42)
4407
+ {
4408
+ $p_header['filename'] = "";
4409
+ $p_header['status'] = "invalid_header";
4410
+
4411
+ // ----- Error log
4412
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
4413
+
4414
+ // ----- Return
4415
+ return PclZip::errorCode();
4416
+ }
4417
+
4418
+ // ----- Extract the values
4419
+ $p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data);
4420
+
4421
+ // ----- Get filename
4422
+ if ($p_header['filename_len'] != 0)
4423
+ $p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']);
4424
+ else
4425
+ $p_header['filename'] = '';
4426
+
4427
+ // ----- Get extra
4428
+ if ($p_header['extra_len'] != 0)
4429
+ $p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']);
4430
+ else
4431
+ $p_header['extra'] = '';
4432
+
4433
+ // ----- Get comment
4434
+ if ($p_header['comment_len'] != 0)
4435
+ $p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']);
4436
+ else
4437
+ $p_header['comment'] = '';
4438
+
4439
+ // ----- Extract properties
4440
+
4441
+ // ----- Recuperate date in UNIX format
4442
+ //if ($p_header['mdate'] && $p_header['mtime'])
4443
+ // TBC : bug : this was ignoring time with 0/0/0
4444
+ if (1)
4445
+ {
4446
+ // ----- Extract time
4447
+ $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
4448
+ $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
4449
+ $v_seconde = ($p_header['mtime'] & 0x001F)*2;
4450
+
4451
+ // ----- Extract date
4452
+ $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
4453
+ $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
4454
+ $v_day = $p_header['mdate'] & 0x001F;
4455
+
4456
+ // ----- Get UNIX date format
4457
+ $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
4458
+
4459
+ }
4460
+ else
4461
+ {
4462
+ $p_header['mtime'] = time();
4463
+ }
4464
+
4465
+ // ----- Set the stored filename
4466
+ $p_header['stored_filename'] = $p_header['filename'];
4467
+
4468
+ // ----- Set default status to ok
4469
+ $p_header['status'] = 'ok';
4470
+
4471
+ // ----- Look if it is a directory
4472
+ if (substr($p_header['filename'], -1) == '/') {
4473
+ //$p_header['external'] = 0x41FF0010;
4474
+ $p_header['external'] = 0x00000010;
4475
+ }
4476
+
4477
+
4478
+ // ----- Return
4479
+ return $v_result;
4480
+ }
4481
+ // --------------------------------------------------------------------------------
4482
+
4483
+ // --------------------------------------------------------------------------------
4484
+ // Function : privCheckFileHeaders()
4485
+ // Description :
4486
+ // Parameters :
4487
+ // Return Values :
4488
+ // 1 on success,
4489
+ // 0 on error;
4490
+ // --------------------------------------------------------------------------------
4491
+ function privCheckFileHeaders(&$p_local_header, &$p_central_header)
4492
+ {
4493
+ $v_result=1;
4494
+
4495
+ // ----- Check the static values
4496
+ // TBC
4497
+ if ($p_local_header['filename'] != $p_central_header['filename']) {
4498
+ }
4499
+ if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) {
4500
+ }
4501
+ if ($p_local_header['flag'] != $p_central_header['flag']) {
4502
+ }
4503
+ if ($p_local_header['compression'] != $p_central_header['compression']) {
4504
+ }
4505
+ if ($p_local_header['mtime'] != $p_central_header['mtime']) {
4506
+ }
4507
+ if ($p_local_header['filename_len'] != $p_central_header['filename_len']) {
4508
+ }
4509
+
4510
+ // ----- Look for flag bit 3
4511
+ if (($p_local_header['flag'] & 8) == 8) {
4512
+ $p_local_header['size'] = $p_central_header['size'];
4513
+ $p_local_header['compressed_size'] = $p_central_header['compressed_size'];
4514
+ $p_local_header['crc'] = $p_central_header['crc'];
4515
+ }
4516
+
4517
+ // ----- Return
4518
+ return $v_result;
4519
+ }
4520
+ // --------------------------------------------------------------------------------
4521
+
4522
+ // --------------------------------------------------------------------------------
4523
+ // Function : privReadEndCentralDir()
4524
+ // Description :
4525
+ // Parameters :
4526
+ // Return Values :
4527
+ // --------------------------------------------------------------------------------
4528
+ function privReadEndCentralDir(&$p_central_dir)
4529
+ {
4530
+ $v_result=1;
4531
+
4532
+ // ----- Go to the end of the zip file
4533
+ $v_size = filesize($this->zipname);
4534
+ @fseek($this->zip_fd, $v_size);
4535
+ if (@ftell($this->zip_fd) != $v_size)
4536
+ {
4537
+ // ----- Error log
4538
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\'');
4539
+
4540
+ // ----- Return
4541
+ return PclZip::errorCode();
4542
+ }
4543
+
4544
+ // ----- First try : look if this is an archive with no commentaries (most of the time)
4545
+ // in this case the end of central dir is at 22 bytes of the file end
4546
+ $v_found = 0;
4547
+ if ($v_size > 26) {
4548
+ @fseek($this->zip_fd, $v_size-22);
4549
+ if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22))
4550
+ {
4551
+ // ----- Error log
4552
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
4553
+
4554
+ // ----- Return
4555
+ return PclZip::errorCode();
4556
+ }
4557
+
4558
+ // ----- Read for bytes
4559
+ $v_binary_data = @fread($this->zip_fd, 4);
4560
+ $v_data = @unpack('Vid', $v_binary_data);
4561
+
4562
+ // ----- Check signature
4563
+ if ($v_data['id'] == 0x06054b50) {
4564
+ $v_found = 1;
4565
+ }
4566
+
4567
+ $v_pos = ftell($this->zip_fd);
4568
+ }
4569
+
4570
+ // ----- Go back to the maximum possible size of the Central Dir End Record
4571
+ if (!$v_found) {
4572
+ $v_maximum_size = 65557; // 0xFFFF + 22;
4573
+ if ($v_maximum_size > $v_size)
4574
+ $v_maximum_size = $v_size;
4575
+ @fseek($this->zip_fd, $v_size-$v_maximum_size);
4576
+ if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size))
4577
+ {
4578
+ // ----- Error log
4579
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
4580
+
4581
+ // ----- Return
4582
+ return PclZip::errorCode();
4583
+ }
4584
+
4585
+ // ----- Read byte per byte in order to find the signature
4586
+ $v_pos = ftell($this->zip_fd);
4587
+ $v_bytes = 0x00000000;
4588
+ while ($v_pos < $v_size)
4589
+ {
4590
+ // ----- Read a byte
4591
+ $v_byte = @fread($this->zip_fd, 1);
4592
+
4593
+ // ----- Add the byte
4594
+ //$v_bytes = ($v_bytes << 8) | Ord($v_byte);
4595
+ // Note we mask the old value down such that once shifted we can never end up with more than a 32bit number
4596
+ // Otherwise on systems where we have 64bit integers the check below for the magic number will fail.
4597
+ $v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte);
4598
+
4599
+ // ----- Compare the bytes
4600
+ if ($v_bytes == 0x504b0506)
4601
+ {
4602
+ $v_pos++;
4603
+ break;
4604
+ }
4605
+
4606
+ $v_pos++;
4607
+ }
4608
+
4609
+ // ----- Look if not found end of central dir
4610
+ if ($v_pos == $v_size)
4611
+ {
4612
+
4613
+ // ----- Error log
4614
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature");
4615
+
4616
+ // ----- Return
4617
+ return PclZip::errorCode();
4618
+ }
4619
+ }
4620
+
4621
+ // ----- Read the first 18 bytes of the header
4622
+ $v_binary_data = fread($this->zip_fd, 18);
4623
+
4624
+ // ----- Look for invalid block size
4625
+ if (strlen($v_binary_data) != 18)
4626
+ {
4627
+
4628
+ // ----- Error log
4629
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));
4630
+
4631
+ // ----- Return
4632
+ return PclZip::errorCode();
4633
+ }
4634
+
4635
+ // ----- Extract the values
4636
+ $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
4637
+
4638
+ // ----- Check the global size
4639
+ if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {
4640
+
4641
+ // ----- Removed in release 2.2 see readme file
4642
+ // The check of the file size is a little too strict.
4643
+ // Some bugs where found when a zip is encrypted/decrypted with 'crypt'.
4644
+ // While decrypted, zip has training 0 bytes
4645
+ if (0) {
4646
+ // ----- Error log
4647
+ PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT,
4648
+ 'The central dir is not at the end of the archive.'
4649
+ .' Some trailing bytes exists after the archive.');
4650
+
4651
+ // ----- Return
4652
+ return PclZip::errorCode();
4653
+ }
4654
+ }
4655
+
4656
+ // ----- Get comment
4657
+ if ($v_data['comment_size'] != 0) {
4658
+ $p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']);
4659
+ }
4660
+ else
4661
+ $p_central_dir['comment'] = '';
4662
+
4663
+ $p_central_dir['entries'] = $v_data['entries'];
4664
+ $p_central_dir['disk_entries'] = $v_data['disk_entries'];
4665
+ $p_central_dir['offset'] = $v_data['offset'];
4666
+ $p_central_dir['size'] = $v_data['size'];
4667
+ $p_central_dir['disk'] = $v_data['disk'];
4668
+ $p_central_dir['disk_start'] = $v_data['disk_start'];
4669
+
4670
+ // TBC
4671
+ //for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) {
4672
+ //}
4673
+
4674
+ // ----- Return
4675
+ return $v_result;
4676
+ }
4677
+ // --------------------------------------------------------------------------------
4678
+
4679
+ // --------------------------------------------------------------------------------
4680
+ // Function : privDeleteByRule()
4681
+ // Description :
4682
+ // Parameters :
4683
+ // Return Values :
4684
+ // --------------------------------------------------------------------------------
4685
+ function privDeleteByRule(&$p_result_list, &$p_options)
4686
+ {
4687
+ $v_result=1;
4688
+ $v_list_detail = array();
4689
+
4690
+ // ----- Open the zip file
4691
+ if (($v_result=$this->privOpenFd('rb')) != 1)
4692
+ {
4693
+ // ----- Return
4694
+ return $v_result;
4695
+ }
4696
+
4697
+ // ----- Read the central directory informations
4698
+ $v_central_dir = array();
4699
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
4700
+ {
4701
+ $this->privCloseFd();
4702
+ return $v_result;
4703
+ }
4704
+
4705
+ // ----- Go to beginning of File
4706
+ @rewind($this->zip_fd);
4707
+
4708
+ // ----- Scan all the files
4709
+ // ----- Start at beginning of Central Dir
4710
+ $v_pos_entry = $v_central_dir['offset'];
4711
+ @rewind($this->zip_fd);
4712
+ if (@fseek($this->zip_fd, $v_pos_entry))
4713
+ {
4714
+ // ----- Close the zip file
4715
+ $this->privCloseFd();
4716
+
4717
+ // ----- Error log
4718
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
4719
+
4720
+ // ----- Return
4721
+ return PclZip::errorCode();
4722
+ }
4723
+
4724
+ // ----- Read each entry
4725
+ $v_header_list = array();
4726
+ $j_start = 0;
4727
+ for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
4728
+ {
4729
+
4730
+ // ----- Read the file header
4731
+ $v_header_list[$v_nb_extracted] = array();
4732
+ if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1)
4733
+ {
4734
+ // ----- Close the zip file
4735
+ $this->privCloseFd();
4736
+
4737
+ return $v_result;
4738
+ }
4739
+
4740
+
4741
+ // ----- Store the index
4742
+ $v_header_list[$v_nb_extracted]['index'] = $i;
4743
+
4744
+ // ----- Look for the specific extract rules
4745
+ $v_found = false;
4746
+
4747
+ // ----- Look for extract by name rule
4748
+ if ( (isset($p_options[PCLZIP_OPT_BY_NAME]))
4749
+ && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
4750
+
4751
+ // ----- Look if the filename is in the list
4752
+ for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_found); $j++) {
4753
+
4754
+ // ----- Look for a directory
4755
+ if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
4756
+
4757
+ // ----- Look if the directory is in the filename path
4758
+ if ( (strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
4759
+ && (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
4760
+ $v_found = true;
4761
+ }
4762
+ elseif ( (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */
4763
+ && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
4764
+ $v_found = true;
4765
+ }
4766
+ }
4767
+ // ----- Look for a filename
4768
+ elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
4769
+ $v_found = true;
4770
+ }
4771
+ }
4772
+ }
4773
+
4774
+ // ----- Look for extract by ereg rule
4775
+ // ereg() is deprecated with PHP 5.3
4776
+ /*
4777
+ else if ( (isset($p_options[PCLZIP_OPT_BY_EREG]))
4778
+ && ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
4779
+
4780
+ if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
4781
+ $v_found = true;
4782
+ }
4783
+ }
4784
+ */
4785
+
4786
+ // ----- Look for extract by preg rule
4787
+ else if ( (isset($p_options[PCLZIP_OPT_BY_PREG]))
4788
+ && ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
4789
+
4790
+ if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
4791
+ $v_found = true;
4792
+ }
4793
+ }
4794
+
4795
+ // ----- Look for extract by index rule
4796
+ else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX]))
4797
+ && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
4798
+
4799
+ // ----- Look if the index is in the list
4800
+ for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_found); $j++) {
4801
+
4802
+ if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
4803
+ $v_found = true;
4804
+ }
4805
+ if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
4806
+ $j_start = $j+1;
4807
+ }
4808
+
4809
+ if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
4810
+ break;
4811
+ }
4812
+ }
4813
+ }
4814
+ else {
4815
+ $v_found = true;
4816
+ }
4817
+
4818
+ // ----- Look for deletion
4819
+ if ($v_found)
4820
+ {
4821
+ unset($v_header_list[$v_nb_extracted]);
4822
+ }
4823
+ else
4824
+ {
4825
+ $v_nb_extracted++;
4826
+ }
4827
+ }
4828
+
4829
+ // ----- Look if something need to be deleted
4830
+ if ($v_nb_extracted > 0) {
4831
+
4832
+ // ----- Creates a temporay file
4833
+ $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
4834
+
4835
+ // ----- Creates a temporary zip archive
4836
+ $v_temp_zip = new PclZip($v_zip_temp_name);
4837
+
4838
+ // ----- Open the temporary zip file in write mode
4839
+ if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) {
4840
+ $this->privCloseFd();
4841
+
4842
+ // ----- Return
4843
+ return $v_result;
4844
+ }
4845
+
4846
+ // ----- Look which file need to be kept
4847
+ for ($i=0; $i<sizeof($v_header_list); $i++) {
4848
+
4849
+ // ----- Calculate the position of the header
4850
+ @rewind($this->zip_fd);
4851
+ if (@fseek($this->zip_fd, $v_header_list[$i]['offset'])) {
4852
+ // ----- Close the zip file
4853
+ $this->privCloseFd();
4854
+ $v_temp_zip->privCloseFd();
4855
+ @unlink($v_zip_temp_name);
4856
+
4857
+ // ----- Error log
4858
+ PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
4859
+
4860
+ // ----- Return
4861
+ return PclZip::errorCode();
4862
+ }
4863
+
4864
+ // ----- Read the file header
4865
+ $v_local_header = array();
4866
+ if (($v_result = $this->privReadFileHeader($v_local_header)) != 1) {
4867
+ // ----- Close the zip file
4868
+ $this->privCloseFd();
4869
+ $v_temp_zip->privCloseFd();
4870
+ @unlink($v_zip_temp_name);
4871
+
4872
+ // ----- Return
4873
+ return $v_result;
4874
+ }
4875
+
4876
+ // ----- Check that local file header is same as central file header
4877
+ if ($this->privCheckFileHeaders($v_local_header,
4878
+ $v_header_list[$i]) != 1) {
4879
+ // TBC
4880
+ }
4881
+ unset($v_local_header);
4882
+
4883
+ // ----- Write the file header
4884
+ if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) {
4885
+ // ----- Close the zip file
4886
+ $this->privCloseFd();
4887
+ $v_temp_zip->privCloseFd();
4888
+ @unlink($v_zip_temp_name);
4889
+
4890
+ // ----- Return
4891
+ return $v_result;
4892
+ }
4893
+
4894
+ // ----- Read/write the data block
4895
+ if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) {
4896
+ // ----- Close the zip file
4897
+ $this->privCloseFd();
4898
+ $v_temp_zip->privCloseFd();
4899
+ @unlink($v_zip_temp_name);
4900
+
4901
+ // ----- Return
4902
+ return $v_result;
4903
+ }
4904
+ }
4905
+
4906
+ // ----- Store the offset of the central dir
4907
+ $v_offset = @ftell($v_temp_zip->zip_fd);
4908
+
4909
+ // ----- Re-Create the Central Dir files header
4910
+ for ($i=0; $i<sizeof($v_header_list); $i++) {
4911
+ // ----- Create the file header
4912
+ if (($v_result = $v_temp_zip->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
4913
+ $v_temp_zip->privCloseFd();
4914
+ $this->privCloseFd();
4915
+ @unlink($v_zip_temp_name);
4916
+
4917
+ // ----- Return
4918
+ return $v_result;
4919
+ }
4920
+
4921
+ // ----- Transform the header to a 'usable' info
4922
+ $v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
4923
+ }
4924
+
4925
+
4926
+ // ----- Zip file comment
4927
+ $v_comment = '';
4928
+ if (isset($p_options[PCLZIP_OPT_COMMENT])) {
4929
+ $v_comment = $p_options[PCLZIP_OPT_COMMENT];
4930
+ }
4931
+
4932
+ // ----- Calculate the size of the central header
4933
+ $v_size = @ftell($v_temp_zip->zip_fd)-$v_offset;
4934
+
4935
+ // ----- Create the central dir footer
4936
+ if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) {
4937
+ // ----- Reset the file list
4938
+ unset($v_header_list);
4939
+ $v_temp_zip->privCloseFd();
4940
+ $this->privCloseFd();
4941
+ @unlink($v_zip_temp_name);
4942
+
4943
+ // ----- Return
4944
+ return $v_result;
4945
+ }
4946
+
4947
+ // ----- Close
4948
+ $v_temp_zip->privCloseFd();
4949
+ $this->privCloseFd();
4950
+
4951
+ // ----- Delete the zip file
4952
+ // TBC : I should test the result ...
4953
+ @unlink($this->zipname);
4954
+
4955
+ // ----- Rename the temporary file
4956
+ // TBC : I should test the result ...
4957
+ //@rename($v_zip_temp_name, $this->zipname);
4958
+ PclZipUtilRename($v_zip_temp_name, $this->zipname);
4959
+
4960
+ // ----- Destroy the temporary archive
4961
+ unset($v_temp_zip);
4962
+ }
4963
+
4964
+ // ----- Remove every files : reset the file
4965
+ else if ($v_central_dir['entries'] != 0) {
4966
+ $this->privCloseFd();
4967
+
4968
+ if (($v_result = $this->privOpenFd('wb')) != 1) {
4969
+ return $v_result;
4970
+ }
4971
+
4972
+ if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) {
4973
+ return $v_result;
4974
+ }
4975
+
4976
+ $this->privCloseFd();
4977
+ }
4978
+
4979
+ // ----- Return
4980
+ return $v_result;
4981
+ }
4982
+ // --------------------------------------------------------------------------------
4983
+
4984
+ // --------------------------------------------------------------------------------
4985
+ // Function : privDirCheck()
4986
+ // Description :
4987
+ // Check if a directory exists, if not it creates it and all the parents directory
4988
+ // which may be useful.
4989
+ // Parameters :
4990
+ // $p_dir : Directory path to check.
4991
+ // Return Values :
4992
+ // 1 : OK
4993
+ // -1 : Unable to create directory
4994
+ // --------------------------------------------------------------------------------
4995
+ function privDirCheck($p_dir, $p_is_dir=false)
4996
+ {
4997
+ $v_result = 1;
4998
+
4999
+
5000
+ // ----- Remove the final '/'
5001
+ if (($p_is_dir) && (substr($p_dir, -1)=='/'))
5002
+ {
5003
+ $p_dir = substr($p_dir, 0, strlen($p_dir)-1);
5004
+ }
5005
+
5006
+ // ----- Check the directory availability
5007
+ if ((is_dir($p_dir)) || ($p_dir == ""))
5008
+ {
5009
+ return 1;
5010
+ }
5011
+
5012
+ // ----- Extract parent directory
5013
+ $p_parent_dir = dirname($p_dir);
5014
+
5015
+ // ----- Just a check
5016
+ if ($p_parent_dir != $p_dir)
5017
+ {
5018
+ // ----- Look for parent directory
5019
+ if ($p_parent_dir != "")
5020
+ {
5021
+ if (($v_result = $this->privDirCheck($p_parent_dir)) != 1)
5022
+ {
5023
+ return $v_result;
5024
+ }
5025
+ }
5026
+ }
5027
+
5028
+ // ----- Create the directory
5029
+ if (!@mkdir($p_dir, 0777))
5030
+ {
5031
+ // ----- Error log
5032
+ PclZip::privErrorLog(PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'");
5033
+
5034
+ // ----- Return
5035
+ return PclZip::errorCode();
5036
+ }
5037
+
5038
+ // ----- Return
5039
+ return $v_result;
5040
+ }
5041
+ // --------------------------------------------------------------------------------
5042
+
5043
+ // --------------------------------------------------------------------------------
5044
+ // Function : privMerge()
5045
+ // Description :
5046
+ // If $p_archive_to_add does not exist, the function exit with a success result.
5047
+ // Parameters :
5048
+ // Return Values :
5049
+ // --------------------------------------------------------------------------------
5050
+ function privMerge(&$p_archive_to_add)
5051
+ {
5052
+ $v_result=1;
5053
+
5054
+ // ----- Look if the archive_to_add exists
5055
+ if (!is_file($p_archive_to_add->zipname))
5056
+ {
5057
+
5058
+ // ----- Nothing to merge, so merge is a success
5059
+ $v_result = 1;
5060
+
5061
+ // ----- Return
5062
+ return $v_result;
5063
+ }
5064
+
5065
+ // ----- Look if the archive exists
5066
+ if (!is_file($this->zipname))
5067
+ {
5068
+
5069
+ // ----- Do a duplicate
5070
+ $v_result = $this->privDuplicate($p_archive_to_add->zipname);
5071
+
5072
+ // ----- Return
5073
+ return $v_result;
5074
+ }
5075
+
5076
+ // ----- Open the zip file
5077
+ if (($v_result=$this->privOpenFd('rb')) != 1)
5078
+ {
5079
+ // ----- Return
5080
+ return $v_result;
5081
+ }
5082
+
5083
+ // ----- Read the central directory informations
5084
+ $v_central_dir = array();
5085
+ if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
5086
+ {
5087
+ $this->privCloseFd();
5088
+ return $v_result;
5089
+ }
5090
+
5091
+ // ----- Go to beginning of File
5092
+ @rewind($this->zip_fd);
5093
+
5094
+ // ----- Open the archive_to_add file
5095
+ if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1)
5096
+ {
5097
+ $this->privCloseFd();
5098
+
5099
+ // ----- Return
5100
+ return $v_result;
5101
+ }
5102
+
5103
+ // ----- Read the central directory informations
5104
+ $v_central_dir_to_add = array();
5105
+ if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1)
5106
+ {
5107
+ $this->privCloseFd();
5108
+ $p_archive_to_add->privCloseFd();
5109
+
5110
+ return $v_result;
5111
+ }
5112
+
5113
+ // ----- Go to beginning of File
5114
+ @rewind($p_archive_to_add->zip_fd);
5115
+
5116
+ // ----- Creates a temporay file
5117
+ $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
5118
+
5119
+ // ----- Open the temporary file in write mode
5120
+ if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
5121
+ {
5122
+ $this->privCloseFd();
5123
+ $p_archive_to_add->privCloseFd();
5124
+
5125
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
5126
+
5127
+ // ----- Return
5128
+ return PclZip::errorCode();
5129
+ }
5130
+
5131
+ // ----- Copy the files from the archive to the temporary file
5132
+ // TBC : Here I should better append the file and go back to erase the central dir
5133
+ $v_size = $v_central_dir['offset'];
5134
+ while ($v_size != 0)
5135
+ {
5136
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5137
+ $v_buffer = fread($this->zip_fd, $v_read_size);
5138
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5139
+ $v_size -= $v_read_size;
5140
+ }
5141
+
5142
+ // ----- Copy the files from the archive_to_add into the temporary file
5143
+ $v_size = $v_central_dir_to_add['offset'];
5144
+ while ($v_size != 0)
5145
+ {
5146
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5147
+ $v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size);
5148
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5149
+ $v_size -= $v_read_size;
5150
+ }
5151
+
5152
+ // ----- Store the offset of the central dir
5153
+ $v_offset = @ftell($v_zip_temp_fd);
5154
+
5155
+ // ----- Copy the block of file headers from the old archive
5156
+ $v_size = $v_central_dir['size'];
5157
+ while ($v_size != 0)
5158
+ {
5159
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5160
+ $v_buffer = @fread($this->zip_fd, $v_read_size);
5161
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5162
+ $v_size -= $v_read_size;
5163
+ }
5164
+
5165
+ // ----- Copy the block of file headers from the archive_to_add
5166
+ $v_size = $v_central_dir_to_add['size'];
5167
+ while ($v_size != 0)
5168
+ {
5169
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5170
+ $v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size);
5171
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
5172
+ $v_size -= $v_read_size;
5173
+ }
5174
+
5175
+ // ----- Merge the file comments
5176
+ $v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment'];
5177
+
5178
+ // ----- Calculate the size of the (new) central header
5179
+ $v_size = @ftell($v_zip_temp_fd)-$v_offset;
5180
+
5181
+ // ----- Swap the file descriptor
5182
+ // Here is a trick : I swap the temporary fd with the zip fd, in order to use
5183
+ // the following methods on the temporary fil and not the real archive fd
5184
+ $v_swap = $this->zip_fd;
5185
+ $this->zip_fd = $v_zip_temp_fd;
5186
+ $v_zip_temp_fd = $v_swap;
5187
+
5188
+ // ----- Create the central dir footer
5189
+ if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1)
5190
+ {
5191
+ $this->privCloseFd();
5192
+ $p_archive_to_add->privCloseFd();
5193
+ @fclose($v_zip_temp_fd);
5194
+ $this->zip_fd = null;
5195
+
5196
+ // ----- Reset the file list
5197
+ unset($v_header_list);
5198
+
5199
+ // ----- Return
5200
+ return $v_result;
5201
+ }
5202
+
5203
+ // ----- Swap back the file descriptor
5204
+ $v_swap = $this->zip_fd;
5205
+ $this->zip_fd = $v_zip_temp_fd;
5206
+ $v_zip_temp_fd = $v_swap;
5207
+
5208
+ // ----- Close
5209
+ $this->privCloseFd();
5210
+ $p_archive_to_add->privCloseFd();
5211
+
5212
+ // ----- Close the temporary file
5213
+ @fclose($v_zip_temp_fd);
5214
+
5215
+ // ----- Delete the zip file
5216
+ // TBC : I should test the result ...
5217
+ @unlink($this->zipname);
5218
+
5219
+ // ----- Rename the temporary file
5220
+ // TBC : I should test the result ...
5221
+ //@rename($v_zip_temp_name, $this->zipname);
5222
+ PclZipUtilRename($v_zip_temp_name, $this->zipname);
5223
+
5224
+ // ----- Return
5225
+ return $v_result;
5226
+ }
5227
+ // --------------------------------------------------------------------------------
5228
+
5229
+ // --------------------------------------------------------------------------------
5230
+ // Function : privDuplicate()
5231
+ // Description :
5232
+ // Parameters :
5233
+ // Return Values :
5234
+ // --------------------------------------------------------------------------------
5235
+ function privDuplicate($p_archive_filename)
5236
+ {
5237
+ $v_result=1;
5238
+
5239
+ // ----- Look if the $p_archive_filename exists
5240
+ if (!is_file($p_archive_filename))
5241
+ {
5242
+
5243
+ // ----- Nothing to duplicate, so duplicate is a success.
5244
+ $v_result = 1;
5245
+
5246
+ // ----- Return
5247
+ return $v_result;
5248
+ }
5249
+
5250
+ // ----- Open the zip file
5251
+ if (($v_result=$this->privOpenFd('wb')) != 1)
5252
+ {
5253
+ // ----- Return
5254
+ return $v_result;
5255
+ }
5256
+
5257
+ // ----- Open the temporary file in write mode
5258
+ if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0)
5259
+ {
5260
+ $this->privCloseFd();
5261
+
5262
+ PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode');
5263
+
5264
+ // ----- Return
5265
+ return PclZip::errorCode();
5266
+ }
5267
+
5268
+ // ----- Copy the files from the archive to the temporary file
5269
+ // TBC : Here I should better append the file and go back to erase the central dir
5270
+ $v_size = filesize($p_archive_filename);
5271
+ while ($v_size != 0)
5272
+ {
5273
+ $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
5274
+ $v_buffer = fread($v_zip_temp_fd, $v_read_size);
5275
+ @fwrite($this->zip_fd, $v_buffer, $v_read_size);
5276
+ $v_size -= $v_read_size;
5277
+ }
5278
+
5279
+ // ----- Close
5280
+ $this->privCloseFd();
5281
+
5282
+ // ----- Close the temporary file
5283
+ @fclose($v_zip_temp_fd);
5284
+
5285
+ // ----- Return
5286
+ return $v_result;
5287
+ }
5288
+ // --------------------------------------------------------------------------------
5289
+
5290
+ // --------------------------------------------------------------------------------
5291
+ // Function : privErrorLog()
5292
+ // Description :
5293
+ // Parameters :
5294
+ // --------------------------------------------------------------------------------
5295
+ function privErrorLog($p_error_code=0, $p_error_string='')
5296
+ {
5297
+ if (PCLZIP_ERROR_EXTERNAL == 1) {
5298
+ PclError($p_error_code, $p_error_string);
5299
+ }
5300
+ else {
5301
+ $this->error_code = $p_error_code;
5302
+ $this->error_string = $p_error_string;
5303
+ }
5304
+ }
5305
+ // --------------------------------------------------------------------------------
5306
+
5307
+ // --------------------------------------------------------------------------------
5308
+ // Function : privErrorReset()
5309
+ // Description :
5310
+ // Parameters :
5311
+ // --------------------------------------------------------------------------------
5312
+ function privErrorReset()
5313
+ {
5314
+ if (PCLZIP_ERROR_EXTERNAL == 1) {
5315
+ PclErrorReset();
5316
+ }
5317
+ else {
5318
+ $this->error_code = 0;
5319
+ $this->error_string = '';
5320
+ }
5321
+ }
5322
+ // --------------------------------------------------------------------------------
5323
+
5324
+ // --------------------------------------------------------------------------------
5325
+ // Function : privDisableMagicQuotes()
5326
+ // Description :
5327
+ // Parameters :
5328
+ // Return Values :
5329
+ // --------------------------------------------------------------------------------
5330
+ function privDisableMagicQuotes()
5331
+ {
5332
+ $v_result=1;
5333
+
5334
+ // ----- Look if function exists
5335
+ if ( (!function_exists("get_magic_quotes_runtime"))
5336
+ || (!function_exists("set_magic_quotes_runtime"))) {
5337
+ return $v_result;
5338
+ }
5339
+
5340
+ // ----- Look if already done
5341
+ if ($this->magic_quotes_status != -1) {
5342
+ return $v_result;
5343
+ }
5344
+
5345
+ // ----- Get and memorize the magic_quote value
5346
+ $this->magic_quotes_status = @get_magic_quotes_runtime();
5347
+
5348
+ // ----- Disable magic_quotes
5349
+ if ($this->magic_quotes_status == 1) {
5350
+ @set_magic_quotes_runtime(0);
5351
+ }
5352
+
5353
+ // ----- Return
5354
+ return $v_result;
5355
+ }
5356
+ // --------------------------------------------------------------------------------
5357
+
5358
+ // --------------------------------------------------------------------------------
5359
+ // Function : privSwapBackMagicQuotes()
5360
+ // Description :
5361
+ // Parameters :
5362
+ // Return Values :
5363
+ // --------------------------------------------------------------------------------
5364
+ function privSwapBackMagicQuotes()
5365
+ {
5366
+ $v_result=1;
5367
+
5368
+ // ----- Look if function exists
5369
+ if ( (!function_exists("get_magic_quotes_runtime"))
5370
+ || (!function_exists("set_magic_quotes_runtime"))) {
5371
+ return $v_result;
5372
+ }
5373
+
5374
+ // ----- Look if something to do
5375
+ if ($this->magic_quotes_status != -1) {
5376
+ return $v_result;
5377
+ }
5378
+
5379
+ // ----- Swap back magic_quotes
5380
+ if ($this->magic_quotes_status == 1) {
5381
+ @set_magic_quotes_runtime($this->magic_quotes_status);
5382
+ }
5383
+
5384
+ // ----- Return
5385
+ return $v_result;
5386
+ }
5387
+ // --------------------------------------------------------------------------------
5388
+
5389
+ }
5390
+ // End of class
5391
+ // --------------------------------------------------------------------------------
5392
+
5393
+ // --------------------------------------------------------------------------------
5394
+ // Function : PclZipUtilPathReduction()
5395
+ // Description :
5396
+ // Parameters :
5397
+ // Return Values :
5398
+ // --------------------------------------------------------------------------------
5399
+ function PclZipUtilPathReduction($p_dir)
5400
+ {
5401
+ $v_result = "";
5402
+
5403
+ // ----- Look for not empty path
5404
+ if ($p_dir != "") {
5405
+ // ----- Explode path by directory names
5406
+ $v_list = explode("/", $p_dir);
5407
+
5408
+ // ----- Study directories from last to first
5409
+ $v_skip = 0;
5410
+ for ($i=sizeof($v_list)-1; $i>=0; $i--) {
5411
+ // ----- Look for current path
5412
+ if ($v_list[$i] == ".") {
5413
+ // ----- Ignore this directory
5414
+ // Should be the first $i=0, but no check is done
5415
+ }
5416
+ else if ($v_list[$i] == "..") {
5417
+ $v_skip++;
5418
+ }
5419
+ else if ($v_list[$i] == "") {
5420
+ // ----- First '/' i.e. root slash
5421
+ if ($i == 0) {
5422
+ $v_result = "/".$v_result;
5423
+ if ($v_skip > 0) {
5424
+ // ----- It is an invalid path, so the path is not modified
5425
+ // TBC
5426
+ $v_result = $p_dir;
5427
+ $v_skip = 0;
5428
+ }
5429
+ }
5430
+ // ----- Last '/' i.e. indicates a directory
5431
+ else if ($i == (sizeof($v_list)-1)) {
5432
+ $v_result = $v_list[$i];
5433
+ }
5434
+ // ----- Double '/' inside the path
5435
+ else {
5436
+ // ----- Ignore only the double '//' in path,
5437
+ // but not the first and last '/'
5438
+ }
5439
+ }
5440
+ else {
5441
+ // ----- Look for item to skip
5442
+ if ($v_skip > 0) {
5443
+ $v_skip--;
5444
+ }
5445
+ else {
5446
+ $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:"");
5447
+ }
5448
+ }
5449
+ }
5450
+
5451
+ // ----- Look for skip
5452
+ if ($v_skip > 0) {
5453
+ while ($v_skip > 0) {
5454
+ $v_result = '../'.$v_result;
5455
+ $v_skip--;
5456
+ }
5457
+ }
5458
+ }
5459
+
5460
+ // ----- Return
5461
+ return $v_result;
5462
+ }
5463
+ // --------------------------------------------------------------------------------
5464
+
5465
+ // --------------------------------------------------------------------------------
5466
+ // Function : PclZipUtilPathInclusion()
5467
+ // Description :
5468
+ // This function indicates if the path $p_path is under the $p_dir tree. Or,
5469
+ // said in an other way, if the file or sub-dir $p_path is inside the dir
5470
+ // $p_dir.
5471
+ // The function indicates also if the path is exactly the same as the dir.
5472
+ // This function supports path with duplicated '/' like '//', but does not
5473
+ // support '.' or '..' statements.
5474
+ // Parameters :
5475
+ // Return Values :
5476
+ // 0 if $p_path is not inside directory $p_dir
5477
+ // 1 if $p_path is inside directory $p_dir
5478
+ // 2 if $p_path is exactly the same as $p_dir
5479
+ // --------------------------------------------------------------------------------
5480
+ function PclZipUtilPathInclusion($p_dir, $p_path)
5481
+ {
5482
+ $v_result = 1;
5483
+
5484
+ // ----- Look for path beginning by ./
5485
+ if ( ($p_dir == '.')
5486
+ || ((strlen($p_dir) >=2) && (substr($p_dir, 0, 2) == './'))) {
5487
+ $p_dir = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_dir, 1);
5488
+ }
5489
+ if ( ($p_path == '.')
5490
+ || ((strlen($p_path) >=2) && (substr($p_path, 0, 2) == './'))) {
5491
+ $p_path = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_path, 1);
5492
+ }
5493
+
5494
+ // ----- Explode dir and path by directory separator
5495
+ $v_list_dir = explode("/", $p_dir);
5496
+ $v_list_dir_size = sizeof($v_list_dir);
5497
+ $v_list_path = explode("/", $p_path);
5498
+ $v_list_path_size = sizeof($v_list_path);
5499
+
5500
+ // ----- Study directories paths
5501
+ $i = 0;
5502
+ $j = 0;
5503
+ while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
5504
+
5505
+ // ----- Look for empty dir (path reduction)
5506
+ if ($v_list_dir[$i] == '') {
5507
+ $i++;
5508
+ continue;
5509
+ }
5510
+ if ($v_list_path[$j] == '') {
5511
+ $j++;
5512
+ continue;
5513
+ }
5514
+
5515
+ // ----- Compare the items
5516
+ if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != '')) {
5517
+ $v_result = 0;
5518
+ }
5519
+
5520
+ // ----- Next items
5521
+ $i++;
5522
+ $j++;
5523
+ }
5524
+
5525
+ // ----- Look if everything seems to be the same
5526
+ if ($v_result) {
5527
+ // ----- Skip all the empty items
5528
+ while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++;
5529
+ while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++;
5530
+
5531
+ if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
5532
+ // ----- There are exactly the same
5533
+ $v_result = 2;
5534
+ }
5535
+ else if ($i < $v_list_dir_size) {
5536
+ // ----- The path is shorter than the dir
5537
+ $v_result = 0;
5538
+ }
5539
+ }
5540
+
5541
+ // ----- Return
5542
+ return $v_result;
5543
+ }
5544
+ // --------------------------------------------------------------------------------
5545
+
5546
+ // --------------------------------------------------------------------------------
5547
+ // Function : PclZipUtilCopyBlock()
5548
+ // Description :
5549
+ // Parameters :
5550
+ // $p_mode : read/write compression mode
5551
+ // 0 : src & dest normal
5552
+ // 1 : src gzip, dest normal
5553
+ // 2 : src normal, dest gzip
5554
+ // 3 : src & dest gzip
5555
+ // Return Values :
5556
+ // --------------------------------------------------------------------------------
5557
+ function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0)
5558
+ {
5559
+ $v_result = 1;
5560
+
5561
+ if ($p_mode==0)
5562
+ {
5563
+ while ($p_size != 0)
5564
+ {
5565
+ $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
5566
+ $v_buffer = @fread($p_src, $v_read_size);
5567
+ @fwrite($p_dest, $v_buffer, $v_read_size);
5568
+ $p_size -= $v_read_size;
5569
+ }
5570
+ }
5571
+ else if ($p_mode==1)
5572
+ {
5573
+ while ($p_size != 0)
5574
+ {
5575
+ $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
5576
+ $v_buffer = @gzread($p_src, $v_read_size);
5577
+ @fwrite($p_dest, $v_buffer, $v_read_size);
5578
+ $p_size -= $v_read_size;
5579
+ }
5580
+ }
5581
+ else if ($p_mode==2)
5582
+ {
5583
+ while ($p_size != 0)
5584
+ {
5585
+ $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
5586
+ $v_buffer = @fread($p_src, $v_read_size);
5587
+ @gzwrite($p_dest, $v_buffer, $v_read_size);
5588
+ $p_size -= $v_read_size;
5589
+ }
5590
+ }
5591
+ else if ($p_mode==3)
5592
+ {
5593
+ while ($p_size != 0)
5594
+ {
5595
+ $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
5596
+ $v_buffer = @gzread($p_src, $v_read_size);
5597
+ @gzwrite($p_dest, $v_buffer, $v_read_size);
5598
+ $p_size -= $v_read_size;
5599
+ }
5600
+ }
5601
+
5602
+ // ----- Return
5603
+ return $v_result;
5604
+ }
5605
+ // --------------------------------------------------------------------------------
5606
+
5607
+ // --------------------------------------------------------------------------------
5608
+ // Function : PclZipUtilRename()
5609
+ // Description :
5610
+ // This function tries to do a simple rename() function. If it fails, it
5611
+ // tries to copy the $p_src file in a new $p_dest file and then unlink the
5612
+ // first one.
5613
+ // Parameters :
5614
+ // $p_src : Old filename
5615
+ // $p_dest : New filename
5616
+ // Return Values :
5617
+ // 1 on success, 0 on failure.
5618
+ // --------------------------------------------------------------------------------
5619
+ function PclZipUtilRename($p_src, $p_dest)
5620
+ {
5621
+ $v_result = 1;
5622
+
5623
+ // ----- Try to rename the files
5624
+ if (!@rename($p_src, $p_dest)) {
5625
+
5626
+ // ----- Try to copy & unlink the src
5627
+ if (!@copy($p_src, $p_dest)) {
5628
+ $v_result = 0;
5629
+ }
5630
+ else if (!@unlink($p_src)) {
5631
+ $v_result = 0;
5632
+ }
5633
+ }
5634
+
5635
+ // ----- Return
5636
+ return $v_result;
5637
+ }
5638
+ // --------------------------------------------------------------------------------
5639
+
5640
+ // --------------------------------------------------------------------------------
5641
+ // Function : PclZipUtilOptionText()
5642
+ // Description :
5643
+ // Translate option value in text. Mainly for debug purpose.
5644
+ // Parameters :
5645
+ // $p_option : the option value.
5646
+ // Return Values :
5647
+ // The option text value.
5648
+ // --------------------------------------------------------------------------------
5649
+ function PclZipUtilOptionText($p_option)
5650
+ {
5651
+
5652
+ $v_list = get_defined_constants();
5653
+ for (reset($v_list); $v_key = key($v_list); next($v_list)) {
5654
+ $v_prefix = substr($v_key, 0, 10);
5655
+ if (( ($v_prefix == 'PCLZIP_OPT')
5656
+ || ($v_prefix == 'PCLZIP_CB_')
5657
+ || ($v_prefix == 'PCLZIP_ATT'))
5658
+ && ($v_list[$v_key] == $p_option)) {
5659
+ return $v_key;
5660
+ }
5661
+ }
5662
+
5663
+ $v_result = 'Unknown';
5664
+
5665
+ return $v_result;
5666
+ }
5667
+ // --------------------------------------------------------------------------------
5668
+
5669
+ // --------------------------------------------------------------------------------
5670
+ // Function : PclZipUtilTranslateWinPath()
5671
+ // Description :
5672
+ // Translate windows path by replacing '\' by '/' and optionally removing
5673
+ // drive letter.
5674
+ // Parameters :
5675
+ // $p_path : path to translate.
5676
+ // $p_remove_disk_letter : true | false
5677
+ // Return Values :
5678
+ // The path translated.
5679
+ // --------------------------------------------------------------------------------
5680
+ function PclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter=true)
5681
+ {
5682
+ if (stristr(php_uname(), 'windows')) {
5683
+ // ----- Look for potential disk letter
5684
+ if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) {
5685
+ $p_path = substr($p_path, $v_position+1);
5686
+ }
5687
+ // ----- Change potential windows directory separator
5688
+ if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
5689
+ $p_path = strtr($p_path, '\\', '/');
5690
+ }
5691
+ }
5692
+ return $p_path;
5693
+ }
5694
+ // --------------------------------------------------------------------------------
5695
+
5696
+
5697
+ ?>
models/file/record.php CHANGED
@@ -22,8 +22,10 @@ class PMXI_File_Record extends PMXI_Model_Record {
22
 
23
  parent::insert();
24
 
 
 
25
  if (isset($this->id) and ! is_null($file_contents)) {
26
- file_put_contents(PMXI_Plugin::ROOT_DIR . '/history/' . $this->id, $file_contents);
27
  }
28
 
29
  $list = new PMXI_File_List();
@@ -44,7 +46,8 @@ class PMXI_File_Record extends PMXI_Model_Record {
44
  parent::update();
45
 
46
  if (isset($this->id) and ! is_null($file_contents)) {
47
- file_put_contents(PMXI_Plugin::ROOT_DIR . '/history/' . $this->id, $file_contents);
 
48
  }
49
 
50
  return $this;
@@ -52,7 +55,8 @@ class PMXI_File_Record extends PMXI_Model_Record {
52
 
53
  public function __isset($field) {
54
  if ('contents' == $field and ! $this->offsetExists($field)) {
55
- return isset($this->id) and file_exists(PMXI_Plugin::ROOT_DIR . '/history/' . $this->id);
 
56
  }
57
  return parent::__isset($field);
58
  }
@@ -60,7 +64,8 @@ class PMXI_File_Record extends PMXI_Model_Record {
60
  public function __get($field) {
61
  if ('contents' == $field and ! $this->offsetExists('contents')) {
62
  if (isset($this->contents)) {
63
- $this['contents'] = file_get_contents(PMXI_Plugin::ROOT_DIR . '/history/' . $this->id);
 
64
  } else {
65
  $this->contents = NULL;
66
  }
@@ -70,7 +75,8 @@ class PMXI_File_Record extends PMXI_Model_Record {
70
 
71
  public function delete() {
72
  if ($this->id) { // delete history file first
73
- $file_name = PMXI_Plugin::ROOT_DIR . '/history/' . $this->id;
 
74
  is_file($file_name) and unlink($file_name);
75
  }
76
  return parent::delete();
22
 
23
  parent::insert();
24
 
25
+ $uploads = wp_upload_dir();
26
+
27
  if (isset($this->id) and ! is_null($file_contents)) {
28
+ file_put_contents($uploads['basedir'] . '/wpallimport_history/' . $this->id, $file_contents);
29
  }
30
 
31
  $list = new PMXI_File_List();
46
  parent::update();
47
 
48
  if (isset($this->id) and ! is_null($file_contents)) {
49
+ $uploads = wp_upload_dir();
50
+ file_put_contents($uploads['basedir'] . '/wpallimport_history/' . $this->id, $file_contents);
51
  }
52
 
53
  return $this;
55
 
56
  public function __isset($field) {
57
  if ('contents' == $field and ! $this->offsetExists($field)) {
58
+ $uploads = wp_upload_dir();
59
+ return isset($this->id) and file_exists($uploads['basedir'] . '/wpallimport_history/' . $this->id);
60
  }
61
  return parent::__isset($field);
62
  }
64
  public function __get($field) {
65
  if ('contents' == $field and ! $this->offsetExists('contents')) {
66
  if (isset($this->contents)) {
67
+ $uploads = wp_upload_dir();
68
+ $this['contents'] = file_get_contents($uploads['basedir'] . '/wpallimport_history/' . $this->id);
69
  } else {
70
  $this->contents = NULL;
71
  }
75
 
76
  public function delete() {
77
  if ($this->id) { // delete history file first
78
+ $uploads = wp_upload_dir();
79
+ $file_name = $uploads['basedir'] . '/wpallimport_history/' . $this->id;
80
  is_file($file_name) and unlink($file_name);
81
  }
82
  return parent::delete();
models/import/record.php CHANGED
@@ -6,20 +6,12 @@ class PMXI_Import_Record extends PMXI_Model_Record {
6
  * Some pre-processing logic, such as removing control characters from xml to prevent parsing errors
7
  * @param string $xml
8
  */
9
- public static function preprocessXml( & $xml) {
10
- //$xml = preg_replace('%\pC(?<!\s)%u', '', $xml); // remove control chars but not white-spacing ones
11
- //use HTML::Entities;
12
 
13
- $xml = preg_replace("/&.{0,}?;/",'',$xml);
14
 
15
  }
16
 
17
- public static function uft8decodeXml( & $xml ){
18
-
19
- $xml = str_replace(array("&"), array("&amp;"), utf8_decode($xml));
20
-
21
- }
22
-
23
  /**
24
  * Validate XML to be valid for improt
25
  * @param string $xml
@@ -30,16 +22,15 @@ class PMXI_Import_Record extends PMXI_Model_Record {
30
  if (FALSE === $xml or '' == $xml) {
31
  $errors and $errors->add('form-validation', __('XML file does not exist, not accessible or empty', 'pmxi_plugin'));
32
  } else {
33
-
34
- if (PMXI_Plugin::getInstance()->getOption('utf8_decode')) PMXI_Import_Record::uft8decodeXml($xml);
35
- if (PMXI_Plugin::getInstance()->getOption('html_entities')) PMXI_Import_Record::preprocessXml($xml);
36
 
37
  libxml_use_internal_errors(true);
38
  libxml_clear_errors();
39
  $_x = @simplexml_load_string($xml);
40
  $xml_errors = libxml_get_errors();
41
  libxml_clear_errors();
42
- if ($xml_errors) {
43
  $error_msg = '<strong>' . __('Invalid XML', 'pmxi_plugin') . '</strong><ul>';
44
  foreach($xml_errors as $error) {
45
  $error_msg .= '<li>';
@@ -50,7 +41,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
50
  $error_msg .= '</li>';
51
  }
52
  $error_msg .= '</ul>';
53
- $errors and $errors->add('form-validation', $error_msg);
54
  } else {
55
  return true;
56
  }
@@ -65,114 +56,7 @@ class PMXI_Import_Record extends PMXI_Model_Record {
65
  public function __construct($data = array()) {
66
  parent::__construct($data);
67
  $this->setTable(PMXI_Plugin::getInstance()->getTablePrefix() . 'imports');
68
- }
69
-
70
- /**
71
- * Check whether current import should be perfomed again according to scheduling options
72
- */
73
- public function isDue()
74
- {
75
- if ( ! $this->scheduled or date('YmdHi') <= date('YmdHi', strtotime($this->registered_on))) return false; // scheduling is disabled or the task has been executed this very minute
76
- if ('0000-00-00 00:00:00' == $this->registered_on) return true; // never executed but scheduled
77
-
78
- $task = new _PMXI_Import_Record_Cron_Parser($this->scheduled);
79
- return $task->isDue($this->registered_on);
80
- }
81
-
82
- /**
83
- * Import all files matched by path
84
- * @param callback[optional] $logger Method where progress messages are submmitted
85
- * @return PMXI_Import_Record
86
- * @chainable
87
- */
88
- public function execute($logger = NULL) {
89
- $this->set('registered_on', date('Y-m-d H:i:s'))->save(); // update registered_on to indicated that job has been exectured even if no files are going to be imported by the rest of the method
90
-
91
- if ($this->path) {
92
- if (in_array($this->type, array('ftp', 'file'))) { // file paths support patterns
93
- $logger and call_user_func($logger, __('Reading files for import...', 'pmxi_plugin'));
94
- $files = PMXI_Helper::safe_glob($this->path, PMXI_Helper::GLOB_NODIR | PMXI_Helper::GLOB_PATH);
95
- $logger and call_user_func($logger, sprintf(_n('%s file found', '%s files found', count($files), 'pmxi_plugin'), count($files)));
96
- } else { // single file path
97
- $files = array($this->path);
98
- }
99
-
100
- foreach ($files as $ind => $path) {
101
- $logger and call_user_func($logger, sprintf(__('Importing %s (%s of %s)', 'pmxi_plugin'), $path, $ind + 1, count($files)));
102
-
103
- $contents = get_headers($path,1 );
104
-
105
- if (preg_match('%\W(zip)$%i', trim($path))){
106
-
107
- $uploads = wp_upload_dir();
108
-
109
- $newfile = $uploads['path']."/".md5(time()).'.zip';
110
-
111
- if (!copy($path, $newfile)) {
112
- $this->errors->add('form-validation', __('Failed upload ZIP archive', 'pmxi_plugin'));
113
- }
114
-
115
- $zip = zip_open($newfile);
116
- if (is_resource($zip)) {
117
- $uploads = wp_upload_dir();
118
- if($uploads['error']){
119
- $this->errors->add('form-validation', __('Can not create upload folder. Permision denied', 'pmxi_plugin'));
120
- }
121
- $filename = '';
122
- while ($zip_entry = zip_read($zip)) {
123
- $filename = zip_entry_name($zip_entry);
124
- $fp = fopen($uploads['path']."/".$filename, "w");
125
- if (zip_entry_open($zip, $zip_entry, "r")) {
126
- $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
127
- fwrite($fp,"$buf");
128
- zip_entry_close($zip_entry);
129
- fclose($fp);
130
- }
131
- break;
132
- }
133
- zip_close($zip);
134
- unlink($newfile);
135
- if (preg_match('%\W(csv)$%i', trim($filename)) or PMXI_Plugin::detect_csv($contents['Content-Type']))
136
- $xml = PMXI_Plugin::csv_to_xml($uploads['path'] .'/'. $filename);
137
- else
138
- $xml = @file_get_contents($uploads['path'] .'/'. $filename);
139
- }
140
-
141
- } elseif (preg_match('%\W(csv)$%i', trim($path)) or PMXI_Plugin::detect_csv($contents['Content-Type'])) {
142
- $uploads = wp_upload_dir();
143
- $fdata = file_get_contents($path);
144
- $fdata = utf8_encode($fdata);
145
- $tmpname = md5(time()).'.csv';
146
- file_put_contents($uploads['path'] .'/'. $tmpname, $fdata);
147
- $xml = PMXI_Plugin::csv_to_xml($uploads['path'] .'/'. $tmpname);
148
- }
149
- else
150
- {
151
- ob_start();
152
- readgzfile($path);
153
- $xml = ob_get_clean();
154
-
155
- $wp_uploads = wp_upload_dir();
156
- $url = $wp_uploads['url'] .'/'. basename($path);
157
- file_put_contents($wp_uploads['path'] .'/'. basename($path), $xml);
158
- chmod($wp_uploads['path'] .'/'. basename($path), '0755');
159
-
160
- if ($contents = get_headers($url,1 ) and PMXI_Plugin::detect_csv($contents['Content-Type'])) $xml = PMXI_Plugin::csv_to_xml($wp_uploads['path']. basename($path));
161
- }
162
- if ( ! $xml) {
163
- $logger and call_user_func($logger, __('<b>ERROR</b>', 'pmxi_plugin') . ': file is not accessible or empty');
164
- } elseif ( ! PMXI_Import_Record::validateXml($xml)) {
165
- $logger and call_user_func($logger, __('<b>ERROR</b>', 'pmxi_plugin') . ': file is not a properly fromatted XML document');
166
- } else {
167
- do_action( 'pmxi_before_xml_import' );
168
- $this->process($xml, $logger);
169
- do_action( 'pmxi_after_xml_import' );
170
- }
171
- }
172
- $logger and call_user_func($logger, __('Complete', 'pmxi_plugin'));
173
- }
174
- return $this;
175
- }
176
 
177
  /**
178
  * Perform import operation
@@ -181,25 +65,18 @@ class PMXI_Import_Record extends PMXI_Model_Record {
181
  * @return PMXI_Import_Record
182
  * @chainable
183
  */
184
- public function process($xml, $logger = NULL) {
185
  add_filter('user_has_cap', array($this, '_filter_has_cap_unfiltered_html')); kses_init(); // do not perform special filtering for imported content
186
 
187
- $this->options += PMXI_Plugin::get_default_import_options(); // make sure all options are defined
188
-
189
- $history_file = new PMXI_File_Record();
190
- $history_file->set(array(
191
- 'name' => $this->name,
192
- 'import_id' => $this->id,
193
- 'path' => $this->path,
194
- 'contents' => $xml,
195
- 'registered_on' => date('Y-m-d H:i:s'),
196
- ))->save();
197
 
198
  $postRecord = new PMXI_Post_Record();
199
 
200
  $tmp_files = array();
201
  // compose records to import
202
  $records = array();
 
203
  if ($this->options['is_import_specified']) {
204
  foreach (preg_split('% *, *%', $this->options['import_specified'], -1, PREG_SPLIT_NO_EMPTY) as $chank) {
205
  if (preg_match('%^(\d+)-(\d+)$%', $chank, $mtch)) {
@@ -208,45 +85,125 @@ class PMXI_Import_Record extends PMXI_Model_Record {
208
  $records = array_merge($records, array(intval($chank)));
209
  }
210
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
  }
212
- try {
213
 
214
- $logger and call_user_func($logger, __('Composing titles...', 'pmxi_plugin'));
215
  $titles = XmlImportParser::factory($xml, $this->xpath, $this->template['title'], $file)->parse($records); $tmp_files[] = $file;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
 
217
- $logger and call_user_func($logger, __('Composing contents...', 'pmxi_plugin'));
218
  $contents = XmlImportParser::factory(
219
  (intval($this->template['is_keep_linebreaks']) ? $xml : preg_replace('%\r\n?|\n%', ' ', $xml)),
220
  $this->xpath,
221
  $this->template['content'],
222
  $file)->parse($records
223
  ); $tmp_files[] = $file;
224
-
225
- $logger and call_user_func($logger, __('Composing dates...', 'pmxi_plugin'));
226
-
227
- $dates = XmlImportParser::factory($xml, $this->xpath, $this->options['date'], $file)->parse($records); $tmp_files[] = $file;
228
- $warned = array(); // used to prevent the same notice displaying several times
229
- foreach ($dates as $i => $d) {
230
- $time = strtotime($d);
231
- if (FALSE === $time) {
232
- in_array($d, $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: unrecognized date format `%s`, assigning current date', 'pmxi_plugin'), $warned[] = $d));
233
- $time = time();
 
 
 
234
  }
235
- $dates[$i] = date('Y-m-d H:i:s', $time);
236
- }
237
-
238
- if ('post' == $this->options['type']) {
239
- $tags = array();
240
- if ($this->options['tags']) {
241
- $logger and call_user_func($logger, __('Composing tags...', 'pmxi_plugin'));
242
- $tags_raw = XmlImportParser::factory($xml, $this->xpath, $this->options['tags'], $file)->parse($records); $tmp_files[] = $file;
243
- foreach ($tags_raw as $i => $t_raw) {
244
- $tags[$i] = '';
245
- if ('' != $t_raw) $tags[$i] = implode(', ', str_getcsv($t_raw, $this->options['tags_delim']));
246
  }
247
- } else {
248
- count($titles) and $tags = array_fill(0, count($titles), '');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
  }
 
 
 
 
 
 
 
250
 
251
  $cats = array();
252
 
@@ -254,44 +211,52 @@ class PMXI_Import_Record extends PMXI_Model_Record {
254
 
255
  if ((!empty($categories_hierarchy) and is_array($categories_hierarchy))){
256
 
257
- $logger and call_user_func($logger, __('Composing categories...', 'pmxi_plugin'));
258
  $categories = array();
259
 
260
- foreach ($categories_hierarchy as $category) $categories[] = $category->xpath;
261
-
262
- $cats_raw = XmlImportParser::factory($xml, $this->xpath, ((!empty($categories)) ? implode(',', $categories) : ''), $file)->parse($records); $tmp_files[] = $file;
263
- $warned = array(); // used to prevent the same notice displaying several times
264
- foreach ($cats_raw as $i => $c_raw) {
265
- $cats[$i] = array();
266
- if ('' != $c_raw) foreach (str_getcsv($c_raw, ',') as $j => $c) if ('' != $c) {
267
- $cat = get_term_by('name', $c, 'category') or ctype_digit($c) and $cat = get_term_by('id', $c, 'category');
268
- if ( ! $cat) { // create category automatically
269
- if (!empty($categories_hierarchy[$j]->parent_id)) {
270
- $parent_id = $this->reverse_hierarchy($categories_hierarchy, $c_raw, $categories_hierarchy[$j]->parent_id, $warned);
271
- $cat_id = wp_create_category($c, $parent_id);
272
- if ( ! $cat_id) {
273
- in_array($c, $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to create category `%s`, skipping', 'pmxi_plugin'), $warned[] = $c));
274
- } else {
275
- $cats[$i][] = $cat_id;
 
 
 
 
 
276
  }
277
- }
278
- else {
279
- $cat_id = wp_create_category($c);
280
- if ( ! $cat_id) {
281
- in_array($c, $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to create category `%s`, skipping', 'pmxi_plugin'), $warned[] = $c));
282
- } else {
283
- $cats[$i][] = $cat_id;
 
 
 
 
284
  }
285
- }
286
- } else {
287
- $cats[$i][] = $cat->term_id;
288
  }
 
289
  }
290
- }
291
- } else {
292
  count($titles) and $cats = array_fill(0, count($titles), '');
293
  }
294
- }
295
  // [custom taxonomies]
296
  $taxonomies = array();
297
  $taxonomies_param = $this->options['type'].'_taxonomies';
@@ -302,212 +267,295 @@ class PMXI_Import_Record extends PMXI_Model_Record {
302
  } else {
303
  $taxonomies_object_type = 'post';
304
  }
 
305
  if (!empty($this->options[$taxonomies_param]) and is_array($this->options[$taxonomies_param])): foreach ($this->options[$taxonomies_param] as $tx_name => $tx_template) if ('' != $tx_template) {
306
- $tx = get_taxonomy($tx_name);
307
  if (in_array($taxonomies_object_type, $tx->object_type)) {
308
- $logger and call_user_func($logger, sprintf(__('Composing terms for `%s` taxonomy...', 'pmxi_plugin'), $tx->labels->name));
309
  $txes = array();
310
-
311
- $taxonomies_hierarchy = json_decode($tx_template);
312
- foreach ($taxonomies_hierarchy as $taxonomy) $txes[] = $taxonomy->xpath;
313
-
314
- $txes_raw = XmlImportParser::factory($xml, $this->xpath, ((!empty($txes)) ? implode(',', $txes) : ''), $file)->parse($records); $tmp_files[] = $file;
315
- $warned = array();
316
- foreach ($txes_raw as $i => $tx_raw) {
317
- $taxonomies[$tx_name][$i] = array();
318
- if ('' != $tx_raw) foreach (str_getcsv($tx_raw, ',') as $j => $c) if ('' != $c) {
319
- $cat = get_term_by('name', $c, $tx_name) or ctype_digit($c) and $cat = get_term_by('id', $c, $tx_name);
320
- if ( ! $cat) { // create taxonomy automatically
321
- if (!empty($taxonomies_hierarchy[$j]->parent_id)) {
322
- $parent_term_id = $this->reverse_hierarchy($taxonomies_hierarchy, $tx_raw, $taxonomies_hierarchy[$j]->parent_id, $warned);
323
-
324
- $term = wp_insert_term(
325
- $c, // the term
326
- $tx_name, // the taxonomy
327
- array(
328
- 'parent'=> $parent_term_id
329
- )
330
- );
331
- $cat_id = $term['term_id'];
332
- if ( ! $cat_id) {
333
- in_array($c, $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to create category `%s`, skipping', 'pmxi_plugin'), $warned[] = $c));
334
- } else {
335
- $taxonomies[$tx_name][$i][] = $c;
336
- }
337
- }
338
- else {
339
- $term = wp_insert_term(
340
- $c, // the term
341
- $tx_name // the taxonomy
342
- );
343
- $cat_id = $term['term_id'];
344
- if ( ! $cat_id) {
345
- in_array($c, $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to create category `%s`, skipping', 'pmxi_plugin'), $warned[] = $c));
346
- } else {
347
- $taxonomies[$tx_name][$i][] = $c;
348
  }
349
- }
350
- } else {
351
- $taxonomies[$tx_name][$i][] = $cat->name;
 
 
 
 
 
 
 
 
 
 
352
  }
353
- }
 
354
  }
355
  }
356
  }; endif;
357
- // [/custom taxonomies]
358
-
359
- $logger and call_user_func($logger, __('Composing custom parameters...', 'pmxi_plugin'));
360
- $meta_keys = array(); $meta_values = array();
361
- foreach ($this->options['custom_name'] as $j => $custom_name) {
362
- $meta_keys[$j] = XmlImportParser::factory($xml, $this->xpath, $custom_name, $file)->parse($records); $tmp_files[] = $file;
363
- $meta_values[$j] = XmlImportParser::factory($xml, $this->xpath, $this->options['custom_value'][$j], $file)->parse($records); $tmp_files[] = $file;
364
- }
365
- // serialized custom post fields
366
- $serialized_meta = array();
367
- if (!empty($meta_keys)){
368
- foreach ($meta_keys as $j => $custom_name) {
369
- if (!in_array($custom_name[0], array_keys($serialized_meta))){
370
- $serialized_meta[$custom_name[0]] = array($meta_values[$j]);
371
- }
372
- else{
373
- $serialized_meta[$custom_name[0]][] = $meta_values[$j];
374
- }
375
- }
376
- }
377
  if ( ! (($uploads = wp_upload_dir()) && false === $uploads['error'])) {
378
- $logger and call_user_func($logger, __('<b>ERROR</b>', 'pmxi_plugin') . ': ' . $uploads['error']);
379
- $logger and call_user_func($logger, __('<b>WARNING</b>: No featured images will be created', 'pmxi_plugin'));
 
380
  } else {
381
- $logger and call_user_func($logger, __('Composing URLs for featured images...', 'pmxi_plugin'));
382
- $featured_images = array();
383
- if ($this->options['featured_image']) {
384
- // Detect if images is separated by comma
385
- $imgs = explode(',',$this->options['featured_image']);
386
- if (!empty($imgs)){
387
  $parse_multiple = true;
388
- foreach($imgs as $img) if (!preg_match("/{.*}/", trim($img))) $parse_multiple = false;
389
 
390
  if ($parse_multiple)
391
  {
392
- foreach($imgs as $img)
393
  {
394
- $posts_images = XmlImportParser::factory($xml, $this->xpath, trim($img), $file)->parse($records); $tmp_files[] = $file;
395
- foreach($posts_images as $i => $val) $featured_images[$i][] = $val;
396
  }
397
  }
398
  else
399
  {
400
- $featured_images = XmlImportParser::factory($xml, $this->xpath, $this->options['featured_image'], $file)->parse($records); $tmp_files[] = $file;
401
  }
402
  }
403
 
404
  } else {
405
- count($titles) and $featured_images = array_fill(0, count($titles), '');
406
  }
407
- }
408
- $logger and call_user_func($logger, __('Composing unique keys...', 'pmxi_plugin'));
 
409
  $unique_keys = XmlImportParser::factory($xml, $this->xpath, $this->options['unique_key'], $file)->parse($records); $tmp_files[] = $file;
410
 
411
- $logger and call_user_func($logger, __('Processing posts...', 'pmxi_plugin'));
412
 
413
  if ('post' == $this->options['type'] and '' != $this->options['custom_type']) {
414
  $post_type = $this->options['custom_type'];
415
  } else {
416
  $post_type = $this->options['type'];
417
- }
418
-
419
  $current_post_ids = array();
420
- foreach ($titles as $i => $void) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
421
  $articleData = array(
422
  'post_type' => $post_type,
423
  'post_status' => $this->options['status'],
424
  'comment_status' => $this->options['comment_status'],
425
  'ping_status' => $this->options['ping_status'],
426
- 'post_title' => $titles[$i],
427
- 'post_content' => $contents[$i],
 
 
428
  'post_date' => $dates[$i],
429
  'post_date_gmt' => get_gmt_from_date($dates[$i]),
430
- 'post_author' => $this->options['author'],
 
431
  );
432
- if ('post' == $articleData['post_type']) {
433
- $articleData += array(
434
- 'post_category' => $cats[$i],
435
- 'tags_input' => $tags[$i],
436
- );
437
- } else { // page
438
  $articleData += array(
439
  'menu_order' => $this->options['order'],
440
  'post_parent' => $this->options['parent'],
441
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
442
  }
443
- $postRecord->clear();
444
- // find corresponding article among previously imported
445
- $postRecord->getBy(array(
446
- 'unique_key' => $unique_keys[$i],
447
- 'import_id' => $this->id,
448
- ));
449
- if ( ! $postRecord->isEmpty()) {
450
- $post_to_update = get_post($post_to_update_id = $postRecord->post_id);
451
- if ($post_to_update) { // existing post is found
452
- if ($this->options['is_keep_former_posts']) {
453
- $current_post_ids[] = $postRecord->post_id;
454
- $logger and call_user_func($logger, sprintf(__('<b>SKIPPED</b>: Previously imported record found for `%s`', 'pmxi_plugin'), $articleData['post_title']));
455
- continue;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
456
  }
457
- $articleData['ID'] = $postRecord->post_id;
458
- // preserve date of already existing article when duplicate is found
459
- $articleData['post_date'] = $post_to_update->post_date;
460
- $articleData['post_date_gmt'] = $post_to_update->post_date_gmt;
461
- if ($this->options['is_keep_categories']) { // preserve categories and tags of already existing article if corresponding setting is specified
462
- $cats_list = get_the_category($articleData['ID']);
463
- if (is_wp_error($cats_list)) {
464
- $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to get current categories for article #%d, updating with those read from XML file', 'pmxi_plugin'), $articleData['ID']));
465
- } else {
466
- $cats_new = array();
467
- foreach ($cats_list as $c) {
468
- $cats_new[] = $c->cat_ID;
469
- }
470
- $articleData['post_category'] = $cats_new;
471
  }
472
-
473
- $tags_list = get_the_tags($articleData['ID']);
474
- if (is_wp_error($tags_list)) {
475
- $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to get current tags for article #%d, updating with those read from XML file', 'pmxi_plugin'), $articleData['ID']));
 
 
 
 
476
  } else {
477
- $tags_new = array();
478
- if ($tags_list) foreach ($tags_list as $t) {
479
- $tags_new[] = $t->name;
480
- }
481
- $articleData['tags_input'] = implode(', ', $tags_new);
482
- }
483
-
484
- foreach (array_keys($taxonomies) as $tx_name) {
485
- $txes_list = get_the_terms($articleData['ID'], $tx_name);
486
- if (is_wp_error($txes_list)) {
487
- $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to get current taxonomies for article #%d, updating with those read from XML file', 'pmxi_plugin'), $articleData['ID']));
488
- } else {
489
- $txes_new = array();
490
  foreach ($txes_list as $t) {
491
  $txes_new[] = $t->name;
492
  }
493
- $taxonomies[$tx_name][$i] = $txes_new;
494
- }
495
  }
496
  }
497
- if ($this->options['is_keep_status']) { // preserve status and trashed flag
498
- $articleData['post_status'] = $post_to_update->post_status;
499
- }
500
- if ($this->options['is_keep_content']){ // Re-run an importer to pull in one more custom field... without nuking their edits in the process..
501
- $articleData['post_content'] = $post_to_update->post_content;
502
- }
503
- } else { // existing post not found though it's track was found... clear the leftover, plugin will continue to treat record as new
504
- $postRecord->delete();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505
  }
506
  }
507
-
508
- if ( ! empty($articleData['ID'])) { // handle obsolete attachments (i.e. delete or keep) according to import settings
509
- empty($this->options['is_keep_attachments']) and wp_delete_attachments($articleData['ID']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
510
  }
 
511
  // cloak urls with `WP Wizard Cloak` if corresponding option is set
512
  if ( ! empty($this->options['is_cloak']) and class_exists('PMLC_Plugin')) {
513
  if (preg_match_all('%<a\s[^>]*href=(?(?=")"([^"]*)"|(?(?=\')\'([^\']*)\'|([^\s>]*)))%is', $articleData['post_content'], $matches, PREG_PATTERN_ORDER)) {
@@ -572,7 +620,8 @@ class PMXI_Import_Record extends PMXI_Model_Record {
572
  ));
573
  $dest->insert();
574
  } else {
575
- $logger and call_user_func($logger, sprintf(__('<b>ERROR</b>: Unable to create cloaked link for %s', 'pmxi_plugin'), $url));
 
576
  $link = NULL;
577
  }
578
  }
@@ -582,44 +631,191 @@ class PMXI_Import_Record extends PMXI_Model_Record {
582
  }
583
  }
584
  }
585
- }
586
- // insert article being imported
587
- $pid = wp_insert_post($articleData, true);
 
 
588
  if (is_wp_error($pid)) {
589
- $logger and call_user_func($logger, __('<b>ERROR</b>', 'pmxi_plugin') . ': ' . $pid->get_error_message());
 
590
  } else {
591
 
592
  do_action( 'pmxi_saved_post', $pid); // hook that was triggered immediately after post saved
593
 
594
- $current_post_ids[] = $pid;
595
- // associate post with import
596
- $postRecord->isEmpty() and $postRecord->set(array(
597
- 'post_id' => $pid,
598
- 'import_id' => $this->id,
599
- 'unique_key' => $unique_keys[$i],
600
- ))->insert();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
601
 
602
  // [custom taxonomies]
603
  foreach ($taxonomies as $tx_name => $txes) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
604
  $term_ids = wp_set_object_terms($pid, $txes[$i], $tx_name);
605
  if (is_wp_error($term_ids)) {
606
- $logger and call_user_func($logger, __('<b>ERROR</b>', 'pmxi_plugin') . ': '.$term_ids->get_error_message());
 
607
  }
608
  }
609
  // [/custom taxonomies]
610
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
611
  if (empty($articleData['ID'])) {
 
612
  $logger and call_user_func($logger, sprintf(__('`%s` post created successfully', 'pmxi_plugin'), $articleData['post_title']));
613
  } else {
 
614
  $logger and call_user_func($logger, sprintf(__('`%s` post updated successfully', 'pmxi_plugin'), $articleData['post_title']));
615
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
616
  }
 
 
 
 
 
 
 
 
 
 
617
  wp_cache_flush();
618
- }
619
- if ( ! empty($this->options['is_delete_missing'])) { // delete posts which are not in current import set
620
  $logger and call_user_func($logger, 'Removing previously imported posts which are no longer actual...');
621
- $postList = new PMXI_Post_List();
622
- foreach ($postList->getBy(array('import_id' => $this->id, 'post_id NOT IN' => $current_post_ids)) as $missingPost) {
 
623
  empty($this->options['is_keep_attachments']) and wp_delete_attachments($missingPost['post_id']);
624
  wp_delete_post($missingPost['post_id'], true);
625
  }
@@ -627,57 +823,28 @@ class PMXI_Import_Record extends PMXI_Model_Record {
627
 
628
  } catch (XmlImportException $e) {
629
  $logger and call_user_func($logger, __('<b>ERROR</b>', 'pmxi_plugin') . ': ' . $e->getMessage());
630
- }
 
 
631
  $this->set('registered_on', date('Y-m-d H:i:s'))->save(); // specify execution is successful
632
 
633
- $logger and call_user_func($logger, __('Cleaning temporary data...', 'pmxi_plugin'));
634
  foreach ($tmp_files as $file) { // remove all temporary files created
635
  unlink($file);
636
  }
637
 
638
- if ($this->options['is_delete_source'] and $last_chank) {
639
  $logger and call_user_func($logger, __('Deleting source XML file...', 'pmxi_plugin'));
640
  if ( ! @unlink($this->path)) {
641
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to remove %s', 'pmxi_plugin'), $this->path));
642
  }
643
  }
644
- $logger and call_user_func($logger, 'Done');
645
 
646
  remove_filter('user_has_cap', array($this, '_filter_has_cap_unfiltered_html')); kses_init(); // return any filtering rules back if they has been disabled for import procedure
647
 
648
  return $this;
649
  }
650
-
651
- public function reverse_hierarchy($categories_hierarchy, $c_raw, $parent_id = null, &$warned, $taxonomy = 'category'){
652
- foreach (str_getcsv($c_raw, ',') as $j => $c) if ('' != $c and $categories_hierarchy[$j]->item_id == $parent_id) {
653
- $cat = get_term_by('name', $c, $taxonomy) or ctype_digit($c) and $cat = get_term_by('id', $c, $taxonomy);
654
- if ( ! $cat) { // create category automatically
655
- if (!empty($categories_hierarchy[$j]->parent_id)) {
656
- return $this->reverse_hierarchy($categories_hierarchy, $c_raw, $categories_hierarchy[$j]->parent_id, $warned, $taxonomy);
657
- }
658
- else {
659
- if ($taxonomy == 'category')
660
- {
661
- $cat_id = wp_create_category($c);
662
- }
663
- else{
664
- $term = wp_insert_term(
665
- $c,
666
- $taxonomy
667
- );
668
- $cat_id = $term['term_id'];
669
- }
670
- if ( ! $cat_id) {
671
- in_array($c, $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to create category `%s`, skipping', 'pmxi_plugin'), $warned[] = $c));
672
- } else {
673
- return $cat_id;
674
- }
675
- }
676
- } else {
677
- return $cat->term_id;
678
- }
679
- }
680
- }
681
 
682
  public function _filter_has_cap_unfiltered_html($caps)
683
  {
@@ -688,20 +855,41 @@ class PMXI_Import_Record extends PMXI_Model_Record {
688
  /**
689
  * Find duplicates according to settings
690
  */
691
- public function findDuplicates($articleData)
692
- {
693
- $field = 'post_' . $this->options['duplicate_indicator']; // post_title or post_content
694
- return $this->wpdb->get_col($this->wpdb->prepare("
695
- SELECT ID FROM " . $this->wpdb->posts . "
696
- WHERE
697
- post_type = %s
698
- AND ID != %s
699
- AND REPLACE(REPLACE(REPLACE($field, ' ', ''), '\\t', ''), '\\n', '') = %s
700
- ",
701
- $articleData['post_type'],
702
- isset($articleData['ID']) ? $articleData['ID'] : 0,
703
- preg_replace('%[ \\t\\n]%', '', $articleData[$field])
704
- ));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
705
  }
706
 
707
  /**
@@ -715,9 +903,31 @@ class PMXI_Import_Record extends PMXI_Model_Record {
715
  if ($keepPosts) {
716
  $this->wpdb->query($this->wpdb->prepare('DELETE FROM ' . $post->getTable() . ' WHERE import_id = %s', $this->id));
717
  } else {
 
718
  foreach ($post->getBy('import_id', $this->id)->convertRecords() as $p) {
719
- empty($this->options['is_keep_attachments']) and wp_delete_attachments($p->post_id);
720
- wp_delete_post($p->post_id, TRUE);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
721
  }
722
  }
723
  return $this;
@@ -746,160 +956,3 @@ class PMXI_Import_Record extends PMXI_Model_Record {
746
  }
747
 
748
  }
749
-
750
- /**
751
- * Cron schedule parser
752
- */
753
- class _PMXI_Import_Record_Cron_Parser
754
- {
755
- /**
756
- * @var array Cron parts
757
- */
758
- private $_cronParts;
759
-
760
- /**
761
- * Constructor
762
- *
763
- * @param string $schedule Cron schedule string (e.g. '8 * * * *'). The
764
- * schedule can handle ranges (10-12) and intervals
765
- * (*\/10 [remove the backslash]). Schedule parts should map to
766
- * minute [0-59], hour [0-23], day of month, month [1-12], day of week [1-7]
767
- *
768
- * @throws InvalidArgumentException if $schedule is not a valid cron schedule
769
- */
770
- public function __construct($schedule)
771
- {
772
- $this->_cronParts = explode(' ', $schedule);
773
- if (count($this->_cronParts) != 5) {
774
- throw new Exception($schedule . ' is not a valid cron schedule string');
775
- }
776
- }
777
-
778
- /**
779
- * Check if a date/time unit value satisfies a crontab unit
780
- *
781
- * @param DateTime $nextRun Current next run date
782
- * @param string $unit Date/time unit type (e.g. Y, m, d, H, i)
783
- * @param string $schedule Cron schedule variable
784
- *
785
- * @return bool Returns TRUE if the unit satisfies the constraint
786
- */
787
- public function unitSatisfiesCron(DateTime $nextRun, $unit, $schedule)
788
- {
789
- $unitValue = (int)$nextRun->format($unit);
790
-
791
- if ($schedule == '*') {
792
- return true;
793
- } if (strpos($schedule, '-')) {
794
- list($first, $last) = explode('-', $schedule);
795
- return $unitValue >= $first && $unitValue <= $last;
796
- } else if (strpos($schedule, '*/') !== false) {
797
- list($delimiter, $interval) = explode('*/', $schedule);
798
- return $unitValue % (int)$interval == 0;
799
- } else {
800
- return $unitValue == (int)$schedule;
801
- }
802
- }
803
-
804
- /**
805
- * Get the date in which the cron will run next
806
- *
807
- * @param string|DateTime (optional) $fromTime Set the relative start time
808
- *
809
- * @return DateTime
810
- */
811
- public function getNextRunDate($fromTime = 'now')
812
- {
813
- $nextRun = ($fromTime instanceof DateTime) ? $fromTime : new DateTime($fromTime);
814
- $nextRun->setTime($nextRun->format('H'), $nextRun->format('i'), 0);
815
- $nextRun->modify('+1 minute'); // make sure we don't return the very date is submitted to the function
816
- $nextRunLimit = clone $nextRun; $nextRunLimit->modify('+1 year');
817
-
818
- while ($nextRun < $nextRunLimit) { // Set a hard limit to bail on an impossible date
819
-
820
- // Adjust the month until it matches. Reset day to 1 and reset time.
821
- if ( ! $this->unitSatisfiesCron($nextRun, 'm', $this->getSchedule('month'))) {
822
- $nextRun->modify('+1 month');
823
- $nextRun->setDate($nextRun->format('Y'), $nextRun->format('m'), 1);
824
- $nextRun->setTime(0, 0, 0);
825
- continue;
826
- }
827
-
828
- // Adjust the day of the month by incrementing the day until it matches. Reset time.
829
- if ( ! $this->unitSatisfiesCron($nextRun, 'd', $this->getSchedule('day_of_month'))) {
830
- $nextRun->modify('+1 day');
831
- $nextRun->setTime(0, 0, 0);
832
- continue;
833
- }
834
-
835
- // Adjust the day of week by incrementing the day until it matches. Resest time.
836
- if ( ! $this->unitSatisfiesCron($nextRun, 'N', $this->getSchedule('day_of_week'))) {
837
- $nextRun->modify('+1 day');
838
- $nextRun->setTime(0, 0, 0);
839
- continue;
840
- }
841
-
842
- // Adjust the hour until it matches the set hour. Set seconds and minutes to 0
843
- if ( ! $this->unitSatisfiesCron($nextRun, 'H', $this->getSchedule('hour'))) {
844
- $nextRun->modify('+1 hour');
845
- $nextRun->setTime($nextRun->format('H'), 0, 0);
846
- continue;
847
- }
848
-
849
- // Adjust the minutes until it matches a set minute
850
- if ( ! $this->unitSatisfiesCron($nextRun, 'i', $this->getSchedule('minute'))) {
851
- $nextRun->modify('+1 minute');
852
- continue;
853
- }
854
-
855
- break;
856
- }
857
-
858
- return $nextRun;
859
- }
860
-
861
- /**
862
- * Get all or part of the cron schedule string
863
- *
864
- * @param string $part Specify the part to retrieve or NULL to get the full
865
- * cron schedule string. $part can be the PHP date() part of a date
866
- * formatted string or one of the following values:
867
- * NULL, 'minute', 'hour', 'month', 'day_of_week', 'day_of_month'
868
- *
869
- * @return string
870
- */
871
- public function getSchedule($part = null)
872
- {
873
- switch ($part) {
874
- case 'minute': case 'i':
875
- return $this->_cronParts[0];
876
- case 'hour': case 'H':
877
- return $this->_cronParts[1];
878
- case 'day_of_month': case 'd':
879
- return $this->_cronParts[2];
880
- case 'month': case 'm':
881
- return $this->_cronParts[3];
882
- case 'day_of_week': case 'N':
883
- return $this->_cronParts[4];
884
- default:
885
- return implode(' ', $this->_cronParts);
886
- }
887
- }
888
-
889
- /**
890
- * Deterime if the cron is due to run based on the current time, last run
891
- * time, and the next run time.
892
- *
893
- * If the relative next run time based on the last run time is not equal to
894
- * the next suggested run time based on the current time, then the cron
895
- * needs to run.
896
- *
897
- * @param string|DateTime $lastRun (optional) Date the cron was last run.
898
- *
899
- * @return bool Returns TRUE if the cron is due to run or FALSE if not
900
- */
901
- public function isDue($lastRun = 'now')
902
- {
903
- return $this->getNextRunDate($lastRun) < $this->getNextRunDate();
904
- }
905
- }
6
  * Some pre-processing logic, such as removing control characters from xml to prevent parsing errors
7
  * @param string $xml
8
  */
9
+ public static function preprocessXml( & $xml) {
 
 
10
 
11
+ $xml = str_replace("&", "&amp;", str_replace("&amp;","&", $xml));
12
 
13
  }
14
 
 
 
 
 
 
 
15
  /**
16
  * Validate XML to be valid for improt
17
  * @param string $xml
22
  if (FALSE === $xml or '' == $xml) {
23
  $errors and $errors->add('form-validation', __('XML file does not exist, not accessible or empty', 'pmxi_plugin'));
24
  } else {
25
+
26
+ PMXI_Import_Record::preprocessXml($xml);
 
27
 
28
  libxml_use_internal_errors(true);
29
  libxml_clear_errors();
30
  $_x = @simplexml_load_string($xml);
31
  $xml_errors = libxml_get_errors();
32
  libxml_clear_errors();
33
+ if ($xml_errors) {
34
  $error_msg = '<strong>' . __('Invalid XML', 'pmxi_plugin') . '</strong><ul>';
35
  foreach($xml_errors as $error) {
36
  $error_msg .= '<li>';
41
  $error_msg .= '</li>';
42
  }
43
  $error_msg .= '</ul>';
44
+ $errors and $errors->add('form-validation', $error_msg);
45
  } else {
46
  return true;
47
  }
56
  public function __construct($data = array()) {
57
  parent::__construct($data);
58
  $this->setTable(PMXI_Plugin::getInstance()->getTablePrefix() . 'imports');
59
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
  /**
62
  * Perform import operation
65
  * @return PMXI_Import_Record
66
  * @chainable
67
  */
68
+ public function process($xml, $logger = NULL, $chunk = false, $is_cron = false) {
69
  add_filter('user_has_cap', array($this, '_filter_has_cap_unfiltered_html')); kses_init(); // do not perform special filtering for imported content
70
 
71
+ $this->options += PMXI_Plugin::get_default_import_options(); // make sure all options are defined
72
+ // If import process NOT in large file mode the save history file
 
 
 
 
 
 
 
 
73
 
74
  $postRecord = new PMXI_Post_Record();
75
 
76
  $tmp_files = array();
77
  // compose records to import
78
  $records = array();
79
+ $chunk_records = array();
80
  if ($this->options['is_import_specified']) {
81
  foreach (preg_split('% *, *%', $this->options['import_specified'], -1, PREG_SPLIT_NO_EMPTY) as $chank) {
82
  if (preg_match('%^(\d+)-(\d+)$%', $chank, $mtch)) {
85
  $records = array_merge($records, array(intval($chank)));
86
  }
87
  }
88
+
89
+ $chunk_records = $records;
90
+
91
+ if ($this->large_import == 'Yes' and !empty($records)){
92
+
93
+ $_SESSION['pmxi_import']['count'] = count($records);
94
+
95
+ $records_count = $_SESSION['pmxi_import']['created_records'] + $_SESSION['pmxi_import']['updated_records'] + $_SESSION['pmxi_import']['skipped_records'] + $_SESSION['pmxi_import']['errors'];;
96
+
97
+ if (!in_array($chunk, $records) and (!$this->options['create_chunks'] or $is_cron)){
98
+ $logger and call_user_func($logger, __('<b>SKIPPED</b>: by specified records option', 'pmxi_plugin'));
99
+ $_SESSION['pmxi_import']['warnings']++;
100
+ // Time Elapsed
101
+ if ( ! $is_cron ){
102
+ $progress_msg = '<p class="import_process_bar"> Created ' . $_SESSION['pmxi_import']['created_records'] . ' / Updated ' . $_SESSION['pmxi_import']['updated_records'] . ' of '. $_SESSION['pmxi_import']['count'].' records.</p><span class="import_percent">' . ceil(($records_count/$_SESSION['pmxi_import']['count']) * 100) . '</span><span class="warnings_count">' . $_SESSION['pmxi_import']['warnings'] . '</span><span class="errors_count">' . $_SESSION['pmxi_import']['errors'] . '</span>';
103
+ $logger and call_user_func($logger, $progress_msg);
104
+ }
105
+ $_SESSION['pmxi_import']['chunk_number']++;
106
+ return;
107
+ }
108
+ else $records = array();
109
+ }
110
  }
111
+ try {
112
 
113
+ ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing titles...', 'pmxi_plugin'));
114
  $titles = XmlImportParser::factory($xml, $this->xpath, $this->template['title'], $file)->parse($records); $tmp_files[] = $file;
115
+ if ($this->large_import != 'Yes') $_SESSION['pmxi_import']['count'] = count($titles);
116
+
117
+ ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing excerpts...', 'pmxi_plugin'));
118
+ $post_excerpt = array();
119
+ if (!empty($this->options['post_excerpt'])){
120
+ $post_excerpt = XmlImportParser::factory($xml, $this->xpath, $this->options['post_excerpt'], $file)->parse($records); $tmp_files[] = $file;
121
+ }
122
+ else{
123
+ count($titles) and $post_excerpt = array_fill(0, count($titles), '');
124
+ }
125
+
126
+ ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing authors...', 'pmxi_plugin'));
127
+ $post_author = array();
128
+ $current_user = wp_get_current_user();
129
+
130
+ if (!empty($this->options['author'])){
131
+ $post_author = XmlImportParser::factory($xml, $this->xpath, $this->options['author'], $file)->parse($records); $tmp_files[] = $file;
132
+ foreach ($post_author as $key => $author) {
133
+ $user = get_user_by('login', $author) or $user = get_user_by('slug', $author) or $user = get_user_by('email', $author) or ctype_digit($author) and $user = get_user_by('id', $author);
134
+ $post_author[$key] = (!empty($user)) ? $user->ID : $current_user->ID;
135
+ }
136
+ }
137
+ else{
138
+ count($titles) and $post_author = array_fill(0, count($titles), $current_user->ID);
139
+ }
140
+
141
+ ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing slugs...', 'pmxi_plugin'));
142
+ $post_slug = array();
143
+ if (!empty($this->options['post_slug'])){
144
+ $post_slug = XmlImportParser::factory($xml, $this->xpath, $this->options['post_slug'], $file)->parse($records); $tmp_files[] = $file;
145
+ }
146
+ else{
147
+ count($titles) and $post_slug = array_fill(0, count($titles), '');
148
+ }
149
 
150
+ ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing contents...', 'pmxi_plugin'));
151
  $contents = XmlImportParser::factory(
152
  (intval($this->template['is_keep_linebreaks']) ? $xml : preg_replace('%\r\n?|\n%', ' ', $xml)),
153
  $this->xpath,
154
  $this->template['content'],
155
  $file)->parse($records
156
  ); $tmp_files[] = $file;
157
+
158
+ ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing dates...', 'pmxi_plugin'));
159
+ if ('specific' == $this->options['date_type']) {
160
+ $dates = XmlImportParser::factory($xml, $this->xpath, $this->options['date'], $file)->parse($records); $tmp_files[] = $file;
161
+ $warned = array(); // used to prevent the same notice displaying several times
162
+ foreach ($dates as $i => $d) {
163
+ $time = strtotime($d);
164
+ if (FALSE === $time) {
165
+ in_array($d, $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: unrecognized date format `%s`, assigning current date', 'pmxi_plugin'), $warned[] = $d));
166
+ $_SESSION['pmxi_import']['warnings']++;
167
+ $time = time();
168
+ }
169
+ $dates[$i] = date('Y-m-d H:i:s', $time);
170
  }
171
+ } else {
172
+ $dates_start = XmlImportParser::factory($xml, $this->xpath, $this->options['date_start'], $file)->parse($records); $tmp_files[] = $file;
173
+ $dates_end = XmlImportParser::factory($xml, $this->xpath, $this->options['date_end'], $file)->parse($records); $tmp_files[] = $file;
174
+ $warned = array(); // used to prevent the same notice displaying several times
175
+ foreach ($dates_start as $i => $d) {
176
+ $time_start = strtotime($dates_start[$i]);
177
+ if (FALSE === $time_start) {
178
+ in_array($dates_start[$i], $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: unrecognized date format `%s`, assigning current date', 'pmxi_plugin'), $warned[] = $dates_start[$i]));
179
+ $_SESSION['pmxi_import']['warnings']++;
180
+ $time_start = time();
 
181
  }
182
+ $time_end = strtotime($dates_end[$i]);
183
+ if (FALSE === $time_end) {
184
+ in_array($dates_end[$i], $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: unrecognized date format `%s`, assigning current date', 'pmxi_plugin'), $warned[] = $dates_end[$i]));
185
+ $_SESSION['pmxi_import']['warnings']++;
186
+ $time_end = time();
187
+ }
188
+ $dates[$i] = date('Y-m-d H:i:s', mt_rand($time_start, $time_end));
189
+ }
190
+ }
191
+
192
+ $tags = array();
193
+ if ($this->options['tags']) {
194
+ ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing tags...', 'pmxi_plugin'));
195
+ $tags_raw = XmlImportParser::factory($xml, $this->xpath, $this->options['tags'], $file)->parse($records); $tmp_files[] = $file;
196
+ foreach ($tags_raw as $i => $t_raw) {
197
+ $tags[$i] = '';
198
+ if ('' != $t_raw) $tags[$i] = implode(', ', str_getcsv($t_raw, $this->options['tags_delim']));
199
  }
200
+ } else {
201
+ count($titles) and $tags = array_fill(0, count($titles), '');
202
+ }
203
+
204
+ require_once(ABSPATH . 'wp-admin/includes/taxonomy.php');
205
+
206
+ if ('post' == $this->options['type']) {
207
 
208
  $cats = array();
209
 
211
 
212
  if ((!empty($categories_hierarchy) and is_array($categories_hierarchy))){
213
 
214
+ ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing categories...', 'pmxi_plugin'));
215
  $categories = array();
216
 
217
+ foreach ($categories_hierarchy as $k => $category): if ("" == $category->xpath) continue;
218
+ $cats_raw = XmlImportParser::factory($xml, $this->xpath, str_replace('\'','"',$category->xpath), $file)->parse($records); $tmp_files[] = $file;
219
+ $warned = array(); // used to prevent the same notice displaying several times
220
+ foreach ($cats_raw as $i => $c_raw) {
221
+ if (empty($categories_hierarchy[$k]->cat_ids[$i])) $categories_hierarchy[$k]->cat_ids[$i] = array();
222
+ if (empty($cats[$i])) $cats[$i] = array();
223
+ if ('' != $c_raw) foreach (str_getcsv($c_raw, ',') as $c_cell) if ('' != $c_cell) {
224
+ foreach (str_getcsv($c_cell, $this->options['categories_delim']) as $j => $cc) if ('' != $cc) {
225
+ $cat = get_term_by('name', trim($cc), 'category') or $cat = get_term_by('slug', trim($cc), 'category') or ctype_digit($cc) and $cat = get_term_by('id', trim($cc), 'category');
226
+ if ( !empty($categories_hierarchy[$k]->parent_id) ) {
227
+ foreach ($categories_hierarchy as $key => $value){
228
+ if ($value->item_id == $categories_hierarchy[$k]->parent_id and !empty($value->cat_ids[$i])){
229
+ foreach ($value->cat_ids[$i] as $parent) {
230
+ $cats[$i][] = array(
231
+ 'name' => trim($cc),
232
+ 'parent' => (is_array($parent)) ? $parent['name'] : $parent, // if parent taxonomy exists then return ID else return TITLE
233
+ 'assign' => $category->assign
234
+ );
235
+ }
236
+ }
237
+ }
238
  }
239
+ else {
240
+ if ( !$cat ){
241
+ $cats[$i][] = array(
242
+ 'name' => trim($cc),
243
+ 'parent' => false,
244
+ 'assign' => $category->assign
245
+ );
246
+ }
247
+ else if ( $category->assign ){
248
+ $cats[$i][] = $cat->term_id;
249
+ }
250
  }
251
+ }
 
 
252
  }
253
+ $categories_hierarchy[$k]->cat_ids[$i] = $cats[$i];
254
  }
255
+ endforeach;
256
+ } else{
257
  count($titles) and $cats = array_fill(0, count($titles), '');
258
  }
259
+ }
260
  // [custom taxonomies]
261
  $taxonomies = array();
262
  $taxonomies_param = $this->options['type'].'_taxonomies';
267
  } else {
268
  $taxonomies_object_type = 'post';
269
  }
270
+
271
  if (!empty($this->options[$taxonomies_param]) and is_array($this->options[$taxonomies_param])): foreach ($this->options[$taxonomies_param] as $tx_name => $tx_template) if ('' != $tx_template) {
272
+ $tx = get_taxonomy($tx_name);
273
  if (in_array($taxonomies_object_type, $tx->object_type)) {
274
+ ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, sprintf(__('Composing terms for `%s` taxonomy...', 'pmxi_plugin'), $tx->labels->name));
275
  $txes = array();
276
+
277
+ $taxonomies_hierarchy = json_decode($tx_template);
278
+ foreach ($taxonomies_hierarchy as $k => $taxonomy){ if ("" == $taxonomy->xpath) continue;
279
+ $txes_raw = XmlImportParser::factory($xml, $this->xpath, str_replace('\'','"',$taxonomy->xpath), $file)->parse($records); $tmp_files[] = $file;
280
+ $warned = array();
281
+ foreach ($txes_raw as $i => $tx_raw) {
282
+ if (empty($taxonomies_hierarchy[$k]->txn_names[$i])) $taxonomies_hierarchy[$k]->txn_names[$i] = array();
283
+ if (empty($taxonomies[$tx_name][$i])) $taxonomies[$tx_name][$i] = array();
284
+ if ('' != $tx_raw) foreach (str_getcsv($tx_raw, ',') as $tx_cell) if ('' != $tx_cell) {
285
+ foreach (str_getcsv($tx_cell, (!empty($taxonomy->delim)) ? $taxonomy->delim : ',') as $j => $cc) if ('' != $cc) {
286
+ $cat = get_term_by('name', trim($cc), $tx_name) or $cat = get_term_by('slug', trim($cc), $tx_name) or ctype_digit($cc) and $cat = get_term_by('id', $cc, $tx_name);
287
+ if (!empty($taxonomies_hierarchy[$k]->parent_id)) {
288
+ foreach ($taxonomies_hierarchy as $key => $value){
289
+ if ($value->item_id == $taxonomies_hierarchy[$k]->parent_id and !empty($value->txn_names[$i])){
290
+ foreach ($value->txn_names[$i] as $parent) {
291
+ $taxonomies[$tx_name][$i][] = array(
292
+ 'name' => trim($cc),
293
+ 'parent' => (is_array($parent)) ? $parent['name'] : $parent,
294
+ 'assign' => $taxonomy->assign
295
+ );
296
+ }
297
+ }
298
+ }
299
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
300
  }
301
+ else {
302
+ if ( ! $cat ) {
303
+ $taxonomies[$tx_name][$i][] = array(
304
+ 'name' => trim($cc),
305
+ 'parent' => false,
306
+ 'assign' => $taxonomy->assign
307
+ );
308
+ }
309
+ elseif ($taxonomy->assign) {
310
+ $taxonomies[$tx_name][$i][] = $cc;
311
+ }
312
+ }
313
+ }
314
  }
315
+ $taxonomies_hierarchy[$k]->txn_names[$i] = $taxonomies[$tx_name][$i];
316
+ }
317
  }
318
  }
319
  }; endif;
320
+ // [/custom taxonomies]
321
+
322
+ // serialized attachments
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
323
  if ( ! (($uploads = wp_upload_dir()) && false === $uploads['error'])) {
324
+ $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': ' . $uploads['error']);
325
+ $logger and call_user_func($logger, __('<b>WARNING</b>: No attachments will be created', 'pmxi_plugin'));
326
+ $_SESSION['pmxi_import']['warnings']++;
327
  } else {
328
+ ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing URLs for attachments files...', 'pmxi_plugin'));
329
+ $attachments = array();
330
+ if ($this->options['attachments']) {
331
+ // Detect if attachments is separated by comma
332
+ $atchs = explode(',', $this->options['attachments']);
333
+ if (!empty($atchs)){
334
  $parse_multiple = true;
335
+ foreach($atchs as $atch) if (!preg_match("/{.*}/", trim($atch))) $parse_multiple = false;
336
 
337
  if ($parse_multiple)
338
  {
339
+ foreach($atchs as $atch)
340
  {
341
+ $posts_attachments = XmlImportParser::factory($xml, $this->xpath, trim($atch), $file)->parse($records); $tmp_files[] = $file;
342
+ foreach($posts_attachments as $i => $val) $attachments[$i][] = $val;
343
  }
344
  }
345
  else
346
  {
347
+ $attachments = XmlImportParser::factory($xml, $this->xpath, $this->options['attachments'], $file)->parse($records); $tmp_files[] = $file;
348
  }
349
  }
350
 
351
  } else {
352
+ count($titles) and $attachments = array_fill(0, count($titles), '');
353
  }
354
+ }
355
+
356
+ ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Composing unique keys...', 'pmxi_plugin'));
357
  $unique_keys = XmlImportParser::factory($xml, $this->xpath, $this->options['unique_key'], $file)->parse($records); $tmp_files[] = $file;
358
 
359
+ ($chunk == 1 or (empty($this->large_import) or $this->large_import == 'No')) and $logger and call_user_func($logger, __('Processing posts...', 'pmxi_plugin'));
360
 
361
  if ('post' == $this->options['type'] and '' != $this->options['custom_type']) {
362
  $post_type = $this->options['custom_type'];
363
  } else {
364
  $post_type = $this->options['type'];
365
+ }
366
+
367
  $current_post_ids = array();
368
+ foreach ($titles as $i => $void) {
369
+
370
+ if (!empty($chunk_records) and $this->large_import == 'Yes' and $this->options['create_chunks'] and !$is_cron and !in_array($_SESSION['pmxi_import']['chunk_number'], $chunk_records)) {
371
+ $_SESSION['pmxi_import']['skipped_records']++;
372
+ $_SESSION['pmxi_import']['chunk_number']++;
373
+
374
+ $logger and call_user_func($logger, __('<b>SKIPPED</b>: by specified records option', 'pmxi_plugin'));
375
+ $_SESSION['pmxi_import']['warnings']++;
376
+ // Time Elapsed
377
+ if ( ! $is_cron ){
378
+ $records_count = $_SESSION['pmxi_import']['created_records'] + $_SESSION['pmxi_import']['updated_records'] + $_SESSION['pmxi_import']['skipped_records'] + $_SESSION['pmxi_import']['errors'];
379
+ $progress_msg = '<p class="import_process_bar"> Created ' . $_SESSION['pmxi_import']['created_records'] . ' / Updated ' . $_SESSION['pmxi_import']['updated_records'] . ' of '. $_SESSION['pmxi_import']['count'].' records.</p><span class="import_percent">' . ceil(($records_count/$_SESSION['pmxi_import']['count']) * 100) . '</span><span class="warnings_count">' . $_SESSION['pmxi_import']['warnings'] . '</span><span class="errors_count">' . $_SESSION['pmxi_import']['errors'] . '</span>';
380
+ $logger and call_user_func($logger, $progress_msg);
381
+ }
382
+
383
+ continue;
384
+ }
385
+
386
  $articleData = array(
387
  'post_type' => $post_type,
388
  'post_status' => $this->options['status'],
389
  'comment_status' => $this->options['comment_status'],
390
  'ping_status' => $this->options['ping_status'],
391
+ 'post_title' => ($this->template['is_leave_html']) ? utf8_encode(html_entity_decode($titles[$i])) : $titles[$i],
392
+ 'post_excerpt' => ($this->template['is_leave_html']) ? utf8_encode(html_entity_decode($post_excerpt[$i])) : $post_excerpt[$i],
393
+ 'post_slug' => $post_slug[$i],
394
+ 'post_content' => ($this->template['is_leave_html']) ? utf8_encode(html_entity_decode($contents[$i])) : $contents[$i],
395
  'post_date' => $dates[$i],
396
  'post_date_gmt' => get_gmt_from_date($dates[$i]),
397
+ 'post_author' => $post_author[$i] ,
398
+ 'tags_input' => $tags[$i]
399
  );
400
+
401
+ if ('post' != $articleData['post_type']){
 
 
 
 
402
  $articleData += array(
403
  'menu_order' => $this->options['order'],
404
  'post_parent' => $this->options['parent'],
405
  );
406
+ }
407
+
408
+ // Re-import Records Matching
409
+ $post_to_update = false; $post_to_update_id = false;
410
+
411
+ // if Auto Matching re-import option selected
412
+ if ("manual" != $this->options['duplicate_matching']){
413
+ $postRecord->clear();
414
+ // find corresponding article among previously imported
415
+ $postRecord->getBy(array(
416
+ 'unique_key' => $unique_keys[$i],
417
+ 'import_id' => $this->id,
418
+ ));
419
+ if ( ! $postRecord->isEmpty() )
420
+ $post_to_update = get_post($post_to_update_id = $postRecord->post_id);
421
+
422
+ // if Manual Matching re-import option seleted
423
+ } else {
424
+
425
+ $postRecord->clear();
426
+ // find corresponding article among previously imported
427
+ $postRecord->getBy(array(
428
+ 'unique_key' => $unique_keys[$i],
429
+ 'import_id' => $this->id,
430
+ ));
431
+
432
+ if ('custom field' == $this->options['duplicate_indicator']) {
433
+ $custom_duplicate_value = XmlImportParser::factory($xml, $this->xpath, $this->options['custom_duplicate_value'], $file)->parse($records); $tmp_files[] = $file;
434
+ $custom_duplicate_name = XmlImportParser::factory($xml, $this->xpath, $this->options['custom_duplicate_name'], $file)->parse($records); $tmp_files[] = $file;
435
+ }
436
+ else{
437
+ count($titles) and $custom_duplicate_name = $custom_duplicate_value = array_fill(0, count($titles), '');
438
+ }
439
+
440
+ // handle duplicates according to import settings
441
+ if ($duplicates = $this->findDuplicates($articleData, $custom_duplicate_name[$i], $custom_duplicate_value[$i])) {
442
+ $duplicate_id = array_shift($duplicates);
443
+ if ($duplicate_id) {
444
+ $post_to_update = get_post($post_to_update_id = $duplicate_id);
445
+ }
446
+ }
447
  }
448
+
449
+ // Duplicate record is founded
450
+ if ($post_to_update){
451
+ // Do not update already existing records option selected
452
+ if ("yes" == $this->options['is_keep_former_posts']) {
453
+ $current_post_ids[] = $_SESSION['pmxi_import']['current_post_ids'][] = $post_to_update_id;
454
+ if ($is_cron){
455
+ $tmp_array = (!empty($this->current_post_ids)) ? json_decode($this->current_post_ids, true) : array();
456
+ $tmp_array[] = $post_to_update_id;
457
+ $this->set(array(
458
+ 'current_post_ids' => json_encode($tmp_array)
459
+ ))->save;
460
+ }
461
+ $_SESSION['pmxi_import']['skipped_records']++;
462
+ $logger and call_user_func($logger, sprintf(__('<b>SKIPPED</b>: Previously imported record found for `%s`', 'pmxi_plugin'), $articleData['post_title']));
463
+ $_SESSION['pmxi_import']['warnings']++;
464
+ if ( ! $is_cron ){
465
+ $records_count = $_SESSION['pmxi_import']['created_records'] + $_SESSION['pmxi_import']['updated_records'] + $_SESSION['pmxi_import']['skipped_records'] + $_SESSION['pmxi_import']['errors'];
466
+ $progress_msg = '<p class="import_process_bar"> Created ' . $_SESSION['pmxi_import']['created_records'] . ' / Updated ' . $_SESSION['pmxi_import']['updated_records'] . ' of '. $_SESSION['pmxi_import']['count'].' records.</p><span class="import_percent">' . ceil(($records_count/$_SESSION['pmxi_import']['count']) * 100) . '</span><span class="warnings_count">' . $_SESSION['pmxi_import']['warnings'] . '</span><span class="errors_count">' . $_SESSION['pmxi_import']['errors'] . '</span>';
467
+ $logger and call_user_func($logger, $progress_msg);
468
+ }
469
+ $_SESSION['pmxi_import']['chunk_number']++;
470
+ continue;
471
+ }
472
+ $articleData['ID'] = $post_to_update_id;
473
+ // preserve date of already existing article when duplicate is found
474
+ if ($this->options['is_keep_categories']) { // preserve categories and tags of already existing article if corresponding setting is specified
475
+ $cats_list = get_the_category($articleData['ID']);
476
+ if (is_wp_error($cats_list)) {
477
+ $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to get current categories for article #%d, updating with those read from XML file', 'pmxi_plugin'), $articleData['ID']));
478
+ $_SESSION['pmxi_import']['warnings']++;
479
+ } else {
480
+ $cats_new = array();
481
+ foreach ($cats_list as $c) {
482
+ $cats_new[] = $c->cat_ID;
483
+ }
484
+ $cats[$i] = $cats_new;
485
  }
486
+
487
+ $tags_list = get_the_tags($articleData['ID']);
488
+ if (is_wp_error($tags_list)) {
489
+ $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to get current tags for article #%d, updating with those read from XML file', 'pmxi_plugin'), $articleData['ID']));
490
+ $_SESSION['pmxi_import']['warnings']++;
491
+ } else {
492
+ $tags_new = array();
493
+ if ($tags_list) foreach ($tags_list as $t) {
494
+ $tags_new[] = $t->name;
 
 
 
 
 
495
  }
496
+ $articleData['tags_input'] = implode(', ', $tags_new);
497
+ }
498
+
499
+ foreach (array_keys($taxonomies) as $tx_name) {
500
+ $txes_list = get_the_terms($articleData['ID'], $tx_name);
501
+ if (is_wp_error($txes_list)) {
502
+ $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to get current taxonomies for article #%d, updating with those read from XML file', 'pmxi_plugin'), $articleData['ID']));
503
+ $_SESSION['pmxi_import']['warnings']++;
504
  } else {
505
+ $txes_new = array();
506
+ if (!empty($txes_list)):
 
 
 
 
 
 
 
 
 
 
 
507
  foreach ($txes_list as $t) {
508
  $txes_new[] = $t->name;
509
  }
510
+ endif;
511
+ $taxonomies[$tx_name][$i] = $txes_new;
512
  }
513
  }
514
+ }
515
+ if ($this->options['is_keep_dates']) { // preserve date of already existing article when duplicate is found
516
+ $articleData['post_date'] = $post_to_update->post_date;
517
+ $articleData['post_date_gmt'] = $post_to_update->post_date_gmt;
518
+ }
519
+ if ($this->options['is_keep_status']) { // preserve status and trashed flag
520
+ $articleData['post_status'] = $post_to_update->post_status;
521
+ }
522
+ if ($this->options['is_keep_content']){
523
+ $articleData['post_content'] = $post_to_update->post_content;
524
+ }
525
+ if ($this->options['is_keep_title']){
526
+ $articleData['post_title'] = $post_to_update->post_title;
527
+ }
528
+ if ($this->options['is_keep_excerpt']){
529
+ $articleData['post_excerpt'] = $post_to_update->post_excerpt;
530
+ }
531
+ if ($this->options['is_keep_menu_order']){
532
+ $articleData['menu_order'] = $post_to_update->menu_order;
533
+ }
534
+ // handle obsolete attachments (i.e. delete or keep) according to import settings
535
+ if ( ! $this->options['is_keep_images'] and ! $this->options['no_create_featured_image']){
536
+ wp_delete_attachments($articleData['ID']);
537
  }
538
  }
539
+ elseif ( ! $postRecord->isEmpty() ){
540
+
541
+ // existing post not found though it's track was found... clear the leftover, plugin will continue to treat record as new
542
+ $postRecord->delete();
543
+
544
+ }
545
+
546
+ // no new records are created. it will only update posts it finds matching duplicates for
547
+ if ($this->options['not_create_records'] and empty($articleData['ID'])){
548
+ $_SESSION['pmxi_import']['skipped_records']++;
549
+ $logger and call_user_func($logger, sprintf(__('<b>SKIPPED</b>: by "Not add new records" option for `%s`', 'pmxi_plugin'), $articleData['post_title']));
550
+ if ( ! $is_cron ){
551
+ $records_count = $_SESSION['pmxi_import']['created_records'] + $_SESSION['pmxi_import']['updated_records'] + $_SESSION['pmxi_import']['skipped_records'] + $_SESSION['pmxi_import']['errors'];
552
+ $progress_msg = '<p class="import_process_bar"> Created ' . $_SESSION['pmxi_import']['created_records'] . ' / Updated ' . $_SESSION['pmxi_import']['updated_records'] . ' of '. $_SESSION['pmxi_import']['count'].' records.</p><span class="import_percent">' . ceil(($records_count/$_SESSION['pmxi_import']['count']) * 100) . '</span><span class="warnings_count">' . $_SESSION['pmxi_import']['warnings'] . '</span><span class="errors_count">' . $_SESSION['pmxi_import']['errors'] . '</span>';
553
+ $logger and call_user_func($logger, $progress_msg);
554
+ }
555
+ $_SESSION['pmxi_import']['chunk_number']++;
556
+ continue;
557
  }
558
+
559
  // cloak urls with `WP Wizard Cloak` if corresponding option is set
560
  if ( ! empty($this->options['is_cloak']) and class_exists('PMLC_Plugin')) {
561
  if (preg_match_all('%<a\s[^>]*href=(?(?=")"([^"]*)"|(?(?=\')\'([^\']*)\'|([^\s>]*)))%is', $articleData['post_content'], $matches, PREG_PATTERN_ORDER)) {
620
  ));
621
  $dest->insert();
622
  } else {
623
+ $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to create cloaked link for %s', 'pmxi_plugin'), $url));
624
+ $_SESSION['pmxi_import']['warnings']++;
625
  $link = NULL;
626
  }
627
  }
631
  }
632
  }
633
  }
634
+ }
635
+
636
+ // insert article being imported
637
+ $pid = wp_insert_post($articleData, true);
638
+
639
  if (is_wp_error($pid)) {
640
+ $logger and call_user_func($logger, __('<b>ERROR</b>', 'pmxi_plugin') . ': ' . $pid->get_error_message());
641
+ $_SESSION['pmxi_import']['errors']++;
642
  } else {
643
 
644
  do_action( 'pmxi_saved_post', $pid); // hook that was triggered immediately after post saved
645
 
646
+ $current_post_ids[] = $_SESSION['pmxi_import']['current_post_ids'][] = $pid;
647
+ if ($is_cron){
648
+ $tmp_array = (!empty($this->current_post_ids)) ? json_decode($this->current_post_ids, true) : array();
649
+ $tmp_array[] = $pid;
650
+ $this->set(array(
651
+ 'current_post_ids' => json_encode($tmp_array)
652
+ ))->save();
653
+ }
654
+ if ("manual" != $this->options['duplicate_matching'] or empty($articleData['ID'])){
655
+ // associate post with import
656
+ $postRecord->isEmpty() and $postRecord->set(array(
657
+ 'post_id' => $pid,
658
+ 'import_id' => $this->id,
659
+ 'unique_key' => $unique_keys[$i],
660
+ ))->insert();
661
+ }
662
+
663
+ if ('post' != $articleData['post_type'] and !empty($this->options['page_template'])) update_post_meta($pid, '_wp_page_template', $this->options['page_template']);
664
+
665
+ // [attachments]
666
+ if ( ! empty($uploads) and false === $uploads['error'] and !empty($attachments[$i])) {
667
+
668
+ // you must first include the image.php file
669
+ // for the function wp_generate_attachment_metadata() to work
670
+ require_once(ABSPATH . 'wp-admin/includes/image.php');
671
+
672
+ if ( ! is_array($attachments[$i]) ) $attachments[$i] = array($attachments[$i]);
673
+
674
+ foreach ($attachments[$i] as $attachment) { if ("" == $attachment) continue;
675
+
676
+ $atchs = str_getcsv($attachment, $this->options['atch_delim']);
677
+
678
+ if (!empty($atchs)) {
679
+ foreach ($atchs as $atch_url) { if (empty($atch_url)) continue;
680
+
681
+ $attachment_filename = wp_unique_filename($uploads['path'], basename(parse_url(trim($atch_url), PHP_URL_PATH)));
682
+ $attachment_filepath = $uploads['path'] . '/' . url_title($attachment_filename);
683
+
684
+ if ( ! file_put_contents($attachment_filepath, @file_get_contents(trim($atch_url))) and ! get_file_curl(trim($atch_url), $attachment_filepath)) {
685
+ $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Attachment file %s cannot be saved locally as %s', 'pmxi_plugin'), trim($atch_url), $attachment_filepath));
686
+ $_SESSION['pmxi_import']['warnings']++;
687
+ unlink($attachment_filepath); // delete file since failed upload may result in empty file created
688
+ } elseif( ! $wp_filetype = wp_check_filetype(basename($attachment_filename), null )) {
689
+ $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Can\'t detect attachment file type %s', 'pmxi_plugin'), trim($atch_url)));
690
+ $_SESSION['pmxi_import']['warnings']++;
691
+ } else {
692
+
693
+ $attachment_data = array(
694
+ 'guid' => $uploads['baseurl'] . _wp_relative_upload_path( $attachment_filepath ),
695
+ 'post_mime_type' => $wp_filetype['type'],
696
+ 'post_title' => preg_replace('/\.[^.]+$/', '', basename($attachment_filepath)),
697
+ 'post_content' => '',
698
+ 'post_status' => 'inherit'
699
+ );
700
+ $attach_id = wp_insert_attachment( $attachment_data, $attachment_filepath, $pid );
701
+
702
+ if (is_wp_error($attach_id)) {
703
+ $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': ' . $pid->get_error_message());
704
+ $_SESSION['pmxi_import']['warnings']++;
705
+ } else {
706
+ wp_update_attachment_metadata($attach_id, wp_generate_attachment_metadata($attach_id, $attachment_filepath));
707
+ }
708
+ }
709
+ }
710
+ }
711
+ }
712
+ }
713
+ // [/attachments]
714
 
715
  // [custom taxonomies]
716
  foreach ($taxonomies as $tx_name => $txes) {
717
+ // create term if not exists
718
+ foreach ($txes[$i] as $key => $single_tax) {
719
+ if (is_array($single_tax)){
720
+ $term = term_exists( $single_tax['name'], $tx_name, (!empty($single_tax['parent'])) ? $single_tax['parent'] : '' );
721
+ if ( empty($term) ){
722
+ $term_attr = (!empty($single_tax['parent'])) ? $term_attr = array('parent'=> $single_tax['parent']) : '';
723
+
724
+ $term = wp_insert_term(
725
+ $single_tax['name'], // the term
726
+ $tx_name, // the taxonomy
727
+ $term_attr
728
+ );
729
+ }
730
+
731
+ if ( empty($term) or is_wp_error($term) ){
732
+ unset($txes[$i][$key]);
733
+ $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: `%s`', 'pmxi_plugin'), $term->get_error_message()));
734
+ $_SESSION['pmxi_import']['warnings']++;
735
+ }
736
+ else{
737
+ $cat_id = $term['term_id'];
738
+ if ($cat_id and $single_tax['assign'])
739
+ $txes[$i][$key] = $single_tax['name'];
740
+ else
741
+ unset($txes[$i][$key]);
742
+ }
743
+ }
744
+ }
745
+
746
+ // associate taxes with post
747
  $term_ids = wp_set_object_terms($pid, $txes[$i], $tx_name);
748
  if (is_wp_error($term_ids)) {
749
+ $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': '.$term_ids->get_error_message());
750
+ $_SESSION['pmxi_import']['warnings']++;
751
  }
752
  }
753
  // [/custom taxonomies]
754
 
755
+ // [categories]
756
+ if (!empty($cats[$i])){
757
+ // create categories if it's doesn't exists
758
+ foreach ($cats[$i] as $key => $single_cat) {
759
+ if (is_array($single_cat)){
760
+ if (!empty($single_cat['parent'])){
761
+ $cat = get_term_by('name', $single_cat['parent'], 'category') or $cat = get_term_by('slug', $single_cat['parent'], 'category') or ctype_digit($single_cat['parent']) and $cat = get_term_by('id', $single_cat['parent'], 'category');
762
+ if ($cat)
763
+ $cat_id = wp_create_category($single_cat['name'], $cat->term_id);
764
+ }
765
+ else $cat_id = wp_create_category($single_cat['name']);
766
+
767
+ if ($cat_id and $single_cat['assign'])
768
+ $cats[$i][$key] = $cat_id;
769
+ }
770
+ }
771
+ // associate categories with post
772
+ $cats_ids = wp_set_post_terms($pid, $cats[$i], 'category');
773
+ if (is_wp_error($cats_ids)) {
774
+ $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': '.$cats_ids->get_error_message());
775
+ $_SESSION['pmxi_import']['warnings']++;
776
+ }
777
+ }
778
+ // [/categories]
779
+
780
  if (empty($articleData['ID'])) {
781
+ $_SESSION['pmxi_import']['created_records']++;
782
  $logger and call_user_func($logger, sprintf(__('`%s` post created successfully', 'pmxi_plugin'), $articleData['post_title']));
783
  } else {
784
+ $_SESSION['pmxi_import']['updated_records']++;
785
  $logger and call_user_func($logger, sprintf(__('`%s` post updated successfully', 'pmxi_plugin'), $articleData['post_title']));
786
  }
787
+
788
+ $records_count = 0;
789
+
790
+ // Time Elapsed
791
+ if ( ! $is_cron){
792
+
793
+ if ($this->large_import == 'No') $_SESSION['pmxi_import']['count'] = count($titles);
794
+
795
+ $records_count = $_SESSION['pmxi_import']['created_records'] + $_SESSION['pmxi_import']['updated_records'] + $_SESSION['pmxi_import']['skipped_records'] + $_SESSION['pmxi_import']['errors'];
796
+
797
+ $progress_msg = '<p class="import_process_bar"> Created ' . $_SESSION['pmxi_import']['created_records'] . ' / Updated ' . $_SESSION['pmxi_import']['updated_records'] . ' of '. $_SESSION['pmxi_import']['count'].' records.</p><span class="import_percent">' . ceil(($records_count/$_SESSION['pmxi_import']['count']) * 100) . '</span><span class="warnings_count">' . $_SESSION['pmxi_import']['warnings'] . '</span><span class="errors_count">' . $_SESSION['pmxi_import']['errors'] . '</span>';
798
+ $logger and call_user_func($logger, $progress_msg);
799
+ }
800
+
801
  }
802
+
803
+ if ($this->large_import == 'Yes' and $chunk){
804
+ $this->set(array(
805
+ 'imported' => $this->imported + 1,
806
+ 'created' => $_SESSION['pmxi_import']['created_records'],
807
+ 'updated' => $_SESSION['pmxi_import']['updated_records']
808
+ ))->save();
809
+ $_SESSION['pmxi_import']['chunk_number']++;
810
+ }
811
+
812
  wp_cache_flush();
813
+ }
814
+ if (!$is_cron and ($records_count == $_SESSION['pmxi_import']['count'] + $_SESSION['pmxi_import']['skipped_records']) and ! empty($this->options['is_delete_missing'])) { // delete posts which are not in current import set
815
  $logger and call_user_func($logger, 'Removing previously imported posts which are no longer actual...');
816
+ $postList = new PMXI_Post_List();
817
+
818
+ foreach ($postList->getBy(array('import_id' => $this->id, 'post_id NOT IN' => $_SESSION['pmxi_import']['current_post_ids'])) as $missingPost) {
819
  empty($this->options['is_keep_attachments']) and wp_delete_attachments($missingPost['post_id']);
820
  wp_delete_post($missingPost['post_id'], true);
821
  }
823
 
824
  } catch (XmlImportException $e) {
825
  $logger and call_user_func($logger, __('<b>ERROR</b>', 'pmxi_plugin') . ': ' . $e->getMessage());
826
+ $_SESSION['pmxi_import']['errors']++;
827
+ }
828
+
829
  $this->set('registered_on', date('Y-m-d H:i:s'))->save(); // specify execution is successful
830
 
831
+ !$is_cron and ($records_count == $_SESSION['pmxi_import']['count'] + $_SESSION['pmxi_import']['skipped_records']) and $logger and call_user_func($logger, __('Cleaning temporary data...', 'pmxi_plugin'));
832
  foreach ($tmp_files as $file) { // remove all temporary files created
833
  unlink($file);
834
  }
835
 
836
+ if (($is_cron or $records_count == $_SESSION['pmxi_import']['count'] + $_SESSION['pmxi_import']['skipped_records']) and $this->options['is_delete_source']) {
837
  $logger and call_user_func($logger, __('Deleting source XML file...', 'pmxi_plugin'));
838
  if ( ! @unlink($this->path)) {
839
  $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to remove %s', 'pmxi_plugin'), $this->path));
840
  }
841
  }
842
+ !$is_cron and ($records_count == $_SESSION['pmxi_import']['count'] + $_SESSION['pmxi_import']['skipped_records']) and $logger and call_user_func($logger, 'Done');
843
 
844
  remove_filter('user_has_cap', array($this, '_filter_has_cap_unfiltered_html')); kses_init(); // return any filtering rules back if they has been disabled for import procedure
845
 
846
  return $this;
847
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
848
 
849
  public function _filter_has_cap_unfiltered_html($caps)
850
  {
855
  /**
856
  * Find duplicates according to settings
857
  */
858
+ public function findDuplicates($articleData, $custom_duplicate_name = '', $custom_duplicate_value = '')
859
+ {
860
+ if ('custom field' == $this->options['duplicate_indicator']){
861
+ $duplicate_ids = array();
862
+ $args = array(
863
+ 'post_type' => $articleData['post_type'],
864
+ 'meta_query' => array(
865
+ array(
866
+ 'key' => $custom_duplicate_name,
867
+ 'value' => $custom_duplicate_value,
868
+ )
869
+ )
870
+ );
871
+ $query = new WP_Query( $args );
872
+
873
+ if ( $query->have_posts() ) $duplicate_ids[] = $query->post->ID;
874
+
875
+ wp_reset_postdata();
876
+
877
+ return $duplicate_ids;
878
+ }
879
+ else{
880
+ $field = 'post_' . $this->options['duplicate_indicator']; // post_title or post_content
881
+ return $this->wpdb->get_col($this->wpdb->prepare("
882
+ SELECT ID FROM " . $this->wpdb->posts . "
883
+ WHERE
884
+ post_type = %s
885
+ AND ID != %s
886
+ AND REPLACE(REPLACE(REPLACE($field, ' ', ''), '\\t', ''), '\\n', '') = %s
887
+ ",
888
+ $articleData['post_type'],
889
+ isset($articleData['ID']) ? $articleData['ID'] : 0,
890
+ preg_replace('%[ \\t\\n]%', '', $articleData[$field])
891
+ ));
892
+ }
893
  }
894
 
895
  /**
903
  if ($keepPosts) {
904
  $this->wpdb->query($this->wpdb->prepare('DELETE FROM ' . $post->getTable() . ' WHERE import_id = %s', $this->id));
905
  } else {
906
+ $ids = array();
907
  foreach ($post->getBy('import_id', $this->id)->convertRecords() as $p) {
908
+ empty($this->options['is_keep_attachments']) and empty($this->options['is_keep_images']) and wp_delete_attachments($p->post_id);
909
+ $ids[] = $p->post_id;
910
+ //wp_delete_post($p->post_id, TRUE);
911
+ }
912
+ if (!empty($ids)){
913
+
914
+ /*$sql = "delete a,b,c,d
915
+ FROM ".$this->wpdb->posts." a
916
+ LEFT JOIN ".$this->wpdb->term_relationships." b ON ( a.ID = b.object_id )
917
+ LEFT JOIN ".$this->wpdb->postmeta." c ON ( a.ID = c.post_id )
918
+ LEFT JOIN ".$this->wpdb->term_taxonomy." d ON ( d.term_taxonomy_id = b.term_taxonomy_id )
919
+ LEFT JOIN ".$this->wpdb->terms." e ON ( e.term_id = d.term_id )
920
+ WHERE a.ID IN (".implode(',', $ids).");";*/
921
+
922
+ $sql = "delete a,b,c
923
+ FROM ".$this->wpdb->posts." a
924
+ LEFT JOIN ".$this->wpdb->term_relationships." b ON ( a.ID = b.object_id )
925
+ LEFT JOIN ".$this->wpdb->postmeta." c ON ( a.ID = c.post_id )
926
+ WHERE a.ID IN (".implode(',', $ids).");";
927
+
928
+ $this->wpdb->query(
929
+ $this->wpdb->prepare($sql)
930
+ );
931
  }
932
  }
933
  return $this;
956
  }
957
 
958
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin.php CHANGED
@@ -1,9 +1,9 @@
1
  <?php
2
  /*
3
- Plugin Name: WP All Import
4
- Plugin URI: http://www.wpallimport.com/upgrade-to-pro
5
- Description: The most powerful solution for importing XML and CSV files to WordPress. Create Posts and Pages with content from any XML or CSV file. Perform scheduled updates and overwrite of existing import jobs. Free lite edition.
6
- Version: 2.14
7
  Author: Soflyy
8
  */
9
  /**
@@ -63,8 +63,11 @@ final class PMXI_Plugin {
63
  * @var string
64
  */
65
  const FILE = __FILE__;
66
-
67
- public static $csv_mimes = array('text/comma-separated-values','text/csv','application/csv','application/excel','application/vnd.ms-excel','application/vnd.msexcel','text/anytext', 'text/plain');
 
 
 
68
 
69
  /**
70
  * Return singletone instance
@@ -134,12 +137,24 @@ final class PMXI_Plugin {
134
  return ($this->isNetwork() ? $wpdb->base_prefix : $wpdb->prefix) . self::PREFIX;
135
  }
136
 
 
 
 
 
 
 
 
 
 
137
  /**
138
  * Class constructor containing dispatching logic
139
  * @param string $rootDir Plugin root dir
140
  * @param string $pluginFilePath Plugin main file
141
  */
142
  protected function __construct() {
 
 
 
143
  // regirster autoloading method
144
  if (function_exists('__autoload') and ! in_array('__autoload', spl_autoload_functions())) { // make sure old way of autoloading classes is not broken
145
  spl_autoload_register('__autoload');
@@ -151,11 +166,19 @@ final class PMXI_Plugin {
151
  require_once $filePath;
152
  }
153
 
 
 
 
 
 
 
154
  // init plugin options
155
  $option_name = get_class($this) . '_Options';
156
  $options_default = PMXI_Config::createFromFile(self::ROOT_DIR . '/config/options.php')->toArray();
157
  $this->options = array_intersect_key(get_option($option_name, array()), $options_default) + $options_default;
158
  $this->options = array_intersect_key($options_default, array_flip(array('info_api_url'))) + $this->options; // make sure hidden options apply upon plugin reactivation
 
 
159
  update_option($option_name, $this->options);
160
  $this->options = get_option(get_class($this) . '_Options');
161
 
@@ -196,6 +219,8 @@ final class PMXI_Plugin {
196
  // register admin page pre-dispatcher
197
  add_action('admin_init', array($this, '__adminInit'));
198
 
 
 
199
  }
200
 
201
  /**
@@ -385,12 +410,18 @@ final class PMXI_Plugin {
385
  }
386
 
387
  /**
388
- * Method perfoms transition from version when file history has been stored in dabase to the solution when it stored on disk
389
  * NOTE: the function can be removed when plugin version progress and it's sure matter nobody has ver 1.03
390
  */
391
  public function __ver_1_04_transition_fix() {
392
- if ( ! is_dir(self::ROOT_DIR . '/history') or ! is_writable(self::ROOT_DIR . '/history')) {
393
- die(sprintf(__('History folder %s must be writable', 'pmxi_plugin'), self::ROOT_DIR . '/history'));
 
 
 
 
 
 
394
  }
395
 
396
  $table = $table = $this->getTablePrefix() . 'files';
@@ -402,7 +433,7 @@ final class PMXI_Plugin {
402
  $list = new PMXI_File_List();
403
  for ($i = 1; $list->getBy(NULL, 'id', $i, 1)->count(); $i++) {
404
  foreach ($list->convertRecords() as $file) {
405
- $file->save(); // resave file for file to be stored in history folder
406
  }
407
  }
408
 
@@ -412,6 +443,67 @@ final class PMXI_Plugin {
412
  }
413
  }
414
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
415
  /**
416
  * Method returns default import options, main utility of the method is to avoid warnings when new
417
  * option is introduced but already registered imports don't have it
@@ -423,6 +515,9 @@ final class PMXI_Plugin {
423
  'categories' => '',
424
  'tags' => '',
425
  'tags_delim' => ',',
 
 
 
426
  'post_taxonomies' => array(),
427
  'parent' => '',
428
  'order' => '0',
@@ -437,27 +532,47 @@ final class PMXI_Plugin {
437
  'custom_value' => array(),
438
  'comment_status' => 'open',
439
  'ping_status' => 'open',
440
- 'author' => wp_get_current_user()->ID,
 
441
  'featured_image' => '',
 
442
  'is_import_specified' => 0,
443
  'import_specified' => '',
444
  'is_delete_source' => 0,
445
  'is_cloak' => 0,
446
  'unique_key' => '',
 
447
 
448
  'is_delete_missing' => 0,
449
- 'is_keep_former_posts' => 0,
450
  'is_keep_status' => 0,
 
 
 
451
  'is_keep_categories' => 0,
452
  'is_keep_attachments' => 0,
 
453
  'is_duplicates' => 0,
 
 
 
 
 
454
 
455
  'duplicate_indicator' => 'title',
456
  'duplicate_action' => 'keep',
457
- 'is_first_chank' => 0,
458
  'is_update_previous' => 0,
459
  'is_scheduled' => '',
460
- 'scheduled_period' => ''
 
 
 
 
 
 
 
 
 
461
  );
462
  }
463
 
@@ -470,17 +585,18 @@ final class PMXI_Plugin {
470
 
471
  $csv = new PMXI_CsvParser($csv_url);
472
 
473
- return $csv->toXML();
 
 
 
 
474
 
475
  }
476
- /*
477
- *
478
- * Detect CSV file
479
- *
480
- */
481
- public static function detect_csv($type){
482
- return in_array($type, self::$csv_mimes);
483
  }
 
484
  }
485
 
486
  PMXI_Plugin::getInstance();
1
  <?php
2
  /*
3
+ Plugin Name: WP All Import Lite
4
+ Plugin URI: http://www.wpallimport.com/
5
+ Description: The most powerful solution for importing XML and CSV files to WordPress. Create Posts and Pages with content from any XML or CSV file. Perform scheduled updates and overwrite of existing import jobs. Free lite edition.
6
+ Version: 3.0
7
  Author: Soflyy
8
  */
9
  /**
63
  * @var string
64
  */
65
  const FILE = __FILE__;
66
+ /**
67
+ * Max allowed file size (bytes) to import in default mode
68
+ * @var int
69
+ */
70
+ const LARGE_SIZE = 0; // all files will importing in large import mode
71
 
72
  /**
73
  * Return singletone instance
137
  return ($this->isNetwork() ? $wpdb->base_prefix : $wpdb->prefix) . self::PREFIX;
138
  }
139
 
140
+ /**
141
+ * Return prefix for wordpress database tables
142
+ * @return string
143
+ */
144
+ public function getWPPrefix() {
145
+ global $wpdb;
146
+ return ($this->isNetwork() ? $wpdb->base_prefix : $wpdb->prefix);
147
+ }
148
+
149
  /**
150
  * Class constructor containing dispatching logic
151
  * @param string $rootDir Plugin root dir
152
  * @param string $pluginFilePath Plugin main file
153
  */
154
  protected function __construct() {
155
+
156
+ // create/update required database tables
157
+
158
  // regirster autoloading method
159
  if (function_exists('__autoload') and ! in_array('__autoload', spl_autoload_functions())) { // make sure old way of autoloading classes is not broken
160
  spl_autoload_register('__autoload');
166
  require_once $filePath;
167
  }
168
 
169
+ // create history folder
170
+ $uploads = wp_upload_dir();
171
+ if (!is_dir($uploads['basedir'] . '/wpallimport_history')) wp_mkdir_p($uploads['basedir'] . '/wpallimport_history');
172
+ // create logs folder
173
+ if (!is_dir($uploads['basedir'] . '/wpallimport_logs')) wp_mkdir_p($uploads['basedir'] . '/wpallimport_logs');
174
+
175
  // init plugin options
176
  $option_name = get_class($this) . '_Options';
177
  $options_default = PMXI_Config::createFromFile(self::ROOT_DIR . '/config/options.php')->toArray();
178
  $this->options = array_intersect_key(get_option($option_name, array()), $options_default) + $options_default;
179
  $this->options = array_intersect_key($options_default, array_flip(array('info_api_url'))) + $this->options; // make sure hidden options apply upon plugin reactivation
180
+ if ('' == $this->options['cron_job_key']) $this->options['cron_job_key'] = url_title(rand_char(12));
181
+
182
  update_option($option_name, $this->options);
183
  $this->options = get_option(get_class($this) . '_Options');
184
 
219
  // register admin page pre-dispatcher
220
  add_action('admin_init', array($this, '__adminInit'));
221
 
222
+ $this->__add_feed_type_fix(); // feature to version 2.22
223
+
224
  }
225
 
226
  /**
410
  }
411
 
412
  /**
413
+ * Method perfoms transition from version when file uploads has been stored in dabase to the solution when it stored on disk
414
  * NOTE: the function can be removed when plugin version progress and it's sure matter nobody has ver 1.03
415
  */
416
  public function __ver_1_04_transition_fix() {
417
+ $uploads = wp_upload_dir();
418
+
419
+ if ( ! is_dir($uploads['basedir'] . '/wpallimport_history') or ! is_writable($uploads['basedir'] . '/wpallimport_history')) {
420
+ die(sprintf(__('Uploads folder %s must be writable', 'pmxi_plugin'), $uploads['basedir'] . '/wpallimport_history'));
421
+ }
422
+
423
+ if ( ! is_dir($uploads['basedir'] . '/wpallimport_logs') or ! is_writable($uploads['basedir'] . '/wpallimport_logs')) {
424
+ die(sprintf(__('Uploads folder %s must be writable', 'pmxi_plugin'), $uploads['basedir'] . '/wpallimport_logs'));
425
  }
426
 
427
  $table = $table = $this->getTablePrefix() . 'files';
433
  $list = new PMXI_File_List();
434
  for ($i = 1; $list->getBy(NULL, 'id', $i, 1)->count(); $i++) {
435
  foreach ($list->convertRecords() as $file) {
436
+ $file->save(); // resave file for file to be stored in uploads folder
437
  }
438
  }
439
 
443
  }
444
  }
445
 
446
+ public function __add_feed_type_fix(){
447
+
448
+ $table = $this->getTablePrefix() . 'imports';
449
+ global $wpdb;
450
+ $tablefields = $wpdb->get_results("DESCRIBE {$table};");
451
+ $large_import = false;
452
+ $root_element = false;
453
+ $processing = false;
454
+ $triggered = false;
455
+ $queue_chunk_number = false;
456
+ $current_post_ids = false;
457
+ $first_import = false;
458
+ $count = false;
459
+ $friendly_name = false;
460
+ $imported = false;
461
+ $created = false;
462
+ $updated = false;
463
+ $skipped = false;
464
+
465
+ // Check if field exists
466
+ foreach ($tablefields as $tablefield) {
467
+ if ('large_import' == $tablefield->Field) $large_import = true;
468
+ if ('root_element' == $tablefield->Field) $root_element = true;
469
+ if ('processing' == $tablefield->Field) $processing = true;
470
+ if ('triggered' == $tablefield->Field) $triggered = true;
471
+ if ('current_post_ids' == $tablefield->Field) $current_post_ids = true;
472
+ if ('queue_chunk_number' == $tablefield->Field) $queue_chunk_number = true;
473
+ if ('first_import' == $tablefield->Field) $first_import = true;
474
+ if ('count' == $tablefield->Field) $count = true;
475
+ if ('friendly_name' == $tablefield->Field) $friendly_name = true;
476
+ if ('imported' == $tablefield->Field) $imported = true;
477
+ if ('created' == $tablefield->Field) $created = true;
478
+ if ('updated' == $tablefield->Field) $updated = true;
479
+ if ('skipped' == $tablefield->Field) $skipped = true;
480
+ }
481
+ if (!$large_import) $wpdb->query("ALTER TABLE {$table} ADD `large_import` ENUM( 'Yes', 'No' ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'No';");
482
+ if (!$root_element) $wpdb->query("ALTER TABLE {$table} ADD `root_element` VARCHAR(255) DEFAULT '';");
483
+ if (!$processing) $wpdb->query("ALTER TABLE {$table} ADD `processing` BOOL NOT NULL DEFAULT '0';");
484
+ if (!$triggered) $wpdb->query("ALTER TABLE {$table} ADD `triggered` BOOL NOT NULL DEFAULT '0';");
485
+ if (!$queue_chunk_number) $wpdb->query("ALTER TABLE {$table} ADD `queue_chunk_number` BIGINT(20) NOT NULL DEFAULT '0';");
486
+ if (!$current_post_ids) $wpdb->query("ALTER TABLE {$table} ADD `current_post_ids` TEXT NULL DEFAULT '';");
487
+ if (!$first_import) $wpdb->query("ALTER TABLE {$table} ADD `first_import` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;");
488
+ if (!$count) $wpdb->query("ALTER TABLE {$table} ADD `count` BIGINT(20) NOT NULL DEFAULT '0';");
489
+ if (!$imported) $wpdb->query("ALTER TABLE {$table} ADD `imported` BIGINT(20) NOT NULL DEFAULT '0';");
490
+ if (!$created) $wpdb->query("ALTER TABLE {$table} ADD `created` BIGINT(20) NOT NULL DEFAULT '0';");
491
+ if (!$updated) $wpdb->query("ALTER TABLE {$table} ADD `updated` BIGINT(20) NOT NULL DEFAULT '0';");
492
+ if (!$skipped) $wpdb->query("ALTER TABLE {$table} ADD `skipped` BIGINT(20) NOT NULL DEFAULT '0';");
493
+ if (!$friendly_name) $wpdb->query("ALTER TABLE {$table} ADD `friendly_name` VARCHAR(255) NOT NULL DEFAULT '';");
494
+
495
+ $table = $this->getTablePrefix() . 'templates';
496
+ global $wpdb;
497
+ $tablefields = $wpdb->get_results("DESCRIBE {$table};");
498
+ $is_leave_html = false;
499
+ // Check if field exists
500
+ foreach ($tablefields as $tablefield) {
501
+ if ('is_leave_html' == $tablefield->Field) $is_leave_html = true;
502
+ }
503
+ if (!$is_leave_html) $wpdb->query("ALTER TABLE {$table} ADD `is_leave_html` TINYINT( 1 ) NOT NULL DEFAULT '0';");
504
+
505
+ }
506
+
507
  /**
508
  * Method returns default import options, main utility of the method is to avoid warnings when new
509
  * option is introduced but already registered imports don't have it
515
  'categories' => '',
516
  'tags' => '',
517
  'tags_delim' => ',',
518
+ 'categories_delim' => ',',
519
+ 'featured_delim' => ',',
520
+ 'atch_delim' => ',',
521
  'post_taxonomies' => array(),
522
  'parent' => '',
523
  'order' => '0',
532
  'custom_value' => array(),
533
  'comment_status' => 'open',
534
  'ping_status' => 'open',
535
+ 'create_draft' => 'no',
536
+ 'author' => '',
537
  'featured_image' => '',
538
+ 'attachments' => '',
539
  'is_import_specified' => 0,
540
  'import_specified' => '',
541
  'is_delete_source' => 0,
542
  'is_cloak' => 0,
543
  'unique_key' => '',
544
+ 'feed_type' => 'auto',
545
 
546
  'is_delete_missing' => 0,
547
+ 'is_keep_former_posts' => 'no',
548
  'is_keep_status' => 0,
549
+ 'is_keep_content' => 0,
550
+ 'is_keep_title' => 0,
551
+ 'is_keep_excerpt' => 0,
552
  'is_keep_categories' => 0,
553
  'is_keep_attachments' => 0,
554
+ 'is_keep_images' => 0,
555
  'is_duplicates' => 0,
556
+ 'is_keep_dates' => 0,
557
+ 'is_keep_menu_order' => 0,
558
+ 'records_per_request' => 10,
559
+ 'not_create_records' => 0,
560
+ 'no_create_featured_image' => 0,
561
 
562
  'duplicate_indicator' => 'title',
563
  'duplicate_action' => 'keep',
 
564
  'is_update_previous' => 0,
565
  'is_scheduled' => '',
566
+ 'scheduled_period' => '',
567
+ 'post_excerpt' => '',
568
+ 'post_slug' => '',
569
+ 'keep_custom_fields' => 0,
570
+ 'keep_custom_fields_specific' => '',
571
+ 'friendly_name' => '',
572
+ 'custom_duplicate_name' => '',
573
+ 'custom_duplicate_value' => '',
574
+ 'duplicate_matching' => 'auto',
575
+ 'create_chunks' => 0,
576
  );
577
  }
578
 
585
 
586
  $csv = new PMXI_CsvParser($csv_url);
587
 
588
+ $wp_uploads = wp_upload_dir();
589
+ $tmpname = wp_unique_filename($wp_uploads['path'], str_replace("csv", "xml", basename($csv_url)));
590
+ $xml_file = $wp_uploads['path'] .'/'. $tmpname;
591
+ file_put_contents($xml_file, $csv->toXML());
592
+ return $xml_file;
593
 
594
  }
595
+
596
+ public static function is_ajax(){
597
+ return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') ? true : false ;
 
 
 
 
598
  }
599
+
600
  }
601
 
602
  PMXI_Plugin::getInstance();
readme.txt CHANGED
@@ -1,36 +1,45 @@
1
- === WP All Import ===
2
  Contributors: soflyy
3
  Tags: wordpress, xml, csv, datafeed, import
4
- Requires at least: 3.0
5
- Tested up to: 3.4.2
6
- Stable tag: 2.14
7
 
8
- The most powerful tool for importing any CSV or XML feed to WordPress. --tag
9
 
10
  == Description ==
11
 
 
 
 
 
 
 
 
 
12
  = WP All Import Professional Edition =
 
13
 
14
- [Upgrade to the professional edition of WP All Import.](http://www.wpallimport.com/upgrade-to-pro)
15
 
16
- *WP All Import Pro* is a **significant upgrade** that adds many features to WP All Import Lite:
17
 
18
- [Demo Video](http://www.wpallimport.com/) | [Pricing](http://www.wpallimport.com/order-now/)
19
 
 
20
 
21
- WP All Import is a powerful XML and CSV import plugin.
22
 
23
- WP All Import can be used for everything from building a store with an affiliate datafeed to displaying live stock quotes or sports scores to building a real estate portal.
 
 
 
 
24
 
25
- = Features =
26
 
27
- * Upload XML/CSV from your computer, or get it from a URL/FTP server
28
- * Use XPath to filter a file and only import the entries you want.
29
- * Drag & Drop template tags into the WYSIWYG post editor to design your posts and choose what data goes where.
30
- * Save options & templates.
31
- * Auto-creation of categories based on data in the feed.
32
- * Managing of previous imports
33
 
 
34
 
35
  == Premium Support ==
36
  Upgrade to the professional edition of WP All Import for premium support.
@@ -47,24 +56,30 @@ Either: -
47
 
48
  == Frequently Asked Questions ==
49
 
50
- *What are the differences between the Lite and Professional editions?*
51
- The Professional edition adds support for Custom Fields, Custom Post Types, recurring/scheduled imports, downloading/importing of images, and [more](http://www.wpallimport.com/upgrade-to-pro/).
 
 
 
52
 
53
- *What size files can WP All Import handle?*
54
- Generally, WP All Import can comfortably handle files of up to 100Mb in most shared hosting environments (GoDaddy, HostGator, etc.). On VPS or dedicated hosting environments, the size of file WP All Import can handle is only limited by the power of the server. When importing very large files it is recommended to split them into chunks and import each chunk individually.
55
 
56
- *Does my CSV have to be in any particular format?*
57
- Use pretty much any delimiter you want. It has to work with the [fgetcsv](http://php.net/manual/en/function.fgetcsv.php) PHP function.
 
58
 
59
  == Screenshots ==
60
 
61
  1. Choose file.
62
- 2. Element selector.
63
- 3. Template designer.
64
- 4. Post options.
65
 
66
  == Changelog ==
67
 
 
 
 
68
  = 2.14 =
69
  * Category list delimiter bug fix
70
 
1
+ === WP All Import - Import any XML or CSV File to WordPress ===
2
  Contributors: soflyy
3
  Tags: wordpress, xml, csv, datafeed, import
4
+ Requires at least: 3.5
5
+ Tested up to: 3.5.1
6
+ Stable tag: 3.0
7
 
8
+ WP All Import is an extremely powerful plugin that makes it easy to import any XML or CSV file to WordPress.
9
 
10
  == Description ==
11
 
12
+ WP All Import is an extremely powerful plugin that makes it easy to import any XML or CSV file to WordPress.
13
+
14
+ WP All Import has a four step import process and an intuitive drag & drop interface that makes complicated import tasks simple and fast.
15
+
16
+ There are no special requirements that the elements in your file must be laid out in a certain way. WP All Import really can import any XML or CSV file.
17
+
18
+ WP All Import can be used for everything from building a store with an affiliate datafeed to displaying live stock quotes or sports scores to building a real estate portal.
19
+
20
  = WP All Import Professional Edition =
21
+ [youtube http://www.youtube.com/watch?v=5YYZyYmX3yg /]
22
 
23
+ *WP All Import Pro* is a $99 upgrade that adds the following features to the free version of WP All Import:
24
 
25
+ * Import to Custom Post Types - commonly used to import to Automotiv, OpenHouse, Listings, and WooCommerce, as well as any other theme or plugin that makes use of Custom Post Types.
26
 
27
+ * Cron Job/Recurring Imports - WP All Import pro can check periodically check a file for updates, and add, edit, and delete to the imported posts accordingly.
28
 
29
+ * Import data to Custom Fields - used by many themes, especially those using Custom Post Types - to store data associated with the posts.
30
 
31
+ * Import images to the post media gallery - WP All Import can download images from URLs in an XML or CSV file and put them in the media gallery.
32
 
33
+ * Import files from a URL or FTP server - Download and import files from external websites or FTP servers, even if they are password protected. FTP imports support wildcard patterns, i.e. *.xml, so for example you could download and import all XML files in a certain folder.
34
+
35
+ * URL and FTP imports are integrated with the recurring/cron imports feature, so WP All Import can periodically re-download the files and add, edit, and delete posts accordingly.
36
+
37
+ * Execution of Custom PHP Functions on data, i.e. use something like [my_function({xpath/to/a/field[1]})] in your template, to pass the value of {xpath/to/a/field[1]} to my_function and display whatever it returns.
38
 
39
+ * Pro version customers also get access to our customer portal with documentation and tutorials, and e-mail technical support.
40
 
 
 
 
 
 
 
41
 
42
+ [Upgrade to the professional edition of WP All Import.](http://www.wpallimport.com/upgrade-to-pro)
43
 
44
  == Premium Support ==
45
  Upgrade to the professional edition of WP All Import for premium support.
56
 
57
  == Frequently Asked Questions ==
58
 
59
+ *What Size Files Can WP All Import Handle?*
60
+ With the release of WP All Import version 3, WP All Import can now handle files of any size and any number of records, as long as the web hosting provider can too. Typically, WP All Import can comfortably import files of 100Mb and larger in most shared hosting environments (HostGator, etc). Please see this page for moredetails.
61
+
62
+ *What are the benefits of the $99 professional version?*
63
+ Support for Custom Post Types, Custom Taxonomies, Custom Fields, cron jobs/recurring imports, download and importing of images to the post media gallery, and URL/FTP server uploads.
64
 
65
+ *The answer to all of the following questions is yes:*
 
66
 
67
+ Does this really work with ANY XML or CSV file?
68
+ Can WP All Import get ALL of the data out of the file? Even attributes?
69
+ Does it work with special character encoding like Hebrew, Arabic, Chinese, etc?
70
 
71
  == Screenshots ==
72
 
73
  1. Choose file.
74
+ 2. Template designer.
75
+ 3. Post options.
76
+ 4. Manage imports.
77
 
78
  == Changelog ==
79
 
80
+ = 3.0 =
81
+ * Free edition of 3.0 pro release
82
+
83
  = 2.14 =
84
  * Category list delimiter bug fix
85
 
schema.php CHANGED
@@ -33,18 +33,32 @@ CREATE TABLE {$table_prefix}templates (
33
  title TEXT,
34
  content LONGTEXT,
35
  is_keep_linebreaks TINYINT(1) NOT NULL DEFAULT 0,
 
36
  PRIMARY KEY (id)
37
  ) $charset_collate;
38
  CREATE TABLE {$table_prefix}imports (
39
  id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
40
  name VARCHAR(255) NOT NULL DEFAULT '',
 
41
  type VARCHAR(32) NOT NULL DEFAULT '',
42
- path TEXT,
43
  xpath VARCHAR(255) NOT NULL DEFAULT '',
44
  template LONGTEXT,
45
  options TEXT,
46
  scheduled VARCHAR(64) NOT NULL DEFAULT '',
47
- registered_on DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
 
 
 
 
 
 
 
 
 
 
 
 
48
  PRIMARY KEY (id)
49
  ) $charset_collate;
50
  CREATE TABLE {$table_prefix}posts (
33
  title TEXT,
34
  content LONGTEXT,
35
  is_keep_linebreaks TINYINT(1) NOT NULL DEFAULT 0,
36
+ is_leave_html TINYINT(1) NOT NULL DEFAULT 0,
37
  PRIMARY KEY (id)
38
  ) $charset_collate;
39
  CREATE TABLE {$table_prefix}imports (
40
  id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
41
  name VARCHAR(255) NOT NULL DEFAULT '',
42
+ friendly_name VARCHAR(255) NOT NULL DEFAULT '',
43
  type VARCHAR(32) NOT NULL DEFAULT '',
44
+ path TEXT,
45
  xpath VARCHAR(255) NOT NULL DEFAULT '',
46
  template LONGTEXT,
47
  options TEXT,
48
  scheduled VARCHAR(64) NOT NULL DEFAULT '',
49
+ registered_on DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
50
+ large_import ENUM('Yes','No') NOT NULL DEFAULT 'No',
51
+ root_element VARCHAR(255) DEFAULT '',
52
+ processing BOOL NOT NULL DEFAULT '0',
53
+ triggered BOOL NOT NULL DEFAULT '0',
54
+ queue_chunk_number BIGINT(20) NOT NULL DEFAULT '0',
55
+ current_post_ids TEXT NULL DEFAULT '',
56
+ first_import TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
57
+ count BIGINT(20) NOT NULL DEFAULT '0',
58
+ imported BIGINT(20) NOT NULL DEFAULT '0',
59
+ created BIGINT(20) NOT NULL DEFAULT '0',
60
+ updated BIGINT(20) NOT NULL DEFAULT '0',
61
+ skipped BIGINT(20) NOT NULL DEFAULT '0',
62
  PRIMARY KEY (id)
63
  ) $charset_collate;
64
  CREATE TABLE {$table_prefix}posts (
screenshot-1.png CHANGED
Binary file
screenshot-2.png CHANGED
Binary file
screenshot-3.png CHANGED
Binary file
screenshot-4.png CHANGED
Binary file
static/css/admin.css CHANGED
@@ -7,9 +7,9 @@
7
  margin-bottom: 15px;
8
  }
9
  .pmxi_plugin a.button {
10
- padding: 5px 10px;
11
  margin: 1px;
12
- font-weight: bold;
13
  }
14
  .pmxi_plugin a.help {
15
  overflow: hidden;
@@ -37,6 +37,7 @@
37
  }
38
  .pmxi_plugin .progress-msg {
39
  font-style: italic;
 
40
  }
41
  .pmxi_plugin .inner-content {
42
  max-width: 700px;
@@ -46,6 +47,11 @@
46
  background-repeat: no-repeat;
47
  background-position: center;
48
  }
 
 
 
 
 
49
  .pmxi_plugin a.add-new {
50
  font-size: 18px;
51
  background-color: #eee;
@@ -67,15 +73,20 @@
67
  color: #000;
68
  }
69
  .pmxi_plugin div.input {
70
- line-height: 25px;
71
- height: 25px;
 
72
  }
73
  .pmxi_plugin div.input > * {
74
  vertical-align: middle;
75
  }
 
 
 
 
76
  .pmxi_plugin .note {
77
  color: #666666;
78
- font-size: 11px;
79
  }
80
  .pmxi_plugin div.sub {
81
  padding-left: 20px;
@@ -90,7 +101,7 @@
90
  }
91
  .pmxi_plugin table.layout td {
92
  vertical-align: top;
93
- border: none;
94
  }
95
  .pmxi_plugin table.layout td.left {
96
  min-width: 490px;
@@ -98,7 +109,7 @@
98
  }
99
  .pmxi_plugin table.layout td.right {
100
  padding: 0px 0 16px 20px;
101
- width: 30%;
102
  min-width: 260px;
103
  }
104
  .pmxi_plugin table.layout td.left > h2:first-child {
@@ -121,7 +132,8 @@
121
 
122
  /*@+ Choose File forms */
123
  .pmxi_plugin form.choose-file {
124
- padding-top: 10px;
 
125
  }
126
  .pmxi_plugin form.choose-file h3 {
127
  margin-bottom: 5px;
@@ -136,7 +148,7 @@
136
  }
137
  .pmxi_plugin form.choose-file input.regular-text,
138
  .pmxi_plugin form.choose-file select.regular-text {
139
- width: 300px;
140
  }
141
  .pmxi_plugin #wpcontent form.choose-file select[name="file"],
142
  .pmxi_plugin #wpcontent form.choose-file select[name="reimport"] {
@@ -162,11 +174,9 @@
162
  .pmxi_plugin form.template.edit {
163
  /*width: 700px;*/
164
  }
165
- .pmxi_plugin form.template .load-template {
166
  display: block;
167
- float: right;
168
- padding-top: 7px;
169
- font-size: 12px;
170
  }
171
  .pmxi_plugin form.template .load-template select {
172
  width: 126px;
@@ -244,6 +254,7 @@
244
  }
245
  .pmxi_plugin .post-type-options table.form-table select {
246
  max-width: 300px;
 
247
  }
248
  .pmxi_plugin table.form-table thead td {
249
  font-weight: bold;
@@ -257,24 +268,41 @@
257
  /*@*/
258
 
259
  /*@+ XML representation */
260
- .pmxi_plugin .tag {
261
- border: 1px solid #DFDFDF;
262
- background-color: #fff;
263
- -moz-border-radius: 4px;
264
- -khtml-border-radius: 4px;
265
- -webkit-border-radius: 4px;
266
- border-radius: 4px;
 
 
 
 
 
 
 
 
 
267
  }
268
  .pmxi_plugin .tag .title {
269
  font-weight: bold;
270
  padding: 6px 8px;
271
  color: #464646;
272
- background: url("../../../../../wp-admin/images/gray-grad.png") repeat-x scroll left top #DFDFDF;
273
  font-size: 12px;
274
  }
275
  .pmxi_plugin .tag .xml {
276
- max-height: 600px;
277
  overflow: auto;
 
 
 
 
 
 
 
 
278
  }
279
  .pmxi_plugin .tag .navigation {
280
  float: right;
@@ -287,6 +315,15 @@
287
  text-decoration: none;
288
  }
289
 
 
 
 
 
 
 
 
 
 
290
  .xml {
291
  padding-left: 15px;
292
  }
@@ -464,16 +501,15 @@ table.xml table {
464
  }
465
 
466
  .pmxi_plugin #process{ display:none; }
467
- .pmxi_plugin .load-options{ float:right; font-size:13px; }
468
- .pmxi_plugin form.options table.layout td.right{
469
- position: fixed;
470
  width: 25%;
471
  }
472
  .pmxi_plugin .drag-element{
473
  background: url("../img/drag.png") top right no-repeat;
474
  cursor: pointer;
475
- padding-right: 25px;
476
- background-position: 100% 1px;
477
  }
478
  .sortable li{ position: relative;}
479
  .pmxi_plugin ol{
@@ -481,24 +517,449 @@ table.xml table {
481
  list-style: none;
482
  }
483
  .pmxi_plugin .no-margin{ margin:0px; }
484
- .pmxi_plugin .icon-item{
485
- display: inline-block;;
486
  width: 16px;
487
  height: 16px;
488
  margin: 0px 3px;
489
  }
490
- .pmxi_plugin .add-new-ico{
491
- background: url("../img/ico-add-new.png") no-repeat;
492
- position: absolute;
493
- top:5px;
494
- right: 0px;
 
495
  }
496
 
497
  .pmxi_plugin .remove-ico{
498
  background: url("../img/ico-remove.png") no-repeat;
499
  top:1px;
500
- right:-30px;
501
  position: absolute;
502
  }
503
 
504
- .pmxi_plugin .hidden{ display: none; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  margin-bottom: 15px;
8
  }
9
  .pmxi_plugin a.button {
10
+ /*padding: 5px 10px;
11
  margin: 1px;
12
+ font-weight: bold;*/
13
  }
14
  .pmxi_plugin a.help {
15
  overflow: hidden;
37
  }
38
  .pmxi_plugin .progress-msg {
39
  font-style: italic;
40
+ display: none;
41
  }
42
  .pmxi_plugin .inner-content {
43
  max-width: 700px;
47
  background-repeat: no-repeat;
48
  background-position: center;
49
  }
50
+ .pmxi_plugin .preload {
51
+ background-image: url("../img/loading.png");
52
+ background-repeat: no-repeat;
53
+ background-position: 50% 200px;
54
+ }
55
  .pmxi_plugin a.add-new {
56
  font-size: 18px;
57
  background-color: #eee;
73
  color: #000;
74
  }
75
  .pmxi_plugin div.input {
76
+ /*line-height: 25px;
77
+ height: 25px;*/
78
+ min-height: 21px;
79
  }
80
  .pmxi_plugin div.input > * {
81
  vertical-align: middle;
82
  }
83
+ .pmxi_plugin .options input[type=text], .pmxi_plugin .options select {
84
+ background: #fafafa !important;
85
+ border: 1px solid #aaa !important;
86
+ }
87
  .pmxi_plugin .note {
88
  color: #666666;
89
+ font-size: 9px;
90
  }
91
  .pmxi_plugin div.sub {
92
  padding-left: 20px;
101
  }
102
  .pmxi_plugin table.layout td {
103
  vertical-align: top;
104
+ border: none;
105
  }
106
  .pmxi_plugin table.layout td.left {
107
  min-width: 490px;
109
  }
110
  .pmxi_plugin table.layout td.right {
111
  padding: 0px 0 16px 20px;
112
+ width: 25%;
113
  min-width: 260px;
114
  }
115
  .pmxi_plugin table.layout td.left > h2:first-child {
132
 
133
  /*@+ Choose File forms */
134
  .pmxi_plugin form.choose-file {
135
+ padding-top: 20px;
136
+ position: relative;
137
  }
138
  .pmxi_plugin form.choose-file h3 {
139
  margin-bottom: 5px;
148
  }
149
  .pmxi_plugin form.choose-file input.regular-text,
150
  .pmxi_plugin form.choose-file select.regular-text {
151
+ width: 100%;
152
  }
153
  .pmxi_plugin #wpcontent form.choose-file select[name="file"],
154
  .pmxi_plugin #wpcontent form.choose-file select[name="reimport"] {
174
  .pmxi_plugin form.template.edit {
175
  /*width: 700px;*/
176
  }
177
+ .pmxi_plugin form.template .load-template {
178
  display: block;
179
+ font-size: 12px;
 
 
180
  }
181
  .pmxi_plugin form.template .load-template select {
182
  width: 126px;
254
  }
255
  .pmxi_plugin .post-type-options table.form-table select {
256
  max-width: 300px;
257
+ width:300px;
258
  }
259
  .pmxi_plugin table.form-table thead td {
260
  font-weight: bold;
268
  /*@*/
269
 
270
  /*@+ XML representation */
271
+ .pmxi_plugin .tag {
272
+ background-color: #fff;
273
+ position: fixed;
274
+ width:22%;
275
+ margin-top: 45px;
276
+ border-top: 1px solid #DFDFDF;
277
+ -moz-border-radius-topleft: 4px;
278
+ -webkit-border-top-left-radius: 4px;
279
+ border-top-left-radius: 4px;
280
+ -moz-border-radius-topright: 4px;
281
+ -webkit-border-top-right-radius: 4px;
282
+ border-top-right-radius: 4px;
283
+ }
284
+
285
+ .pmxi_plugin .options .tag{
286
+ margin-top: 0px;
287
  }
288
  .pmxi_plugin .tag .title {
289
  font-weight: bold;
290
  padding: 6px 8px;
291
  color: #464646;
292
+ background: #DFDFDF;
293
  font-size: 12px;
294
  }
295
  .pmxi_plugin .tag .xml {
296
+ max-height: 525px;
297
  overflow: auto;
298
+ border: 1px solid #DFDFDF;
299
+ border-top:none;
300
+ -moz-border-radius-bottomright: 4px;
301
+ -webkit-border-bottom-right-radius: 4px;
302
+ border-bottom-right-radius: 4px;
303
+ -moz-border-radius-bottomleft: 4px;
304
+ -webkit-border-bottom-left-radius: 4px;
305
+ border-bottom-left-radius: 4px;
306
  }
307
  .pmxi_plugin .tag .navigation {
308
  float: right;
315
  text-decoration: none;
316
  }
317
 
318
+ @media screen and (max-height: 700px) {
319
+ .pmxi_plugin .tag {
320
+ height:300px;
321
+ }
322
+ .pmxi_plugin .tag .xml {
323
+ max-height: 265px;
324
+ }
325
+ }
326
+
327
  .xml {
328
  padding-left: 15px;
329
  }
501
  }
502
 
503
  .pmxi_plugin #process{ display:none; }
504
+ .pmxi_plugin .load-options{ float:right; font-size:13px; position: relative; top: -30px; }
505
+ .pmxi_plugin form.options table.layout td.right{
 
506
  width: 25%;
507
  }
508
  .pmxi_plugin .drag-element{
509
  background: url("../img/drag.png") top right no-repeat;
510
  cursor: pointer;
511
+ padding-left: 25px;
512
+ background-position: 0px 1px;
513
  }
514
  .sortable li{ position: relative;}
515
  .pmxi_plugin ol{
517
  list-style: none;
518
  }
519
  .pmxi_plugin .no-margin{ margin:0px; }
520
+ .pmxi_plugin .icon-item, .pmxi_plugin .add-new-custom{
521
+ display: inline-block;
522
  width: 16px;
523
  height: 16px;
524
  margin: 0px 3px;
525
  }
526
+ .pmxi_plugin .add-new-ico, .pmxi_plugin .add-new-custom{
527
+ background: url("../img/ico-add-new.png") no-repeat 0px 4px;
528
+ width:70px;
529
+ height:25px;
530
+ padding-left: 15px;
531
+ color:#21759B;
532
  }
533
 
534
  .pmxi_plugin .remove-ico{
535
  background: url("../img/ico-remove.png") no-repeat;
536
  top:1px;
537
+ right:-4px;
538
  position: absolute;
539
  }
540
 
541
+ .pmxi_plugin .hidden{ display: none; }
542
+
543
+ .pmxi_plugin .fs11 { font-size:11px; }
544
+
545
+ .pmxi_plugin .rel { position: relative; }
546
+
547
+ #type_meta_select{ margin-bottom: 10px; height:1.8em; }
548
+
549
+ .upload_process{
550
+ border: none;
551
+ padding: 1px;
552
+ }
553
+
554
+ #large_import_xpath{ display:none; }
555
+ #large_import{ margin:0px 5px; }
556
+ #download_pmxi_log{
557
+ cursor: pointer;
558
+ margin: 5px 0;
559
+ display: none;
560
+ }
561
+ .pmxi_plugin .import_process_bar, .pmxi_plugin .import_percent{
562
+ display: none;
563
+ }
564
+ /*.pmxi_plugin .import_progress{
565
+ font-size: 14px !important;
566
+ }*/
567
+ .pmxi_plugin #processbar{
568
+ text-align: center;
569
+ visibility: hidden;
570
+ height: 37px;
571
+ padding-top: 18px;
572
+ margin-bottom: 20px;
573
+ border: 1px solid #AAAAAA;
574
+ color: #222222;
575
+ position: relative;
576
+ }
577
+ .pmxi_plugin #processbar div{
578
+ background: #aaa;
579
+ height: 55px;
580
+ width: 0%;
581
+ position: absolute;
582
+ opacity: 0.5;
583
+ top:0;
584
+ }
585
+ .pmxi_plugin #import_progress{
586
+ color: #000000;
587
+ font-size: 13px;
588
+ font-weight: bold;
589
+ opacity: 1;
590
+ }
591
+ .pmxi_plugin #right_progress{ float:right; padding-right: 5px; }
592
+ .pmxi_plugin #left_progress{ float:left; padding-left: 5px; }
593
+ .pmxi_plugin #existing_meta_keys{
594
+ margin-bottom: 10px;
595
+ padding: 2px;
596
+ width: 580px;
597
+ }
598
+ .pmxi_plugin #pmxi_tabs{
599
+ display: none;
600
+ padding-bottom: 20px;
601
+ -moz-border-radius: 4px;
602
+ -khtml-border-radius: 4px;
603
+ -webkit-border-radius: 4px;
604
+ border-radius: 4px;
605
+ }
606
+ .pmxi_plugin .ui-widget-header{
607
+ -moz-border-radius: 4px;
608
+ -khtml-border-radius: 4px;
609
+ -webkit-border-radius: 4px;
610
+ border-radius: 4px;
611
+ }
612
+ .pmxi_plugin .ui-tabs .ui-tabs-nav li{
613
+ -moz-border-top-left-radius: 4px;
614
+ -khtml-border-top-left-radius: 4px;
615
+ -webkit-border-top-left-radius: 4px;
616
+ border-top-left-radius: 4px;
617
+ -moz-border-top-right-radius: 4px;
618
+ -khtml-border-top-right-radius: 4px;
619
+ -webkit-border-top-right-radius: 4px;
620
+ border-top-right-radius: 4px;
621
+ }
622
+ /*.pmxi_plugin .ui-widget-header{
623
+ background: #F2FBD9;
624
+ border: 1px solid #F2FBD9;
625
+ }
626
+ .pmxi_plugin .ui-state-default{
627
+ border:none;
628
+ font-size: 12px;
629
+ font-weight: bold;
630
+ background: #F2FBD9;
631
+ }
632
+ .pmxi_plugin .ui-state-active{
633
+ background: #fff;
634
+ }
635
+ .pmxi_plugin .ui-tabs{
636
+ padding: 0px;
637
+ }*/
638
+ #select-files{
639
+ font-size: 11px !important;
640
+ height:25px;
641
+ }
642
+ .pmxi_plugin .progress{
643
+ position: relative;
644
+ visibility: hidden;
645
+ color: #009039;
646
+ font-size: 13px;
647
+ font-weight: bold;
648
+ margin-top: 10px;
649
+ width: 100%;
650
+ text-align: center;
651
+ border:1px solid #4297D7;
652
+ -moz-border-radius: 4px;
653
+ -khtml-border-radius: 4px;
654
+ -webkit-border-radius: 4px;
655
+ border-radius: 4px;
656
+ }
657
+ .pmxi_plugin #progressbar{
658
+ border: medium none;
659
+ left: 0;
660
+ position: absolute;
661
+ text-align: center;
662
+ top: 8px;
663
+ width: 100%;
664
+ font-size: 12px;
665
+ color:#333;
666
+ }
667
+ .pmxi_plugin #file_name{
668
+ font-size: 16px;
669
+ font-weight: bold;
670
+ margin-left: 10px;
671
+ float: right;
672
+ }
673
+ .pmxi_plugin .ui-progressbar .ui-progressbar-value { /*background-image: url("../img/progress_animated.gif");*/ }
674
+ .pmxi_plugin form.choose-file .submit-buttons{
675
+ /*bottom: -125px;
676
+ position: absolute;
677
+ right: -18px; */
678
+ }
679
+ .pmxi_plugin form#basic .submit-buttons{
680
+ display: none;
681
+ }
682
+ .pmxi_plugin fieldset{
683
+ padding: 20px;
684
+ width:auto;
685
+ }
686
+ .pmxi_plugin .right fieldset{
687
+ padding: 15px;
688
+ }
689
+ .pmxi_plugin .right fieldset input{
690
+ max-width:none;
691
+ padding:6px;
692
+ margin:0px
693
+ }
694
+ .pmxi_plugin .right a{
695
+ text-decoration: underline;
696
+ }
697
+ .pmxi_plugin fieldset legend{
698
+ padding: 0px 5px;
699
+ font-weight: bold;
700
+ }
701
+ .pmxi_plugin .options fieldset legend{
702
+ font-size: 1.17em;
703
+ }
704
+ .pmxi_plugin .matches_count{
705
+ font-weight: bold;
706
+ color:#33AA28;
707
+ }
708
+ .pmxi_plugin .xpath_help{
709
+ /*bottom: -40px;*/
710
+ position: relative;
711
+ text-align: center;
712
+ }
713
+ .pmxi_plugin .btns, .pmxi_plugin .btns input, .pmxi_plugin .btns a{
714
+ float: right;
715
+ }
716
+ .pmxi_plugin .btns input{
717
+ height: 19px;
718
+ margin-left: 5px;
719
+ padding-top: 0;
720
+ }
721
+ .pmxi_plugin .btns a{
722
+ font-weight: bold;
723
+ margin: 0 5px;
724
+ padding: 4px 10px;
725
+ width:70px;
726
+ text-align: center;
727
+ }
728
+ .pmxi_plugin .col3{
729
+ border-right: 1px solid #CCCCCC;
730
+ float: left;
731
+ height: 265px;
732
+ width:30%;
733
+ margin-bottom: 10px;
734
+ padding: 0 1%;
735
+ }
736
+ .pmxi_plugin .col3.last{
737
+ border: none;
738
+ }
739
+ .pmxi_plugin .col3 > div{
740
+ margin-left: 20px;
741
+ }
742
+ .pmxi_plugin .col2{
743
+ float: left;
744
+ width: 50%;
745
+ }
746
+ .pmxi_plugin .col2 fieldset{
747
+ border: 1px solid #CCCCCC;
748
+ margin: 0 5px;
749
+ padding: 5px 2% 5px 5px;
750
+ text-align: center;
751
+ }
752
+ .pmxi_plugin input.small{
753
+ width:25px;
754
+ text-align: center;
755
+ }
756
+ .pmxi_plugin .post_taxonomy{
757
+ margin-bottom: 15px;
758
+ overflow: hidden;
759
+ padding-bottom: 15px;
760
+ }
761
+ .pmxi_plugin .post_taxonomy .delim{
762
+ padding-left: 25px;
763
+ }
764
+ .pmxi_plugin .post_taxonomy .delim .add-new-ico{
765
+ float: right;
766
+ margin-right: 35px;
767
+ margin-top: 5px;
768
+ }
769
+ .pmxi_plugin .post_taxonomy ol.ui-sortable{
770
+ padding-right: 0px;
771
+ }
772
+ .pmxi_plugin .optionsset{
773
+ border:1px solid #ccc;
774
+ }
775
+ .pmxi_plugin .action.remove{
776
+ display: block;
777
+ position: relative;
778
+ }
779
+ .pmxi_plugin .action.remove a{
780
+ background: url("../img/ico-remove.png") no-repeat scroll 0 0 transparent;
781
+ height: 16px;
782
+ position: absolute;
783
+ right: -10px;
784
+ width: 16px;
785
+ }
786
+ .pmxi_plugin .switcher-target-is_keep_former_posts{
787
+ padding-left: 25px;
788
+ }
789
+ .pmxi_plugin form.options{
790
+ position: relative;
791
+ }
792
+ .pmxi_plugin .options_buttons{
793
+ bottom: -75px;
794
+ display: block;
795
+ position: absolute;
796
+ right: 0;
797
+ }
798
+ .pmxi-button{
799
+ border: 1px solid #BBBBBB;
800
+ color: #464646;
801
+ cursor: pointer;
802
+ font-size: 18px !important;
803
+ margin-left: 10px;
804
+ padding: 15px 25px;
805
+ text-decoration: none;
806
+ -moz-border-radius: 3px;
807
+ -khtml-border-radius: 3px;
808
+ -webkit-border-radius: 3px;
809
+ border-radius: 3px;
810
+ }
811
+ .pmxi-button:hover{
812
+ background: #dfdfdf;
813
+ }
814
+ .pmxi_plugin .ui-state-default a{
815
+ font-size: 13px !important;
816
+ }
817
+ .pmxi_plugin .preview{
818
+ float:none;
819
+ text-decoration: none;
820
+ }
821
+ .pmxi_plugin .template-sidebar .tag{
822
+ max-height:550px;
823
+ }
824
+ .pmxi_plugin .options .submit-buttons{
825
+ float: right;
826
+ position: relative;
827
+ text-align: right;
828
+ top: 30px;
829
+ right:-18px;
830
+ }
831
+ .pmxi_plugin .back{
832
+ font-size: 16px;
833
+ color:#21759B;
834
+ }
835
+ .pmxi_plugin .separated_by{
836
+ float: right;
837
+ font-size: 12px;
838
+ color: #999999;
839
+ margin-right: 20px;
840
+ }
841
+ .pmxi_plugin .delim > label{
842
+ color: #999999;
843
+ font-size: 11px;
844
+ }
845
+ .pmxi_plugin .optionsset > table{
846
+ border-bottom: 1px solid #CCCCCC;
847
+ margin-bottom: 20px;
848
+ width: 100%;
849
+ }
850
+ /* Log Bar - Step 5 */
851
+ .pmxi_plugin #logwrapper{
852
+ border: 1px solid #aaa;
853
+ margin-bottom: 20px;
854
+ }
855
+ .pmxi_plugin #logbar{
856
+ padding: 5px 0px;
857
+ text-align: center;
858
+ margin: 10px 0px;
859
+ border: 1px solid #aaa;
860
+ overflow: auto;
861
+ }
862
+ .pmxi_plugin .optionsset > table:last-child{
863
+ border: none;
864
+ }
865
+ .pmxi_plugin #download_log_separator, .pmxi_plugin #download_log{
866
+ display: none;
867
+ }
868
+ .pmxi_plugin #loglist{
869
+ border: 1px solid #AAAAAA;
870
+ height: 400px;
871
+ overflow: auto;
872
+ }
873
+ .pmxi_plugin #loglist > p{
874
+ margin: 0;
875
+ padding: 3px 5px;
876
+ }
877
+ .pmxi_plugin #loglist > p.odd{
878
+ background: #dfdfdf;
879
+ }
880
+ .pmxi_plugin #process_notice{
881
+ color: red;
882
+ text-align: center;
883
+ }
884
+ .pmxi_plugin #reimported_notify{
885
+ border: 1px solid #AFAFAF;
886
+ margin-bottom: 20px;
887
+ padding: 10px 20px;
888
+ }
889
+ .pmxi_plugin #reimported_notify p span{
890
+ color:#ccc;
891
+ }
892
+ .pmxi_plugin .action_buttons{
893
+ overflow: hidden;
894
+ clear: both;
895
+ padding-bottom: 10px;
896
+ }
897
+ /*.pmxi_plugin .action_buttons a{
898
+ border: 1px solid #BBBBBB;
899
+ -moz-border-radius: 3px;
900
+ -khtml-border-radius: 3px;
901
+ -webkit-border-radius: 3px;
902
+ border-radius: 3px;
903
+ color: #464646;
904
+ cursor: pointer;
905
+ font-size: 18px !important;
906
+ margin-right: 10px;
907
+ padding: 15px 25px;
908
+ text-decoration: none;
909
+ display: block;
910
+ width:25px;
911
+ float: left;
912
+ }
913
+ .pmxi_plugin .action_buttons a:hover{
914
+ background: #dfdfdf;
915
+ }*/
916
+ .pmxi_plugin #current_element{
917
+ color:green;
918
+ }
919
+ .pmxi_plugin #current_xml{ display: none;}
920
+ .pmxi_plugin #goto_element{
921
+ display: block;
922
+ float: left;
923
+ height: 47px;
924
+ margin-right: 10px;
925
+ width: 70px !important;
926
+ min-width: 70px;
927
+ text-align: center;
928
+ font-size: 18px;
929
+ }
930
+ .pmxi_plugin .choose-elements table tbody tr td{
931
+ overflow: hidden;
932
+ }
933
+ .pmxi_plugin #plupload-ui h3{
934
+ float: left;
935
+ font-size: 13px;
936
+ font-weight: normal;
937
+ margin-bottom: 0;
938
+ margin-top: 8px;
939
+ }
940
+ .pmxi_plugin #wp-content-media-buttons{
941
+ display: none;
942
+ }
943
+ .pmxi_plugin label{
944
+ -webkit-touch-callout: none;
945
+ -webkit-user-select: none;
946
+ -khtml-user-select: none;
947
+ -moz-user-select: none;
948
+ -ms-user-select: none;
949
+ user-select: none;
950
+ }
951
+ .pmxi_plugin .large_button{
952
+ margin-left: 10px;
953
+ padding: 15px 25px;
954
+ border: 1px solid #C5DBEC;
955
+ }
956
+ .pmxi_plugin .drag-element .assign_post{
957
+ float: left;
958
+ }
959
+ .pmxi_plugin .drag-element .widefat{
960
+ margin-left: 1%;
961
+ width: 90%;
962
+ }
963
+ .pmxi_plugin .upgrade_link{
964
+ color: #21759B;
965
+ }
static/img/loading.gif DELETED
Binary file
static/img/loading.png ADDED
Binary file
static/img/progress_animated.gif ADDED
Binary file
static/js/admin.js CHANGED
@@ -7,8 +7,7 @@
7
  // fix layout position
8
  setTimeout(function () {
9
  $('table.layout').length && $('table.layout td.left h2:first-child').css('margin-top', $('.wrap').offset().top - $('table.layout').offset().top);
10
- }, 10);
11
-
12
 
13
  // help icons
14
  $('a.help').tipsy({
@@ -109,6 +108,7 @@
109
  // choose file form: option selection dynamic
110
  // options form: highlight options of selected post type
111
  $('form.choose-file input[name="type"]').click(function() {
 
112
  var $container = $(this).parents('.file-type-container');
113
  $('.file-type-container').not($container).removeClass('selected').find('.file-type-options').hide();
114
  $container.addClass('selected').find('.file-type-options').show();
@@ -154,7 +154,7 @@
154
  return false;
155
  });
156
  // options form: auto submit when `load options` checkbox is checked
157
- $('form.options').find('input[name="load_options"]').click(function () {
158
  if ($(this).is(':checked')) $(this).parents('form').submit();
159
  });
160
  // options form: auto submit when `reset options` checkbox is checked
@@ -198,7 +198,7 @@
198
  if (action.init) {
199
  this.data('initialized', true);
200
  // add expander
201
- this.find('.xml-expander').click(function () {
202
  var method;
203
  if ('-' == $(this).text()) {
204
  $(this).text('+');
@@ -279,7 +279,7 @@
279
  }
280
  });
281
 
282
- if ($('#content').length) tinymce.dom.Event.add('wp-content-editor-container', 'click', function(e) {
283
  if (dblclickbuf.selected)
284
  {
285
  tinyMCE.activeEditor.selection.setContent(dblclickbuf.value);
@@ -291,7 +291,11 @@
291
 
292
  this.find('.xml-tag.opening > .xml-tag-name, .xml-attr-name').each(function () {
293
  var $this = $(this);
294
- var xpath = '{' + (($this.is('.xml-attr-name') ? $this.parent() : $this.parent().parent()).attr('title').replace(/^\/[^\/]+\/?/, '') || '.') + '}';
 
 
 
 
295
 
296
  $this.mouseover(function (e) {
297
  $drag.val(xpath).offset({left: $this.offset().left - 2, top: $this.offset().top - 2}).width(_w = $this.width() + 4).height($this.height() + 4);
@@ -305,23 +309,53 @@
305
  $('form.choose-elements').each(function () {
306
  var $form = $(this);
307
  $form.find('.xml').xml();
308
- var $input = $form.find('input[name="xpath"]');
309
- $form.find('.xml-tag.opening').bind('mousedown', function () {return false;}).dblclick(function () {
 
 
 
 
 
 
 
310
  if ($form.hasClass('loading')) return; // do nothing if selecting operation is currently under way
311
  $input.val($(this).parents('.xml-element').first().attr('title').replace(/\[\d+\]$/, '')).change();
312
  });
313
  var xpathChanged = function () {
314
- if ($input.val() == $input.data('checkedValue')) return;
315
- $form.addClass('loading');
 
 
 
 
316
  $form.find('.xml-element.selected').removeClass('selected'); // clear current selection
317
  // request server to return elements which correspond to xpath entered
318
  $input.attr('readonly', true).unbind('change', xpathChanged).data('checkedValue', $input.val());
319
- $('.ajax-console').load('admin.php?page=pmxi-admin-import&action=evaluate', {xpath: $input.val()}, function () {
320
- $input.attr('readonly', false).change(xpathChanged);
 
 
321
  $form.removeClass('loading');
 
322
  });
323
  };
324
- $input.change(xpathChanged).change();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325
  $input.keyup(function (e) {
326
  if (13 == e.keyCode) $(this).change();
327
  });
@@ -366,13 +400,23 @@
366
  toleranceElement: '> div',
367
  update: function () {
368
  $(this).parents('td:first').find('.hierarhy-output').val(window.JSON.stringify($(this).nestedSortable('toArray', {startDepthCount: 0})));
369
- if ($('.drag-element:first').find('input').val() == '') $(this).parents('td:first').find('.hierarhy-output').val('');
370
  }
371
  });
372
 
373
  $('.drag-element').find('input').live('blur', function(){
374
  $(this).parents('td:first').find('.hierarhy-output').val(window.JSON.stringify($(this).parents('.sortable:first').nestedSortable('toArray', {startDepthCount: 0})));
375
- if ($('.drag-element:first').find('input').val() == '') $(this).parents('td:first').find('.hierarhy-output').val('');
 
 
 
 
 
 
 
 
 
 
376
  });
377
 
378
  $('.sortable').find('.remove-ico').live('click', function(){
@@ -384,17 +428,118 @@
384
  $(this).attr({'id':'item_'+ (i+1)});
385
  });
386
  parent_td.find('.hierarhy-output').val(window.JSON.stringify(parent_td.find('.sortable:first').nestedSortable('toArray', {startDepthCount: 0})));
387
- if ($('.drag-element:first').find('input').val() == '') parent_td.find('.hierarhy-output').val('');
388
  });
389
 
390
  $('.add-new-ico').click(function(){
391
  var count = $(this).parents('tr:first').find('ol.sortable').find('li').length + 1;
392
- $(this).parents('tr:first').find('ol.sortable').append('<li id="item_'+count+'"><div class="drag-element"><input type="text" value="" class="widefat"></div><a class="icon-item remove-ico" href="javascript:void(0);"></a></li>');
 
 
393
  $('.widefat').bind('focus', insertxpath );
394
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
395
 
396
- /* END Categories hierarchy */
 
 
 
 
397
 
 
 
 
 
 
 
398
 
 
 
 
 
 
 
399
 
400
- });})(jQuery);
7
  // fix layout position
8
  setTimeout(function () {
9
  $('table.layout').length && $('table.layout td.left h2:first-child').css('margin-top', $('.wrap').offset().top - $('table.layout').offset().top);
10
+ }, 10);
 
11
 
12
  // help icons
13
  $('a.help').tipsy({
108
  // choose file form: option selection dynamic
109
  // options form: highlight options of selected post type
110
  $('form.choose-file input[name="type"]').click(function() {
111
+ if ($(this).val() == 'upload' || $(this).val() == 'file' || $(this).val() == 'reimport' || $(this).val() == 'url') $('#large_import').slideDown(); else { $('#large_import').slideUp(); $('#large_import_toggle').removeAttr('checked'); $('#large_import_xpath').slideUp();}
112
  var $container = $(this).parents('.file-type-container');
113
  $('.file-type-container').not($container).removeClass('selected').find('.file-type-options').hide();
114
  $container.addClass('selected').find('.file-type-options').show();
154
  return false;
155
  });
156
  // options form: auto submit when `load options` checkbox is checked
157
+ $('input[name="load_options"]').click(function () {
158
  if ($(this).is(':checked')) $(this).parents('form').submit();
159
  });
160
  // options form: auto submit when `reset options` checkbox is checked
198
  if (action.init) {
199
  this.data('initialized', true);
200
  // add expander
201
+ this.find('.xml-expander').live('click', function () {
202
  var method;
203
  if ('-' == $(this).text()) {
204
  $(this).text('+');
279
  }
280
  });
281
 
282
+ if ($('#content').length && window.tinymce != undefined) tinymce.dom.Event.add('wp-content-editor-container', 'click', function(e) {
283
  if (dblclickbuf.selected)
284
  {
285
  tinyMCE.activeEditor.selection.setContent(dblclickbuf.value);
291
 
292
  this.find('.xml-tag.opening > .xml-tag-name, .xml-attr-name').each(function () {
293
  var $this = $(this);
294
+ var xpath = '.';
295
+ if ($this.is('.xml-attr-name'))
296
+ xpath = '{' + ($this.parents('.xml-element:first').attr('title').replace(/^\/[^\/]+\/?/, '') || '.') + '/@' + $this.html().trim() + '}';
297
+ else
298
+ xpath = '{' + ($this.parent().parent().attr('title').replace(/^\/[^\/]+\/?/, '') || '.') + '}';
299
 
300
  $this.mouseover(function (e) {
301
  $drag.val(xpath).offset({left: $this.offset().left - 2, top: $this.offset().top - 2}).width(_w = $this.width() + 4).height($this.height() + 4);
309
  $('form.choose-elements').each(function () {
310
  var $form = $(this);
311
  $form.find('.xml').xml();
312
+ var $input = $form.find('input[name="xpath"]');
313
+ var $next_element = $form.find('#next_element');
314
+ var $prev_element = $form.find('#prev_element');
315
+ var $goto_element = $form.find('#goto_element');
316
+ var $get_default_xpath = $form.find('#get_default_xpath');
317
+ var $root_element = $form.find('#root_element');
318
+
319
+ var $xml = $('.xml');
320
+ $form.find('.xml-tag.opening').live('mousedown', function () {return false;}).live('dblclick', function () {
321
  if ($form.hasClass('loading')) return; // do nothing if selecting operation is currently under way
322
  $input.val($(this).parents('.xml-element').first().attr('title').replace(/\[\d+\]$/, '')).change();
323
  });
324
  var xpathChanged = function () {
325
+ if ($input.val() == $input.data('checkedValue')) return;
326
+ var xpath_elements = $input.val().split('[');
327
+ var xpath_parts = xpath_elements[0].split('/');
328
+ xpath_elements[0] = '';
329
+ $input.val('/' + xpath_parts[xpath_parts.length - 1] + ((xpath_elements.length) ? xpath_elements.join('[') : ''));
330
+ $form.addClass('loading');
331
  $form.find('.xml-element.selected').removeClass('selected'); // clear current selection
332
  // request server to return elements which correspond to xpath entered
333
  $input.attr('readonly', true).unbind('change', xpathChanged).data('checkedValue', $input.val());
334
+ $xml.css({'visibility':'hidden'});
335
+ $xml.parents('fieldset:first').addClass('preload');
336
+ $('.ajax-console').load('admin.php?page=pmxi-admin-import&action=evaluate', {xpath: $input.val(), show_element: $goto_element.val(), root_element:$root_element.val()}, function () {
337
+ $input.attr('readonly', false).change(function(){$goto_element.val(1); xpathChanged();});
338
  $form.removeClass('loading');
339
+ $xml.parents('fieldset:first').removeClass('preload');
340
  });
341
  };
342
+ $next_element.click(function(){
343
+ var show_element = Math.min((parseInt($goto_element.val()) + 1), parseInt($('.matches_count').html()));
344
+ $goto_element.val(show_element).html( show_element ); $input.data('checkedValue', ''); xpathChanged();
345
+ });
346
+ $prev_element.click(function(){
347
+ var show_element = Math.max((parseInt($goto_element.val()) - 1), 1);
348
+ $goto_element.val(show_element).html( show_element ); $input.data('checkedValue', ''); xpathChanged();
349
+ });
350
+ $goto_element.change(function(){
351
+ var show_element = Math.max(Math.min(parseInt($goto_element.val()), parseInt($('.matches_count').html())), 1);
352
+ $goto_element.val(show_element); $input.data('checkedValue', ''); xpathChanged();
353
+ });
354
+ $get_default_xpath.click(function(){$root_element.val($(this).attr('root')); $goto_element.val(1); $input.val($(this).attr('rel')); xpathChanged();});
355
+ $('.change_root_element').click(function(){
356
+ $root_element.val($(this).attr('rel')); $goto_element.val(1); $input.val('/' + $(this).attr('rel')); xpathChanged();
357
+ });
358
+ $input.change(function(){$goto_element.val(1); xpathChanged();}).change();
359
  $input.keyup(function (e) {
360
  if (13 == e.keyCode) $(this).change();
361
  });
400
  toleranceElement: '> div',
401
  update: function () {
402
  $(this).parents('td:first').find('.hierarhy-output').val(window.JSON.stringify($(this).nestedSortable('toArray', {startDepthCount: 0})));
403
+ if ($(this).parents('td:first').find('input:first').val() == '') $(this).parents('td:first').find('.hierarhy-output').val('');
404
  }
405
  });
406
 
407
  $('.drag-element').find('input').live('blur', function(){
408
  $(this).parents('td:first').find('.hierarhy-output').val(window.JSON.stringify($(this).parents('.sortable:first').nestedSortable('toArray', {startDepthCount: 0})));
409
+ if ($(this).parents('td:first').find('input:first').val() == '') $(this).parents('td:first').find('.hierarhy-output').val('');
410
+ });
411
+
412
+ $('.drag-element').find('input').live('change', function(){
413
+ $(this).parents('td:first').find('.hierarhy-output').val(window.JSON.stringify($(this).parents('.sortable:first').nestedSortable('toArray', {startDepthCount: 0})));
414
+ if ($(this).parents('td:first').find('input:first').val() == '') $(this).parents('td:first').find('.hierarhy-output').val('');
415
+ });
416
+
417
+ $('.drag-element').find('input').live('hover', function(){},function(){
418
+ $(this).parents('td:first').find('.hierarhy-output').val(window.JSON.stringify($(this).parents('.sortable:first').nestedSortable('toArray', {startDepthCount: 0})));
419
+ if ($(this).parents('td:first').find('input:first').val() == '') $(this).parents('td:first').find('.hierarhy-output').val('');
420
  });
421
 
422
  $('.sortable').find('.remove-ico').live('click', function(){
428
  $(this).attr({'id':'item_'+ (i+1)});
429
  });
430
  parent_td.find('.hierarhy-output').val(window.JSON.stringify(parent_td.find('.sortable:first').nestedSortable('toArray', {startDepthCount: 0})));
431
+ if (parent_td.find('input:first').val() == '') parent_td.find('.hierarhy-output').val('');
432
  });
433
 
434
  $('.add-new-ico').click(function(){
435
  var count = $(this).parents('tr:first').find('ol.sortable').find('li').length + 1;
436
+ $(this).parents('tr:first').find('ol.sortable').append('<li id="item_'+count+'"><div class="drag-element"><input type="checkbox" class="assign_post" checked="checked"/><input type="text" value="" class="widefat"></div><a class="icon-item remove-ico" href="javascript:void(0);"></a></li>');
437
+ $(this).parents('td:first').find('.hierarhy-output').val(window.JSON.stringify($(this).parents('.sortable:first').nestedSortable('toArray', {startDepthCount: 0})));
438
+ if ($(this).parents('td:first').find('input:first').val() == '') $(this).parents('td:first').find('.hierarhy-output').val('');
439
  $('.widefat').bind('focus', insertxpath );
440
  });
441
+
442
+ $('form.options').find('input[type=submit]').click(function(e){
443
+ e.preventDefault();
444
+
445
+ $('.hierarhy-output').each(function(){
446
+ $(this).val(window.JSON.stringify($(this).parents('td:first').find('.sortable:first').nestedSortable('toArray', {startDepthCount: 0})));
447
+ if ($(this).parents('td:first').find('input:first').val() == '') $(this).val('');
448
+ });
449
+ if ($(this).attr('name') == 'btn_save_only') $('.save_only').val('1');
450
+ $(this).parents('form:first').submit();
451
+ });
452
+
453
+ /* END Categories hierarchy */
454
+
455
+ // manage screen: cron url
456
+ $('.get_cron_url').each(function () {
457
+ var $form = $(this);
458
+ var $modal = $('<div></div>').dialog({
459
+ autoOpen: false,
460
+ modal: true,
461
+ title: 'Cron URLs',
462
+ width: 760,
463
+ maxHeight: 600,
464
+ open: function(event, ui) {
465
+ $(this).dialog('option', 'height', 'auto').css({'max-height': $(this).dialog('option', 'maxHeight') - $(this).prev().height() - 24, 'overflow-y': 'auto'});
466
+ }
467
+ });
468
+ $form.find('a').click(function () {
469
+ $modal.addClass('loading').empty().dialog('open').dialog('option', 'position', 'center');
470
+ $modal.removeClass('loading').html('<textarea style="width:100%; height:100%;">' + $form.find('a').attr('rel') + '</textarea>').dialog('option', 'position', 'center');
471
+ });
472
+ });
473
+
474
+ // chunk files upload
475
+ if ($('#plupload-ui').length)
476
+ {
477
+ $('#plupload-ui').show();
478
+ $('#html-upload-ui').hide();
479
+
480
+ wplupload = $('#select-files').wplupload({
481
+ runtimes : 'gears,browserplus,html5,flash,silverlight,html4',
482
+ url : 'admin.php?page=pmxi-admin-settings&action=upload',
483
+ container: 'plupload-ui',
484
+ browse_button : 'select-files',
485
+ file_data_name : 'async-upload',
486
+ flash_swf_url : plugin_url + '/static/js/plupload/plupload.flash.swf',
487
+ silverlight_xap_url : plugin_url + '/static/js/plupload/plupload.silverlight.xap',
488
+
489
+ multipart: false,
490
+ max_file_size: '500mb',
491
+ chunk_size: '1mb',
492
+ drop_element: 'plupload-ui'
493
+ });
494
+ }
495
+
496
+ /* END plupload scripts */
497
+
498
+ if ($('#large_import_toggle').is(':checked')) $('#large_import_xpath').slideToggle();
499
+
500
+ $('#large_import_toggle').click(function(){
501
+ $('#large_import_xpath').slideToggle();
502
+ });
503
+
504
+ // Step 4 - custom meta keys helper
505
+
506
+ if ($('#pmxi_tabs').length){
507
+ if ($('form.options').length){
508
+ if ($('#selected_post_type').val() != ''){
509
+ var post_type_founded = false;
510
+ $('input[name=custom_type]').each(function(i){
511
+ if ($(this).val() == $('#selected_post_type').val()) { $('#pmxi_tabs').tabs({ selected:i }).show(); post_type_founded = true; }
512
+ });
513
+ if ( ! post_type_founded){
514
+ $('#pmxi_tabs').tabs({ selected: ($('#selected_type').val() == 'post') ? 0 : 1 }).show();
515
+ }
516
+ }
517
+ else if ($('#selected_type').val() != ''){
518
+ $('#pmxi_tabs').tabs({ selected: ($('#selected_type').val() == 'post') ? 0 : 1 }).show();
519
+ }
520
+ }
521
+ else
522
+ $('#pmxi_tabs').tabs().show();
523
+ }
524
 
525
+ if ($('#upload_process').length){
526
+ $('#upload_process').progressbar({ value: (($('#progressbar').html() != '') ? 100 : 0) });
527
+ if ($('#progressbar').html() != '')
528
+ $('.submit-buttons').show();
529
+ }
530
 
531
+ $('#view_log').live('click', function(){
532
+ $('#import_finished').css({'visibility':'hidden'});
533
+ $('#logwrapper').slideToggle(100, function(){
534
+ $('#import_finished').css({'visibility':'visible'});
535
+ });
536
+ });
537
 
538
+ $(document).scroll(function() {
539
+ if ($(document).scrollTop() > 135)
540
+ $('.tag').css({'top':'30px'});
541
+ else
542
+ $('.tag').css({'top':''});
543
+ });
544
 
545
+ });})(jQuery);
static/js/jquery/css/redmond/images/animated-overlay.gif ADDED
Binary file
static/js/jquery/css/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png ADDED
Binary file
static/js/jquery/css/redmond/images/ui-bg_flat_0_aaaaaa_40x100_1.png ADDED
Binary file
static/js/jquery/css/redmond/images/ui-bg_flat_55_fbec88_40x100.png ADDED
Binary file
static/js/jquery/css/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png ADDED
Binary file
static/js/jquery/css/redmond/images/ui-bg_glass_85_dfeffc_1x400.png ADDED
Binary file
static/js/jquery/css/redmond/images/ui-bg_glass_95_fef1ec_1x400.png ADDED
Binary file
static/js/jquery/css/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png ADDED
Binary file
static/js/jquery/css/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png ADDED
Binary file
static/js/jquery/css/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png ADDED
Binary file
static/js/jquery/css/redmond/images/ui-icons_217bc0_256x240.png ADDED
Binary file
static/js/jquery/css/redmond/images/ui-icons_2e83ff_256x240.png ADDED
Binary file
static/js/jquery/css/redmond/images/ui-icons_469bdd_256x240.png ADDED
Binary file
static/js/jquery/css/redmond/images/ui-icons_6da8d5_256x240.png ADDED
Binary file
static/js/jquery/css/redmond/images/ui-icons_cd0a0a_256x240.png ADDED
Binary file
static/js/jquery/css/redmond/images/ui-icons_d8e7f3_256x240.png ADDED
Binary file
static/js/jquery/css/redmond/images/ui-icons_f9bd01_256x240.png ADDED
Binary file
static/js/jquery/css/redmond/jquery-ui.css ADDED
@@ -0,0 +1,1177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*! jQuery UI - v1.10.0 - 2013-02-06
2
+ * http://jqueryui.com
3
+ * Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
4
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande%2CLucida%20Sans%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=gloss_wave&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=inset_hard&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=glass&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=inset_hard&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=flat&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&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
5
+ * Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */
6
+
7
+ /* Layout helpers
8
+ ----------------------------------*/
9
+ .ui-helper-hidden {
10
+ display: none;
11
+ }
12
+ .ui-helper-hidden-accessible {
13
+ border: 0;
14
+ clip: rect(0 0 0 0);
15
+ height: 1px;
16
+ margin: -1px;
17
+ overflow: hidden;
18
+ padding: 0;
19
+ position: absolute;
20
+ width: 1px;
21
+ }
22
+ .ui-helper-reset {
23
+ margin: 0;
24
+ padding: 0;
25
+ border: 0;
26
+ outline: 0;
27
+ line-height: 1.3;
28
+ text-decoration: none;
29
+ font-size: 100%;
30
+ list-style: none;
31
+ }
32
+ .ui-helper-clearfix:before,
33
+ .ui-helper-clearfix:after {
34
+ content: "";
35
+ display: table;
36
+ }
37
+ .ui-helper-clearfix:after {
38
+ clear: both;
39
+ }
40
+ .ui-helper-clearfix {
41
+ min-height: 0; /* support: IE7 */
42
+ }
43
+ .ui-helper-zfix {
44
+ width: 100%;
45
+ height: 100%;
46
+ top: 0;
47
+ left: 0;
48
+ position: absolute;
49
+ opacity: 0;
50
+ filter:Alpha(Opacity=0);
51
+ }
52
+
53
+ .ui-front {
54
+ z-index: 100;
55
+ }
56
+
57
+
58
+ /* Interaction Cues
59
+ ----------------------------------*/
60
+ .ui-state-disabled {
61
+ cursor: default !important;
62
+ }
63
+
64
+
65
+ /* Icons
66
+ ----------------------------------*/
67
+
68
+ /* states and images */
69
+ .ui-icon {
70
+ display: block;
71
+ text-indent: -99999px;
72
+ overflow: hidden;
73
+ background-repeat: no-repeat;
74
+ }
75
+
76
+
77
+ /* Misc visuals
78
+ ----------------------------------*/
79
+
80
+ /* Overlays */
81
+ .ui-widget-overlay {
82
+ position: fixed;
83
+ top: 0;
84
+ left: 0;
85
+ width: 100%;
86
+ height: 100%;
87
+ }
88
+ .ui-resizable {
89
+ position: relative;
90
+ }
91
+ .ui-resizable-handle {
92
+ position: absolute;
93
+ font-size: 0.1px;
94
+ display: block;
95
+ }
96
+ .ui-resizable-disabled .ui-resizable-handle,
97
+ .ui-resizable-autohide .ui-resizable-handle {
98
+ display: none;
99
+ }
100
+ .ui-resizable-n {
101
+ cursor: n-resize;
102
+ height: 7px;
103
+ width: 100%;
104
+ top: -5px;
105
+ left: 0;
106
+ }
107
+ .ui-resizable-s {
108
+ cursor: s-resize;
109
+ height: 7px;
110
+ width: 100%;
111
+ bottom: -5px;
112
+ left: 0;
113
+ }
114
+ .ui-resizable-e {
115
+ cursor: e-resize;
116
+ width: 7px;
117
+ right: -5px;
118
+ top: 0;
119
+ height: 100%;
120
+ }
121
+ .ui-resizable-w {
122
+ cursor: w-resize;
123
+ width: 7px;
124
+ left: -5px;
125
+ top: 0;
126
+ height: 100%;
127
+ }
128
+ .ui-resizable-se {
129
+ cursor: se-resize;
130
+ width: 12px;
131
+ height: 12px;
132
+ right: 1px;
133
+ bottom: 1px;
134
+ }
135
+ .ui-resizable-sw {
136
+ cursor: sw-resize;
137
+ width: 9px;
138
+ height: 9px;
139
+ left: -5px;
140
+ bottom: -5px;
141
+ }
142
+ .ui-resizable-nw {
143
+ cursor: nw-resize;
144
+ width: 9px;
145
+ height: 9px;
146
+ left: -5px;
147
+ top: -5px;
148
+ }
149
+ .ui-resizable-ne {
150
+ cursor: ne-resize;
151
+ width: 9px;
152
+ height: 9px;
153
+ right: -5px;
154
+ top: -5px;
155
+ }
156
+ .ui-selectable-helper {
157
+ position: absolute;
158
+ z-index: 100;
159
+ border: 1px dotted black;
160
+ }
161
+ .ui-accordion .ui-accordion-header {
162
+ display: block;
163
+ cursor: pointer;
164
+ position: relative;
165
+ margin-top: 2px;
166
+ padding: .5em .5em .5em .7em;
167
+ min-height: 0; /* support: IE7 */
168
+ }
169
+ .ui-accordion .ui-accordion-icons {
170
+ padding-left: 2.2em;
171
+ }
172
+ .ui-accordion .ui-accordion-noicons {
173
+ padding-left: .7em;
174
+ }
175
+ .ui-accordion .ui-accordion-icons .ui-accordion-icons {
176
+ padding-left: 2.2em;
177
+ }
178
+ .ui-accordion .ui-accordion-header .ui-accordion-header-icon {
179
+ position: absolute;
180
+ left: .5em;
181
+ top: 50%;
182
+ margin-top: -8px;
183
+ }
184
+ .ui-accordion .ui-accordion-content {
185
+ padding: 1em 2.2em;
186
+ border-top: 0;
187
+ overflow: auto;
188
+ }
189
+ .ui-autocomplete {
190
+ position: absolute;
191
+ top: 0;
192
+ left: 0;
193
+ cursor: default;
194
+ }
195
+ .ui-button {
196
+ display: inline-block;
197
+ position: relative;
198
+ padding: 0;
199
+ line-height: normal;
200
+ margin-right: .1em;
201
+ cursor: pointer;
202
+ vertical-align: middle;
203
+ text-align: center;
204
+ overflow: visible; /* removes extra width in IE */
205
+ }
206
+ .ui-button,
207
+ .ui-button:visited,
208
+ .ui-button:hover,
209
+ .ui-button:active,
210
+ .large_button:hover {
211
+ background: url("images/ui-bg_glass_75_d0e5f5_1x400.png") repeat-x scroll 50% 50% #D0E5F5;
212
+ border: 1px solid #79B7E7;
213
+ color: #1D5987;
214
+ font-weight: bold;
215
+ }
216
+ /* to make room for the icon, a width needs to be set here */
217
+ .ui-button-icon-only {
218
+ width: 2.2em;
219
+ }
220
+ /* button elements seem to need a little more width */
221
+ button.ui-button-icon-only {
222
+ width: 2.4em;
223
+ }
224
+ .ui-button-icons-only {
225
+ width: 3.4em;
226
+ }
227
+ button.ui-button-icons-only {
228
+ width: 3.7em;
229
+ }
230
+
231
+ /* button text element */
232
+ .ui-button .ui-button-text {
233
+ display: block;
234
+ line-height: normal;
235
+ }
236
+ .ui-button-text-only .ui-button-text {
237
+ padding: .4em 1em;
238
+ }
239
+ .ui-button-icon-only .ui-button-text,
240
+ .ui-button-icons-only .ui-button-text {
241
+ padding: .4em;
242
+ text-indent: -9999999px;
243
+ }
244
+ .ui-button-text-icon-primary .ui-button-text,
245
+ .ui-button-text-icons .ui-button-text {
246
+ padding: .4em 1em .4em 2.1em;
247
+ }
248
+ .ui-button-text-icon-secondary .ui-button-text,
249
+ .ui-button-text-icons .ui-button-text {
250
+ padding: .4em 2.1em .4em 1em;
251
+ }
252
+ .ui-button-text-icons .ui-button-text {
253
+ padding-left: 2.1em;
254
+ padding-right: 2.1em;
255
+ }
256
+ /* no icon support for input elements, provide padding by default */
257
+ input.ui-button {
258
+ padding: .4em 1em;
259
+ }
260
+
261
+ /* button icon element(s) */
262
+ .ui-button-icon-only .ui-icon,
263
+ .ui-button-text-icon-primary .ui-icon,
264
+ .ui-button-text-icon-secondary .ui-icon,
265
+ .ui-button-text-icons .ui-icon,
266
+ .ui-button-icons-only .ui-icon {
267
+ position: absolute;
268
+ top: 50%;
269
+ margin-top: -8px;
270
+ }
271
+ .ui-button-icon-only .ui-icon {
272
+ left: 50%;
273
+ margin-left: -8px;
274
+ }
275
+ .ui-button-text-icon-primary .ui-button-icon-primary,
276
+ .ui-button-text-icons .ui-button-icon-primary,
277
+ .ui-button-icons-only .ui-button-icon-primary {
278
+ left: .5em;
279
+ }
280
+ .ui-button-text-icon-secondary .ui-button-icon-secondary,
281
+ .ui-button-text-icons .ui-button-icon-secondary,
282
+ .ui-button-icons-only .ui-button-icon-secondary {
283
+ right: .5em;
284
+ }
285
+
286
+ /* button sets */
287
+ .ui-buttonset {
288
+ margin-right: 7px;
289
+ }
290
+ .ui-buttonset .ui-button {
291
+ margin-left: 0;
292
+ margin-right: -.3em;
293
+ }
294
+
295
+ /* workarounds */
296
+ /* reset extra padding in Firefox, see h5bp.com/l */
297
+ input.ui-button::-moz-focus-inner,
298
+ button.ui-button::-moz-focus-inner {
299
+ border: 0;
300
+ padding: 0;
301
+ }
302
+ .ui-datepicker {
303
+ width: 17em;
304
+ padding: .2em .2em 0;
305
+ display: none;
306
+ }
307
+ .ui-datepicker .ui-datepicker-header {
308
+ position: relative;
309
+ padding: .2em 0;
310
+ }
311
+ .ui-datepicker .ui-datepicker-prev,
312
+ .ui-datepicker .ui-datepicker-next {
313
+ position: absolute;
314
+ top: 2px;
315
+ width: 1.8em;
316
+ height: 1.8em;
317
+ }
318
+ .ui-datepicker .ui-datepicker-prev-hover,
319
+ .ui-datepicker .ui-datepicker-next-hover {
320
+ top: 1px;
321
+ }
322
+ .ui-datepicker .ui-datepicker-prev {
323
+ left: 2px;
324
+ }
325
+ .ui-datepicker .ui-datepicker-next {
326
+ right: 2px;
327
+ }
328
+ .ui-datepicker .ui-datepicker-prev-hover {
329
+ left: 1px;
330
+ }
331
+ .ui-datepicker .ui-datepicker-next-hover {
332
+ right: 1px;
333
+ }
334
+ .ui-datepicker .ui-datepicker-prev span,
335
+ .ui-datepicker .ui-datepicker-next span {
336
+ display: block;
337
+ position: absolute;
338
+ left: 50%;
339
+ margin-left: -8px;
340
+ top: 50%;
341
+ margin-top: -8px;
342
+ }
343
+ .ui-datepicker .ui-datepicker-title {
344
+ margin: 0 2.3em;
345
+ line-height: 1.8em;
346
+ text-align: center;
347
+ }
348
+ .ui-datepicker .ui-datepicker-title select {
349
+ font-size: 1em;
350
+ margin: 1px 0;
351
+ }
352
+ .ui-datepicker select.ui-datepicker-month-year {
353
+ width: 100%;
354
+ }
355
+ .ui-datepicker select.ui-datepicker-month,
356
+ .ui-datepicker select.ui-datepicker-year {
357
+ width: 49%;
358
+ }
359
+ .ui-datepicker table {
360
+ width: 100%;
361
+ font-size: .9em;
362
+ border-collapse: collapse;
363
+ margin: 0 0 .4em;
364
+ }
365
+ .ui-datepicker th {
366
+ padding: .7em .3em;
367
+ text-align: center;
368
+ font-weight: bold;
369
+ border: 0;
370
+ }
371
+ .ui-datepicker td {
372
+ border: 0;
373
+ padding: 1px;
374
+ }
375
+ .ui-datepicker td span,
376
+ .ui-datepicker td a {
377
+ display: block;
378
+ padding: .2em;
379
+ text-align: right;
380
+ text-decoration: none;
381
+ }
382
+ .ui-datepicker .ui-datepicker-buttonpane {
383
+ background-image: none;
384
+ margin: .7em 0 0 0;
385
+ padding: 0 .2em;
386
+ border-left: 0;
387
+ border-right: 0;
388
+ border-bottom: 0;
389
+ }
390
+ .ui-datepicker .ui-datepicker-buttonpane button {
391
+ float: right;
392
+ margin: .5em .2em .4em;
393
+ cursor: pointer;
394
+ padding: .2em .6em .3em .6em;
395
+ width: auto;
396
+ overflow: visible;
397
+ }
398
+ .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
399
+ float: left;
400
+ }
401
+
402
+ /* with multiple calendars */
403
+ .ui-datepicker.ui-datepicker-multi {
404
+ width: auto;
405
+ }
406
+ .ui-datepicker-multi .ui-datepicker-group {
407
+ float: left;
408
+ }
409
+ .ui-datepicker-multi .ui-datepicker-group table {
410
+ width: 95%;
411
+ margin: 0 auto .4em;
412
+ }
413
+ .ui-datepicker-multi-2 .ui-datepicker-group {
414
+ width: 50%;
415
+ }
416
+ .ui-datepicker-multi-3 .ui-datepicker-group {
417
+ width: 33.3%;
418
+ }
419
+ .ui-datepicker-multi-4 .ui-datepicker-group {
420
+ width: 25%;
421
+ }
422
+ .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
423
+ .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
424
+ border-left-width: 0;
425
+ }
426
+ .ui-datepicker-multi .ui-datepicker-buttonpane {
427
+ clear: left;
428
+ }
429
+ .ui-datepicker-row-break {
430
+ clear: both;
431
+ width: 100%;
432
+ font-size: 0;
433
+ }
434
+
435
+ /* RTL support */
436
+ .ui-datepicker-rtl {
437
+ direction: rtl;
438
+ }
439
+ .ui-datepicker-rtl .ui-datepicker-prev {
440
+ right: 2px;
441
+ left: auto;
442
+ }
443
+ .ui-datepicker-rtl .ui-datepicker-next {
444
+ left: 2px;
445
+ right: auto;
446
+ }
447
+ .ui-datepicker-rtl .ui-datepicker-prev:hover {
448
+ right: 1px;
449
+ left: auto;
450
+ }
451
+ .ui-datepicker-rtl .ui-datepicker-next:hover {
452
+ left: 1px;
453
+ right: auto;
454
+ }
455
+ .ui-datepicker-rtl .ui-datepicker-buttonpane {
456
+ clear: right;
457
+ }
458
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button {
459
+ float: left;
460
+ }
461
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
462
+ .ui-datepicker-rtl .ui-datepicker-group {
463
+ float: right;
464
+ }
465
+ .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
466
+ .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
467
+ border-right-width: 0;
468
+ border-left-width: 1px;
469
+ }
470
+ .ui-dialog {
471
+ position: absolute;
472
+ top: 0;
473
+ left: 0;
474
+ padding: .2em;
475
+ outline: 0;
476
+ }
477
+ .ui-dialog .ui-dialog-titlebar {
478
+ padding: .4em 1em;
479
+ position: relative;
480
+ }
481
+ .ui-dialog .ui-dialog-title {
482
+ float: left;
483
+ margin: .1em 0;
484
+ white-space: nowrap;
485
+ width: 90%;
486
+ overflow: hidden;
487
+ text-overflow: ellipsis;
488
+ }
489
+ .ui-dialog .ui-dialog-titlebar-close {
490
+ position: absolute;
491
+ right: .3em;
492
+ top: 50%;
493
+ width: 21px;
494
+ margin: -10px 0 0 0;
495
+ padding: 1px;
496
+ height: 20px;
497
+ }
498
+ .ui-dialog .ui-dialog-content {
499
+ position: relative;
500
+ border: 0;
501
+ padding: .5em 1em;
502
+ background: none;
503
+ overflow: auto;
504
+ }
505
+ .ui-dialog .ui-dialog-buttonpane {
506
+ text-align: left;
507
+ border-width: 1px 0 0 0;
508
+ background-image: none;
509
+ margin-top: .5em;
510
+ padding: .3em 1em .5em .4em;
511
+ }
512
+ .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
513
+ float: right;
514
+ }
515
+ .ui-dialog .ui-dialog-buttonpane button {
516
+ margin: .5em .4em .5em 0;
517
+ cursor: pointer;
518
+ }
519
+ .ui-dialog .ui-resizable-se {
520
+ width: 12px;
521
+ height: 12px;
522
+ right: -5px;
523
+ bottom: -5px;
524
+ background-position: 16px 16px;
525
+ }
526
+ .ui-draggable .ui-dialog-titlebar {
527
+ cursor: move;
528
+ }
529
+ .ui-menu {
530
+ list-style: none;
531
+ padding: 2px;
532
+ margin: 0;
533
+ display: block;
534
+ outline: none;
535
+ }
536
+ .ui-menu .ui-menu {
537
+ margin-top: -3px;
538
+ position: absolute;
539
+ }
540
+ .ui-menu .ui-menu-item {
541
+ margin: 0;
542
+ padding: 0;
543
+ width: 100%;
544
+ }
545
+ .ui-menu .ui-menu-divider {
546
+ margin: 5px -2px 5px -2px;
547
+ height: 0;
548
+ font-size: 0;
549
+ line-height: 0;
550
+ border-width: 1px 0 0 0;
551
+ }
552
+ .ui-menu .ui-menu-item a {
553
+ text-decoration: none;
554
+ display: block;
555
+ padding: 2px .4em;
556
+ line-height: 1.5;
557
+ min-height: 0; /* support: IE7 */
558
+ font-weight: normal;
559
+ }
560
+ .ui-menu .ui-menu-item a.ui-state-focus,
561
+ .ui-menu .ui-menu-item a.ui-state-active {
562
+ font-weight: normal;
563
+ margin: -1px;
564
+ }
565
+
566
+ .ui-menu .ui-state-disabled {
567
+ font-weight: normal;
568
+ margin: .4em 0 .2em;
569
+ line-height: 1.5;
570
+ }
571
+ .ui-menu .ui-state-disabled a {
572
+ cursor: default;
573
+ }
574
+
575
+ /* icon support */
576
+ .ui-menu-icons {
577
+ position: relative;
578
+ }
579
+ .ui-menu-icons .ui-menu-item a {
580
+ position: relative;
581
+ padding-left: 2em;
582
+ }
583
+
584
+ /* left-aligned */
585
+ .ui-menu .ui-icon {
586
+ position: absolute;
587
+ top: .2em;
588
+ left: .2em;
589
+ }
590
+
591
+ /* right-aligned */
592
+ .ui-menu .ui-menu-icon {
593
+ position: static;
594
+ float: right;
595
+ }
596
+ .ui-progressbar {
597
+ height: 2em;
598
+ text-align: left;
599
+ overflow: hidden;
600
+ }
601
+ .ui-progressbar .ui-progressbar-value {
602
+ margin: -1px;
603
+ height: 100%;
604
+ }
605
+ .ui-progressbar .ui-progressbar-overlay {
606
+ background: url("images/animated-overlay.gif");
607
+ height: 100%;
608
+ filter: alpha(opacity=25);
609
+ opacity: 0.25;
610
+ }
611
+ .ui-progressbar-indeterminate .ui-progressbar-value {
612
+ background-image: none;
613
+ }
614
+ .ui-slider {
615
+ position: relative;
616
+ text-align: left;
617
+ }
618
+ .ui-slider .ui-slider-handle {
619
+ position: absolute;
620
+ z-index: 2;
621
+ width: 1.2em;
622
+ height: 1.2em;
623
+ cursor: default;
624
+ }
625
+ .ui-slider .ui-slider-range {
626
+ position: absolute;
627
+ z-index: 1;
628
+ font-size: .7em;
629
+ display: block;
630
+ border: 0;
631
+ background-position: 0 0;
632
+ }
633
+
634
+ /* For IE8 - See #6727 */
635
+ .ui-slider.ui-state-disabled .ui-slider-handle,
636
+ .ui-slider.ui-state-disabled .ui-slider-range {
637
+ filter: inherit;
638
+ }
639
+
640
+ .ui-slider-horizontal {
641
+ height: .8em;
642
+ }
643
+ .ui-slider-horizontal .ui-slider-handle {
644
+ top: -.3em;
645
+ margin-left: -.6em;
646
+ }
647
+ .ui-slider-horizontal .ui-slider-range {
648
+ top: 0;
649
+ height: 100%;
650
+ }
651
+ .ui-slider-horizontal .ui-slider-range-min {
652
+ left: 0;
653
+ }
654
+ .ui-slider-horizontal .ui-slider-range-max {
655
+ right: 0;
656
+ }
657
+
658
+ .ui-slider-vertical {
659
+ width: .8em;
660
+ height: 100px;
661
+ }
662
+ .ui-slider-vertical .ui-slider-handle {
663
+ left: -.3em;
664
+ margin-left: 0;
665
+ margin-bottom: -.6em;
666
+ }
667
+ .ui-slider-vertical .ui-slider-range {
668
+ left: 0;
669
+ width: 100%;
670
+ }
671
+ .ui-slider-vertical .ui-slider-range-min {
672
+ bottom: 0;
673
+ }
674
+ .ui-slider-vertical .ui-slider-range-max {
675
+ top: 0;
676
+ }
677
+ .ui-spinner {
678
+ position: relative;
679
+ display: inline-block;
680
+ overflow: hidden;
681
+ padding: 0;
682
+ vertical-align: middle;
683
+ }
684
+ .ui-spinner-input {
685
+ border: none;
686
+ background: none;
687
+ color: inherit;
688
+ padding: 0;
689
+ margin: .2em 0;
690
+ vertical-align: middle;
691
+ margin-left: .4em;
692
+ margin-right: 22px;
693
+ }
694
+ .ui-spinner-button {
695
+ width: 16px;
696
+ height: 50%;
697
+ font-size: .5em;
698
+ padding: 0;
699
+ margin: 0;
700
+ text-align: center;
701
+ position: absolute;
702
+ cursor: default;
703
+ display: block;
704
+ overflow: hidden;
705
+ right: 0;
706
+ }
707
+ /* more specificity required here to overide default borders */
708
+ .ui-spinner a.ui-spinner-button {
709
+ border-top: none;
710
+ border-bottom: none;
711
+ border-right: none;
712
+ }
713
+ /* vertical centre icon */
714
+ .ui-spinner .ui-icon {
715
+ position: absolute;
716
+ margin-top: -8px;
717
+ top: 50%;
718
+ left: 0;
719
+ }
720
+ .ui-spinner-up {
721
+ top: 0;
722
+ }
723
+ .ui-spinner-down {
724
+ bottom: 0;
725
+ }
726
+
727
+ /* TR overrides */
728
+ .ui-spinner .ui-icon-triangle-1-s {
729
+ /* need to fix icons sprite */
730
+ background-position: -65px -16px;
731
+ }
732
+ .ui-tabs {
733
+ position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
734
+ padding: .2em;
735
+ }
736
+ .ui-tabs .ui-tabs-nav {
737
+ margin: 0;
738
+ padding: .2em .2em 0;
739
+ }
740
+ .ui-tabs .ui-tabs-nav li {
741
+ list-style: none;
742
+ float: left;
743
+ position: relative;
744
+ top: 0;
745
+ margin: 1px .2em 0 0;
746
+ border-bottom: 0;
747
+ padding: 0;
748
+ white-space: nowrap;
749
+ }
750
+ .ui-tabs .ui-tabs-nav li a {
751
+ float: left;
752
+ padding: .5em 1em;
753
+ text-decoration: none;
754
+ }
755
+ .ui-tabs .ui-tabs-nav li.ui-tabs-active {
756
+ margin-bottom: -1px;
757
+ padding-bottom: 1px;
758
+ }
759
+ .ui-tabs .ui-tabs-nav li.ui-tabs-active a,
760
+ .ui-tabs .ui-tabs-nav li.ui-state-disabled a,
761
+ .ui-tabs .ui-tabs-nav li.ui-tabs-loading a {
762
+ cursor: text;
763
+ }
764
+ .ui-tabs .ui-tabs-nav li a, /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
765
+ .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a {
766
+ cursor: pointer;
767
+ }
768
+ .ui-tabs .ui-tabs-panel {
769
+ display: block;
770
+ border-width: 0;
771
+ padding: 1em 1.4em;
772
+ background: none;
773
+ }
774
+ .ui-tooltip {
775
+ padding: 8px;
776
+ position: absolute;
777
+ z-index: 9999;
778
+ max-width: 300px;
779
+ -webkit-box-shadow: 0 0 5px #aaa;
780
+ box-shadow: 0 0 5px #aaa;
781
+ }
782
+ body .ui-tooltip {
783
+ border-width: 2px;
784
+ }
785
+
786
+ /* Component containers
787
+ ----------------------------------*/
788
+ .ui-widget {
789
+ font-family: Lucida Grande,Lucida Sans,Arial,sans-serif;
790
+ font-size: 1.1em;
791
+ }
792
+ .ui-widget .ui-widget {
793
+ font-size: 1em;
794
+ }
795
+ .ui-widget input,
796
+ .ui-widget select,
797
+ .ui-widget textarea,
798
+ .ui-widget button {
799
+ font-family: Lucida Grande,Lucida Sans,Arial,sans-serif;
800
+ font-size: 1em;
801
+ }
802
+ .ui-widget-content {
803
+ border: 1px solid #a6c9e2;
804
+ background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x;
805
+ color: #222222;
806
+ }
807
+ .ui-widget-content a {
808
+ color: #222222;
809
+ }
810
+ .ui-widget-header {
811
+ border: 1px solid #4297d7;
812
+ background: #5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x;
813
+ color: #ffffff;
814
+ font-weight: bold;
815
+ }
816
+ .ui-widget-header a {
817
+ color: #ffffff;
818
+ }
819
+
820
+ /* Interaction states
821
+ ----------------------------------*/
822
+ .ui-state-default,
823
+ .ui-widget-content .ui-state-default,
824
+ .ui-widget-header .ui-state-default {
825
+ border: 1px solid #c5dbec;
826
+ background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x;
827
+ font-weight: bold;
828
+ color: #2e6e9e;
829
+ }
830
+ .ui-state-default a,
831
+ .ui-state-default a:link,
832
+ .ui-state-default a:visited {
833
+ color: #2e6e9e;
834
+ text-decoration: none;
835
+ }
836
+ .ui-state-hover,
837
+ .ui-widget-content .ui-state-hover,
838
+ .ui-widget-header .ui-state-hover,
839
+ .ui-state-focus,
840
+ .ui-widget-content .ui-state-focus,
841
+ .ui-widget-header .ui-state-focus {
842
+ border: 1px solid #79b7e7;
843
+ background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x;
844
+ font-weight: bold;
845
+ color: #1d5987;
846
+ }
847
+ .ui-state-hover a,
848
+ .ui-state-hover a:hover,
849
+ .ui-state-hover a:link,
850
+ .ui-state-hover a:visited {
851
+ color: #1d5987;
852
+ text-decoration: none;
853
+ }
854
+ .ui-state-active,
855
+ .ui-widget-content .ui-state-active,
856
+ .ui-widget-header .ui-state-active {
857
+ border: 1px solid #79b7e7;
858
+ background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x;
859
+ font-weight: bold;
860
+ color: #e17009;
861
+ }
862
+ .ui-state-active a,
863
+ .ui-state-active a:link,
864
+ .ui-state-active a:visited {
865
+ color: #e17009;
866
+ text-decoration: none;
867
+ }
868
+
869
+ /* Interaction Cues
870
+ ----------------------------------*/
871
+ .ui-state-highlight,
872
+ .ui-widget-content .ui-state-highlight,
873
+ .ui-widget-header .ui-state-highlight {
874
+ border: 1px solid #fad42e;
875
+ background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x;
876
+ color: #363636;
877
+ }
878
+ .ui-state-highlight a,
879
+ .ui-widget-content .ui-state-highlight a,
880
+ .ui-widget-header .ui-state-highlight a {
881
+ color: #363636;
882
+ }
883
+ .ui-state-error,
884
+ .ui-widget-content .ui-state-error,
885
+ .ui-widget-header .ui-state-error {
886
+ border: 1px solid #cd0a0a;
887
+ background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;
888
+ color: #cd0a0a;
889
+ }
890
+ .ui-state-error a,
891
+ .ui-widget-content .ui-state-error a,
892
+ .ui-widget-header .ui-state-error a {
893
+ color: #cd0a0a;
894
+ }
895
+ .ui-state-error-text,
896
+ .ui-widget-content .ui-state-error-text,
897
+ .ui-widget-header .ui-state-error-text {
898
+ color: #cd0a0a;
899
+ }
900
+ .ui-priority-primary,
901
+ .ui-widget-content .ui-priority-primary,
902
+ .ui-widget-header .ui-priority-primary {
903
+ font-weight: bold;
904
+ }
905
+ .ui-priority-secondary,
906
+ .ui-widget-content .ui-priority-secondary,
907
+ .ui-widget-header .ui-priority-secondary {
908
+ opacity: .7;
909
+ filter:Alpha(Opacity=70);
910
+ font-weight: normal;
911
+ }
912
+ .ui-state-disabled,
913
+ .ui-widget-content .ui-state-disabled,
914
+ .ui-widget-header .ui-state-disabled {
915
+ opacity: .35;
916
+ filter:Alpha(Opacity=35);
917
+ background-image: none;
918
+ }
919
+ .ui-state-disabled .ui-icon {
920
+ filter:Alpha(Opacity=35); /* For IE8 - See #6059 */
921
+ }
922
+
923
+ /* Icons
924
+ ----------------------------------*/
925
+
926
+ /* states and images */
927
+ .ui-icon {
928
+ width: 16px;
929
+ height: 16px;
930
+ background-position: 16px 16px;
931
+ }
932
+ .ui-icon,
933
+ .ui-widget-content .ui-icon {
934
+ background-image: url(images/ui-icons_469bdd_256x240.png);
935
+ }
936
+ .ui-widget-header .ui-icon {
937
+ background-image: url(images/ui-icons_d8e7f3_256x240.png);
938
+ }
939
+ .ui-state-default .ui-icon {
940
+ background-image: url(images/ui-icons_6da8d5_256x240.png);
941
+ }
942
+ .ui-state-hover .ui-icon,
943
+ .ui-state-focus .ui-icon {
944
+ background-image: url(images/ui-icons_217bc0_256x240.png);
945
+ }
946
+ .ui-state-active .ui-icon {
947
+ background-image: url(images/ui-icons_f9bd01_256x240.png);
948
+ }
949
+ .ui-state-highlight .ui-icon {
950
+ background-image: url(images/ui-icons_2e83ff_256x240.png);
951
+ }
952
+ .ui-state-error .ui-icon,
953
+ .ui-state-error-text .ui-icon {
954
+ background-image: url(images/ui-icons_cd0a0a_256x240.png);
955
+ }
956
+
957
+ /* positioning */
958
+ .ui-icon-carat-1-n { background-position: 0 0; }
959
+ .ui-icon-carat-1-ne { background-position: -16px 0; }
960
+ .ui-icon-carat-1-e { background-position: -32px 0; }
961
+ .ui-icon-carat-1-se { background-position: -48px 0; }
962
+ .ui-icon-carat-1-s { background-position: -64px 0; }
963
+ .ui-icon-carat-1-sw { background-position: -80px 0; }
964
+ .ui-icon-carat-1-w { background-position: -96px 0; }
965
+ .ui-icon-carat-1-nw { background-position: -112px 0; }
966
+ .ui-icon-carat-2-n-s { background-position: -128px 0; }
967
+ .ui-icon-carat-2-e-w { background-position: -144px 0; }
968
+ .ui-icon-triangle-1-n { background-position: 0 -16px; }
969
+ .ui-icon-triangle-1-ne { background-position: -16px -16px; }
970
+ .ui-icon-triangle-1-e { background-position: -32px -16px; }
971
+ .ui-icon-triangle-1-se { background-position: -48px -16px; }
972
+ .ui-icon-triangle-1-s { background-position: -64px -16px; }
973
+ .ui-icon-triangle-1-sw { background-position: -80px -16px; }
974
+ .ui-icon-triangle-1-w { background-position: -96px -16px; }
975
+ .ui-icon-triangle-1-nw { background-position: -112px -16px; }
976
+ .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
977
+ .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
978
+ .ui-icon-arrow-1-n { background-position: 0 -32px; }
979
+ .ui-icon-arrow-1-ne { background-position: -16px -32px; }
980
+ .ui-icon-arrow-1-e { background-position: -32px -32px; }
981
+ .ui-icon-arrow-1-se { background-position: -48px -32px; }
982
+ .ui-icon-arrow-1-s { background-position: -64px -32px; }
983
+ .ui-icon-arrow-1-sw { background-position: -80px -32px; }
984
+ .ui-icon-arrow-1-w { background-position: -96px -32px; }
985
+ .ui-icon-arrow-1-nw { background-position: -112px -32px; }
986
+ .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
987
+ .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
988
+ .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
989
+ .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
990
+ .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
991
+ .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
992
+ .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
993
+ .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
994
+ .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
995
+ .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
996
+ .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
997
+ .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
998
+ .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
999
+ .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
1000
+ .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
1001
+ .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
1002
+ .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
1003
+ .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
1004
+ .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
1005
+ .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
1006
+ .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
1007
+ .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
1008
+ .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
1009
+ .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
1010
+ .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
1011
+ .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
1012
+ .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
1013
+ .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
1014
+ .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
1015
+ .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
1016
+ .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
1017
+ .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
1018
+ .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
1019
+ .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
1020
+ .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
1021
+ .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
1022
+ .ui-icon-arrow-4 { background-position: 0 -80px; }
1023
+ .ui-icon-arrow-4-diag { background-position: -16px -80px; }
1024
+ .ui-icon-extlink { background-position: -32px -80px; }
1025
+ .ui-icon-newwin { background-position: -48px -80px; }
1026
+ .ui-icon-refresh { background-position: -64px -80px; }
1027
+ .ui-icon-shuffle { background-position: -80px -80px; }
1028
+ .ui-icon-transfer-e-w { background-position: -96px -80px; }
1029
+ .ui-icon-transferthick-e-w { background-position: -112px -80px; }
1030
+ .ui-icon-folder-collapsed { background-position: 0 -96px; }
1031
+ .ui-icon-folder-open { background-position: -16px -96px; }
1032
+ .ui-icon-document { background-position: -32px -96px; }
1033
+ .ui-icon-document-b { background-position: -48px -96px; }
1034
+ .ui-icon-note { background-position: -64px -96px; }
1035
+ .ui-icon-mail-closed { background-position: -80px -96px; }
1036
+ .ui-icon-mail-open { background-position: -96px -96px; }
1037
+ .ui-icon-suitcase { background-position: -112px -96px; }
1038
+ .ui-icon-comment { background-position: -128px -96px; }
1039
+ .ui-icon-person { background-position: -144px -96px; }
1040
+ .ui-icon-print { background-position: -160px -96px; }
1041
+ .ui-icon-trash { background-position: -176px -96px; }
1042
+ .ui-icon-locked { background-position: -192px -96px; }
1043
+ .ui-icon-unlocked { background-position: -208px -96px; }
1044
+ .ui-icon-bookmark { background-position: -224px -96px; }
1045
+ .ui-icon-tag { background-position: -240px -96px; }
1046
+ .ui-icon-home { background-position: 0 -112px; }
1047
+ .ui-icon-flag { background-position: -16px -112px; }
1048
+ .ui-icon-calendar { background-position: -32px -112px; }
1049
+ .ui-icon-cart { background-position: -48px -112px; }
1050
+ .ui-icon-pencil { background-position: -64px -112px; }
1051
+ .ui-icon-clock { background-position: -80px -112px; }
1052
+ .ui-icon-disk { background-position: -96px -112px; }
1053
+ .ui-icon-calculator { background-position: -112px -112px; }
1054
+ .ui-icon-zoomin { background-position: -128px -112px; }
1055
+ .ui-icon-zoomout { background-position: -144px -112px; }
1056
+ .ui-icon-search { background-position: -160px -112px; }
1057
+ .ui-icon-wrench { background-position: -176px -112px; }
1058
+ .ui-icon-gear { background-position: -192px -112px; }
1059
+ .ui-icon-heart { background-position: -208px -112px; }
1060
+ .ui-icon-star { background-position: -224px -112px; }
1061
+ .ui-icon-link { background-position: -240px -112px; }
1062
+ .ui-icon-cancel { background-position: 0 -128px; }
1063
+ .ui-icon-plus { background-position: -16px -128px; }
1064
+ .ui-icon-plusthick { background-position: -32px -128px; }
1065
+ .ui-icon-minus { background-position: -48px -128px; }
1066
+ .ui-icon-minusthick { background-position: -64px -128px; }
1067
+ .ui-icon-close { background-position: -80px -128px; }
1068
+ .ui-icon-closethick { background-position: -96px -128px; }
1069
+ .ui-icon-key { background-position: -112px -128px; }
1070
+ .ui-icon-lightbulb { background-position: -128px -128px; }
1071
+ .ui-icon-scissors { background-position: -144px -128px; }
1072
+ .ui-icon-clipboard { background-position: -160px -128px; }
1073
+ .ui-icon-copy { background-position: -176px -128px; }
1074
+ .ui-icon-contact { background-position: -192px -128px; }
1075
+ .ui-icon-image { background-position: -208px -128px; }
1076
+ .ui-icon-video { background-position: -224px -128px; }
1077
+ .ui-icon-script { background-position: -240px -128px; }
1078
+ .ui-icon-alert { background-position: 0 -144px; }
1079
+ .ui-icon-info { background-position: -16px -144px; }
1080
+ .ui-icon-notice { background-position: -32px -144px; }
1081
+ .ui-icon-help { background-position: -48px -144px; }
1082
+ .ui-icon-check { background-position: -64px -144px; }
1083
+ .ui-icon-bullet { background-position: -80px -144px; }
1084
+ .ui-icon-radio-on { background-position: -96px -144px; }
1085
+ .ui-icon-radio-off { background-position: -112px -144px; }
1086
+ .ui-icon-pin-w { background-position: -128px -144px; }
1087
+ .ui-icon-pin-s { background-position: -144px -144px; }
1088
+ .ui-icon-play { background-position: 0 -160px; }
1089
+ .ui-icon-pause { background-position: -16px -160px; }
1090
+ .ui-icon-seek-next { background-position: -32px -160px; }
1091
+ .ui-icon-seek-prev { background-position: -48px -160px; }
1092
+ .ui-icon-seek-end { background-position: -64px -160px; }
1093
+ .ui-icon-seek-start { background-position: -80px -160px; }
1094
+ /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
1095
+ .ui-icon-seek-first { background-position: -80px -160px; }
1096
+ .ui-icon-stop { background-position: -96px -160px; }
1097
+ .ui-icon-eject { background-position: -112px -160px; }
1098
+ .ui-icon-volume-off { background-position: -128px -160px; }
1099
+ .ui-icon-volume-on { background-position: -144px -160px; }
1100
+ .ui-icon-power { background-position: 0 -176px; }
1101
+ .ui-icon-signal-diag { background-position: -16px -176px; }
1102
+ .ui-icon-signal { background-position: -32px -176px; }
1103
+ .ui-icon-battery-0 { background-position: -48px -176px; }
1104
+ .ui-icon-battery-1 { background-position: -64px -176px; }
1105
+ .ui-icon-battery-2 { background-position: -80px -176px; }
1106
+ .ui-icon-battery-3 { background-position: -96px -176px; }
1107
+ .ui-icon-circle-plus { background-position: 0 -192px; }
1108
+ .ui-icon-circle-minus { background-position: -16px -192px; }
1109
+ .ui-icon-circle-close { background-position: -32px -192px; }
1110
+ .ui-icon-circle-triangle-e { background-position: -48px -192px; }
1111
+ .ui-icon-circle-triangle-s { background-position: -64px -192px; }
1112
+ .ui-icon-circle-triangle-w { background-position: -80px -192px; }
1113
+ .ui-icon-circle-triangle-n { background-position: -96px -192px; }
1114
+ .ui-icon-circle-arrow-e { background-position: -112px -192px; }
1115
+ .ui-icon-circle-arrow-s { background-position: -128px -192px; }
1116
+ .ui-icon-circle-arrow-w { background-position: -144px -192px; }
1117
+ .ui-icon-circle-arrow-n { background-position: -160px -192px; }
1118
+ .ui-icon-circle-zoomin { background-position: -176px -192px; }
1119
+ .ui-icon-circle-zoomout { background-position: -192px -192px; }
1120
+ .ui-icon-circle-check { background-position: -208px -192px; }
1121
+ .ui-icon-circlesmall-plus { background-position: 0 -208px; }
1122
+ .ui-icon-circlesmall-minus { background-position: -16px -208px; }
1123
+ .ui-icon-circlesmall-close { background-position: -32px -208px; }
1124
+ .ui-icon-squaresmall-plus { background-position: -48px -208px; }
1125
+ .ui-icon-squaresmall-minus { background-position: -64px -208px; }
1126
+ .ui-icon-squaresmall-close { background-position: -80px -208px; }
1127
+ .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
1128
+ .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
1129
+ .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
1130
+ .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
1131
+ .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
1132
+ .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
1133
+
1134
+
1135
+ /* Misc visuals
1136
+ ----------------------------------*/
1137
+
1138
+ /* Corner radius */
1139
+ .ui-corner-all,
1140
+ .ui-corner-top,
1141
+ .ui-corner-left,
1142
+ .ui-corner-tl {
1143
+ border-top-left-radius: 5px;
1144
+ }
1145
+ .ui-corner-all,
1146
+ .ui-corner-top,
1147
+ .ui-corner-right,
1148
+ .ui-corner-tr {
1149
+ border-top-right-radius: 5px;
1150
+ }
1151
+ .ui-corner-all,
1152
+ .ui-corner-bottom,
1153
+ .ui-corner-left,
1154
+ .ui-corner-bl {
1155
+ border-bottom-left-radius: 5px;
1156
+ }
1157
+ .ui-corner-all,
1158
+ .ui-corner-bottom,
1159
+ .ui-corner-right,
1160
+ .ui-corner-br {
1161
+ border-bottom-right-radius: 5px;
1162
+ }
1163
+
1164
+ /* Overlays */
1165
+ .ui-widget-overlay {
1166
+ background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;
1167
+ opacity: .3;
1168
+ filter: Alpha(Opacity=30);
1169
+ }
1170
+ .ui-widget-shadow {
1171
+ margin: -8px 0 0 -8px;
1172
+ padding: 8px;
1173
+ background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;
1174
+ opacity: .3;
1175
+ filter: Alpha(Opacity=30);
1176
+ border-radius: 8px;
1177
+ }
static/js/jquery/jquery.mjs.nestedSortable.js CHANGED
@@ -345,7 +345,7 @@
345
  }
346
 
347
  if (id) {
348
- ret.push({"item_id": id[2], "parent_id": pid, "depth": depth, "left": left, "right": right, "xpath":$(item).find('input').val()});
349
  }
350
 
351
  left = right + 1;
345
  }
346
 
347
  if (id) {
348
+ ret.push({"item_id": id[2], "parent_id": pid, "delim": $(item).parents('.post_taxonomy:first').find('input.tax_delim').val(), "left": left, "right": right, "xpath":$(item).find('input.widefat').val(), "assign":$(item).find('input.assign_post').is(':checked')});
349
  }
350
 
351
  left = right + 1;
static/js/jquery/moment.js ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ // moment.js
2
+ // version : 1.7.2
3
+ // author : Tim Wood
4
+ // license : MIT
5
+ // momentjs.com
6
+ (function(a){function E(a,b,c,d){var e=c.lang();return e[a].call?e[a](c,d):e[a][b]}function F(a,b){return function(c){return K(a.call(this,c),b)}}function G(a){return function(b){var c=a.call(this,b);return c+this.lang().ordinal(c)}}function H(a,b,c){this._d=a,this._isUTC=!!b,this._a=a._a||null,this._lang=c||!1}function I(a){var b=this._data={},c=a.years||a.y||0,d=a.months||a.M||0,e=a.weeks||a.w||0,f=a.days||a.d||0,g=a.hours||a.h||0,h=a.minutes||a.m||0,i=a.seconds||a.s||0,j=a.milliseconds||a.ms||0;this._milliseconds=j+i*1e3+h*6e4+g*36e5,this._days=f+e*7,this._months=d+c*12,b.milliseconds=j%1e3,i+=J(j/1e3),b.seconds=i%60,h+=J(i/60),b.minutes=h%60,g+=J(h/60),b.hours=g%24,f+=J(g/24),f+=e*7,b.days=f%30,d+=J(f/30),b.months=d%12,c+=J(d/12),b.years=c,this._lang=!1}function J(a){return a<0?Math.ceil(a):Math.floor(a)}function K(a,b){var c=a+"";while(c.length<b)c="0"+c;return c}function L(a,b,c){var d=b._milliseconds,e=b._days,f=b._months,g;d&&a._d.setTime(+a+d*c),e&&a.date(a.date()+e*c),f&&(g=a.date(),a.date(1).month(a.month()+f*c).date(Math.min(g,a.daysInMonth())))}function M(a){return Object.prototype.toString.call(a)==="[object Array]"}function N(a,b){var c=Math.min(a.length,b.length),d=Math.abs(a.length-b.length),e=0,f;for(f=0;f<c;f++)~~a[f]!==~~b[f]&&e++;return e+d}function O(a,b,c,d){var e,f,g=[];for(e=0;e<7;e++)g[e]=a[e]=a[e]==null?e===2?1:0:a[e];return a[7]=g[7]=b,a[8]!=null&&(g[8]=a[8]),a[3]+=c||0,a[4]+=d||0,f=new Date(0),b?(f.setUTCFullYear(a[0],a[1],a[2]),f.setUTCHours(a[3],a[4],a[5],a[6])):(f.setFullYear(a[0],a[1],a[2]),f.setHours(a[3],a[4],a[5],a[6])),f._a=g,f}function P(a,c){var d,e,g=[];!c&&h&&(c=require("./lang/"+a));for(d=0;d<i.length;d++)c[i[d]]=c[i[d]]||f.en[i[d]];for(d=0;d<12;d++)e=b([2e3,d]),g[d]=new RegExp("^"+(c.months[d]||c.months(e,""))+"|^"+(c.monthsShort[d]||c.monthsShort(e,"")).replace(".",""),"i");return c.monthsParse=c.monthsParse||g,f[a]=c,c}function Q(a){var c=typeof a=="string"&&a||a&&a._lang||null;return c?f[c]||P(c):b}function R(a){return a.match(/\[.*\]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function S(a){var b=a.match(k),c,d;for(c=0,d=b.length;c<d;c++)D[b[c]]?b[c]=D[b[c]]:b[c]=R(b[c]);return function(e){var f="";for(c=0;c<d;c++)f+=typeof b[c].call=="function"?b[c].call(e,a):b[c];return f}}function T(a,b){function d(b){return a.lang().longDateFormat[b]||b}var c=5;while(c--&&l.test(b))b=b.replace(l,d);return A[b]||(A[b]=S(b)),A[b](a)}function U(a){switch(a){case"DDDD":return p;case"YYYY":return q;case"S":case"SS":case"SSS":case"DDD":return o;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":case"a":case"A":return r;case"Z":case"ZZ":return s;case"T":return t;case"MM":case"DD":case"YY":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":return n;default:return new RegExp(a.replace("\\",""))}}function V(a,b,c,d){var e,f;switch(a){case"M":case"MM":c[1]=b==null?0:~~b-1;break;case"MMM":case"MMMM":for(e=0;e<12;e++)if(Q().monthsParse[e].test(b)){c[1]=e,f=!0;break}f||(c[8]=!1);break;case"D":case"DD":case"DDD":case"DDDD":b!=null&&(c[2]=~~b);break;case"YY":c[0]=~~b+(~~b>70?1900:2e3);break;case"YYYY":c[0]=~~Math.abs(b);break;case"a":case"A":d.isPm=(b+"").toLowerCase()==="pm";break;case"H":case"HH":case"h":case"hh":c[3]=~~b;break;case"m":case"mm":c[4]=~~b;break;case"s":case"ss":c[5]=~~b;break;case"S":case"SS":case"SSS":c[6]=~~(("0."+b)*1e3);break;case"Z":case"ZZ":d.isUTC=!0,e=(b+"").match(x),e&&e[1]&&(d.tzh=~~e[1]),e&&e[2]&&(d.tzm=~~e[2]),e&&e[0]==="+"&&(d.tzh=-d.tzh,d.tzm=-d.tzm)}b==null&&(c[8]=!1)}function W(a,b){var c=[0,0,1,0,0,0,0],d={tzh:0,tzm:0},e=b.match(k),f,g;for(f=0;f<e.length;f++)g=(U(e[f]).exec(a)||[])[0],g&&(a=a.slice(a.indexOf(g)+g.length)),D[e[f]]&&V(e[f],g,c,d);return d.isPm&&c[3]<12&&(c[3]+=12),d.isPm===!1&&c[3]===12&&(c[3]=0),O(c,d.isUTC,d.tzh,d.tzm)}function X(a,b){var c,d=a.match(m)||[],e,f=99,g,h,i;for(g=0;g<b.length;g++)h=W(a,b[g]),e=T(new H(h),b[g]).match(m)||[],i=N(d,e),i<f&&(f=i,c=h);return c}function Y(a){var b="YYYY-MM-DDT",c;if(u.exec(a)){for(c=0;c<4;c++)if(w[c][1].exec(a)){b+=w[c][0];break}return s.exec(a)?W(a,b+" Z"):W(a,b)}return new Date(a)}function Z(a,b,c,d,e){var f=e.relativeTime[a];return typeof f=="function"?f(b||1,!!c,a,d):f.replace(/%d/i,b||1)}function $(a,b,c){var e=d(Math.abs(a)/1e3),f=d(e/60),g=d(f/60),h=d(g/24),i=d(h/365),j=e<45&&["s",e]||f===1&&["m"]||f<45&&["mm",f]||g===1&&["h"]||g<22&&["hh",g]||h===1&&["d"]||h<=25&&["dd",h]||h<=45&&["M"]||h<345&&["MM",d(h/30)]||i===1&&["y"]||["yy",i];return j[2]=b,j[3]=a>0,j[4]=c,Z.apply({},j)}function _(a,c){b.fn[a]=function(a){var b=this._isUTC?"UTC":"";return a!=null?(this._d["set"+b+c](a),this):this._d["get"+b+c]()}}function ab(a){b.duration.fn[a]=function(){return this._data[a]}}function bb(a,c){b.duration.fn["as"+a]=function(){return+this/c}}var b,c="1.7.2",d=Math.round,e,f={},g="en",h=typeof module!="undefined"&&module.exports,i="months|monthsShort|weekdays|weekdaysShort|weekdaysMin|longDateFormat|calendar|relativeTime|ordinal|meridiem".split("|"),j=/^\/?Date\((\-?\d+)/i,k=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?|.)/g,l=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?)/g,m=/([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,n=/\d\d?/,o=/\d{1,3}/,p=/\d{3}/,q=/\d{1,4}/,r=/[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i,s=/Z|[\+\-]\d\d:?\d\d/i,t=/T/i,u=/^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,v="YYYY-MM-DDTHH:mm:ssZ",w=[["HH:mm:ss.S",/T\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/T\d\d:\d\d:\d\d/],["HH:mm",/T\d\d:\d\d/],["HH",/T\d\d/]],x=/([\+\-]|\d\d)/gi,y="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"),z={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},A={},B="DDD w M D d".split(" "),C="M D H h m s w".split(" "),D={M:function(){return this.month()+1},MMM:function(a){return E("monthsShort",this.month(),this,a)},MMMM:function(a){return E("months",this.month(),this,a)},D:function(){return this.date()},DDD:function(){var a=new Date(this.year(),this.month(),this.date()),b=new Date(this.year(),0,1);return~~((a-b)/864e5+1.5)},d:function(){return this.day()},dd:function(a){return E("weekdaysMin",this.day(),this,a)},ddd:function(a){return E("weekdaysShort",this.day(),this,a)},dddd:function(a){return E("weekdays",this.day(),this,a)},w:function(){var a=new Date(this.year(),this.month(),this.date()-this.day()+5),b=new Date(a.getFullYear(),0,4);return~~((a-b)/864e5/7+1.5)},YY:function(){return K(this.year()%100,2)},YYYY:function(){return K(this.year(),4)},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return K(~~(this.milliseconds()/10),2)},SSS:function(){return K(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return a<0&&(a=-a,b="-"),b+K(~~(a/60),2)+":"+K(~~a%60,2)},ZZ:function(){var a=-this.zone(),b="+";return a<0&&(a=-a,b="-"),b+K(~~(10*a/6),4)}};while(B.length)e=B.pop(),D[e+"o"]=G(D[e]);while(C.length)e=C.pop(),D[e+e]=F(D[e],2);D.DDDD=F(D.DDD,3),b=function(c,d){if(c===null||c==="")return null;var e,f;return b.isMoment(c)?new H(new Date(+c._d),c._isUTC,c._lang):(d?M(d)?e=X(c,d):e=W(c,d):(f=j.exec(c),e=c===a?new Date:f?new Date(+f[1]):c instanceof Date?c:M(c)?O(c):typeof c=="string"?Y(c):new Date(c)),new H(e))},b.utc=function(a,c){return M(a)?new H(O(a,!0),!0):(typeof a=="string"&&!s.exec(a)&&(a+=" +0000",c&&(c+=" Z")),b(a,c).utc())},b.unix=function(a){return b(a*1e3)},b.duration=function(a,c){var d=b.isDuration(a),e=typeof a=="number",f=d?a._data:e?{}:a,g;return e&&(c?f[c]=a:f.milliseconds=a),g=new I(f),d&&(g._lang=a._lang),g},b.humanizeDuration=function(a,c,d){return b.duration(a,c===!0?null:c).humanize(c===!0?!0:d)},b.version=c,b.defaultFormat=v,b.lang=function(a,c){var d;if(!a)return g;(c||!f[a])&&P(a,c);if(f[a]){for(d=0;d<i.length;d++)b[i[d]]=f[a][i[d]];b.monthsParse=f[a].monthsParse,g=a}},b.langData=Q,b.isMoment=function(a){return a instanceof H},b.isDuration=function(a){return a instanceof I},b.lang("en",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}}),b.fn=H.prototype={clone:function(){return b(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this._d.toString()},toDate:function(){return this._d},toArray:function(){var a=this;return[a.year(),a.month(),a.date(),a.hours(),a.minutes(),a.seconds(),a.milliseconds(),!!this._isUTC]},isValid:function(){return this._a?this._a[8]!=null?!!this._a[8]:!N(this._a,(this._a[7]?b.utc(this._a):b(this._a)).toArray()):!isNaN(this._d.getTime())},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(a){return T(this,a?a:b.defaultFormat)},add:function(a,c){var d=c?b.duration(+c,a):b.duration(a);return L(this,d,1),this},subtract:function(a,c){var d=c?b.duration(+c,a):b.duration(a);return L(this,d,-1),this},diff:function(a,c,e){var f=this._isUTC?b(a).utc():b(a).local(),g=(this.zone()-f.zone())*6e4,h=this._d-f._d-g,i=this.year()-f.year(),j=this.month()-f.month(),k=this.date()-f.date(),l;return c==="months"?l=i*12+j+k/30:c==="years"?l=i+(j+k/30)/12:l=c==="seconds"?h/1e3:c==="minutes"?h/6e4:c==="hours"?h/36e5:c==="days"?h/864e5:c==="weeks"?h/6048e5:h,e?l:d(l)},from:function(a,c){return b.duration(this.diff(a)).lang(this._lang).humanize(!c)},fromNow:function(a){return this.from(b(),a)},calendar:function(){var a=this.diff(b().sod(),"days",!0),c=this.lang().calendar,d=c.sameElse,e=a<-6?d:a<-1?c.lastWeek:a<0?c.lastDay:a<1?c.sameDay:a<2?c.nextDay:a<7?c.nextWeek:d;return this.format(typeof e=="function"?e.apply(this):e)},isLeapYear:function(){var a=this.year();return a%4===0&&a%100!==0||a%400===0},isDST:function(){return this.zone()<b([this.year()]).zone()||this.zone()<b([this.year(),5]).zone()},day:function(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return a==null?b:this.add({d:a-b})},startOf:function(a){switch(a.replace(/s$/,"")){case"year":this.month(0);case"month":this.date(1);case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return this},endOf:function(a){return this.startOf(a).add(a.replace(/s?$/,"s"),1).subtract("ms",1)},sod:function(){return this.clone().startOf("day")},eod:function(){return this.clone().endOf("day")},zone:function(){return this._isUTC?0:this._d.getTimezoneOffset()},daysInMonth:function(){return b.utc([this.year(),this.month()+1,0]).date()},lang:function(b){return b===a?Q(this):(this._lang=b,this)}};for(e=0;e<y.length;e++)_(y[e].toLowerCase(),y[e]);_("year","FullYear"),b.duration.fn=I.prototype={weeks:function(){return J(this.days()/7)},valueOf:function(){return this._milliseconds+this._days*864e5+this._months*2592e6},humanize:function(a){var b=+this,c=this.lang().relativeTime,d=$(b,!a,this.lang()),e=b<=0?c.past:c.future;return a&&(typeof e=="function"?d=e(d):d=e.replace(/%s/i,d)),d},lang:b.fn.lang};for(e in z)z.hasOwnProperty(e)&&(bb(e,z[e]),ab(e.toLowerCase()));bb("Weeks",6048e5),h&&(module.exports=b),typeof ender=="undefined"&&(this.moment=b),typeof define=="function"&&define.amd&&define("moment",[],function(){return b})}).call(this);
static/js/plupload/plupload.flash.swf ADDED
Binary file
static/js/plupload/plupload.full.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ /*1.5b*/
2
+ (function(){var f=0,l=[],n={},j={},a={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"},m=/[<>&\"\']/g,b,c=window.setTimeout,d={},e;function h(){this.returnValue=false}function k(){this.cancelBubble=true}(function(o){var p=o.split(/,/),q,s,r;for(q=0;q<p.length;q+=2){r=p[q+1].split(/ /);for(s=0;s<r.length;s++){j[r[s]]=p[q]}}})("application/msword,doc dot,application/pdf,pdf,application/pgp-signature,pgp,application/postscript,ps ai eps,application/rtf,rtf,application/vnd.ms-excel,xls xlb,application/vnd.ms-powerpoint,ppt pps pot,application/zip,zip,application/x-shockwave-flash,swf swfl,application/vnd.openxmlformats,docx pptx xlsx,audio/mpeg,mpga mpega mp2 mp3,audio/x-wav,wav,audio/mp4,m4a,image/bmp,bmp,image/gif,gif,image/jpeg,jpeg jpg jpe,image/photoshop,psd,image/png,png,image/svg+xml,svg svgz,image/tiff,tiff tif,text/html,htm html xhtml,text/rtf,rtf,video/mpeg,mpeg mpg mpe,video/quicktime,qt mov,video/mp4,mp4,video/x-m4v,m4v,video/x-flv,flv,video/x-ms-wmv,wmv,video/avi,avi,video/webm,webm,video/vnd.rn-realvideo,rv,text/csv,csv,text/plain,asc txt text diff log,application/octet-stream,exe");var g={VERSION:"1.5b",STOPPED:1,STARTED:2,QUEUED:1,UPLOADING:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,IMAGE_FORMAT_ERROR:-700,IMAGE_MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,mimeTypes:j,extend:function(o){g.each(arguments,function(p,q){if(q>0){g.each(p,function(s,r){o[r]=s})}});return o},cleanName:function(o){var p,q;q=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"];for(p=0;p<q.length;p+=2){o=o.replace(q[p],q[p+1])}o=o.replace(/\s+/g,"_");o=o.replace(/[^a-z0-9_\-\.]+/gi,"");return o},addRuntime:function(o,p){p.name=o;l[o]=p;l.push(p);return p},guid:function(){var o=new Date().getTime().toString(32),p;for(p=0;p<5;p++){o+=Math.floor(Math.random()*65535).toString(32)}return(g.guidPrefix||"p")+o+(f++).toString(32)},buildUrl:function(p,o){var q="";g.each(o,function(s,r){q+=(q?"&":"")+encodeURIComponent(r)+"="+encodeURIComponent(s)});if(q){p+=(p.indexOf("?")>0?"&":"?")+q}return p},each:function(r,s){var q,p,o;if(r){q=r.length;if(q===b){for(p in r){if(r.hasOwnProperty(p)){if(s(r[p],p)===false){return}}}}else{for(o=0;o<q;o++){if(s(r[o],o)===false){return}}}}},formatSize:function(o){if(o===b||/\D/.test(o)){return g.translate("N/A")}if(o>1073741824){return Math.round(o/1073741824,1)+" GB"}if(o>1048576){return Math.round(o/1048576,1)+" MB"}if(o>1024){return Math.round(o/1024,1)+" KB"}return o+" b"},getPos:function(p,t){var u=0,s=0,w,v=document,q,r;p=p;t=t||v.body;function o(C){var A,B,z=0,D=0;if(C){B=C.getBoundingClientRect();A=v.compatMode==="CSS1Compat"?v.documentElement:v.body;z=B.left+A.scrollLeft;D=B.top+A.scrollTop}return{x:z,y:D}}if(p&&p.getBoundingClientRect&&(navigator.userAgent.indexOf("MSIE")>0&&v.documentMode!==8)){q=o(p);r=o(t);return{x:q.x-r.x,y:q.y-r.y}}w=p;while(w&&w!=t&&w.nodeType){u+=w.offsetLeft||0;s+=w.offsetTop||0;w=w.offsetParent}w=p.parentNode;while(w&&w!=t&&w.nodeType){u-=w.scrollLeft||0;s-=w.scrollTop||0;w=w.parentNode}return{x:u,y:s}},getSize:function(o){return{w:o.offsetWidth||o.clientWidth,h:o.offsetHeight||o.clientHeight}},parseSize:function(o){var p;if(typeof(o)=="string"){o=/^([0-9]+)([mgk]?)$/.exec(o.toLowerCase().replace(/[^0-9mkg]/g,""));p=o[2];o=+o[1];if(p=="g"){o*=1073741824}if(p=="m"){o*=1048576}if(p=="k"){o*=1024}}return o},xmlEncode:function(o){return o?(""+o).replace(m,function(p){return a[p]?"&"+a[p]+";":p}):o},toArray:function(q){var p,o=[];for(p=0;p<q.length;p++){o[p]=q[p]}return o},addI18n:function(o){return g.extend(n,o)},translate:function(o){return n[o]||o},isEmptyObj:function(o){if(o===b){return true}for(var p in o){return false}return true},hasClass:function(q,p){var o;if(q.className==""){return false}o=new RegExp("(^|\\s+)"+p+"(\\s+|$)");return o.test(q.className)},addClass:function(p,o){if(!g.hasClass(p,o)){p.className=p.className==""?o:p.className.replace(/\s+$/,"")+" "+o}},removeClass:function(q,p){var o=new RegExp("(^|\\s+)"+p+"(\\s+|$)");q.className=q.className.replace(o,function(s,r,t){return r===" "&&t===" "?" ":""})},getStyle:function(p,o){if(p.currentStyle){return p.currentStyle[o]}else{if(window.getComputedStyle){return window.getComputedStyle(p,null)[o]}}},addEvent:function(t,o,u){var s,r,q,p;p=arguments[3];o=o.toLowerCase();if(e===b){e="Plupload_"+g.guid()}if(t.addEventListener){s=u;t.addEventListener(o,s,false)}else{if(t.attachEvent){s=function(){var v=window.event;if(!v.target){v.target=v.srcElement}v.preventDefault=h;v.stopPropagation=k;u(v)};t.attachEvent("on"+o,s)}}if(t[e]===b){t[e]=g.guid()}if(!d.hasOwnProperty(t[e])){d[t[e]]={}}r=d[t[e]];if(!r.hasOwnProperty(o)){r[o]=[]}r[o].push({func:s,orig:u,key:p})},removeEvent:function(t,o){var r,u,q;if(typeof(arguments[2])=="function"){u=arguments[2]}else{q=arguments[2]}o=o.toLowerCase();if(t[e]&&d[t[e]]&&d[t[e]][o]){r=d[t[e]][o]}else{return}for(var p=r.length-1;p>=0;p--){if(r[p].key===q||r[p].orig===u){if(t.detachEvent){t.detachEvent("on"+o,r[p].func)}else{if(t.removeEventListener){t.removeEventListener(o,r[p].func,false)}}r[p].orig=null;r[p].func=null;r.splice(p,1);if(u!==b){break}}}if(!r.length){delete d[t[e]][o]}if(g.isEmptyObj(d[t[e]])){delete d[t[e]];try{delete t[e]}catch(s){t[e]=b}}},removeAllEvents:function(p){var o=arguments[1];if(p[e]===b||!p[e]){return}g.each(d[p[e]],function(r,q){g.removeEvent(p,q,o)})}};g.Uploader=function(r){var p={},u,t=[],q;u=new g.QueueProgress();r=g.extend({chunk_size:0,multipart:true,multi_selection:true,file_data_name:"file",filters:[]},r);function s(){var w,x=0,v;if(this.state==g.STARTED){for(v=0;v<t.length;v++){if(!w&&t[v].status==g.QUEUED){w=t[v];w.status=g.UPLOADING;if(this.trigger("BeforeUpload",w)){this.trigger("UploadFile",w)}}else{x++}}if(x==t.length){this.trigger("UploadComplete",t);this.stop()}}}function o(){var w,v;u.reset();for(w=0;w<t.length;w++){v=t[w];if(v.size!==b){u.size+=v.size;u.loaded+=v.loaded}else{u.size=b}if(v.status==g.DONE){u.uploaded++}else{if(v.status==g.FAILED){u.failed++}else{u.queued++}}}if(u.size===b){u.percent=t.length>0?Math.ceil(u.uploaded/t.length*100):0}else{u.bytesPerSec=Math.ceil(u.loaded/((+new Date()-q||1)/1000));u.percent=u.size>0?Math.ceil(u.loaded/u.size*100):0}}g.extend(this,{state:g.STOPPED,runtime:"",features:{},files:t,settings:r,total:u,id:g.guid(),init:function(){var A=this,B,x,w,z=0,y;if(typeof(r.preinit)=="function"){r.preinit(A)}else{g.each(r.preinit,function(D,C){A.bind(C,D)})}r.page_url=r.page_url||document.location.pathname.replace(/\/[^\/]+$/g,"/");if(!/^(\w+:\/\/|\/)/.test(r.url)){r.url=r.page_url+r.url}r.chunk_size=g.parseSize(r.chunk_size);r.max_file_size=g.parseSize(r.max_file_size);A.bind("FilesAdded",function(C,F){var E,D,H=0,I,G=r.filters;if(G&&G.length){I=[];g.each(G,function(J){g.each(J.extensions.split(/,/),function(K){if(/^\s*\*\s*$/.test(K)){I.push("\\.*")}else{I.push("\\."+K.replace(new RegExp("["+("/^$.*+?|()[]{}\\".replace(/./g,"\\$&"))+"]","g"),"\\$&"))}})});I=new RegExp(I.join("|")+"$","i")}for(E=0;E<F.length;E++){D=F[E];D.loaded=0;D.percent=0;D.status=g.QUEUED;if(I&&!I.test(D.name)){C.trigger("Error",{code:g.FILE_EXTENSION_ERROR,message:g.translate("File extension error."),file:D});continue}if(D.size!==b&&D.size>r.max_file_size){C.trigger("Error",{code:g.FILE_SIZE_ERROR,message:g.translate("File size error."),file:D});continue}t.push(D);H++}if(H){c(function(){A.trigger("QueueChanged");A.refresh()},1)}else{return false}});if(r.unique_names){A.bind("UploadFile",function(C,D){var F=D.name.match(/\.([^.]+)$/),E="tmp";if(F){E=F[1]}D.target_name=D.id+"."+E})}A.bind("UploadProgress",function(C,D){D.percent=D.size>0?Math.ceil(D.loaded/D.size*100):100;o()});A.bind("StateChanged",function(C){if(C.state==g.STARTED){q=(+new Date())}else{if(C.state==g.STOPPED){for(B=C.files.length-1;B>=0;B--){if(C.files[B].status==g.UPLOADING){C.files[B].status=g.QUEUED;o()}}}}});A.bind("QueueChanged",o);A.bind("Error",function(C,D){if(D.file){D.file.status=g.FAILED;o();if(C.state==g.STARTED){c(function(){s.call(A)},1)}}});A.bind("FileUploaded",function(C,D){D.status=g.DONE;D.loaded=D.size;C.trigger("UploadProgress",D);c(function(){s.call(A)},1)});if(r.runtimes){x=[];y=r.runtimes.split(/\s?,\s?/);for(B=0;B<y.length;B++){if(l[y[B]]){x.push(l[y[B]])}}}else{x=l}function v(){var F=x[z++],E,C,D;if(F){E=F.getFeatures();C=A.settings.required_features;if(C){C=C.split(",");for(D=0;D<C.length;D++){if(!E[C[D]]){v();return}}}F.init(A,function(G){if(G&&G.success){A.features=E;A.runtime=F.name;A.trigger("Init",{runtime:F.name});A.trigger("PostInit");A.refresh()}else{v()}})}else{A.trigger("Error",{code:g.INIT_ERROR,message:g.translate("Init error.")})}}v();if(typeof(r.init)=="function"){r.init(A)}else{g.each(r.init,function(D,C){A.bind(C,D)})}},refresh:function(){this.trigger("Refresh")},start:function(){if(this.state!=g.STARTED){this.state=g.STARTED;this.trigger("StateChanged");s.call(this)}},stop:function(){if(this.state!=g.STOPPED){this.state=g.STOPPED;this.trigger("StateChanged")}},getFile:function(w){var v;for(v=t.length-1;v>=0;v--){if(t[v].id===w){return t[v]}}},removeFile:function(w){var v;for(v=t.length-1;v>=0;v--){if(t[v].id===w.id){return this.splice(v,1)[0]}}},splice:function(x,v){var w;w=t.splice(x===b?0:x,v===b?t.length:v);this.trigger("FilesRemoved",w);this.trigger("QueueChanged");return w},trigger:function(w){var y=p[w.toLowerCase()],x,v;if(y){v=Array.prototype.slice.call(arguments);v[0]=this;for(x=0;x<y.length;x++){if(y[x].func.apply(y[x].scope,v)===false){return false}}}return true},hasEventListener:function(v){return !!p[v.toLowerCase()]},bind:function(v,x,w){var y;v=v.toLowerCase();y=p[v]||[];y.push({func:x,scope:w||this});p[v]=y},unbind:function(v){v=v.toLowerCase();var y=p[v],w,x=arguments[1];if(y){if(x!==b){for(w=y.length-1;w>=0;w--){if(y[w].func===x){y.splice(w,1);break}}}else{y=[]}if(!y.length){delete p[v]}}},unbindAll:function(){var v=this;g.each(p,function(x,w){v.unbind(w)})},destroy:function(){this.trigger("Destroy");this.unbindAll()}})};g.File=function(r,p,q){var o=this;o.id=r;o.name=p;o.size=q;o.loaded=0;o.percent=0;o.status=0};g.Runtime=function(){this.getFeatures=function(){};this.init=function(o,p){}};g.QueueProgress=function(){var o=this;o.size=0;o.loaded=0;o.uploaded=0;o.failed=0;o.queued=0;o.percent=0;o.bytesPerSec=0;o.reset=function(){o.size=o.loaded=o.uploaded=o.failed=o.queued=o.percent=o.bytesPerSec=0}};g.runtimes={};window.plupload=g})();(function(){if(window.google&&google.gears){return}var a=null;if(typeof GearsFactory!="undefined"){a=new GearsFactory()}else{try{a=new ActiveXObject("Gears.Factory");if(a.getBuildInfo().indexOf("ie_mobile")!=-1){a.privateSetGlobalObject(this)}}catch(b){if((typeof navigator.mimeTypes!="undefined")&&navigator.mimeTypes["application/x-googlegears"]){a=document.createElement("object");a.style.display="none";a.width=0;a.height=0;a.type="application/x-googlegears";document.documentElement.appendChild(a)}}}if(!a){return}if(!window.google){window.google={}}if(!google.gears){google.gears={factory:a}}})();(function(e,b,c,d){var f={};function a(h,k,m){var g,j,l,o;j=google.gears.factory.create("beta.canvas");try{j.decode(h);if(!k.width){k.width=j.width}if(!k.height){k.height=j.height}o=Math.min(width/j.width,height/j.height);if(o<1||(o===1&&m==="image/jpeg")){j.resize(Math.round(j.width*o),Math.round(j.height*o));if(k.quality){return j.encode(m,{quality:k.quality/100})}return j.encode(m)}}catch(n){}return h}c.runtimes.Gears=c.addRuntime("gears",{getFeatures:function(){return{dragdrop:true,jpgresize:true,pngresize:true,chunks:true,progress:true,multipart:true}},init:function(j,l){var k;if(!e.google||!google.gears){return l({success:false})}try{k=google.gears.factory.create("beta.desktop")}catch(h){return l({success:false})}function g(o){var n,m,p=[],q;for(m=0;m<o.length;m++){n=o[m];q=c.guid();f[q]=n.blob;p.push(new c.File(q,n.name,n.blob.length))}j.trigger("FilesAdded",p)}j.bind("PostInit",function(){var n=j.settings,m=b.getElementById(n.drop_element);if(m){c.addEvent(m,"dragover",function(o){k.setDropEffect(o,"copy");o.preventDefault()},j.id);c.addEvent(m,"drop",function(p){var o=k.getDragData(p,"application/x-gears-files");if(o){g(o.files)}p.preventDefault()},j.id);m=0}c.addEvent(b.getElementById(n.browse_button),"click",function(s){var r=[],p,o,q;s.preventDefault();no_type_restriction:for(p=0;p<n.filters.length;p++){q=n.filters[p].extensions.split(",");for(o=0;o<q.length;o++){if(q[o]==="*"){r=[];break no_type_restriction}r.push("."+q[o])}}k.openFiles(g,{singleFile:!n.multi_selection,filter:r})},j.id)});j.bind("UploadFile",function(s,p){var u=0,t,q,r=0,o=s.settings.resize,m;if(o&&/\.(png|jpg|jpeg)$/i.test(p.name)){f[p.id]=a(f[p.id],o,/\.png$/i.test(p.name)?"image/png":"image/jpeg")}p.size=f[p.id].length;q=s.settings.chunk_size;m=q>0;t=Math.ceil(p.size/q);if(!m){q=p.size;t=1}function n(){var z,B,w=s.settings.multipart,v=0,A={name:p.target_name||p.name},x=s.settings.url;function y(D){var C,I="----pluploadboundary"+c.guid(),F="--",H="\r\n",E,G;if(w){z.setRequestHeader("Content-Type","multipart/form-data; boundary="+I);C=google.gears.factory.create("beta.blobbuilder");c.each(c.extend(A,s.settings.multipart_params),function(K,J){C.append(F+I+H+'Content-Disposition: form-data; name="'+J+'"'+H+H);C.append(K+H)});G=c.mimeTypes[p.name.replace(/^.+\.([^.]+)/,"$1").toLowerCase()]||"application/octet-stream";C.append(F+I+H+'Content-Disposition: form-data; name="'+s.settings.file_data_name+'"; filename="'+p.name+'"'+H+"Content-Type: "+G+H+H);C.append(D);C.append(H+F+I+F+H);E=C.getAsBlob();v=E.length-D.length;D=E}z.send(D)}if(p.status==c.DONE||p.status==c.FAILED||s.state==c.STOPPED){return}if(m){A.chunk=u;A.chunks=t}B=Math.min(q,p.size-(u*q));if(!w){x=c.buildUrl(s.settings.url,A)}z=google.gears.factory.create("beta.httprequest");z.open("POST",x);if(!w){z.setRequestHeader("Content-Disposition",'attachment; filename="'+p.name+'"');z.setRequestHeader("Content-Type","application/octet-stream")}c.each(s.settings.headers,function(D,C){z.setRequestHeader(C,D)});z.upload.onprogress=function(C){p.loaded=r+C.loaded-v;s.trigger("UploadProgress",p)};z.onreadystatechange=function(){var C;if(z.readyState==4){if(z.status==200){C={chunk:u,chunks:t,response:z.responseText,status:z.status};s.trigger("ChunkUploaded",p,C);if(C.cancelled){p.status=c.FAILED;return}r+=B;if(++u>=t){p.status=c.DONE;s.trigger("FileUploaded",p,{response:z.responseText,status:z.status})}else{n()}}else{s.trigger("Error",{code:c.HTTP_ERROR,message:c.translate("HTTP Error."),file:p,chunk:u,chunks:t,status:z.status})}}};if(u<t){y(f[p.id].slice(u*q,B))}}n()});j.bind("Destroy",function(m){var n,o,p={browseButton:m.settings.browse_button,dropElm:m.settings.drop_element};for(n in p){o=b.getElementById(p[n]);if(o){c.removeAllEvents(o,m.id)}}});l({success:true})}})})(window,document,plupload);(function(g,b,d,e){var a={},h={};function c(o){var n,m=typeof o,j,l,k;if(o===e||o===null){return"null"}if(m==="string"){n="\bb\tt\nn\ff\rr\"\"''\\\\";return'"'+o.replace(/([\u0080-\uFFFF\x00-\x1f\"])/g,function(r,q){var p=n.indexOf(q);if(p+1){return"\\"+n.charAt(p+1)}r=q.charCodeAt().toString(16);return"\\u"+"0000".substring(r.length)+r})+'"'}if(m=="object"){j=o.length!==e;n="";if(j){for(l=0;l<o.length;l++){if(n){n+=","}n+=c(o[l])}n="["+n+"]"}else{for(k in o){if(o.hasOwnProperty(k)){if(n){n+=","}n+=c(k)+":"+c(o[k])}}n="{"+n+"}"}return n}return""+o}function f(s){var v=false,j=null,o=null,k,l,m,u,n,q=0;try{try{o=new ActiveXObject("AgControl.AgControl");if(o.IsVersionSupported(s)){v=true}o=null}catch(r){var p=navigator.plugins["Silverlight Plug-In"];if(p){k=p.description;if(k==="1.0.30226.2"){k="2.0.30226.2"}l=k.split(".");while(l.length>3){l.pop()}while(l.length<4){l.push(0)}m=s.split(".");while(m.length>4){m.pop()}do{u=parseInt(m[q],10);n=parseInt(l[q],10);q++}while(q<m.length&&u===n);if(u<=n&&!isNaN(u)){v=true}}}}catch(t){v=false}return v}d.silverlight={trigger:function(n,k){var m=a[n],l,j;if(m){j=d.toArray(arguments).slice(1);j[0]="Silverlight:"+k;setTimeout(function(){m.trigger.apply(m,j)},0)}}};d.runtimes.Silverlight=d.addRuntime("silverlight",{getFeatures:function(){return{jpgresize:true,pngresize:true,chunks:true,progress:true,multipart:true}},init:function(p,q){var o,m="",n=p.settings.filters,l,k=b.body;if(!f("2.0.31005.0")||(g.opera&&g.opera.buildNumber)){q({success:false});return}h[p.id]=false;a[p.id]=p;o=b.createElement("div");o.id=p.id+"_silverlight_container";d.extend(o.style,{position:"absolute",top:"0px",background:p.settings.shim_bgcolor||"transparent",zIndex:99999,width:"100px",height:"100px",overflow:"hidden",opacity:p.settings.shim_bgcolor||b.documentMode>8?"":0.01});o.className="plupload silverlight";if(p.settings.container){k=b.getElementById(p.settings.container);if(d.getStyle(k,"position")==="static"){k.style.position="relative"}}k.appendChild(o);for(l=0;l<n.length;l++){m+=(m!=""?"|":"")+n[l].title+" | *."+n[l].extensions.replace(/,/g,";*.")}o.innerHTML='<object id="'+p.id+'_silverlight" data="data:application/x-silverlight," type="application/x-silverlight-2" style="outline:none;" width="1024" height="1024"><param name="source" value="'+p.settings.silverlight_xap_url+'"/><param name="background" value="Transparent"/><param name="windowless" value="true"/><param name="enablehtmlaccess" value="true"/><param name="initParams" value="id='+p.id+",filter="+m+",multiselect="+p.settings.multi_selection+'"/></object>';function j(){return b.getElementById(p.id+"_silverlight").content.Upload}p.bind("Silverlight:Init",function(){var r,s={};if(h[p.id]){return}h[p.id]=true;p.bind("Silverlight:StartSelectFiles",function(t){r=[]});p.bind("Silverlight:SelectFile",function(t,w,u,v){var x;x=d.guid();s[x]=w;s[w]=x;r.push(new d.File(x,u,v))});p.bind("Silverlight:SelectSuccessful",function(){if(r.length){p.trigger("FilesAdded",r)}});p.bind("Silverlight:UploadChunkError",function(t,w,u,x,v){p.trigger("Error",{code:d.IO_ERROR,message:"IO Error.",details:v,file:t.getFile(s[w])})});p.bind("Silverlight:UploadFileProgress",function(t,x,u,w){var v=t.getFile(s[x]);if(v.status!=d.FAILED){v.size=w;v.loaded=u;t.trigger("UploadProgress",v)}});p.bind("Refresh",function(t){var u,v,w;u=b.getElementById(t.settings.browse_button);if(u){v=d.getPos(u,b.getElementById(t.settings.container));w=d.getSize(u);d.extend(b.getElementById(t.id+"_silverlight_container").style,{top:v.y+"px",left:v.x+"px",width:w.w+"px",height:w.h+"px"})}});p.bind("Silverlight:UploadChunkSuccessful",function(t,w,u,z,y){var x,v=t.getFile(s[w]);x={chunk:u,chunks:z,response:y};t.trigger("ChunkUploaded",v,x);if(v.status!=d.FAILED){j().UploadNextChunk()}if(u==z-1){v.status=d.DONE;t.trigger("FileUploaded",v,{response:y})}});p.bind("Silverlight:UploadSuccessful",function(t,w,u){var v=t.getFile(s[w]);v.status=d.DONE;t.trigger("FileUploaded",v,{response:u})});p.bind("FilesRemoved",function(t,v){var u;for(u=0;u<v.length;u++){j().RemoveFile(s[v[u].id])}});p.bind("UploadFile",function(t,v){var w=t.settings,u=w.resize||{};j().UploadFile(s[v.id],t.settings.url,c({name:v.target_name||v.name,mime:d.mimeTypes[v.name.replace(/^.+\.([^.]+)/,"$1").toLowerCase()]||"application/octet-stream",chunk_size:w.chunk_size,image_width:u.width,image_height:u.height,image_quality:u.quality||90,multipart:!!w.multipart,multipart_params:w.multipart_params||{},file_data_name:w.file_data_name,headers:w.headers}))});p.bind("Silverlight:MouseEnter",function(t){var u,v;u=b.getElementById(p.settings.browse_button);v=t.settings.browse_button_hover;if(u&&v){d.addClass(u,v)}});p.bind("Silverlight:MouseLeave",function(t){var u,v;u=b.getElementById(p.settings.browse_button);v=t.settings.browse_button_hover;if(u&&v){d.removeClass(u,v)}});p.bind("Silverlight:MouseLeftButtonDown",function(t){var u,v;u=b.getElementById(p.settings.browse_button);v=t.settings.browse_button_active;if(u&&v){d.addClass(u,v);d.addEvent(b.body,"mouseup",function(){d.removeClass(u,v)})}});p.bind("Sliverlight:StartSelectFiles",function(t){var u,v;u=b.getElementById(p.settings.browse_button);v=t.settings.browse_button_active;if(u&&v){d.removeClass(u,v)}});p.bind("Destroy",function(t){var u;d.removeAllEvents(b.body,t.id);delete h[t.id];delete a[t.id];u=b.getElementById(t.id+"_silverlight_container");if(u){k.removeChild(u)}});q({success:true})})}})})(window,document,plupload);(function(f,b,d,e){var a={},g={};function c(){var h;try{h=navigator.plugins["Shockwave Flash"];h=h.description}catch(k){try{h=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(j){h="0.0"}}h=h.match(/\d+/g);return parseFloat(h[0]+"."+h[1])}d.flash={trigger:function(k,h,j){setTimeout(function(){var n=a[k],m,l;if(n){n.trigger("Flash:"+h,j)}},0)}};d.runtimes.Flash=d.addRuntime("flash",{getFeatures:function(){return{jpgresize:true,pngresize:true,maxWidth:8091,maxHeight:8091,chunks:true,progress:true,multipart:true}},init:function(k,p){var o,j,l,q=0,h=b.body;if(c()<10){p({success:false});return}g[k.id]=false;a[k.id]=k;o=b.getElementById(k.settings.browse_button);j=b.createElement("div");j.id=k.id+"_flash_container";d.extend(j.style,{position:"absolute",top:"0px",background:k.settings.shim_bgcolor||"transparent",zIndex:99999,width:"100%",height:"100%"});j.className="plupload flash";if(k.settings.container){h=b.getElementById(k.settings.container);if(d.getStyle(h,"position")==="static"){h.style.position="relative"}}h.appendChild(j);l="id="+escape(k.id);j.innerHTML='<object id="'+k.id+'_flash" width="100%" height="100%" style="outline:0" type="application/x-shockwave-flash" data="'+k.settings.flash_swf_url+'"><param name="movie" value="'+k.settings.flash_swf_url+'" /><param name="flashvars" value="'+l+'" /><param name="wmode" value="transparent" /><param name="allowscriptaccess" value="always" /></object>';function n(){return b.getElementById(k.id+"_flash")}function m(){if(q++>5000){p({success:false});return}if(!g[k.id]){setTimeout(m,1)}}m();o=j=null;k.bind("Flash:Init",function(){var s={},r;n().setFileFilters(k.settings.filters,k.settings.multi_selection);if(g[k.id]){return}g[k.id]=true;k.bind("UploadFile",function(t,v){var w=t.settings,u=k.settings.resize||{};n().uploadFile(s[v.id],w.url,{name:v.target_name||v.name,mime:d.mimeTypes[v.name.replace(/^.+\.([^.]+)/,"$1").toLowerCase()]||"application/octet-stream",chunk_size:w.chunk_size,width:u.width,height:u.height,quality:u.quality,multipart:w.multipart,multipart_params:w.multipart_params||{},file_data_name:w.file_data_name,format:/\.(jpg|jpeg)$/i.test(v.name)?"jpg":"png",headers:w.headers,urlstream_upload:w.urlstream_upload})});k.bind("Flash:UploadProcess",function(u,t){var v=u.getFile(s[t.id]);if(v.status!=d.FAILED){v.loaded=t.loaded;v.size=t.size;u.trigger("UploadProgress",v)}});k.bind("Flash:UploadChunkComplete",function(t,v){var w,u=t.getFile(s[v.id]);w={chunk:v.chunk,chunks:v.chunks,response:v.text};t.trigger("ChunkUploaded",u,w);if(u.status!=d.FAILED){n().uploadNextChunk()}if(v.chunk==v.chunks-1){u.status=d.DONE;t.trigger("FileUploaded",u,{response:v.text})}});k.bind("Flash:SelectFiles",function(t,w){var v,u,x=[],y;for(u=0;u<w.length;u++){v=w[u];y=d.guid();s[y]=v.id;s[v.id]=y;x.push(new d.File(y,v.name,v.size))}if(x.length){k.trigger("FilesAdded",x)}});k.bind("Flash:SecurityError",function(t,u){k.trigger("Error",{code:d.SECURITY_ERROR,message:d.translate("Security error."),details:u.message,file:k.getFile(s[u.id])})});k.bind("Flash:GenericError",function(t,u){k.trigger("Error",{code:d.GENERIC_ERROR,message:d.translate("Generic error."),details:u.message,file:k.getFile(s[u.id])})});k.bind("Flash:IOError",function(t,u){k.trigger("Error",{code:d.IO_ERROR,message:d.translate("IO error."),details:u.message,file:k.getFile(s[u.id])})});k.bind("Flash:ImageError",function(t,u){k.trigger("Error",{code:parseInt(u.code,10),message:d.translate("Image error."),file:k.getFile(s[u.id])})});k.bind("Flash:StageEvent:rollOver",function(t){var u,v;u=b.getElementById(k.settings.browse_button);v=t.settings.browse_button_hover;if(u&&v){d.addClass(u,v)}});k.bind("Flash:StageEvent:rollOut",function(t){var u,v;u=b.getElementById(k.settings.browse_button);v=t.settings.browse_button_hover;if(u&&v){d.removeClass(u,v)}});k.bind("Flash:StageEvent:mouseDown",function(t){var u,v;u=b.getElementById(k.settings.browse_button);v=t.settings.browse_button_active;if(u&&v){d.addClass(u,v);d.addEvent(b.body,"mouseup",function(){d.removeClass(u,v)},t.id)}});k.bind("Flash:StageEvent:mouseUp",function(t){var u,v;u=b.getElementById(k.settings.browse_button);v=t.settings.browse_button_active;if(u&&v){d.removeClass(u,v)}});k.bind("Flash:ExifData",function(t,u){k.trigger("ExifData",k.getFile(s[u.id]),u.data)});k.bind("Flash:GpsData",function(t,u){k.trigger("GpsData",k.getFile(s[u.id]),u.data)});k.bind("QueueChanged",function(t){k.refresh()});k.bind("FilesRemoved",function(t,v){var u;for(u=0;u<v.length;u++){n().removeFile(s[v[u].id])}});k.bind("StateChanged",function(t){k.refresh()});k.bind("Refresh",function(t){var u,v,w;n().setFileFilters(k.settings.filters,k.settings.multi_selection);u=b.getElementById(t.settings.browse_button);if(u){v=d.getPos(u,b.getElementById(t.settings.container));w=d.getSize(u);d.extend(b.getElementById(t.id+"_flash_container").style,{top:v.y+"px",left:v.x+"px",width:w.w+"px",height:w.h+"px"})}});k.bind("Destroy",function(t){var u;d.removeAllEvents(b.body,t.id);delete g[t.id];delete a[t.id];u=b.getElementById(t.id+"_flash_container");if(u){h.removeChild(u)}});p({success:true})})}})})(window,document,plupload);(function(a){a.runtimes.BrowserPlus=a.addRuntime("browserplus",{getFeatures:function(){return{dragdrop:true,jpgresize:true,pngresize:true,chunks:true,progress:true,multipart:true}},init:function(g,j){var e=window.BrowserPlus,h={},d=g.settings,c=d.resize;function f(o){var n,m,k=[],l,p;for(m=0;m<o.length;m++){l=o[m];p=a.guid();h[p]=l;k.push(new a.File(p,l.name,l.size))}if(m){g.trigger("FilesAdded",k)}}function b(){g.bind("PostInit",function(){var n,l=d.drop_element,p=g.id+"_droptarget",k=document.getElementById(l),m;function q(s,r){e.DragAndDrop.AddDropTarget({id:s},function(t){e.DragAndDrop.AttachCallbacks({id:s,hover:function(u){if(!u&&r){r()}},drop:function(u){if(r){r()}f(u)}},function(){})})}function o(){document.getElementById(p).style.top="-1000px"}if(k){if(document.attachEvent&&(/MSIE/gi).test(navigator.userAgent)){n=document.createElement("div");n.setAttribute("id",p);a.extend(n.style,{position:"absolute",top:"-1000px",background:"red",filter:"alpha(opacity=0)",opacity:0});document.body.appendChild(n);a.addEvent(k,"dragenter",function(s){var r,t;r=document.getElementById(l);t=a.getPos(r);a.extend(document.getElementById(p).style,{top:t.y+"px",left:t.x+"px",width:r.offsetWidth+"px",height:r.offsetHeight+"px"})});q(p,o)}else{q(l)}}a.addEvent(document.getElementById(d.browse_button),"click",function(w){var u=[],s,r,v=d.filters,t;w.preventDefault();no_type_restriction:for(s=0;s<v.length;s++){t=v[s].extensions.split(",");for(r=0;r<t.length;r++){if(t[r]==="*"){u=[];break no_type_restriction}u.push(a.mimeTypes[t[r]])}}e.FileBrowse.OpenBrowseDialog({mimeTypes:u},function(x){if(x.success){f(x.value)}})});k=n=null});g.bind("UploadFile",function(n,k){var m=h[k.id],s={},l=n.settings.chunk_size,o,p=[];function r(t,v){var u;if(k.status==a.FAILED){return}s.name=k.target_name||k.name;if(l){s.chunk=""+t;s.chunks=""+v}u=p.shift();e.Uploader.upload({url:n.settings.url,files:{file:u},cookies:document.cookies,postvars:a.extend(s,n.settings.multipart_params),progressCallback:function(y){var x,w=0;o[t]=parseInt(y.filePercent*u.size/100,10);for(x=0;x<o.length;x++){w+=o[x]}k.loaded=w;n.trigger("UploadProgress",k)}},function(x){var w,y;if(x.success){w=x.value.statusCode;if(l){n.trigger("ChunkUploaded",k,{chunk:t,chunks:v,response:x.value.body,status:w})}if(p.length>0){r(++t,v)}else{k.status=a.DONE;n.trigger("FileUploaded",k,{response:x.value.body,status:w});if(w>=400){n.trigger("Error",{code:a.HTTP_ERROR,message:a.translate("HTTP Error."),file:k,status:w})}}}else{n.trigger("Error",{code:a.GENERIC_ERROR,message:a.translate("Generic Error."),file:k,details:x.error})}})}function q(t){k.size=t.size;if(l){e.FileAccess.chunk({file:t,chunkSize:l},function(w){if(w.success){var x=w.value,u=x.length;o=Array(u);for(var v=0;v<u;v++){o[v]=0;p.push(x[v])}r(0,u)}})}else{o=Array(1);p.push(t);r(0,1)}}if(c&&/\.(png|jpg|jpeg)$/i.test(k.name)){BrowserPlus.ImageAlter.transform({file:m,quality:c.quality||90,actions:[{scale:{maxwidth:c.width,maxheight:c.height}}]},function(t){if(t.success){q(t.value.file)}})}else{q(m)}});j({success:true})}if(e){e.init(function(l){var k=[{service:"Uploader",version:"3"},{service:"DragAndDrop",version:"1"},{service:"FileBrowse",version:"1"},{service:"FileAccess",version:"2"}];if(c){k.push({service:"ImageAlter",version:"4"})}if(l.success){e.require({services:k},function(m){if(m.success){b()}else{j()}})}else{j()}})}else{j()}}})})(plupload);(function(h,k,j,e){var c={},g;function m(o,p){var n;if("FileReader" in h){n=new FileReader();n.readAsDataURL(o);n.onload=function(){p(n.result)}}else{return p(o.getAsDataURL())}}function l(o,p){var n;if("FileReader" in h){n=new FileReader();n.readAsBinaryString(o);n.onload=function(){p(n.result)}}else{return p(o.getAsBinary())}}function d(r,p,n,v){var q,o,u,s,t=this;m(c[r.id],function(w){q=k.createElement("canvas");q.style.display="none";k.body.appendChild(q);o=q.getContext("2d");u=new Image();u.onerror=u.onabort=function(){v({success:false})};u.onload=function(){var B,x,z,y,A;if(!p.width){p.width=u.width}if(!p.height){p.height=u.height}s=Math.min(p.width/u.width,p.height/u.height);if(s<1||(s===1&&n==="image/jpeg")){B=Math.round(u.width*s);x=Math.round(u.height*s);q.width=B;q.height=x;o.drawImage(u,0,0,B,x);if(n==="image/jpeg"){y=new f(atob(w.substring(w.indexOf("base64,")+7)));if(y.headers&&y.headers.length){A=new a();if(A.init(y.get("exif")[0])){A.setExif("PixelXDimension",B);A.setExif("PixelYDimension",x);y.set("exif",A.getBinary());if(t.hasEventListener("ExifData")){t.trigger("ExifData",r,A.EXIF())}if(t.hasEventListener("GpsData")){t.trigger("GpsData",r,A.GPS())}}}if(p.quality){try{w=q.toDataURL(n,p.quality/100)}catch(C){w=q.toDataURL(n)}}}else{w=q.toDataURL(n)}w=w.substring(w.indexOf("base64,")+7);w=atob(w);if(y&&y.headers&&y.headers.length){w=y.restore(w);y.purge()}q.parentNode.removeChild(q);v({success:true,data:w})}else{v({success:false})}};u.src=w})}j.runtimes.Html5=j.addRuntime("html5",{getFeatures:function(){var t,o,s,r,q,n,p;p=(function(){var y=navigator,x=y.userAgent,z=y.vendor,v,u,w;v=/WebKit/.test(x);w=v&&z.indexOf("Apple")!==-1;u=h.opera&&h.opera.buildNumber;return{ie:!v&&!u&&(/MSIE/gi).test(x)&&(/Explorer/gi).test(y.appName),webkit:v,gecko:!v&&/Gecko/.test(x),safari:w,safariwin:w&&navigator.platform.indexOf("Win")!==-1,opera:!!u}}());o=s=q=n=false;if(h.XMLHttpRequest){t=new XMLHttpRequest();s=!!t.upload;o=!!(t.sendAsBinary||t.upload)}if(o){r=!!(t.sendAsBinary||(h.Uint8Array&&h.ArrayBuffer));q=!!(File&&(File.prototype.getAsDataURL||h.FileReader)&&r);n=!!(File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice))}g=p.safariwin;return{html5:o,dragdrop:(function(){var u=k.createElement("div");return("draggable" in u)||("ondragstart" in u&&"ondrop" in u)}()),jpgresize:q,pngresize:q,multipart:q||!!h.FileReader||!!h.FormData,canSendBinary:r,cantSendBlobInFormData:!!(p.gecko&&h.FormData&&h.FileReader&&!FileReader.prototype.readAsArrayBuffer),progress:s,chunks:n,triggerDialog:(p.gecko&&h.FormData||p.webkit)}},init:function(p,q){var n;function o(v){var t,s,u=[],w,r={};for(s=0;s<v.length;s++){t=v[s];if(r[t.name]){continue}r[t.name]=true;w=j.guid();c[w]=t;u.push(new j.File(w,t.fileName||t.name,t.fileSize||t.size))}if(u.length){p.trigger("FilesAdded",u)}}n=this.getFeatures();if(!n.html5){q({success:false});return}p.bind("Init",function(v){var F,E,B=[],u,C,s=v.settings.filters,t,A,r=k.body,D;F=k.createElement("div");F.id=v.id+"_html5_container";j.extend(F.style,{position:"absolute",background:p.settings.shim_bgcolor||"transparent",width:"100px",height:"100px",overflow:"hidden",zIndex:99999,opacity:p.settings.shim_bgcolor?"":0});F.className="plupload html5";if(p.settings.container){r=k.getElementById(p.settings.container);if(j.getStyle(r,"position")==="static"){r.style.position="relative"}}r.appendChild(F);no_type_restriction:for(u=0;u<s.length;u++){t=s[u].extensions.split(/,/);for(C=0;C<t.length;C++){if(t[C]==="*"){B=[];break no_type_restriction}A=j.mimeTypes[t[C]];if(A){B.push(A)}}}F.innerHTML='<input id="'+p.id+'_html5" style="font-size:999px" type="file" accept="'+B.join(",")+'" '+(p.settings.multi_selection?'multiple="multiple"':"")+" />";F.scrollTop=100;D=k.getElementById(p.id+"_html5");if(v.features.triggerDialog){j.extend(D.style,{position:"absolute",width:"100%",height:"100%"})}else{j.extend(D.style,{cssFloat:"right",styleFloat:"right"})}D.onchange=function(){o(this.files);this.value=""};E=k.getElementById(v.settings.browse_button);if(E){var x=v.settings.browse_button_hover,z=v.settings.browse_button_active,w=v.features.triggerDialog?E:F;if(x){j.addEvent(w,"mouseover",function(){j.addClass(E,x)},v.id);j.addEvent(w,"mouseout",function(){j.removeClass(E,x)},v.id)}if(z){j.addEvent(w,"mousedown",function(){j.addClass(E,z)},v.id);j.addEvent(k.body,"mouseup",function(){j.removeClass(E,z)},v.id)}if(v.features.triggerDialog){j.addEvent(E,"click",function(y){k.getElementById(v.id+"_html5").click();y.preventDefault()},v.id)}}});p.bind("PostInit",function(){var r=k.getElementById(p.settings.drop_element);if(r){if(g){j.addEvent(r,"dragenter",function(v){var u,s,t;u=k.getElementById(p.id+"_drop");if(!u){u=k.createElement("input");u.setAttribute("type","file");u.setAttribute("id",p.id+"_drop");u.setAttribute("multiple","multiple");j.addEvent(u,"change",function(){o(this.files);j.removeEvent(u,"change",p.id);u.parentNode.removeChild(u)},p.id);r.appendChild(u)}s=j.getPos(r,k.getElementById(p.settings.container));t=j.getSize(r);if(j.getStyle(r,"position")==="static"){j.extend(r.style,{position:"relative"})}j.extend(u.style,{position:"absolute",display:"block",top:0,left:0,width:t.w+"px",height:t.h+"px",opacity:0})},p.id);return}j.addEvent(r,"dragover",function(s){s.preventDefault()},p.id);j.addEvent(r,"drop",function(t){var s=t.dataTransfer;if(s&&s.files){o(s.files)}t.preventDefault()},p.id)}});p.bind("Refresh",function(r){var s,t,u,w,v;s=k.getElementById(p.settings.browse_button);if(s){t=j.getPos(s,k.getElementById(r.settings.container));u=j.getSize(s);w=k.getElementById(p.id+"_html5_container");j.extend(w.style,{top:t.y+"px",left:t.x+"px",width:u.w+"px",height:u.h+"px"});if(p.features.triggerDialog){if(j.getStyle(s,"position")==="static"){j.extend(s.style,{position:"relative"})}v=parseInt(j.getStyle(s,"z-index"),10);if(isNaN(v)){v=0}j.extend(s.style,{zIndex:v});j.extend(w.style,{zIndex:v-1})}}});p.bind("UploadFile",function(r,t){var u=r.settings,x,s;function w(z,C,y){var A;if(File.prototype.slice){try{z.slice();return z.slice(C,y)}catch(B){return z.slice(C,y-C)}}else{if(A=File.prototype.webkitSlice||File.prototype.mozSlice){return A.call(z,C,y)}else{return null}}}function v(z){var C=0,B=0,y=("FileReader" in h)?new FileReader:null,D=typeof(z)==="string";function A(){var I,M,K,L,H,J,F,E=r.settings.url;function G(W){var T=0,U=new XMLHttpRequest,X=U.upload,N="----pluploadboundary"+j.guid(),O,P="--",V="\r\n",R="";if(X){X.onprogress=function(Y){t.loaded=Math.min(t.size,B+Y.loaded-T);r.trigger("UploadProgress",t)}}U.onreadystatechange=function(){var Y,aa;if(U.readyState==4){try{Y=U.status}catch(Z){Y=0}if(Y>=400){r.trigger("Error",{code:j.HTTP_ERROR,message:j.translate("HTTP Error."),file:t,status:Y})}else{if(K){aa={chunk:C,chunks:K,response:U.responseText,status:Y};r.trigger("ChunkUploaded",t,aa);B+=J;if(aa.cancelled){t.status=j.FAILED;return}t.loaded=Math.min(t.size,(C+1)*H)}else{t.loaded=t.size}r.trigger("UploadProgress",t);W=I=O=R=null;if(!K||++C>=K){t.status=j.DONE;r.trigger("FileUploaded",t,{response:U.responseText,status:Y})}else{A()}}U=null}};if(r.settings.multipart&&n.multipart){L.name=t.target_name||t.name;U.open("post",E,true);j.each(r.settings.headers,function(Z,Y){U.setRequestHeader(Y,Z)});if(!D&&!!h.FormData){O=new FormData();j.each(j.extend(L,r.settings.multipart_params),function(Z,Y){O.append(Y,Z)});O.append(r.settings.file_data_name,W);U.send(O);return}if(D){U.setRequestHeader("Content-Type","multipart/form-data; boundary="+N);j.each(j.extend(L,r.settings.multipart_params),function(Z,Y){R+=P+N+V+'Content-Disposition: form-data; name="'+Y+'"'+V+V;R+=unescape(encodeURIComponent(Z))+V});F=j.mimeTypes[t.name.replace(/^.+\.([^.]+)/,"$1").toLowerCase()]||"application/octet-stream";R+=P+N+V+'Content-Disposition: form-data; name="'+r.settings.file_data_name+'"; filename="'+unescape(encodeURIComponent(t.name))+'"'+V+"Content-Type: "+F+V+V+W+V+P+N+P+V;T=R.length-W.length;W=R;if(U.sendAsBinary){U.sendAsBinary(W)}else{if(n.canSendBinary){var S=new Uint8Array(W.length);for(var Q=0;Q<W.length;Q++){S[Q]=(W.charCodeAt(Q)&255)}U.send(S.buffer)}}return}}E=j.buildUrl(r.settings.url,j.extend(L,r.settings.multipart_params));U.open("post",E,true);U.setRequestHeader("Content-Type","application/octet-stream");j.each(r.settings.headers,function(Z,Y){U.setRequestHeader(Y,Z)});U.send(W)}if(t.status==j.DONE||t.status==j.FAILED||r.state==j.STOPPED){return}L={name:t.target_name||t.name};if(u.chunk_size&&t.size>u.chunk_size&&(n.chunks||typeof(z)=="string")){H=u.chunk_size;K=Math.ceil(t.size/H);J=Math.min(H,t.size-(C*H));if(typeof(z)=="string"){I=z.substring(C*H,C*H+J)}else{I=w(z,C*H,C*H+J)}L.chunk=C;L.chunks=K}else{J=t.size;I=z}if(y&&n.cantSendBlobInFormData&&n.chunks&&r.settings.chunk_size){y.onload=function(){D=true;G(y.result)};y.readAsBinaryString(I)}else{G(I)}}A()}x=c[t.id];if(n.jpgresize&&r.settings.resize&&/\.(png|jpg|jpeg)$/i.test(t.name)){d.call(r,t,r.settings.resize,/\.png$/i.test(t.name)?"image/png":"image/jpeg",function(y){if(y.success){t.size=y.data.length;v(y.data)}else{v(x)}})}else{if(!n.chunks&&n.jpgresize){l(x,v)}else{v(x)}}});p.bind("Destroy",function(r){var t,u,s=k.body,v={inputContainer:r.id+"_html5_container",inputFile:r.id+"_html5",browseButton:r.settings.browse_button,dropElm:r.settings.drop_element};for(t in v){u=k.getElementById(v[t]);if(u){j.removeAllEvents(u,r.id)}}j.removeAllEvents(k.body,r.id);if(r.settings.container){s=k.getElementById(r.settings.container)}s.removeChild(k.getElementById(v.inputContainer))});q({success:true})}});function b(){var q=false,o;function r(t,v){var s=q?0:-8*(v-1),w=0,u;for(u=0;u<v;u++){w|=(o.charCodeAt(t+u)<<Math.abs(s+u*8))}return w}function n(u,s,t){var t=arguments.length===3?t:o.length-s-1;o=o.substr(0,s)+u+o.substr(t+s)}function p(t,u,w){var x="",s=q?0:-8*(w-1),v;for(v=0;v<w;v++){x+=String.fromCharCode((u>>Math.abs(s+v*8))&255)}n(x,t,w)}return{II:function(s){if(s===e){return q}else{q=s}},init:function(s){q=false;o=s},SEGMENT:function(s,u,t){switch(arguments.length){case 1:return o.substr(s,o.length-s-1);case 2:return o.substr(s,u);case 3:n(t,s,u);break;default:return o}},BYTE:function(s){return r(s,1)},SHORT:function(s){return r(s,2)},LONG:function(s,t){if(t===e){return r(s,4)}else{p(s,t,4)}},SLONG:function(s){var t=r(s,4);return(t>2147483647?t-4294967296:t)},STRING:function(s,t){var u="";for(t+=s;s<t;s++){u+=String.fromCharCode(r(s,1))}return u}}}function f(s){var u={65505:{app:"EXIF",name:"APP1",signature:"Exif\0"},65506:{app:"ICC",name:"APP2",signature:"ICC_PROFILE\0"},65517:{app:"IPTC",name:"APP13",signature:"Photoshop 3.0\0"}},t=[],r,n,p=e,q=0,o;r=new b();r.init(s);if(r.SHORT(0)!==65496){return}n=2;o=Math.min(1048576,s.length);while(n<=o){p=r.SHORT(n);if(p>=65488&&p<=65495){n+=2;continue}if(p===65498||p===65497){break}q=r.SHORT(n+2)+2;if(u[p]&&r.STRING(n+4,u[p].signature.length)===u[p].signature){t.push({hex:p,app:u[p].app.toUpperCase(),name:u[p].name.toUpperCase(),start:n,length:q,segment:r.SEGMENT(n,q)})}n+=q}r.init(null);return{headers:t,restore:function(y){r.init(y);var w=new f(y);if(!w.headers){return false}for(var x=w.headers.length;x>0;x--){var z=w.headers[x-1];r.SEGMENT(z.start,z.length,"")}w.purge();n=r.SHORT(2)==65504?4+r.SHORT(4):2;for(var x=0,v=t.length;x<v;x++){r.SEGMENT(n,0,t[x].segment);n+=t[x].length}return r.SEGMENT()},get:function(x){var y=[];for(var w=0,v=t.length;w<v;w++){if(t[w].app===x.toUpperCase()){y.push(t[w].segment)}}return y},set:function(y,x){var z=[];if(typeof(x)==="string"){z.push(x)}else{z=x}for(var w=ii=0,v=t.length;w<v;w++){if(t[w].app===y.toUpperCase()){t[w].segment=z[ii];t[w].length=z[ii].length;ii++}if(ii>=z.length){break}}},purge:function(){t=[];r.init(null)}}}function a(){var q,n,o={},t;q=new b();n={tiff:{274:"Orientation",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer"},exif:{36864:"ExifVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",36867:"DateTimeOriginal",33434:"ExposureTime",33437:"FNumber",34855:"ISOSpeedRatings",37377:"ShutterSpeedValue",37378:"ApertureValue",37383:"MeteringMode",37384:"LightSource",37385:"Flash",41986:"ExposureMode",41987:"WhiteBalance",41990:"SceneCaptureType",41988:"DigitalZoomRatio",41992:"Contrast",41993:"Saturation",41994:"Sharpness"},gps:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude"}};t={ColorSpace:{1:"sRGB",0:"Uncalibrated"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{1:"Daylight",2:"Fliorescent",3:"Tungsten",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 -5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire.",1:"Flash fired.",5:"Strobe return light not detected.",7:"Strobe return light detected.",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},ExposureMode:{0:"Auto exposure",1:"Manual exposure",2:"Auto bracket"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},GPSLatitudeRef:{N:"North latitude",S:"South latitude"},GPSLongitudeRef:{E:"East longitude",W:"West longitude"}};function p(u,C){var w=q.SHORT(u),z,F,G,B,A,v,x,D,E=[],y={};for(z=0;z<w;z++){x=v=u+12*z+2;G=C[q.SHORT(x)];if(G===e){continue}B=q.SHORT(x+=2);A=q.LONG(x+=2);x+=4;E=[];switch(B){case 1:case 7:if(A>4){x=q.LONG(x)+o.tiffHeader}for(F=0;F<A;F++){E[F]=q.BYTE(x+F)}break;case 2:if(A>4){x=q.LONG(x)+o.tiffHeader}y[G]=q.STRING(x,A-1);continue;case 3:if(A>2){x=q.LONG(x)+o.tiffHeader}for(F=0;F<A;F++){E[F]=q.SHORT(x+F*2)}break;case 4:if(A>1){x=q.LONG(x)+o.tiffHeader}for(F=0;F<A;F++){E[F]=q.LONG(x+F*4)}break;case 5:x=q.LONG(x)+o.tiffHeader;for(F=0;F<A;F++){E[F]=q.LONG(x+F*4)/q.LONG(x+F*4+4)}break;case 9:x=q.LONG(x)+o.tiffHeader;for(F=0;F<A;F++){E[F]=q.SLONG(x+F*4)}break;case 10:x=q.LONG(x)+o.tiffHeader;for(F=0;F<A;F++){E[F]=q.SLONG(x+F*4)/q.SLONG(x+F*4+4)}break;default:continue}D=(A==1?E[0]:E);if(t.hasOwnProperty(G)&&typeof D!="object"){y[G]=t[G][D]}else{y[G]=D}}return y}function s(){var v=e,u=o.tiffHeader;q.II(q.SHORT(u)==18761);if(q.SHORT(u+=2)!==42){return false}o.IFD0=o.tiffHeader+q.LONG(u+=2);v=p(o.IFD0,n.tiff);o.exifIFD=("ExifIFDPointer" in v?o.tiffHeader+v.ExifIFDPointer:e);o.gpsIFD=("GPSInfoIFDPointer" in v?o.tiffHeader+v.GPSInfoIFDPointer:e);return true}function r(w,u,z){var B,y,x,A=0;if(typeof(u)==="string"){var v=n[w.toLowerCase()];for(hex in v){if(v[hex]===u){u=hex;break}}}B=o[w.toLowerCase()+"IFD"];y=q.SHORT(B);for(i=0;i<y;i++){x=B+12*i+2;if(q.SHORT(x)==u){A=x+8;break}}if(!A){return false}q.LONG(A,z);return true}return{init:function(u){o={tiffHeader:10};if(u===e||!u.length){return false}q.init(u);if(q.SHORT(0)===65505&&q.STRING(4,5).toUpperCase()==="EXIF\0"){return s()}return false},EXIF:function(){var u;u=p(o.exifIFD,n.exif);if(u.ExifVersion){u.ExifVersion=String.fromCharCode(u.ExifVersion[0],u.ExifVersion[1],u.ExifVersion[2],u.ExifVersion[3])}return u},GPS:function(){var u;u=p(o.gpsIFD,n.gps);if(u.GPSVersionID){u.GPSVersionID=u.GPSVersionID.join(".")}return u},setExif:function(u,v){if(u!=="PixelXDimension"&&u!=="PixelYDimension"){return false}return r("exif",u,v)},getBinary:function(){return q.SEGMENT()}}}})(window,document,plupload);(function(d,a,b,c){function e(f){return a.getElementById(f)}b.runtimes.Html4=b.addRuntime("html4",{getFeatures:function(){var f=(function(){var l=navigator,k=l.userAgent,m=l.vendor,h,g,j;h=/WebKit/.test(k);j=h&&m.indexOf("Apple")!==-1;g=d.opera&&d.opera.buildNumber;return{ie:!h&&!g&&(/MSIE/gi).test(k)&&(/Explorer/gi).test(l.appName),webkit:h,gecko:!h&&/Gecko/.test(k),safari:j,safariwin:j&&navigator.platform.indexOf("Win")!==-1,opera:!!g}}());return{multipart:true,triggerDialog:(f.gecko&&d.FormData||f.webkit)}},init:function(f,g){f.bind("Init",function(p){var j=a.body,n,h="javascript",k,x,q,z=[],r=/MSIE/.test(navigator.userAgent),t=[],m=p.settings.filters,o,l,s,w;no_type_restriction:for(o=0;o<m.length;o++){l=m[o].extensions.split(/,/);for(w=0;w<l.length;w++){if(l[w]==="*"){t=[];break no_type_restriction}s=b.mimeTypes[l[w]];if(s){t.push(s)}}}t=t.join(",");function v(){var C,A,y,B;q=b.guid();z.push(q);C=a.createElement("form");C.setAttribute("id","form_"+q);C.setAttribute("method","post");C.setAttribute("enctype","multipart/form-data");C.setAttribute("encoding","multipart/form-data");C.setAttribute("target",p.id+"_iframe");C.style.position="absolute";A=a.createElement("input");A.setAttribute("id","input_"+q);A.setAttribute("type","file");A.setAttribute("accept",t);A.setAttribute("size",1);B=e(p.settings.browse_button);if(p.features.triggerDialog&&B){b.addEvent(e(p.settings.browse_button),"click",function(D){A.click();D.preventDefault()},p.id)}b.extend(A.style,{width:"100%",height:"100%",opacity:0,fontSize:"999px"});b.extend(C.style,{overflow:"hidden"});y=p.settings.shim_bgcolor;if(y){C.style.background=y}if(r){b.extend(A.style,{filter:"alpha(opacity=0)"})}b.addEvent(A,"change",function(G){var E=G.target,D,F=[],H;if(E.value){e("form_"+q).style.top=-1048575+"px";D=E.value.replace(/\\/g,"/");D=D.substring(D.length,D.lastIndexOf("/")+1);F.push(new b.File(q,D));if(!p.features.triggerDialog){b.removeAllEvents(C,p.id)}else{b.removeEvent(B,"click",p.id)}b.removeEvent(A,"change",p.id);v();if(F.length){f.trigger("FilesAdded",F)}}},p.id);C.appendChild(A);j.appendChild(C);p.refresh()}function u(){var y=a.createElement("div");y.innerHTML='<iframe id="'+p.id+'_iframe" name="'+p.id+'_iframe" src="'+h+':&quot;&quot;" style="display:none"></iframe>';n=y.firstChild;j.appendChild(n);b.addEvent(n,"load",function(D){var E=D.target,C,A;if(!k){return}try{C=E.contentWindow.document||E.contentDocument||d.frames[E.id].document}catch(B){p.trigger("Error",{code:b.SECURITY_ERROR,message:b.translate("Security error."),file:k});return}A=C.documentElement.innerText||C.documentElement.textContent;if(A){k.status=b.DONE;k.loaded=1025;k.percent=100;p.trigger("UploadProgress",k);p.trigger("FileUploaded",k,{response:A})}},p.id)}if(p.settings.container){j=e(p.settings.container);if(b.getStyle(j,"position")==="static"){j.style.position="relative"}}p.bind("UploadFile",function(y,B){var C,A;if(B.status==b.DONE||B.status==b.FAILED||y.state==b.STOPPED){return}C=e("form_"+B.id);A=e("input_"+B.id);A.setAttribute("name",y.settings.file_data_name);C.setAttribute("action",y.settings.url);b.each(b.extend({name:B.target_name||B.name},y.settings.multipart_params),function(F,D){var E=a.createElement("input");b.extend(E,{type:"hidden",name:D,value:F});C.insertBefore(E,C.firstChild)});k=B;e("form_"+q).style.top=-1048575+"px";C.submit();C.parentNode.removeChild(C)});p.bind("FileUploaded",function(y){y.refresh()});p.bind("StateChanged",function(y){if(y.state==b.STARTED){u()}if(y.state==b.STOPPED){d.setTimeout(function(){b.removeEvent(n,"load",y.id);n.parentNode.removeChild(n)},0)}});p.bind("Refresh",function(A){var G,B,C,D,y,H,I,F,E;G=e(A.settings.browse_button);if(G){y=b.getPos(G,e(A.settings.container));H=b.getSize(G);I=e("form_"+q);F=e("input_"+q);b.extend(I.style,{top:y.y+"px",left:y.x+"px",width:H.w+"px",height:H.h+"px"});if(A.features.triggerDialog){if(b.getStyle(G,"position")==="static"){b.extend(G.style,{position:"relative"})}E=parseInt(G.style.zIndex,10);if(isNaN(E)){E=0}b.extend(G.style,{zIndex:E});b.extend(I.style,{zIndex:E-1})}C=A.settings.browse_button_hover;D=A.settings.browse_button_active;B=A.features.triggerDialog?G:I;if(C){b.addEvent(B,"mouseover",function(){b.addClass(G,C)},A.id);b.addEvent(B,"mouseout",function(){b.removeClass(G,C)},A.id)}if(D){b.addEvent(B,"mousedown",function(){b.addClass(G,D)},A.id);b.addEvent(a.body,"mouseup",function(){b.removeClass(G,D)},A.id)}}});f.bind("FilesRemoved",function(y,B){var A,C;for(A=0;A<B.length;A++){C=e("form_"+B[A].id);if(C){C.parentNode.removeChild(C)}}});f.bind("Destroy",function(y){var A,B,C,D={inputContainer:"form_"+q,inputFile:"input_"+q,browseButton:y.settings.browse_button};for(A in D){B=e(D[A]);if(B){b.removeAllEvents(B,y.id)}}b.removeAllEvents(a.body,y.id);b.each(z,function(F,E){C=e("form_"+F);if(C){j.removeChild(C)}})});v()});g({success:true})}})})(window,document,plupload);
static/js/plupload/plupload.silverlight.xap ADDED
Binary file
static/js/plupload/wplupload.js ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function(window, $, undefined) {
2
+
3
+ var _parent = window.dialogArguments || opener || parent || top;
4
+
5
+ $.fn.wplupload = function($options) {
6
+ var $up, $defaults = {
7
+ runtimes : 'gears,browserplus,html5,flash,silverlight,html4',
8
+ browse_button_hover: 'hover',
9
+ browse_button_active: 'active'
10
+ };
11
+
12
+ $options = $.extend({}, $defaults, $options);
13
+
14
+ return this.each(function() {
15
+ var $this = $(this);
16
+
17
+ $up = new plupload.Uploader($options);
18
+
19
+
20
+ /*$up.bind('Init', function(up) {
21
+ var dropElm = $('#' + up.settings.drop_element);
22
+ if (dropElm.length && up.features.dragdrop) {
23
+ dropElm.bind('dragenter', function() {
24
+ $(this).css('border', '3px dashed #cccccc');
25
+ });
26
+ dropElm.bind('dragout drop', function() {
27
+ $(this).css('border', 'none');
28
+ });
29
+ }
30
+ });*/
31
+
32
+ $up.bind('FilesAdded', function(up, files) {
33
+ $.each(files, function(i, file) {
34
+ // Create a progress bar containing the filename
35
+ $('#basic').find('.submit-buttons').hide();
36
+ $('#progress').css({'visibility':'visible'});
37
+ })
38
+ });
39
+
40
+ $up.init();
41
+
42
+ $up.bind('Error', function(up, err) {
43
+ $('#upload_process').html(err.message);
44
+ });
45
+
46
+ $up.bind('FilesAdded', function(up, files) {
47
+ // Disable submit and enable cancel
48
+
49
+ $('#cancel-upload').removeAttr('disabled');
50
+
51
+ $up.start();
52
+ });
53
+
54
+ $up.bind('UploadFile', function(up, file, r) {
55
+
56
+ });
57
+
58
+ $up.bind('UploadProgress', function(up, file) {
59
+ // Lengthen the progress bar
60
+ $('#progressbar').html('Uploading data feed ... ' + file.percent + '%');
61
+ $('#upload_process').progressbar({value:file.percent});
62
+
63
+ });
64
+
65
+
66
+ $up.bind('FileUploaded', function(up, file, r) {
67
+ var fetch = typeof(shortform) == 'undefined' ? 1 : 2;
68
+
69
+ r = _parseJSON(r.response);
70
+
71
+ $('#filepath').val(r.name);
72
+
73
+ $('#progressbar').html('Upload Complete - ' + file.name + ' (' + ( (file.size / (1024*1024) >= 1) ? (file.size / (1024*1024)).toFixed(2) + 'mb' : (file.size / (1024)).toFixed(2) + 'kb') + ')');
74
+
75
+ $('#basic').find('.submit-buttons').show();
76
+
77
+ if (r.OK) {
78
+
79
+ }
80
+ });
81
+
82
+ $up.bind('UploadComplete', function(up) {
83
+ $('#cancel-upload').attr('disabled', 'disabled');
84
+ });
85
+
86
+ $('#cancel-upload').click(function() {
87
+ var i, file;
88
+
89
+ $up.stop();
90
+
91
+ i = $up.files.length;
92
+ for (i = $up.files.length - 1; i >= 0; i--) {
93
+ file = $up.files[i];
94
+ if ($.inArray(file.status, [plupload.QUEUED, plupload.UPLOADING]) !== -1) {
95
+ $up.removeFile($up.getFile(file.id));
96
+ }
97
+ }
98
+
99
+ $('#cancel-upload').attr('disabled', 'disabled');
100
+
101
+ });
102
+
103
+ });
104
+ };
105
+
106
+ function _parseJSON(r) {
107
+ var obj;
108
+ try {
109
+ obj = $.parseJSON(r);
110
+ } catch (e) {
111
+ obj = { OK : 0 };
112
+ }
113
+ return obj;
114
+ }
115
+
116
+ }(window, jQuery));
static/js/pmxi.js CHANGED
@@ -2,13 +2,6 @@
2
  * plugin javascript
3
  */
4
  (function($){$(function () {
5
-
6
- $('#dismiss').click(function(){
7
-
8
- $(this).parents('div.error:first').slideUp();
9
- $.post('admin.php?page=pmxi-admin-settings&action=dismiss', {dismiss: true}, function (data) {
10
-
11
- }, 'html');
12
- })
13
 
14
  });})(jQuery);
2
  * plugin javascript
3
  */
4
  (function($){$(function () {
5
+
 
 
 
 
 
 
 
6
 
7
  });})(jQuery);
views/admin/import/element_after.php CHANGED
@@ -1,39 +1,58 @@
1
  <form class="choose-elements no-enter-submit" method="post">
 
 
 
 
 
 
 
 
 
2
  <table class="layout">
3
  <tr>
4
  <td class="left">
5
- <h2><?php _e('Import XML/CSV - Step 2: Element Selector', 'pmxi_plugin') ?><br/><span class="taglines"><?php _e('select which elements you wish to import', 'pmxi_plugin') ?></span></h2>
6
- <hr />
7
-
8
-
9
- <p>
10
- <?php _e('<b>Choose elements for import by double clicking on corresponding opening tag. Recurring sibling elements, if present, are selected automatically.</b>', 'pmxi_plugin') ?>
11
- </p>
12
-
13
- <div class="ajax-console">
14
- <?php if ($this->errors->get_error_codes()): ?>
15
- <?php $this->error() ?>
16
- <?php endif ?>
17
- </div>
18
-
19
- <div class="xml">
20
- <?php $this->render_xml_element($dom->documentElement) ?>
21
- </div>
22
  </td>
23
  <td class="right">
24
- <p>
25
- <?php _e('Advaned users: use <a href="http://www.w3schools.com/xpath/default.asp" target="_blank">XPath syntax.</a> If you are unable to figure out what XPath you need to match certain elements you are trying to import, contact <a href="http://www.wpallimport.com/support" target="_blank">support</a> and include your XML file. We will get back to you with the XPath.', 'pmxi_plugin') ?>
26
- </p>
27
- <p>
28
- <?php _e('Tip: change [1], [2], [3], etc. to [*] to match more elements.', 'pmxi_plugin') ?>
29
- </p>
30
- <div><input type="text" name="xpath" value="<?php echo esc_attr($post['xpath']) ?>" /></div>
31
- <p class="submit-buttons">
32
- <a href="<?php echo $this->baseUrl ?>" class="button back">Back</a>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  &nbsp;
34
  <input type="hidden" name="is_submitted" value="1" />
35
  <?php wp_nonce_field('choose-elements', '_wpnonce_choose-elements') ?>
36
- <input type="submit" class="button-primary" value="<?php _e('Continue', 'pmxi_plugin') ?> &gt;&gt;" />
37
  </p>
38
  </td>
39
  </tr>
1
  <form class="choose-elements no-enter-submit" method="post">
2
+ <h2><?php _e('Import XML/CSV - Step 2: Select Elements', 'pmxi_plugin') ?></h2>
3
+
4
+ <h3><?php _e('<b>Double-click on an element below to select it and its siblings.</b>', 'pmxi_plugin') ?></h3>
5
+
6
+ <div class="ajax-console">
7
+ <?php if ($this->errors->get_error_codes()): ?>
8
+ <?php $this->error() ?>
9
+ <?php endif ?>
10
+ </div>
11
  <table class="layout">
12
  <tr>
13
  <td class="left">
14
+ <fieldset class="widefat">
15
+ <legend>Current XML tree</legend>
16
+ <div class="action_buttons">
17
+ <a href="javascript:void(0);" id="prev_element" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only large_button" style="float:left;">&lang;&lang;</a>
18
+ <a href="javascript:void(0);" id="next_element" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only large_button" style="float:left; margin-right:15px;">&rang;&rang;</a>
19
+ <div style="float:left;">
20
+ <span style="font-size:18px; padding-top:15px; float:left; margin-right:10px;">Go to: </span><input type="text" id="goto_element" value="1"/>
21
+ </div>
22
+ </div>
23
+ <div class="xml" style="min-height:400px;">
24
+ <?php //$this->render_xml_element($dom->documentElement) ?>
25
+ </div>
26
+ </fieldset>
 
 
 
 
27
  </td>
28
  <td class="right">
29
+ <fieldset class="widefat">
30
+ <legend>Advanced</legend>
31
+ <p>Current XPath:</p>
32
+ <div>
33
+ <input type="text" name="xpath" value="<?php echo esc_attr($post['xpath']) ?>" style="max-width:none;" />
34
+ <input type="hidden" id="root_element" name="root_element" value="<?php echo $_SESSION['pmxi_import']['source']['root_element']; ?>"/>
35
+ <?php
36
+ if (!empty($elements_cloud)){
37
+ ?>
38
+ &nbsp; <br/><label>What element are you looking for?</label>&nbsp; <br/>
39
+ <?php
40
+ $root_elements = array();
41
+ foreach ($elements_cloud as $tag => $count)
42
+ $root_elements[] = '<a href="javascript:void(0);" rel="'. $tag .'" class="change_root_element">' . $tag . '</a>';
43
+ echo implode(', ', $root_elements);
44
+ }
45
+ ?>
46
+ &nbsp; <br/><br/>or <a href="javascript:void(0);" rel="<?php echo esc_attr($post['xpath']) ?>" root="<?php echo $_SESSION['pmxi_import']['source']['root_element']; ?>" id="get_default_xpath">get default xPath</a>
47
+ </div> <br><br>
48
+ <a href="http://www.w3schools.com/xpath/default.asp" target='_blank'>XPath Tutorial</a> - For further help, <a href="http://www.wpallimport.com/support" target='_blank'>contact us</a>.
49
+ </fieldset>
50
+ <p class="submit-buttons" style="text-align:right;">
51
+ <a href="<?php echo $this->baseUrl ?>" class="back">Back</a>
52
  &nbsp;
53
  <input type="hidden" name="is_submitted" value="1" />
54
  <?php wp_nonce_field('choose-elements', '_wpnonce_choose-elements') ?>
55
+ <input type="submit" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only large_button" value="<?php _e('Next', 'pmxi_plugin') ?>" />
56
  </p>
57
  </td>
58
  </tr>
views/admin/import/evaluate.php CHANGED
@@ -1,15 +1,20 @@
1
  <div class="updated">
2
- <p><?php printf(__('Specified XPath matches <strong>%s</strong> %s.', 'pmxi_plugin'), $node_list_count, _n('element', 'elements', $node_list_count, 'pmxi_plugin')) ?></p>
3
- <?php if (PMXI_Plugin::getInstance()->getOption('highlight_limit') and $node_list->length > PMXI_Plugin::getInstance()->getOption('highlight_limit')): ?>
4
  <p><?php _e('<strong>Note</strong>: Highlighting is turned off since can be very slow on large sets of elements.', 'pmxi_plugin') ?></p>
5
  <?php endif ?>
6
  </div>
 
 
 
7
  <script type="text/javascript">
8
- (function($){
9
  var paths = <?php echo json_encode($paths) ?>;
10
  var $xml = $('.xml');
 
 
11
  for (var i = 0; i < paths.length; i++) {
12
  $xml.find('.xml-element[title="' + paths[i] + '"]').addClass('selected').parents('.xml-element').find('> .xml-content.collapsed').removeClass('collapsed').parent().find('> .xml-expander').html('-');
13
- }
14
  })(jQuery);
15
  </script>
1
  <div class="updated">
2
+ <p><?php printf(__('Current selection matches <span class="matches_count">%s</span> %s.', 'pmxi_plugin'), $node_list_count, _n('element', 'elements', $node_list_count, 'pmxi_plugin')) ?></p>
3
+ <?php if (PMXI_Plugin::getInstance()->getOption('highlight_limit') and $elements->length > PMXI_Plugin::getInstance()->getOption('highlight_limit')): ?>
4
  <p><?php _e('<strong>Note</strong>: Highlighting is turned off since can be very slow on large sets of elements.', 'pmxi_plugin') ?></p>
5
  <?php endif ?>
6
  </div>
7
+ <div id="current_xml">
8
+ <?php $this->render_xml_element($elements->item( ($_POST['show_element'] and !$_SESSION['pmxi_import']['large_file']) ? $_POST['show_element'] - 1 : 0 ), false, '//'); ?>
9
+ </div>
10
  <script type="text/javascript">
11
+ (function($){
12
  var paths = <?php echo json_encode($paths) ?>;
13
  var $xml = $('.xml');
14
+
15
+ $xml.html($('#current_xml').html()).css({'visibility':'visible'});
16
  for (var i = 0; i < paths.length; i++) {
17
  $xml.find('.xml-element[title="' + paths[i] + '"]').addClass('selected').parents('.xml-element').find('> .xml-content.collapsed').removeClass('collapsed').parent().find('> .xml-expander').html('-');
18
+ }
19
  })(jQuery);
20
  </script>
views/admin/import/index.php CHANGED
@@ -1,101 +1,122 @@
1
- <table class="layout">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  <tr>
3
  <td class="left">
4
- <h2><?php _e('Import XML/CSV - Step 1: Choose Your File', 'pmxi_plugin') ?><br/><span class="taglines"><?php _e('choose which CSV or XML file you want to import', 'pmxi_plugin') ?></span></h2>
5
- <hr />
6
 
7
  <?php if ($this->errors->get_error_codes()): ?>
8
  <?php $this->error() ?>
9
  <?php endif ?>
10
-
11
- <form method="post" class="choose-file no-enter-submit" enctype="multipart/form-data" autocomplete="off">
 
 
 
 
 
 
 
 
 
12
  <input type="hidden" name="is_submitted" value="1" />
13
  <?php wp_nonce_field('upload-xml', '_wpnonce_upload-xml') ?>
14
-
15
  <div class="file-type-container">
16
  <h3>
17
- <input type="radio" id="type_upload" name="type" value="upload" <?php echo 'upload' == $post['type'] ? 'checked="checked"' : '' ?> />
18
- <label for="type_upload"><?php _e('Upload XML/CSV File From Your Computer', 'pmxi_plugin') ?></label>
19
  </h3>
20
- <div class="file-type-options">
21
- <input type="file" class="regular-text" name="upload" />
22
- <div class="note"><strong><?php _e('Warning', 'pmxi_plugin') ?></strong>: <?php printf(__('Your host allows a maximum filesize of <strong>%sB</strong> for uploads', 'pmxi_plugin'), ini_get('upload_max_filesize')) ?></div>
23
- </div>
 
 
 
 
 
 
 
24
  </div>
25
  <div class="file-type-container">
26
  <h3>
27
- <input type="radio" id="type_url" name="type" value="url" <?php echo 'url' == $post['type'] ? 'checked="checked"' : '' ?> />
28
- <label for="type_url"><?php _e('Get XML/CSV File From URL', 'pmxi_plugin') ?></label>
29
  </h3>
30
  <div class="file-type-options">
31
- <input type="text" class="regular-text" name="url" value="<?php echo esc_attr($post['url']) ?>" />
 
32
  </div>
33
  </div>
34
  <div class="file-type-container">
35
  <h3>
36
- <input type="radio" id="type_ftp" name="type" value="ftp" <?php echo 'ftp' == $post['type'] ? 'checked="checked"' : '' ?> />
37
- <label for="type_ftp"><?php _e('Get XML/CSV File Via FTP', 'pmxi_plugin') ?>*</label>
38
  </h3>
39
  <div class="file-type-options">
40
- <input type="text" class="regular-text" name="ftp[url]" value="<?php echo esc_attr($post['ftp']['url']) ?>" /><br />
41
- <input type="text" name="ftp[user]" title="username" /><strong>:</strong><input type="password" name="ftp[pass]" title="passowrd" />
42
- <div class="note"><b>*</b>&nbsp;<?php _e('These options support shell wildcard patterns<a href="#help" class="help" title="A shell wildcard pattern is a string used by *nix systems for referencing several files at once. The most common case is using asterisk symbol in the place of any set of characters, e.g. `*.xml` would correspond to any file with `xml` extension.">?</a> which enables linking several XML files to the same import. The option is useful when the exact source path is not known upfront or is going to change, e.g. some content providers submit XML files each time with a new name.', 'pmxi_plugin') ?></div>
 
43
  </div>
44
  </div>
45
  <div class="file-type-container">
46
  <h3>
47
- <input type="radio" id="type_file" name="type" value="file" <?php echo 'file' == $post['type'] ? 'checked="checked"' : '' ?> />
48
- <label for="type_file"><?php _e('Get XML/CSV File On This Server', 'pmxi_plugin') ?>*</label>
49
  </h3>
50
  <div class="file-type-options">
51
- <input type="text" id="__FILE_SOURCE" class="regular-text autocomplete" name="file" value="<?php echo esc_attr($post['file']) ?>" />
52
  <?php
53
- $local_files = array_merge(
54
- PMXI_Helper::safe_glob(PMXI_Plugin::ROOT_DIR . '/upload/*.xml', PMXI_Helper::GLOB_RECURSE),
55
- PMXI_Helper::safe_glob(PMXI_Plugin::ROOT_DIR . '/upload/*.gz', PMXI_Helper::GLOB_RECURSE),
56
- PMXI_Helper::safe_glob(PMXI_Plugin::ROOT_DIR . '/upload/*.csv', PMXI_Helper::GLOB_RECURSE)
57
- );
58
- sort($local_files);
 
59
  ?>
60
  <script type="text/javascript">
61
  __FILE_SOURCE = <?php echo json_encode($local_files) ?>;
62
  </script>
63
  <div class="note"><?php printf(__('Upload files to <strong>%s</strong> and they will appear in this list', 'pmxi_plugin'), PMXI_Plugin::ROOT_DIR . '/upload/') ?></div>
 
64
  </div>
65
  </div>
66
- <?php if ($history->count()): ?>
67
- <div class="file-type-container">
68
- <h3>
69
- <input type="radio" id="type_reimport" name="type" value="reimport" <?php echo 'reimport' == $post['type'] ? 'checked="checked"' : '' ?> />
70
- <label for="type_reimport"><?php _e('Get Previously Imported XML or CSV', 'pmxi_plugin') ?></label>
71
- </h3>
72
- <div class="file-type-options">
73
- <input type="text" id="__REIMPORT_SOURCE" class="regular-text autocomplete" name="reimport" value="<?php echo esc_attr($post['reimport']) ?>" readonly="readonly" />
74
- <?php
75
- $reimports = array();
76
- foreach ($history as $file) $reimports[] = '#' . $file['id'] . ': ' . $file['name'] . __(' on ', 'pmxi_plugin') . mysql2date('Y/m/d', $file['registered_on']) . ' - ' . preg_replace('%^(\w+://[^:]+:)[^@]+@%', '$1*****@', $file['path']);
77
- ?>
78
- <script type="text/javascript">
79
- __REIMPORT_SOURCE = <?php echo json_encode($reimports) ?>;
80
- </script>
81
- </div>
82
- </div>
83
- <?php endif ?>
84
-
85
- <div class="file-type-container">
86
- <?php if ($imports->count()): ?>
87
- <div class="input">
88
- <input type="checkbox" id="is_update_previous" name="is_update_previous" class="switcher" disabled="disabled"/>
89
- <label for="is_update_previous"><?php _e('Update Previous Import', 'pmxi_plugin') ?></label>
90
- </div>
91
- <a href="http://www.wpallimport.com/upgrade-to-pro?from=upi" target="_blank">Upgrade to pro to update previous imports.</a>
92
- <?php endif ?>
93
- <p class="submit-buttons">
94
- <input type="hidden" name="is_submitted" value="1" />
95
- <?php wp_nonce_field('choose-file', '_wpnonce_choose-file') ?>
96
- <input type="submit" class="button-primary" value="<?php _e('Continue', 'pmxi_plugin') ?> &gt;&gt;" />
97
- </p>
98
- </div>
99
  <br />
100
  <table><tr><td class="note"></td></tr></table>
101
  </form>
1
+ <?php
2
+
3
+ $l10n = array(
4
+ 'queue_limit_exceeded' => 'You have attempted to queue too many files.',
5
+ 'file_exceeds_size_limit' => 'This file exceeds the maximum upload size for this site.',
6
+ 'zero_byte_file' => 'This file is empty. Please try another.',
7
+ 'invalid_filetype' => 'This file type is not allowed. Please try another.',
8
+ 'default_error' => 'An error occurred in the upload. Please try again later.',
9
+ 'missing_upload_url' => 'There was a configuration error. Please contact the server administrator.',
10
+ 'upload_limit_exceeded' => 'You may only upload 1 file.',
11
+ 'http_error' => 'HTTP error.',
12
+ 'upload_failed' => 'Upload failed.',
13
+ 'io_error' => 'IO error.',
14
+ 'security_error' => 'Security error.',
15
+ 'file_cancelled' => 'File canceled.',
16
+ 'upload_stopped' => 'Upload stopped.',
17
+ 'dismiss' => 'Dismiss',
18
+ 'crunching' => 'Crunching&hellip;',
19
+ 'deleted' => 'moved to the trash.',
20
+ 'error_uploading' => 'has failed to upload due to an error',
21
+ 'cancel_upload' => 'Cancel upload',
22
+ 'dismiss' => 'Dismiss'
23
+ );
24
+
25
+ ?>
26
+ <script type="text/javascript">
27
+ var plugin_url = '<?php echo PMXI_ROOT_URL; ?>';
28
+ var swfuploadL10n = <?php echo json_encode($l10n); ?>;
29
+ </script>
30
+ <table class="layout pmxi_step_1">
31
  <tr>
32
  <td class="left">
33
+ <h2><?php _e('Import XML/CSV - Step 1: Choose Your File', 'pmxi_plugin') ?></h2>
34
+ <h3><?php _e('Specify the file containing the data to be imported.', 'pmxi_plugin') ?></h3>
35
 
36
  <?php if ($this->errors->get_error_codes()): ?>
37
  <?php $this->error() ?>
38
  <?php endif ?>
39
+ <?php
40
+ if ( ! $reimported_import->isEmpty()):
41
+ ?>
42
+ <div id="reimported_notify">
43
+ <p><?php _e( 'You are importing a new file for: <b>' . $reimported_import->name . '</b>' , 'pmxi_plugin' );?></p>
44
+ <p><span><?php _e( 'Last imported on ' . date("m-d-Y H:i:s", strtotime($reimported_import->registered_on)) , 'pmxi_plugin' ); ?></span></p>
45
+ </div>
46
+ <?php
47
+ endif;
48
+ ?>
49
+ <form method="post" class="choose-file no-enter-submit" enctype="multipart/form-data" autocomplete="off">
50
  <input type="hidden" name="is_submitted" value="1" />
51
  <?php wp_nonce_field('upload-xml', '_wpnonce_upload-xml') ?>
 
52
  <div class="file-type-container">
53
  <h3>
54
+ <input type="radio" id="type_upload" name="type" value="upload" checked="checked" />
55
+ <label for="type_upload"><?php _e('Upload File From Your Computer', 'pmxi_plugin') ?></label>
56
  </h3>
57
+ <div id="plupload-ui" class="file-type-options">
58
+ <div>
59
+ <h3 style="float:left; margin-top:5px;"><label><?php _e( 'Choose file to upload...' ); ?></label></h3>&nbsp;&nbsp;
60
+ <input type="hidden" name="filepath" value="<?php echo $post['filepath'] ?>" id="filepath"/>
61
+ <span><input id="select-files" type="button" value="<?php esc_attr_e('Select File'); ?>" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" /></span>
62
+ <div id="progress" class="progress" <?php if (!empty($post['filepath'])):?>style="visibility: visible;"<?php endif;?>>
63
+ <div id="upload_process" class="upload_process"></div>
64
+ <div id="progressbar" class="progressbar"><?php if (!empty($post['filepath'])) _e( 'Import Complete - '.basename($post['filepath']).' 100%', 'pmxi_plugin'); ?></div>
65
+ </div>
66
+ </div>
67
+ </div>
68
  </div>
69
  <div class="file-type-container">
70
  <h3>
71
+ <input type="radio" id="type_url" name="type" value="url" />
72
+ <label for="type_url"><?php _e('Download File From URL', 'pmxi_plugin') ?></label>
73
  </h3>
74
  <div class="file-type-options">
75
+ <input type="text" class="regular-text" name="url" value="" disabled="disabled" />
76
+ <a href="http://www.wpallimport.com/upgrade-to-pro?from=upi" target="_blank" class="upgrade_link">Upgrade to the paid edition of WP All Import to use this feature.</a>
77
  </div>
78
  </div>
79
  <div class="file-type-container">
80
  <h3>
81
+ <input type="radio" id="type_ftp" name="type" value="ftp" />
82
+ <label for="type_ftp"><?php _e('Download File(s) From FTP Server', 'pmxi_plugin') ?></label>
83
  </h3>
84
  <div class="file-type-options">
85
+ <input type="text" class="regular-text" name="ftp[url]" value="<?php echo esc_attr($post['ftp']['url']) ?>" disabled="disabled" /><br />
86
+ <input type="text" name="ftp[user]" title="username" style='width: 150px;' disabled="disabled"/><strong>:</strong><input type="password" name="ftp[pass]" title="passowrd" style='width: 150px;' disabled="disabled"/>
87
+ <div class="note"><?php _e('You may use an asterisk to load multiple files. For example, ftp://example.com/datafeeds/*.xml', 'pmxi_plugin') ?></div>
88
+ <a href="http://www.wpallimport.com/upgrade-to-pro?from=upi" target="_blank" class="upgrade_link">Upgrade to the paid edition of WP All Import to use this feature.</a>
89
  </div>
90
  </div>
91
  <div class="file-type-container">
92
  <h3>
93
+ <input type="radio" id="type_file" name="type" value="file" />
94
+ <label for="type_file"><?php _e('Use Already Uploaded File', 'pmxi_plugin') ?></label>
95
  </h3>
96
  <div class="file-type-options">
97
+ <input type="text" id="__FILE_SOURCE" class="regular-text autocomplete" name="file" value="" disabled="disabled"/>
98
  <?php
99
+ $local_files = array_merge(
100
+ PMXI_Helper::safe_glob(PMXI_Plugin::ROOT_DIR . '/upload/*.xml', PMXI_Helper::GLOB_RECURSE),
101
+ PMXI_Helper::safe_glob(PMXI_Plugin::ROOT_DIR . '/upload/*.gz', PMXI_Helper::GLOB_RECURSE),
102
+ PMXI_Helper::safe_glob(PMXI_Plugin::ROOT_DIR . '/upload/*.zip', PMXI_Helper::GLOB_RECURSE),
103
+ PMXI_Helper::safe_glob(PMXI_Plugin::ROOT_DIR . '/upload/*.csv', PMXI_Helper::GLOB_RECURSE)
104
+ );
105
+ sort($local_files);
106
  ?>
107
  <script type="text/javascript">
108
  __FILE_SOURCE = <?php echo json_encode($local_files) ?>;
109
  </script>
110
  <div class="note"><?php printf(__('Upload files to <strong>%s</strong> and they will appear in this list', 'pmxi_plugin'), PMXI_Plugin::ROOT_DIR . '/upload/') ?></div>
111
+ <a href="http://www.wpallimport.com/upgrade-to-pro?from=upi" target="_blank" class="upgrade_link">Upgrade to the paid edition of WP All Import to use this feature.</a>
112
  </div>
113
  </div>
114
+ <div id="url_upload_status"></div>
115
+ <p class="submit-buttons">
116
+ <input type="hidden" name="is_submitted" value="1" />
117
+ <?php wp_nonce_field('choose-file', '_wpnonce_choose-file') ?>
118
+ <input type="submit" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only large_button" value="<?php _e('Next', 'pmxi_plugin') ?>" id="advanced_upload"/>
119
+ </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  <br />
121
  <table><tr><td class="note"></td></tr></table>
122
  </form>
views/admin/import/options.php CHANGED
@@ -1,20 +1,21 @@
1
  <?php
 
2
  if (!function_exists('reverse_taxonomies_html')) {
3
- function reverse_taxonomies_html($post_taxonomies, $item_id, $i){
4
  $childs = array();
5
- foreach ($post_taxonomies as $j => $cat) if ($cat->parent_id == $item_id) { $childs[] = $cat; }
6
-
7
  if (!empty($childs)){
8
  ?>
9
  <ol>
10
  <?php
11
  foreach ($childs as $child_cat){
12
  $i++;
13
- ?>
14
  <li id="item_<?php echo $i; ?>">
15
- <div class="drag-element"><input class="widefat" type="text" value="<?php echo $child_cat->xpath; ?>"/></div><a href="javascript:void(0);" class="icon-item remove-ico"></a>
16
  <?php echo reverse_taxonomies_html($post_taxonomies, $child_cat->item_id, $i); ?>
17
- </li>
18
  <?php
19
  }
20
  ?>
@@ -24,382 +25,137 @@
24
  }
25
  }
26
  ?>
27
- <form class="options <?php echo ! $this->isWizard ? 'edit' : '' ?>" method="post">
28
- <table class="layout">
29
- <tr>
30
- <td class="left">
31
- <h2>
32
- <?php if ($this->isWizard): ?>
33
- <?php if ($is_loaded_template && !$load_options): ?>
34
- <span class="load-options">
35
- Load Options...&nbsp;<input type="checkbox" name="load_options" /><a class="help" href="#help" original-title="Load options from selected template.">?</a>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  </span>
37
- <?php elseif ($is_loaded_template): ?>
38
- <span class="load-options">
39
- Reset Options...&nbsp;<input type="checkbox" name="reset_options" /><a class="help" href="#help" original-title="Reset options.">?</a>
 
 
40
  </span>
41
- <?php endif; ?>
42
- <?php _e('Import XML/CSV - Step 4: Post Options', 'pmxi_plugin') ?><br/><span class="taglines"><?php _e('options for the created posts', 'pmxi_plugin') ?></span>
43
- <?php else: ?>
44
- <?php _e('Edit Import Options', 'pmxi_plugin') ?>
 
 
 
 
 
 
 
45
  <?php endif ?>
46
- </h2>
47
- <hr />
48
-
49
- <?php if ($this->errors->get_error_codes()): ?>
50
- <?php $this->error() ?>
51
- <?php endif ?>
52
-
53
- <div class="post-type-container">
54
- <h3>
55
- <input type="radio" id="type_post" name="type" value="post" <?php echo 'post' == $post['type'] ? 'checked="checked"' : '' ?> />
56
- <label for="type_post"><?php _e('Create Posts', 'pmxi_plugin') ?></label>
57
- </h3>
58
- <div class="post-type-options">
59
- <table class="form-table">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  <tr>
61
- <th><?php _e('Categories', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php _e('Enter Category IDs or Names.', 'pmxi_plugin') ?>">?</a></th>
62
- <td>
63
- <ol class="sortable no-margin">
64
- <?php if (!empty($post['categories'])):?>
65
- <?php
66
- $categories = json_decode($post['categories']);
67
- if (!empty($categories) and is_array($categories)): foreach ($categories as $i => $cat) {
68
- if (is_null($cat->parent_id) or empty($cat->parent_id))
69
- {
70
- ?>
71
- <li id="item_<?php echo ($i+1); ?>">
72
- <div class="drag-element"><input type="text" class="widefat" value="<?php echo $cat->xpath; ?>"/></div>
73
- <?php echo reverse_taxonomies_html($categories, $cat->item_id, ($i+1)); ?>
74
- </li>
75
- <?php
76
- }
77
- }; else: ?>
78
- <li id="item_1"><div class="drag-element"><input type="text" class="widefat" value=""/></div></li>
79
- <?php endif;?>
80
- <?php else: ?>
81
- <li id="item_1"><div class="drag-element"><input type="text" class="widefat" value=""/></div></li>
82
- <?php endif; ?>
83
- </ol>
84
- <input type="hidden" class="hierarhy-output" name="categories" value="<?php echo esc_attr($post['categories']) ?>"/>
85
- <div class="hidden" id="dialog-confirm-category-removing" title="Delete categories?">Remove only current category or current category with subcategories?</div>
86
- </td>
87
- <td class="delim">
88
- <a href="javascript:void(0);" class="icon-item add-new-ico"></a>
89
- <a href="#help" class="help" title="<?php _e('Drag&Drop inputs to create categories hierarchy', 'pmxi_plugin') ?>">?</a>
90
- </td>
91
- </tr>
92
- <tr>
93
- <th><?php _e('Tags', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php _e('Enter tags separated by commas.', 'pmxi_plugin') ?>">?</a></th>
94
- <td><input type="text" name="tags" class="widefat" value="<?php echo esc_attr($post['tags']) ?>" /></td>
95
- <td class="delim">
96
- <input type="text" class="small" name="tags_delim" maxlength="1" value="<?php echo esc_attr($post['tags_delim']) ?>" />
97
- <a href="#help" class="help" title="<?php _e('Delimiter used for tag list', 'pmxi_plugin') ?>">?</a>
98
- </td>
99
- </tr>
100
- <tr>
101
- <td colspan="3"> <a href="http://www.wpallimport.com/upgrade-to-pro?from=cpt" target="_blank">To import to Custom Post Types, upgrade to pro.</a> </td>
102
- </tr>
103
- <?php $post_taxonomies = array_diff_key(get_taxonomies_by_object_type(array('post'), 'object'), array_flip(array('category', 'post_tag', 'post_format'))) ?>
104
- <?php foreach ($post_taxonomies as $ctx): ?>
105
- <tr class="post_taxonomy" data-type="<?php echo implode(' ', $ctx->object_type) ?>">
106
- <th><nobr><?php echo $ctx->labels->name ?> <a href="#help" class="help" title="<?php _e('Enter taxonomy <b>'.$ctx->labels->name.'</b> terms IDs or Names.', 'pmxi_plugin') ?>">?</a></nobr></th>
107
- <td>
108
- <ol class="sortable no-margin">
109
- <?php if (!empty($post['post_taxonomies'][$ctx->name])):
110
- $taxonomies_hierarchy = json_decode($post['post_taxonomies'][$ctx->name]);
111
- if (!empty($taxonomies_hierarchy) and is_array($taxonomies_hierarchy)): foreach ($taxonomies_hierarchy as $i => $cat) {
112
- if (is_null($cat->parent_id) or empty($cat->parent_id))
113
- {
114
- ?>
115
- <li id="item_<?php echo ($i+1); ?>">
116
- <div class="drag-element"><input type="text" class="widefat" value="<?php echo $cat->xpath; ?>"/></div>
117
- <?php echo reverse_taxonomies_html($taxonomies_hierarchy, $cat->item_id, ($i+1)); ?>
118
- </li>
119
- <?php
120
- }
121
- }; else:?>
122
- <li id="item_1"><div class="drag-element"><input type="text" class="widefat" value=""/></div></li>
123
- <?php endif;
124
- else: ?>
125
- <li id="item_1"><div class="drag-element"><input type="text" class="widefat" value=""/></div></li>
126
- <?php endif; ?>
127
- </ol>
128
- <input type="hidden" class="hierarhy-output" name="post_taxonomies[<?php echo $ctx->name ?>]" value="<?php echo esc_attr($post['post_taxonomies'][$ctx->name]) ?>"/>
129
- </td>
130
- <td class="delim">
131
- <a href="javascript:void(0);" class="icon-item add-new-ico"></a>
132
- <a href="#help" class="help" title="<?php _e('Drag&Drop inputs to create taxonomies hierarchy', 'pmxi_plugin') ?>">?</a>
133
  </td>
134
- </tr>
135
- <?php endforeach; ?>
136
- </table>
137
- </div>
138
- </div>
139
- <div class="post-type-container">
140
- <h3>
141
- <input type="radio" id="type_page" name="type" value="page" <?php echo 'page' == $post['type'] ? 'checked="checked"' : '' ?> />
142
- <label for="type_page"><?php _e('Create Pages', 'pmxi_plugin') ?></label>
143
- </h3>
144
- <div class="post-type-options">
145
- <table class="form-table">
146
- <tr>
147
- <th><?php _e('Page Template', 'pmxi_plugin') ?></th>
148
- <td>
149
- <select name="page_template" id="page_template">
150
- <option value='default'><?php _e('Default', 'pmxi_plugin') ?></option>
151
- <?php page_template_dropdown($template); ?>
152
- </select>
153
- </td>
154
- </tr>
155
- <tr>
156
- <th><?php _e('Parent Page', 'pmxi_plugin') ?></th>
157
- <td>
158
- <?php wp_dropdown_pages(array('post_type' => 'page', 'selected' => $post['parent'], 'name' => 'parent', 'show_option_none' => __('(no parent)', 'pmxi_plugin'), 'sort_column'=> 'menu_order, post_title',)) ?>
159
- </td>
160
- </tr>
161
- <tr>
162
- <th><?php _e('Order', 'pmxi_plugin') ?></th>
163
- <td><input type="text" class="small-text" name="order" value="<?php echo esc_attr($post['order']) ?>" /></td>
164
- </tr>
165
- <?php $page_taxonomies = get_taxonomies_by_object_type('page', 'object') ?>
166
- <?php foreach ($page_taxonomies as $ctx): ?>
167
- <tr class="page_taxonomy" data-type="<?php echo implode(' ', $ctx->object_type) ?>">
168
- <th><nobr><?php echo $ctx->labels->name ?> <a href="#help" class="help" title="<?php _e('Enter taxonomy <b>'.$ctx->labels->name.'</b> terms IDs or Names.', 'pmxi_plugin') ?>">?</a></nobr></th>
169
- <td>
170
- <ol class="sortable no-margin">
171
- <?php if (!empty($post['page_taxonomies'][$ctx->name])):
172
- $taxonomies_hierarchy = json_decode($post['page_taxonomies'][$ctx->name]);
173
- foreach ($taxonomies_hierarchy as $i => $cat) {
174
- if (is_null($cat->parent_id) or empty($cat->parent_id))
175
- {
176
- ?>
177
- <li id="item_<?php echo ($i+1); ?>">
178
- <div class="drag-element"><input type="text" class="widefat" value="<?php echo $cat->xpath; ?>"/></div>
179
- <?php echo reverse_taxonomies_html($taxonomies_hierarchy, $cat->item_id, ($i+1)); ?>
180
- </li>
181
- <?php
182
- }
183
- }
184
- else: ?>
185
- <li id="item_1"><div class="drag-element"><input type="text" class="widefat" value=""/></div></li>
186
- <?php endif; ?>
187
- </ol>
188
- <input type="hidden" class="hierarhy-output" name="page_taxonomies[<?php echo $ctx->name ?>]" value="<?php echo esc_attr($post['page_taxonomies'][$ctx->name]) ?>"/>
189
- <!--input type="text" name="page_taxonomies[<?php echo $ctx->name ?>]" class="widefat" value="<?php echo esc_attr(isset($post['page_taxonomies'][$ctx->name]) ? $post['page_taxonomies'][$ctx->name] : '') ?>" /-->
190
  </td>
191
- <td class="delim">
192
- <a href="javascript:void(0);" class="icon-item add-new-ico"></a>
193
- <a href="#help" class="help" title="<?php _e('Drag&Drop inputs to create taxonomies hierarchy', 'pmxi_plugin') ?>">?</a>
194
  </td>
195
  </tr>
196
- <?php endforeach ?>
197
- </table>
198
- </div>
199
- </div>
200
-
201
- <h2><?php _e('Generic Options', 'pmxi_plugin') ?></h2>
202
- <hr />
203
-
204
- <div class="input">
205
- <input type="hidden" name="is_import_specified" value="0" />
206
- <input type="checkbox" id="is_import_specified" class="switcher" name="is_import_specified" value="1" <?php echo $post['is_import_specified'] ? 'checked="checked"': '' ?>/>
207
- <label for="is_import_specified"><?php _e('Import only specified records', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php _e('Enter records or record ranges separated by commas, e.g. <b>1,5,7-10</b> would import the first, the fifth, and the seventh to tenth.', 'pmxi_plugin') ?>">?</a></label>
208
- <span class="switcher-target-is_import_specified" style="vertical-align:middle">
209
- <input type="text" name="import_specified" value="<?php echo esc_attr($post['import_specified']) ?>" />
210
- </span>
211
- </div>
212
- <div>
213
- <input type="hidden" name="is_duplicates" value="0" />
214
- <input type="checkbox" id="is_duplicates" class="switcher" name="is_duplicates" value="1" disabled="disabled"/>
215
- <label for="is_duplicates"><?php _e('Check for duplicates', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php _e('This option allows you to specify action for articles being imported which have duplicates in WordPress database.<br /><br /><b>Important</b>: This option applies only to pages or posts not associated with current import. To manage overwrite rules for records previously created by import operation currently being updated please see `Reimport / Update Options` section below.', 'pmxi_plugin') ?>">?</a></label>
216
- <a href="http://www.wpallimport.com/upgrade-to-pro?from=cfd" target="_blank">Upgrade to pro for automatic duplicate detection.</a>
217
- </div>
218
- <?php if (in_array($source_type, array('ftp', 'file'))): ?>
219
- <div class="input">
220
- <input type="hidden" name="is_delete_source" value="0" />
221
- <input type="checkbox" id="is_delete_source" name="is_delete_source" value="1" <?php echo $post['is_delete_source'] ? 'checked="checked"': '' ?>/>
222
- <label for="is_delete_source"><?php _e('Delete source XML file after importing', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php _e('This setting takes effect only when script has access rights to perform the action, e.g. file is not deleted when pulled via HTTP or delete permission is not granted to the user that script is executed under.', 'pmxi_plugin') ?>">?</a></label>
223
- </div>
224
- <?php endif ?>
225
- <?php if (class_exists('PMLC_Plugin')): // option is only valid when `WP Wizard Cloak` pluign is enabled ?>
226
- <div class="input">
227
- <input type="hidden" name="is_cloak" value="0" />
228
- <input type="checkbox" id="is_cloak" name="is_cloak" value="1" <?php echo $post['is_cloak'] ? 'checked="checked"': '' ?>/>
229
- <label for="is_cloak"><?php _e('Auto-Cloak Links', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php printf(__('Automatically process all links present in body of created post or page with <b>%s</b> plugin', 'pmxi_plugin'), PMLC_Plugin::getInstance()->getName()) ?>">?</a></label>
230
- </div>
231
- <?php endif ?>
232
- <?php if (in_array($source_type, array('url', 'ftp', 'file'))): ?>
233
- <div class="input">
234
- <input type="hidden" name="is_scheduled" value="0" />
235
- <input type="checkbox" id="is_scheduled" class="switcher" name="is_scheduled" value="1" disabled="disabled"/>
236
- <label for="is_scheduled"><?php _e('Recurring import', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php _e('Consider this option if you want this import task to be run automatically on regular basis.', 'pmxi_plugin') ?>">?</a></label>
237
- <a href="http://www.wpallimport.com/upgrade-to-pro?from=ri" target="_blank">Upgrade to pro for recurring/scheduled imports.</a>
238
- </div>
239
  <?php endif ?>
240
- <h3><?php _e('Post Status', 'pmxi_plugin') ?></h3>
241
- <div>
242
- <input type="radio" id="status_publish" name="status" value="publish" <?php echo 'publish' == $post['status'] ? 'checked="checked"' : '' ?> />
243
- <label for="status_publish"><?php _e('Published', 'pmxi_plugin') ?></label>
244
- &nbsp;
245
- <input type="radio" id="status_draft" name="status" value="draft" <?php echo 'draft' == $post['status'] ? 'checked="checked"' : '' ?> />
246
- <label for="status_draft"><?php _e('Draft', 'pmxi_plugin') ?></label>
247
- </div>
248
-
249
- <h3><?php _e('Post Dates', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php _e('Use any format supported by <b>strtotime</b>', 'pmxi_plugin') ?>">?</a></h3>
250
- <div class="input">
251
- <input type="radio" id="date_type_specific" class="switcher" name="date_type" value="specific" checked="checked"/>
252
- <label for="date_type_specific">
253
- <?php _e('As specified', 'pmxi_plugin') ?>
254
- </label>
255
- <span class="switcher-target-date_type_specific" style="vertical-align:middle">
256
- <input type="text" class="datepicker" name="date" value="<?php echo esc_attr($post['date']) ?>" />
257
- </span>
258
- </div>
259
- <div class="input">
260
- <input type="radio" id="date_type_random" class="switcher" value="random" disabled="disabled" />
261
- <label for="date_type_random">
262
- <?php _e('Random dates', 'pmxi_plugin') ?>
263
- </label>
264
- <span class="" style="vertical-align:middle">
265
- <?php _e('between', 'pmxi_plugin') ?>
266
- <input type="text" class="datepicker" name="date_start" value="<?php echo esc_attr($post['date_start']) ?>" />
267
- <?php _e('and', 'pmxi_plugin') ?>
268
- <input type="text" class="datepicker" name="date_end" value="<?php echo esc_attr($post['date_end']) ?>" />
269
- </span>
270
- <a href="http://www.wpallimport.com/upgrade-to-pro?from=rd" target="_blank">To create posts with random dates, upgrade to pro.</a>
271
- </div>
272
-
273
- <h3><?php _e('Custom Fields', 'pmxi_plugin') ?></h3>
274
- <table class="form-table custom-params">
275
- <thead>
276
- <tr>
277
- <td><?php _e('Name', 'pmxi_plugin') ?></td>
278
- <td><?php _e('Value', 'pmxi_plugin') ?></td>
279
- <td></td>
280
- </tr>
281
- </thead>
282
- <tbody>
283
- <tr class="form-field">
284
- <td><input type="text" name="custom_name[]" value="" disabled="disabled"/></td>
285
- <td><textarea name="custom_value[]" disabled="disabled"></textarea></td>
286
- <td class="action remove"></td>
287
- </tr>
288
- <tr>
289
- <td colspan="3"> <a href="http://www.wpallimport.com/upgrade-to-pro?from=cf" target="_blank">To import data to Custom Fields (including fields in Custom Post Types), upgrade to pro.</a> </td>
290
- </tr>
291
- </tbody>
292
- </table>
293
- <br />
294
- <div>
295
- <input type="hidden" name="comment_status" value="closed" />
296
- <input type="checkbox" id="comment_status" name="comment_status" value="open" <?php echo 'open' == $post['comment_status'] ? 'checked="checked"' : '' ?> />
297
- <label for="comment_status"><?php _e('Allow Comments', 'pmxi_plugin') ?></label>
298
- </div>
299
- <div>
300
- <input type="hidden" name="ping_status" value="closed" />
301
- <input type="checkbox" id="ping_status" name="ping_status" value="open" <?php echo 'open' == $post['ping_status'] ? 'checked="checked"' : '' ?> />
302
- <label for="ping_status"><?php _e('Allow Trackbacks and Pingbacks', 'pmxi_plugin') ?></label>
303
- </div>
304
-
305
- <h3><?php _e('Post Author', 'pmxi_plugin') ?></h3>
306
- <div>
307
- <?php wp_dropdown_users(array('name' => 'author', 'selected' => $post['author'])); ?>
308
- </div>
309
-
310
- <h3><?php _e('Featured Image', 'pmxi_plugin') ?></h3>
311
- <div>
312
- <input type="text" name="featured_image" disabled="disabled" style="width:300px;" value="<?php echo esc_attr($post['featured_image']) ?>" /> <span>Separate multiple image URLs with commas</span> <br/>
313
- <a href="http://www.wpallimport.com/upgade-to-pro?from=fi" target="_blank">To import images to the post image gallery and set the Featured Image, upgrade to pro.</a>
314
- </div>
315
-
316
- <h2><?php _e('Reimport / Update Options', 'pmxi_plugin') ?></h2>
317
- <hr />
318
-
319
- <h3>
320
- <?php _e('Post Unique Key', 'pmxi_plugin') ?>
321
- <a href="#help" class="help" title="<?php _e('XPath expression which is used to detect correspondence between previously imported records and new ones. An expression used for the title is suitable in the most cases, but using recurring tag unique attribute, e.g. ID, if present, is good alternative as well.', 'pmxi_plugin') ?>">?</a>
322
- </h3>
323
- <div class="input">
324
- <input type="text" class="smaller-text" name="unique_key" value="<?php echo esc_attr($post['unique_key']) ?>" <?php echo ! ($this->isWizard && $update_previous->isEmpty()) ? 'disabled="disabled"' : '' ?>/>
325
- </div>
326
- <br />
327
- <div>
328
- <input type="hidden" name="is_delete_missing" value="0" />
329
- <input type="checkbox" id="is_delete_missing" name="is_delete_missing" value="1" <?php echo $post['is_delete_missing'] ? 'checked="checked"': '' ?> />
330
- <label for="is_delete_missing"><?php _e('Delete missing records', 'pmxi_plugin') ?></label>
331
- <a href="#help" class="help" title="<?php _e('Check this option if you want to delete posts from previous import operation which are not found among newly impoprted set.', 'pmxi_plugin') ?>">?</a>
332
- </div>
333
- <div>
334
- <input type="hidden" name="is_keep_former_posts" value="0" />
335
- <input type="checkbox" id="is_keep_former_posts" name="is_keep_former_posts" value="1" <?php echo $post['is_keep_former_posts'] ? 'checked="checked"': '' ?> class="switcher switcher-reversed" />
336
- <label for="is_keep_former_posts"><?php _e('Do not update already existing records', 'pmxi_plugin') ?></label>
337
- <a href="#help" class="help" title="<?php _e('Check this option if you do not want to update already esisting records. The option is useful if you plan to manually edit imported records and do not want them to be overwritten.<br /><br /><b>Important</b>: The option applies to the posts or pages associated with the import being updated. To handle potential conflicts with post or pages which are not associated with this import please use `Check for duplicates` option in `General Options` secion above.', 'pmxi_plugin') ?>">?</a>
338
- </div>
339
- <div class="switcher-target-is_keep_former_posts">
340
- <div>
341
- <input type="hidden" name="is_keep_status" value="0" />
342
- <input type="checkbox" id="is_keep_status" name="is_keep_status" value="1" <?php echo $post['is_keep_status'] ? 'checked="checked"': '' ?> />
343
- <label for="is_keep_status"><?php _e('Keep status', 'pmxi_plugin') ?></label>
344
- <a href="#help" class="help" title="<?php _e('Check this option if you do not want previously imported posts to change their publish status or being restored from Trash.', 'pmxi_plugin') ?>">?</a>
345
- </div>
346
- <div>
347
- <input type="hidden" name="is_keep_content" value="0" />
348
- <input type="checkbox" id="is_keep_content" name="is_keep_content" value="1" <?php echo $post['is_keep_content'] ? 'checked="checked"': '' ?> />
349
- <label for="is_keep_content"><?php _e('Keep content', 'pmxi_plugin') ?></label>
350
- <a href="#help" class="help" title="<?php _e('Re-run an importer to pull in one more custom field... without nuking their edits in the process..', 'pmxi_plugin') ?>">?</a>
351
- </div>
352
- <div>
353
- <input type="hidden" name="is_keep_categories" value="0" />
354
- <input type="checkbox" id="is_keep_categories" name="is_keep_categories" value="1" <?php echo $post['is_keep_categories'] ? 'checked="checked"': '' ?> />
355
- <label for="is_keep_categories"><?php _e('Keep categories, tags and taxonomies', 'pmxi_plugin') ?></label>
356
- <a href="#help" class="help" title="<?php _e('Check this option if you do not want previously imported posts to change their category, tag and custom taxonomies associations upon reimport.', 'pmxi_plugin') ?>">?</a>
357
- </div>
358
- </div>
359
- <div>
360
- <input type="hidden" name="is_keep_attachments" value="0" />
361
- <input type="checkbox" id="is_keep_attachments" name="is_keep_attachments" value="1" <?php echo $post['is_keep_attachments'] ? 'checked="checked"': '' ?> />
362
- <label for="is_keep_attachments"><?php _e('Keep attachments when records removed', 'pmxi_plugin') ?></label>
363
- <a href="#help" class="help" title="<?php _e('Check this option if you want attachments like featured image to be kept in media library after parent post or page is removed or replaced during reimport operation.', 'pmxi_plugin') ?>">?</a>
364
- </div>
365
-
366
- <br />
367
- <p>
368
- <?php wp_nonce_field('options', '_wpnonce_options') ?>
369
- <input type="hidden" name="is_submitted" value="1" />
370
-
371
- <?php if ($this->isWizard): ?>
372
- <a href="<?php echo add_query_arg('action', 'template', $this->baseUrl) ?>" class="button back"><?php _e('Back', 'pmxi_plugin') ?></a>
373
- &nbsp;
374
- <input type="submit" class="button-primary ajax-import" value="<?php _e('Save &amp; Create Posts', 'pmxi_plugin') ?>" />
375
-
376
- <?php if (in_array($source_type, array('url', 'ftp', 'file'))): ?>
377
- or
378
- <input type="submit" name="save_only" class="button" value="<?php _e('Save Only', 'pmxi_plugin') ?>" />
379
- <?php endif ?>
380
-
381
- <?php else: ?>
382
- <input type="submit" class="button-primary" value="<?php _e('Edit', 'pmxi_plugin') ?>" />
383
- <?php endif ?>
384
- </p>
385
-
386
  </td>
387
- <?php if ($this->isWizard or $this->isTemplateEdit): ?>
388
- <td class="right">
389
- <p><?php _e('Drag &amp; Drop opening tag of an element for inserting corresponding XPath into a form element.', 'pmxi_plugin') ?></p>
390
- <?php $this->tag() ?>
391
- </td>
392
- <?php endif ?>
393
- </tr>
394
- </table>
395
- </form>
396
- <script type="text/javascript">
397
- (function($){$(function(){
398
- $('select[name="custom_type"]').change(function () {
399
- var type = $(this).val(); if ('' == type) type = 'post';
400
- $('tr.post_taxonomy').each(function () {
401
- $(this)[$.inArray(type, $(this).data('type').split(' ')) < 0 ? 'hide' : 'fadeIn']();
402
- });
403
- }).change();
404
- });})(jQuery);
405
- </script>
1
  <?php
2
+
3
  if (!function_exists('reverse_taxonomies_html')) {
4
+ function reverse_taxonomies_html($post_taxonomies, $item_id, &$i){
5
  $childs = array();
6
+ foreach ($post_taxonomies as $j => $cat) if ($cat->parent_id == $item_id) { $childs[] = $cat; }
7
+
8
  if (!empty($childs)){
9
  ?>
10
  <ol>
11
  <?php
12
  foreach ($childs as $child_cat){
13
  $i++;
14
+ ?>
15
  <li id="item_<?php echo $i; ?>">
16
+ <div class="drag-element"><input type="checkbox" class="assign_post" <?php if ($child_cat->assign): ?>checked="checked"<?php endif; ?>/><input class="widefat" type="text" value="<?php echo $child_cat->xpath; ?>"/></div><a href="javascript:void(0);" class="icon-item remove-ico"></a>
17
  <?php echo reverse_taxonomies_html($post_taxonomies, $child_cat->item_id, $i); ?>
18
+ </li>
19
  <?php
20
  }
21
  ?>
25
  }
26
  }
27
  ?>
28
+ <?php $custom_types = get_post_types(array('_builtin' => false), 'objects'); ?>
29
+ <input type="hidden" id="selected_post_type" value="<?php echo (!empty($post['custom_type'])) ? $post['custom_type'] : '';?>">
30
+ <input type="hidden" id="selected_type" value="<?php echo (!empty($post['type'])) ? $post['type'] : '';?>">
31
+ <h2>
32
+ <?php if ($this->isWizard): ?>
33
+ <?php _e('Import XML/CSV - Step 4: Options', 'pmxi_plugin') ?>
34
+ <?php else: ?>
35
+ <?php _e('Edit Import Options', 'pmxi_plugin') ?>
36
+ <?php endif ?>
37
+ </h2>
38
+ <h3>Click the appropriate tab to choose the type of posts to create.</h3>
39
+
40
+ <?php if ($this->errors->get_error_codes()): ?>
41
+ <?php $this->error() ?>
42
+ <?php endif ?>
43
+ <table class="layout">
44
+ <tr>
45
+ <td class="left">
46
+ <?php if ($this->isWizard): ?>
47
+ <?php if ($is_loaded_template && !$load_options): ?>
48
+ <form class="options <?php echo ! $this->isWizard ? 'edit' : '' ?>" method="post">
49
+ <span class="load-options">
50
+ Load Options...&nbsp;<input type="checkbox" name="load_options" /><a class="help" href="#help" original-title="Load options from selected template.">?</a>
51
  </span>
52
+ </form>
53
+ <?php elseif ($is_loaded_template): ?>
54
+ <form class="options <?php echo ! $this->isWizard ? 'edit' : '' ?>" method="post">
55
+ <span class="load-options">
56
+ Reset Options...&nbsp;<input type="checkbox" name="reset_options" /><a class="help" href="#help" original-title="Reset options.">?</a>
57
  </span>
58
+ </form>
59
+ <?php endif; ?>
60
+ <?php endif; ?>
61
+ <div id="pmxi_tabs">
62
+ <ul>
63
+ <li><a href="#tabs-1">Posts</a></li>
64
+ <li><a href="#tabs-2">Pages</a></li>
65
+ <?php if (count($custom_types)): ?>
66
+ <?php foreach ($custom_types as $key => $ct): ?>
67
+ <li><a href="#tabs-<?php echo $key; ?>"><?php echo $ct->labels->name ?></a></li>
68
+ <?php endforeach ?>
69
  <?php endif ?>
70
+ </ul>
71
+
72
+ <!-- Post Options -->
73
+
74
+ <div id="tabs-1"> <!-- Basic -->
75
+ <form class="options <?php echo ! $this->isWizard ? 'edit' : '' ?>" method="post">
76
+ <input type="hidden" name="type" value="post"/>
77
+ <input type="hidden" name="custom_type" value=""/>
78
+ <div class="post-type-options">
79
+ <table class="form-table" style="max-width:none;">
80
+ <?php
81
+ $post_type = 'post';
82
+ $entry = 'post';
83
+ include( 'options/_main_options_template.php' );
84
+ include( 'options/_taxonomies_template.php' );
85
+ include( 'options/_categories_template.php' );
86
+ include( 'options/_custom_fields_template.php' );
87
+ include( 'options/_featured_template.php' );
88
+ include( 'options/_author_template.php' );
89
+ include( 'options/_reimport_template.php' );
90
+ ?>
91
+ </table>
92
+ </div>
93
+
94
+ <?php include( 'options/_buttons_template.php' ); ?>
95
+
96
+ </form>
97
+ </div>
98
+
99
+ <!-- Page Options -->
100
+
101
+ <div id="tabs-2">
102
+ <form class="options <?php echo ! $this->isWizard ? 'edit' : '' ?>" method="post">
103
+ <input type="hidden" name="type" value="page"/>
104
+ <input type="hidden" name="custom_type" value=""/>
105
+ <div class="post-type-options">
106
+ <table class="form-table" style="max-width:none;">
107
+
108
+ <?php include( 'options/_main_options_template.php' ); ?>
109
+
110
  <tr>
111
+ <td align="center" width="33%">
112
+ <label><?php _e('Page Template', 'pmxi_plugin') ?></label> <br>
113
+ <select name="page_template" id="page_template">
114
+ <option value='default'><?php _e('Default', 'pmxi_plugin') ?></option>
115
+ <?php page_template_dropdown($post['page_template']); ?>
116
+ </select>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  </td>
118
+ <td align="center" width="33%">
119
+ <label><?php _e('Parent Page', 'pmxi_plugin') ?></label> <br>
120
+ <?php wp_dropdown_pages(array('post_type' => 'page', 'selected' => $post['parent'], 'name' => 'parent', 'show_option_none' => __('(no parent)', 'pmxi_plugin'), 'sort_column'=> 'menu_order, post_title',)) ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  </td>
122
+ <td align="center" width="33%">
123
+ <label><?php _e('Order', 'pmxi_plugin') ?></label> <br>
124
+ <input type="text" class="" name="order" value="<?php echo esc_attr($post['order']) ?>" />
125
  </td>
126
  </tr>
127
+ <?php
128
+ $post_type = 'post';
129
+ $entry = 'page';
130
+ include( 'options/_taxonomies_template.php' );
131
+ include( 'options/_featured_template.php' );
132
+ include( 'options/_reimport_template.php' );
133
+ ?>
134
+ </table>
135
+ </div>
136
+
137
+ <?php include( 'options/_buttons_template.php' ); ?>
138
+
139
+ </form>
140
+ </div>
141
+
142
+ <!-- Custom Post Types -->
143
+
144
+ <?php if (count($custom_types)): ?>
145
+ <?php foreach ($custom_types as $key => $ct): ?>
146
+ <div id="tabs-<?php echo $key;?>">
147
+
148
+ <p><a href="http://www.wpallimport.com/upgrade-to-pro?from=upi" target="_blank" class="upgrade_link">Upgrade to the paid edition of WP All Import to use this feature.</a></p>
149
+
150
+ </div>
151
+ <?php endforeach ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  <?php endif ?>
153
+ </div>
154
+ </td>
155
+ <?php if ($this->isWizard or $this->isTemplateEdit): ?>
156
+ <td class="right options">
157
+ <?php $this->tag() ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  </td>
159
+ <?php endif ?>
160
+ </tr>
161
+ </table>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/admin/import/options/_author_template.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <tr>
2
+ <td colspan="3">
3
+ <h3><?php _e('Post Author', 'pmxi_plugin') ?></h3>
4
+ <div>
5
+ <input type="text" name="author" value="<?php echo esc_attr($post['author']) ?>"/> <a href="#help" class="help" title="<?php _e('Value that contains user ID, login, slug or email.', 'pmxi_plugin') ?>">?</a>
6
+ </div>
7
+ </td>
8
+ </tr>
9
+ <tr>
10
+ <td colspan="3">
11
+ <h3><?php _e('Post Excerpt', 'pmxi_plugin') ?></h3>
12
+ <div>
13
+ <input type="text" name="post_excerpt" style="width:100%;" value="<?php echo esc_attr($post['post_excerpt']) ?>" />
14
+ </div>
15
+ <h3><?php _e('Post Slug', 'pmxi_plugin') ?></h3>
16
+ <div>
17
+ <input type="text" name="post_slug" style="width:100%;" value="<?php echo esc_attr($post['post_slug']) ?>" />
18
+ </div> <br><br>
19
+ </td>
20
+ </tr>
views/admin/import/options/_buttons_template.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <br>
2
+ <div class="input">
3
+ <label for="save_import_as">Friendly Name</label> <input type="text" name="friendly_name" title="<?php _e('Save friendly name...', 'pmxi_plugin') ?>" style="vertical-align:middle; font-size:11px; background:#fff !important;" value="<?php echo esc_attr($post['friendly_name']) ?>" />
4
+ </div>
5
+ <br>
6
+ <?php if ($_SESSION['pmxi_import']['large_file'] or (!empty($import) and $import->large_import == 'Yes')):?>
7
+ <div class="input">
8
+ <label for="records_per_request">Records Per Iteration</label> <input type="text" name="records_per_request" style="vertical-align:middle; font-size:11px; background:#fff !important; width: 40px;" value="<?php echo esc_attr($post['records_per_request']) ?>" />
9
+ <a href="#help" class="help" title="<?php _e('Your feed was detected as a &quot;large&quot; file. The import process will be executed via AJAX requests. To make import process faster you can increase the number of records imported per iteration. Higher numbers put more strain on your server but make the import process take less time. 10 is a very safe number. To speed up the process, try 100 or more, especially if your import settings are simple and you are not downloading images.', 'pmxi_plugin') ?>">?</a>
10
+ </div>
11
+ <div class="input">
12
+ <input type="hidden" name="create_chunks" value="0" />
13
+ <input type="checkbox" id="create_chunks_<?php echo $entry; ?>" name="create_chunks" value="1" <?php echo $post['create_chunks'] ? 'checked="checked"': '' ?>/>
14
+ <label for="create_chunks_<?php echo $entry; ?>"><?php _e('create chunks', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php _e('This setting will split importing feed to chunks with 100 records per chunk.', 'pmxi_plugin') ?>">?</a></label>
15
+ </div>
16
+ <br>
17
+ <?php endif; ?>
18
+ <div class="input">
19
+ <input type="hidden" name="is_import_specified" value="0" />
20
+ <input type="checkbox" id="is_import_specified_<?php echo $entry; ?>" class="switcher" name="is_import_specified" value="1" <?php echo $post['is_import_specified'] ? 'checked="checked"': '' ?>/>
21
+ <label for="is_import_specified_<?php echo $entry; ?>"><?php _e('Import only specified records', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php _e('Enter records or record ranges separated by commas, e.g. <b>1,5,7-10</b> would import the first, the fifth, and the seventh to tenth.', 'pmxi_plugin') ?>">?</a></label>
22
+ <span class="switcher-target-is_import_specified_<?php echo $entry; ?>" style="vertical-align:middle">
23
+ <div class="input" style="display:inline;">
24
+ <input type="text" name="import_specified" value="<?php echo esc_attr($post['import_specified']) ?>" style="width:50%;"/>
25
+ </div>
26
+ </span>
27
+ </div>
28
+ <?php if (in_array($source_type, array('ftp', 'file'))): ?>
29
+ <div class="input">
30
+ <input type="hidden" name="is_delete_source" value="0" />
31
+ <input type="checkbox" id="is_delete_source_<?php echo $entry; ?>" name="is_delete_source" value="1" <?php echo $post['is_delete_source'] ? 'checked="checked"': '' ?>/>
32
+ <label for="is_delete_source_<?php echo $entry; ?>"><?php _e('Delete source XML file after importing', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php _e('This setting takes effect only when script has access rights to perform the action, e.g. file is not deleted when pulled via HTTP or delete permission is not granted to the user that script is executed under.', 'pmxi_plugin') ?>">?</a></label>
33
+ </div>
34
+ <?php endif; ?>
35
+ <?php if (class_exists('PMLC_Plugin')): // option is only valid when `WP Wizard Cloak` pluign is enabled ?>
36
+ <div class="input">
37
+ <input type="hidden" name="is_cloak" value="0" />
38
+ <input type="checkbox" id="is_cloak_<?php echo $entry; ?>" name="is_cloak" value="1" <?php echo $post['is_cloak'] ? 'checked="checked"': '' ?>/>
39
+ <label for="is_cloak_<?php echo $entry; ?>"><?php _e('Auto-Cloak Links', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php printf(__('Automatically process all links present in body of created post or page with <b>%s</b> plugin', 'pmxi_plugin'), PMLC_Plugin::getInstance()->getName()) ?>">?</a></label>
40
+ </div> <br>
41
+ <?php endif; ?>
42
+ <p class="submit-buttons">
43
+ <?php wp_nonce_field('options', '_wpnonce_options') ?>
44
+ <input type="hidden" name="is_submitted" value="1" />
45
+
46
+ <?php if ($this->isWizard): ?>
47
+
48
+ <a href="<?php echo add_query_arg('action', 'template', $this->baseUrl) ?>" class="back"><?php _e('Back', 'pmxi_plugin') ?></a>
49
+
50
+ <?php if (in_array($source_type, array('url', 'ftp', 'file'))): ?>
51
+ <input type="hidden" class="save_only" value="0" name="save_only"/>
52
+ <span style="font-size:16px;">or</span> <input type="submit" name="btn_save_only" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only large_button" value="<?php _e('Save Only', 'pmxi_plugin') ?>" />
53
+ <?php endif ?>
54
+
55
+ <input type="submit" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only large_button" value="<?php _e('Finish', 'pmxi_plugin') ?>" />
56
+
57
+ <?php else: ?>
58
+ <a href="<?php echo remove_query_arg('id', remove_query_arg('action', $this->baseUrl)); ?>" class="back"><?php _e('Back', 'pmxi_plugin') ?></a>
59
+ <input type="submit" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only large_button" value="<?php _e('Save', 'pmxi_plugin') ?>" />
60
+ <?php endif ?>
61
+ </p>
views/admin/import/options/_categories_template.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <tr>
2
+ <td colspan="3">
3
+ <div class="col2">
4
+ <fieldset style="margin-left:0px;">
5
+ <legend><?php _e('Categories', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php _e('Uncheck a box and the category will still be created, but the post will not be assigned to it.', 'pmxi_plugin') ?>">?</a></legend>
6
+ <ol class="sortable no-margin">
7
+ <?php if (!empty($post['categories'])):?>
8
+ <?php
9
+ $categories = json_decode($post['categories']);
10
+
11
+ if (empty($categories)) $categories = explode(',', $post['categories']);
12
+
13
+ if (!empty($categories) and is_array($categories)): $i = 0; foreach ($categories as $cat) { $i++;
14
+ if (is_null($cat->parent_id) or empty($cat->parent_id))
15
+ {
16
+ ?>
17
+ <li id="item_<?php echo $i; ?>">
18
+ <div class="drag-element"><input type="checkbox" class="assign_post" <?php if ($cat->assign): ?>checked="checked"<?php endif; ?>/><input type="text" class="widefat" value="<?php echo (is_object($cat)) ? $cat->xpath : $cat; ?>"/></div><?php if ($i>1):?><a href="javascript:void(0);" class="icon-item remove-ico"></a><?php endif;?>
19
+ <?php if (is_object($cat)) echo reverse_taxonomies_html($categories, $cat->item_id, $i); ?>
20
+ </li>
21
+ <?php
22
+ }
23
+ }; else: ?>
24
+ <li id="item_1"><div class="drag-element"><input type="checkbox" class="assign_post" checked="checked"/><input type="text" class="widefat" value=""/></div></li>
25
+ <?php endif;?>
26
+ <?php else: ?>
27
+ <li id="item_1"><div class="drag-element"><input type="checkbox" class="assign_post" checked="checked"/><input type="text" class="widefat" value=""/></div></li>
28
+ <?php endif; ?>
29
+ </ol>
30
+ <a href="javascript:void(0);" class="icon-item add-new-ico">Add more</a> <br><br>
31
+ <input type="hidden" class="hierarhy-output" name="categories" value="<?php echo esc_attr($post['categories']) ?>"/>
32
+ <div class="hidden" id="dialog-confirm-category-removing" title="Delete categories?">Remove only current category or current category with subcategories?</div>
33
+ <div class="delim">
34
+ <label><?php _e('Separated by', 'pmxi_plugin'); ?></label>
35
+ <input type="text" class="small" name="categories_delim" maxlength="1" value="<?php echo esc_attr($post['categories_delim']) ?>" />
36
+ <!--a href="#help" class="help" title="<?php _e('Delimiter used for tag list', 'pmxi_plugin') ?>">?</a-->
37
+ </div>
38
+ </fieldset>
39
+ </div>
40
+ <div class="col2">
41
+ <fieldset style="padding:5px; margin-right:0px;">
42
+ <legend><?php _e('Tags', 'pmxi_plugin') ?> </legend>
43
+ <!--a href="#help" class="help" title="<?php _e('Enter tags separated by commas.', 'pmxi_plugin') ?>">?</a-->
44
+ <input type="text" name="tags" class="widefat" value="<?php echo esc_attr($post['tags']) ?>" /> <br> <br>
45
+ <div class="delim">
46
+ <label><?php _e('Separated by', 'pmxi_plugin'); ?></label>
47
+ <input type="text" class="small" name="tags_delim" maxlength="1" value="<?php echo esc_attr($post['tags_delim']) ?>" />
48
+ <!--a href="#help" class="help" title="<?php _e('Delimiter used for tag list', 'pmxi_plugin') ?>">?</a-->
49
+ </div>
50
+ </fieldset>
51
+ </div>
52
+ </td>
53
+ </tr>
views/admin/import/options/_custom_fields_template.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <tr>
2
+ <td colspan="3" style="border-bottom:1px solid #ccc;">
3
+ <fieldset class="optionsset" style="text-align:center;">
4
+ <legend>Custom Fields</legend>
5
+ <table class="form-table custom-params" style="max-width:none; border:none;">
6
+ <thead>
7
+ <tr>
8
+ <td><?php _e('Name', 'pmxi_plugin') ?></td>
9
+ <td><?php _e('Value', 'pmxi_plugin') ?></td>
10
+ <td></td>
11
+ </tr>
12
+ </thead>
13
+ <tbody>
14
+ <tr class="form-field">
15
+ <td><input type="text" name="custom_name[]" value="" disabled="disabled" /></td>
16
+ <td class="action remove">
17
+ <textarea name="custom_value[]" disabled="disabled"></textarea>
18
+ </td>
19
+ </tr>
20
+ <tr>
21
+ <td colspan="3"><a href="#add" title="<?php _e('add', 'pmxi_plugin')?>" class="action add-new-custom"><?php _e('Add more', 'pmxi_plugin') ?></a></td>
22
+ </tr>
23
+ </tbody>
24
+ </table>
25
+ <select class="existing_meta_keys">
26
+ <option value="">Existing Custom Fields...</option>
27
+ <?php
28
+ $hide_fields = array('_wp_page_template', '_edit_lock', '_edit_last', '_wp_trash_meta_status', '_wp_trash_meta_time');
29
+ if (!empty($meta_keys) and $meta_keys->count()):
30
+ foreach ($meta_keys as $meta_key) { if (in_array($meta_key['meta_key'], $hide_fields) or strpos($meta_key['meta_key'], '_wp') === 0) continue;
31
+ ?>
32
+ <option value="<?php echo $meta_key['meta_key'];?>"><?php echo $meta_key['meta_key'];?></option>
33
+ <?php
34
+ }
35
+ endif;
36
+ ?>
37
+ </select>
38
+ <br><br>
39
+ <a href="http://www.wpallimport.com/upgrade-to-pro?from=upi" target="_blank" class="upgrade_link">Upgrade to the paid edition of WP All Import to use this feature.</a>
40
+ </fieldset>
41
+ <br>
42
+ </td>
43
+ </tr>
views/admin/import/options/_featured_template.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <tr>
2
+ <td colspan="3">
3
+ <h3>
4
+ <?php _e('Download & Import Images To The Post Media Gallery', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php _e('Specify URLs or XPath Template Tags to download and import images to the post media gallery. The first image will be set as the Featured Image. Example: <pre>{image[1]},{image[2]},{image[3]}</pre> Separate your URLs or XPath Template Tags with the comma. <i>Separated by</i> character will use if xPath value contains multiple URLs, for example: <br> \'http://test.com/first.jpg | http://test.com/second.png\'.', 'pmxi_plugin') ?>">?</a>
5
+ <span class="separated_by">Separated by</span>
6
+ </h3>
7
+ <div>
8
+ <input type="text" name="featured_image" style="width:92%;" value="<?php echo esc_attr($post['featured_image']) ?>" disabled="disabled"/>
9
+ <input type="text" class="small" name="featured_delim" maxlength="1" value="<?php echo esc_attr($post['featured_delim']) ?>" style="width:5%; text-align:center;" disabled="disabled"/>
10
+ </div>
11
+ <div class="input">
12
+ <input type="hidden" name="create_draft" value="no" />
13
+ <input type="checkbox" id="create_draft_<?php echo $entry; ?>" name="create_draft" value="yes" <?php echo 'yes' == $post['create_draft'] ? 'checked="checked"' : '' ?> disabled="disabled"/>
14
+ <label for="create_draft_<?php echo $entry; ?>"><?php _e('<small>If no images are downloaded successfully, create entry as Draft.</small>', 'pmxi_plugin') ?></label>
15
+ </div>
16
+ <a href="http://www.wpallimport.com/upgrade-to-pro?from=upi" target="_blank" class="upgrade_link">Upgrade to the paid edition of WP All Import to use this feature.</a>
17
+ <h3>
18
+ <?php _e('Download & Import Attachments', 'pmxi_plugin') ?>
19
+ <span class="separated_by">Separated by</span>
20
+ </h3>
21
+ <div>
22
+ <input type="text" name="attachments" style="width:92%;" value="<?php echo esc_attr($post['attachments']) ?>" />
23
+ <input type="text" class="small" name="atch_delim" maxlength="1" value="<?php echo esc_attr($post['atch_delim']) ?>" style="width:5%; text-align:center;"/>
24
+ </div>
25
+ <br>
26
+ </td>
27
+ </tr>
views/admin/import/options/_main_options_template.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <tr>
2
+ <td colspan="3" style="border-bottom:1px solid #ccc;">
3
+ <div class="col2" style="margin-bottom:20px;">
4
+ <h3><?php _e('Post Status', 'pmxi_plugin') ?></h3>
5
+ <div>
6
+ <div class="input">
7
+ <input type="radio" id="status_publish_<?php echo $entry; ?>" name="status" value="publish" <?php echo 'publish' == $post['status'] ? 'checked="checked"' : '' ?> />
8
+ <label for="status_publish_<?php echo $entry; ?>"><?php _e('Published', 'pmxi_plugin') ?></label>
9
+ </div>
10
+ <div class="input">
11
+ <input type="radio" id="status_draft_<?php echo $entry; ?>" name="status" value="draft" <?php echo 'draft' == $post['status'] ? 'checked="checked"' : '' ?> />
12
+ <label for="status_draft_<?php echo $entry; ?>"><?php _e('Draft', 'pmxi_plugin') ?></label>
13
+ </div>
14
+ <br>
15
+ <div class="input">
16
+ <input type="hidden" name="comment_status" value="closed" />
17
+ <input type="checkbox" id="comment_status_<?php echo $entry; ?>" name="comment_status" value="open" <?php echo 'open' == $post['comment_status'] ? 'checked="checked"' : '' ?> />
18
+ <label for="comment_status_<?php echo $entry; ?>"><?php _e('Allow Comments', 'pmxi_plugin') ?></label>
19
+ </div>
20
+ <div class="input">
21
+ <input type="hidden" name="ping_status" value="closed" />
22
+ <input type="checkbox" id="ping_status_<?php echo $entry; ?>" name="ping_status" value="open" <?php echo 'open' == $post['ping_status'] ? 'checked="checked"' : '' ?> />
23
+ <label for="ping_status_<?php echo $entry; ?>"><?php _e('Allow Trackbacks and Pingbacks', 'pmxi_plugin') ?></label>
24
+ </div>
25
+ </div>
26
+ </div>
27
+ <div class="col2">
28
+ <h3><?php _e('Post Dates', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php _e('Use any format supported by the PHP <b>strtotime</b> function. That means pretty much any human-readable date will work.', 'pmxi_plugin') ?>">?</a></h3>
29
+ <div class="input">
30
+ <input type="radio" id="date_type_specific_<?php echo $entry; ?>" class="switcher" name="date_type" value="specific" <?php echo 'random' != $post['date_type'] ? 'checked="checked"' : '' ?> />
31
+ <label for="date_type_specific_<?php echo $entry; ?>">
32
+ <?php _e('As specified', 'pmxi_plugin') ?>
33
+ </label>
34
+ <span class="switcher-target-date_type_specific_<?php echo $entry; ?>" style="vertical-align:middle">
35
+ <input type="text" class="datepicker" name="date" value="<?php echo esc_attr($post['date']) ?>" style="width:40%;"/>
36
+ </span>
37
+ </div>
38
+ <div class="input">
39
+ <input type="radio" id="date_type_random_<?php echo $entry; ?>" class="switcher" name="date_type" value="random" <?php echo 'random' == $post['date_type'] ? 'checked="checked"' : '' ?> />
40
+ <label for="date_type_random_<?php echo $entry; ?>">
41
+ <?php _e('Random dates', 'pmxi_plugin') ?><a href="#help" class="help" title="<?php _e('Posts will be randomly assigned dates in this range. WordPress ensures posts with dates in the future will not appear until their date has been reached.', 'pmxi_plugin') ?>">?</a>
42
+ </label> <br>
43
+ <span class="switcher-target-date_type_random_<?php echo $entry; ?>" style="vertical-align:middle">
44
+ <input type="text" class="datepicker" name="date_start" value="<?php echo esc_attr($post['date_start']) ?>" />
45
+ <?php _e('and', 'pmxi_plugin') ?>
46
+ <input type="text" class="datepicker" name="date_end" value="<?php echo esc_attr($post['date_end']) ?>" />
47
+ </span>
48
+ </div>
49
+ </div>
50
+ <!--div class="col3 last">
51
+ <div class="input">
52
+ <input type="hidden" name="is_duplicates" value="0" />
53
+ <input type="checkbox" id="is_duplicates_<?php echo $entry; ?>" class="switcher" name="is_duplicates" value="1" <?php echo $post['is_duplicates'] ? 'checked="checked"': '' ?>/>
54
+ <label for="is_duplicates_<?php echo $entry; ?>"><?php _e('Check for duplicates', 'pmxi_plugin') ?> <a href="#help" class="help" title="<?php _e('This option allows you to specify action for articles being imported which have duplicates in WordPress database.<br /><br /><b>Important</b>: This option applies only to pages or posts not associated with current import. To manage overwrite rules for records previously created by import operation currently being updated please see `Reimport / Update Options` section below.', 'pmxi_plugin') ?>">?</a></label>
55
+ <div class="switcher-target-is_duplicates_<?php echo $entry; ?>">
56
+ <div class="input">
57
+ <span style="vertical-align:middle"><?php _e('Determine duplicates by', 'pmxi_plugin') ?></span><br>
58
+ <input type="radio" id="duplicate_indicator_title_<?php echo $entry; ?>" class="switcher" name="duplicate_indicator" value="title" <?php echo 'title' == $post['duplicate_indicator'] ? 'checked="checked"': '' ?>/>
59
+ <label for="duplicate_indicator_title_<?php echo $entry; ?>"><?php _e('title', 'pmxi_plugin' )?></label><br>
60
+ <input type="radio" id="duplicate_indicator_content_<?php echo $entry; ?>" class="switcher" name="duplicate_indicator" value="content" <?php echo 'content' == $post['duplicate_indicator'] ? 'checked="checked"': '' ?>/>
61
+ <label for="duplicate_indicator_content_<?php echo $entry; ?>"><?php _e('content', 'pmxi_plugin' )?></label><br>
62
+ <input type="radio" id="duplicate_indicator_custom_field_<?php echo $entry; ?>" class="switcher" name="duplicate_indicator" value="custom field" <?php echo 'custom field' == $post['duplicate_indicator'] ? 'checked="checked"': '' ?>/>
63
+ <label for="duplicate_indicator_custom_field_<?php echo $entry; ?>"><?php _e('custom field', 'pmxi_plugin' )?></label><br>
64
+ <span class="switcher-target-duplicate_indicator_custom_field_<?php echo $entry; ?>" style="vertical-align:middle">
65
+ <?php _e('Name', 'pmxi_plugin') ?>
66
+ <input type="text" name="custom_duplicate_name" value="<?php echo esc_attr($post['custom_duplicate_name']) ?>" /><br>
67
+ <?php _e('Value', 'pmxi_plugin') ?>
68
+ <input type="text" name="custom_duplicate_value" value="<?php echo esc_attr($post['custom_duplicate_value']) ?>" />
69
+ </span>
70
+ </div>
71
+ <div class="input">
72
+ <span style="vertical-align:middle"><?php _e('When found:', 'pmxi_plugin') ?></span> <br>
73
+ <input type="radio" id="duplicate_action_keep_<?php echo $entry; ?>" name="duplicate_action" value="keep" <?php echo 'keep' == $post['duplicate_action'] ? 'checked="checked"': '' ?> class="switcher"/>
74
+ <label for="duplicate_action_keep_<?php echo $entry; ?>"><?php _e('keep existing and skip new', 'pmxi_plugin' )?></label> <br>
75
+ <input type="radio" id="duplicate_action_rewrite_<?php echo $entry; ?>" name="duplicate_action" value="rewrite" <?php echo 'rewrite' == $post['duplicate_action'] ? 'checked="checked"': '' ?> class="switcher"/>
76
+ <label for="duplicate_action_rewrite_<?php echo $entry; ?>"><?php _e('remove existing and add new', 'pmxi_plugin' )?></label> <br>
77
+ <input type="radio" id="duplicate_action_update_<?php echo $entry; ?>" name="duplicate_action" value="update" <?php echo 'update' == $post['duplicate_action'] ? 'checked="checked"': '' ?> class="switcher"/>
78
+ <label for="duplicate_action_update_<?php echo $entry; ?>"><?php _e('update existing', 'pmxi_plugin' )?></label>
79
+ <span class="switcher-target-duplicate_action_update_<?php echo $entry; ?>" style="vertical-align:middle">
80
+ <div class="input" style="padding-left:20px;">
81
+ <input type="hidden" name="not_create_records" value="0" />
82
+ <input type="checkbox" id="not_create_records_<?php echo $entry; ?>" name="not_create_records" value="1" <?php echo $post['not_create_records'] ? 'checked="checked"' : '' ?> />
83
+ <label for="not_create_records_<?php echo $entry; ?>"><?php _e('NOT create new records', 'pmxi_plugin') ?></label>
84
+ </div>
85
+ </span>
86
+ </div>
87
+ </div>
88
+ </div>
89
+ </div-->
90
+ </td>
91
+ </tr>
92
+ <tr>
93
+ <td colspan="3">
94
+ <h3 style="text-align:center; color:#999;">Drag elements from the XML tree on the right to any textbox below.</h3>
95
+ </td>
96
+ </tr>
views/admin/import/options/_reimport_template.php ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <tr>
2
+ <td colspan="3">
3
+ <fieldset class="optionsset">
4
+ <legend>Record Matching</legend>
5
+ <div class="input" style="margin-bottom:15px;">
6
+ <input type="radio" id="auto_matching_<?php echo $entry; ?>" class="switcher" name="duplicate_matching" value="auto" <?php echo 'manual' != $post['duplicate_matching'] ? 'checked="checked"': '' ?>/>
7
+ <label for="auto_matching_<?php echo $entry; ?>"><?php _e('Automatic Record Matching', 'pmxi_plugin' )?></label><br>
8
+ <div class="switcher-target-auto_matching_<?php echo $entry; ?>" style="padding-left:17px;">
9
+ <div class="input">
10
+ <label><?php _e("Unique key"); ?></label>
11
+ <input type="text" class="smaller-text" name="unique_key" style="width:300px;" value="<?php echo esc_attr($post['unique_key']) ?>" <?php echo ! ($this->isWizard && $update_previous->isEmpty()) ? 'disabled="disabled"' : '' ?>/>
12
+ <a href="#help" class="help" title="<?php _e('Specify something that is unique for all records. If posts are being updated and not just created during a brand new import, the problem is that the value of the unique key is not unique.', 'pmxi_plugin') ?>">?</a>
13
+ </div>
14
+ </div>
15
+ <input type="radio" id="manual_matching_<?php echo $entry; ?>" class="switcher" name="duplicate_matching" value="manual" <?php echo 'manual' == $post['duplicate_matching'] ? 'checked="checked"': '' ?>/>
16
+ <label for="manual_matching_<?php echo $entry; ?>"><?php _e('Manual Record Matching', 'pmxi_plugin' )?></label>
17
+ <a href="#help" class="help" title="<?php _e('This allows you to match records by something other than Unique Key.', 'pmxi_plugin') ?>">?</a>
18
+ <div class="switcher-target-manual_matching_<?php echo $entry; ?>" style="padding-left:17px;">
19
+ <div class="input">
20
+ <span style="vertical-align:middle"><?php _e('Match records based on...', 'pmxi_plugin') ?></span><br>
21
+ <input type="radio" id="duplicate_indicator_title_<?php echo $entry; ?>" class="switcher" name="duplicate_indicator" value="title" <?php echo 'title' == $post['duplicate_indicator'] ? 'checked="checked"': '' ?>/>
22
+ <label for="duplicate_indicator_title_<?php echo $entry; ?>"><?php _e('title', 'pmxi_plugin' )?></label><br>
23
+ <input type="radio" id="duplicate_indicator_content_<?php echo $entry; ?>" class="switcher" name="duplicate_indicator" value="content" <?php echo 'content' == $post['duplicate_indicator'] ? 'checked="checked"': '' ?>/>
24
+ <label for="duplicate_indicator_content_<?php echo $entry; ?>"><?php _e('content', 'pmxi_plugin' )?></label><br>
25
+ <input type="radio" id="duplicate_indicator_custom_field_<?php echo $entry; ?>" class="switcher" name="duplicate_indicator" value="custom field" <?php echo 'custom field' == $post['duplicate_indicator'] ? 'checked="checked"': '' ?>/>
26
+ <label for="duplicate_indicator_custom_field_<?php echo $entry; ?>"><?php _e('custom field', 'pmxi_plugin' )?></label><br>
27
+ <span class="switcher-target-duplicate_indicator_custom_field_<?php echo $entry; ?>" style="vertical-align:middle" style="padding-left:17px;">
28
+ <?php _e('Name', 'pmxi_plugin') ?>
29
+ <input type="text" name="custom_duplicate_name" value="<?php echo esc_attr($post['custom_duplicate_name']) ?>" /><br>
30
+ <?php _e('Value', 'pmxi_plugin') ?>
31
+ <input type="text" name="custom_duplicate_value" value="<?php echo esc_attr($post['custom_duplicate_value']) ?>" />
32
+ </span>
33
+ </div>
34
+ </div>
35
+ </div>
36
+ <hr>
37
+ <div class="input">
38
+ <input type="hidden" name="not_create_records" value="0" />
39
+ <input type="checkbox" id="not_create_records_<?php echo $entry; ?>" name="not_create_records" value="1" <?php echo $post['not_create_records'] ? 'checked="checked"' : '' ?> />
40
+ <label for="not_create_records_<?php echo $entry; ?>"><?php _e('Do Not Add New Records', 'pmxi_plugin') ?></label>
41
+ </div>
42
+ <div class="input">
43
+ <input type="hidden" name="is_delete_missing" value="0" />
44
+ <input type="checkbox" id="is_delete_missing_<?php echo $entry; ?>" name="is_delete_missing" value="1" <?php echo $post['is_delete_missing'] ? 'checked="checked"': '' ?> class="switcher"/>
45
+ <label for="is_delete_missing_<?php echo $entry; ?>"><?php _e('Delete missing records', 'pmxi_plugin') ?></label>
46
+ <a href="#help" class="help" title="<?php _e('Check this option if you want to delete posts from previous import operation which are not found among newly impoprted set.', 'pmxi_plugin') ?>">?</a>
47
+ </div>
48
+ <div class="switcher-target-is_delete_missing_<?php echo $entry; ?>" style="padding-left:17px;">
49
+ <div class="input">
50
+ <input type="hidden" name="is_keep_attachments" value="0" />
51
+ <input type="checkbox" id="is_keep_attachments_<?php echo $entry; ?>" name="is_keep_attachments" value="1" <?php echo $post['is_keep_attachments'] ? 'checked="checked"': '' ?> />
52
+ <label for="is_keep_attachments_<?php echo $entry; ?>"><?php _e('Keep attachments when records removed', 'pmxi_plugin') ?></label>
53
+ <a href="#help" class="help" title="<?php _e('Check this option if you want attachments like featured image to be kept in media library after parent post or page is removed or replaced during reimport operation.', 'pmxi_plugin') ?>">?</a>
54
+ </div>
55
+ </div>
56
+ <div class="input">
57
+ <input type="radio" id="is_keep_former_posts_<?php echo $entry; ?>" name="is_keep_former_posts" value="yes" <?php echo "yes" == $post['is_keep_former_posts'] ? 'checked="checked"': '' ?> class="switcher" />
58
+ <label for="is_keep_former_posts_<?php echo $entry; ?>"><?php _e('Do not update already existing records', 'pmxi_plugin') ?></label> <br>
59
+ <input type="radio" id="is_not_keep_former_posts_<?php echo $entry; ?>" name="is_keep_former_posts" value="no" <?php echo "yes" != $post['is_keep_former_posts'] ? 'checked="checked"': '' ?> class="switcher" />
60
+ <label for="is_not_keep_former_posts_<?php echo $entry; ?>"><?php _e('Update existing records', 'pmxi_plugin') ?></label>
61
+ <div class="switcher-target-is_not_keep_former_posts_<?php echo $entry; ?>" style="padding-left:17px;">
62
+ <div class="input">
63
+ <input type="hidden" name="is_keep_status" value="0" />
64
+ <input type="checkbox" id="is_keep_status_<?php echo $entry; ?>" name="is_keep_status" value="1" <?php echo $post['is_keep_status'] ? 'checked="checked"': '' ?> />
65
+ <label for="is_keep_status_<?php echo $entry; ?>"><?php _e('Keep status', 'pmxi_plugin') ?></label>
66
+ <a href="#help" class="help" title="<?php _e('Check this option if you do not want previously imported posts to change their publish status or being restored from Trash.', 'pmxi_plugin') ?>">?</a>
67
+ </div>
68
+ <div class="input">
69
+ <input type="hidden" name="is_keep_title" value="0" />
70
+ <input type="checkbox" id="is_keep_title_<?php echo $entry; ?>" name="is_keep_title" value="1" <?php echo $post['is_keep_title'] ? 'checked="checked"': '' ?> />
71
+ <label for="is_keep_title_<?php echo $entry; ?>"><?php _e('Keep title', 'pmxi_plugin') ?></label>
72
+ <a href="#help" class="help" title="<?php _e('Check this option if you do not want previously imported posts to change their titles.', 'pmxi_plugin') ?>">?</a>
73
+ </div>
74
+ <div class="input">
75
+ <input type="hidden" name="is_keep_excerpt" value="0" />
76
+ <input type="checkbox" id="is_keep_excerpt_<?php echo $entry; ?>" name="is_keep_excerpt" value="1" <?php echo $post['is_keep_excerpt'] ? 'checked="checked"': '' ?> />
77
+ <label for="is_keep_excerpt_<?php echo $entry; ?>"><?php _e('Keep excerpt', 'pmxi_plugin') ?></label>
78
+ <a href="#help" class="help" title="<?php _e('Check this option if you do not want previously imported posts to change their excerpts.', 'pmxi_plugin') ?>">?</a>
79
+ </div>
80
+ <div class="input">
81
+ <input type="hidden" name="is_keep_dates" value="0" />
82
+ <input type="checkbox" id="is_keep_dates_<?php echo $entry; ?>" name="is_keep_dates" value="1" <?php echo $post['is_keep_dates'] ? 'checked="checked"': '' ?> />
83
+ <label for="is_keep_dates_<?php echo $entry; ?>"><?php _e('Keep dates', 'pmxi_plugin') ?></label>
84
+ <a href="#help" class="help" title="<?php _e('Check this option if you do not want previously imported posts to change their publish dates.', 'pmxi_plugin') ?>">?</a>
85
+ </div>
86
+ <div class="input">
87
+ <input type="hidden" name="is_keep_menu_order" value="0" />
88
+ <input type="checkbox" id="is_keep_menu_order_<?php echo $entry; ?>" name="is_keep_menu_order" value="1" <?php echo $post['is_keep_menu_order'] ? 'checked="checked"': '' ?> />
89
+ <label for="is_keep_menu_order_<?php echo $entry; ?>"><?php _e('Keep menu order', 'pmxi_plugin') ?></label>
90
+ <a href="#help" class="help" title="<?php _e('Check this option if you do not want previously imported posts to change their menu order.', 'pmxi_plugin') ?>">?</a>
91
+ </div>
92
+ <div class="input">
93
+ <input type="hidden" name="is_keep_content" value="0" />
94
+ <input type="checkbox" id="is_keep_content_<?php echo $entry; ?>" name="is_keep_content" value="1" <?php echo $post['is_keep_content'] ? 'checked="checked"': '' ?> />
95
+ <label for="is_keep_content_<?php echo $entry; ?>"><?php _e('Keep content', 'pmxi_plugin') ?></label>
96
+ <a href="#help" class="help" title="<?php _e('Check this option if you do not want previously imported posts to change their content.', 'pmxi_plugin') ?>">?</a>
97
+ </div>
98
+ <div class="input">
99
+ <input type="hidden" name="is_keep_categories" value="0" />
100
+ <input type="checkbox" id="is_keep_categories_<?php echo $entry; ?>" name="is_keep_categories" value="1" <?php echo $post['is_keep_categories'] ? 'checked="checked"': '' ?> />
101
+ <label for="is_keep_categories_<?php echo $entry; ?>"><?php _e('Keep categories, tags and taxonomies', 'pmxi_plugin') ?></label>
102
+ <a href="#help" class="help" title="<?php _e('Check this option if you do not want previously imported posts to change their category, tag and custom taxonomies associations upon reimport.', 'pmxi_plugin') ?>">?</a>
103
+ </div>
104
+ <div class="input">
105
+ <input type="hidden" name="is_keep_images" value="0" />
106
+ <input type="checkbox" id="is_keep_images_<?php echo $entry; ?>" name="is_keep_images" value="1" <?php echo $post['is_keep_images'] ? 'checked="checked"': '' ?> />
107
+ <label for="is_keep_images_<?php echo $entry; ?>"><?php _e('Do not import images', 'pmxi_plugin') ?></label>
108
+ <a href="#help" class="help" title="<?php _e('This will keep the featured image if it exists, so you could modify the post image manually, and then do a reimport, and it would not overwrite the manually modified post image.', 'pmxi_plugin') ?>">?</a>
109
+ </div>
110
+ <div class="input">
111
+ <input type="hidden" name="no_create_featured_image" value="0" />
112
+ <input type="checkbox" id="no_create_featured_image_<?php echo $entry; ?>" name="no_create_featured_image" value="1" <?php echo $post['no_create_featured_image'] ? 'checked="checked"': '' ?> />
113
+ <label for="no_create_featured_image_<?php echo $entry; ?>"><?php _e('Only keep images for posts that already have images.', 'pmxi_plugin') ?></label>
114
+ <a href="#help" class="help" title="<?php _e('This option will keep images for posts that already have images, and import images for posts that do not already have images.', 'pmxi_plugin') ?>">?</a>
115
+ </div>
116
+ <div class="input">
117
+ <input type="hidden" name="keep_custom_fields" value="0" />
118
+ <input type="checkbox" id="keep_custom_fields_<?php echo $entry; ?>" name="keep_custom_fields" value="1" <?php echo $post['keep_custom_fields'] ? 'checked="checked"': '' ?> class="switcher switcher-reversed"/>
119
+ <label for="keep_custom_fields_<?php echo $entry; ?>"><?php _e('Keep custom fields', 'pmxi_plugin') ?></label>
120
+ <a href="#help" class="help" title="<?php _e('If Keep Custom Fields box is checked, it will keep all Custom Fields, and add any new Custom Fields specified in Custom Fields section, as long as they do not overwrite existing fields. If \'Only keep this Custom Fields\' is specified, it will only keep the specified fields.', 'pmxi_plugin') ?>">?</a>
121
+ </div>
122
+ <div class="switcher-target-keep_custom_fields_<?php echo $entry; ?>" style="padding-left:17px;">
123
+ <div class="input">
124
+ <label for="keep_custom_fields_specific"><?php _e('Only Keep These Custom Fields <small>(separate field names with commas)</small>', 'pmxi_plugin') ?></label>
125
+ <input type="text" id="keep_custom_fields_specific" name="keep_custom_fields_specific" style="width:100%;" value="<?php echo esc_attr($post['keep_custom_fields_specific']) ?>" />
126
+ </div>
127
+ </div>
128
+ </div>
129
+ </div>
130
+ </fieldset>
131
+ </td>
132
+ </tr>
views/admin/import/options/_taxonomies_template.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $post_taxonomies = array_diff_key(get_taxonomies_by_object_type(array($post_type), 'object'), array_flip(array('category', 'post_tag', 'post_format')));
3
+ if ( ! empty($post_taxonomies)): ?>
4
+ <tr>
5
+ <td colspan="3">
6
+ <fieldset class="optionsset">
7
+ <legend>Custom Taxonomies</legend>
8
+ <?php foreach ($post_taxonomies as $ctx): ?>
9
+ <table>
10
+ <tr>
11
+ <td>
12
+ <div class="post_taxonomy">
13
+ <div class="col2" style="width:35%;">
14
+ <nobr><?php echo $ctx->labels->name ?></nobr>
15
+ </div>
16
+ <div class="col2" style="width:65%;">
17
+ <ol class="sortable no-margin">
18
+ <?php if (!empty($post['post_taxonomies'][$ctx->name])):
19
+ $taxonomies_hierarchy = json_decode($post['post_taxonomies'][$ctx->name]);
20
+ if (!empty($taxonomies_hierarchy) and is_array($taxonomies_hierarchy)): $i = 0; foreach ($taxonomies_hierarchy as $cat) { $i++;
21
+ if (is_null($cat->parent_id) or empty($cat->parent_id))
22
+ {
23
+ ?>
24
+ <li id="item_<?php echo $i; ?>">
25
+ <div class="drag-element"><input type="checkbox" class="assign_post" <?php if ($cat->assign): ?>checked="checked"<?php endif; ?>/><input type="text" class="widefat" value="<?php echo $cat->xpath; ?>"/></div><?php if ($i>1):?><a href="javascript:void(0);" class="icon-item remove-ico"></a><?php endif;?>
26
+ <?php echo reverse_taxonomies_html($taxonomies_hierarchy, $cat->item_id, $i); ?>
27
+ </li>
28
+ <?php
29
+ }
30
+ }; else:?>
31
+ <li id="item_1"><div class="drag-element"><input type="checkbox" class="assign_post" checked="checked"/><input type="text" class="widefat" value=""/></div></li>
32
+ <?php endif;
33
+ else: ?>
34
+ <li id="item_1"><div class="drag-element"><input type="checkbox" class="assign_post" checked="checked"/><input type="text" class="widefat" value=""/></div></li>
35
+ <?php endif; ?>
36
+ </ol>
37
+ <input type="hidden" class="hierarhy-output" name="post_taxonomies[<?php echo $ctx->name ?>]" value="<?php echo esc_attr($post['post_taxonomies'][$ctx->name]) ?>"/>
38
+ <div class="delim">
39
+ <label><?php _e('Separated by', 'pmxi_plugin'); ?></label>
40
+ <input type="text" class="small tax_delim" maxlength="1" value="<?php echo (!empty($ctx->delim)) ? $ctx->delim : ',' ?>" />
41
+ <a href="javascript:void(0);" class="icon-item add-new-ico">Add more</a>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ </td>
46
+ </tr>
47
+ </table>
48
+ <?php endforeach; ?>
49
+ </fieldset>
50
+ </td>
51
+ </tr>
52
+ <?php endif;
53
+ ?>
views/admin/import/process.php CHANGED
@@ -1,31 +1,112 @@
1
  <div class="inner-content">
2
  <h2><?php _e('Import XML - <span id="status">Processing...</span>', 'pmxi_plugin') ?></h2>
3
- <hr />
4
-
5
- <p><?php _e('Importing may take some time. Please do not close browser or refresh the page untill process is complete.', 'pmxi_plugin') ?></p>
 
 
 
 
 
 
 
 
 
 
 
6
  </div>
7
 
8
  <script type="text/javascript">
9
  //<![CDATA[
10
  (function($){
11
  $('#status').each(function () {
 
 
 
 
 
 
 
 
 
 
 
 
12
  var $this = $(this);
13
  if ($this.html().match(/\.{3}$/)) {
14
  var dots = 0;
15
  var status = $this.html().replace(/\.{3}$/, '');
16
- var interval ;
 
17
  interval = setInterval(function () {
18
- if ($this.html().match(new RegExp(status + '\\.{1,3}$', ''))) {
19
- $this.html(status + '...'.substr(0, dots++ % 3 + 1));
20
- } else {
21
- clearInterval(interval);
22
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  }, 1000);
 
24
  }
25
  });
26
  window.onbeforeunload = function () {
27
  return 'WARNING:\nImport process in under way, leaving the page will interrupt\nthe operation and most likely to cause leftovers in posts.';
28
- };
29
  })(jQuery);
 
30
  //]]>
31
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <div class="inner-content">
2
  <h2><?php _e('Import XML - <span id="status">Processing...</span>', 'pmxi_plugin') ?></h2>
3
+ <hr />
4
+ <p id="process_notice"><?php _e('Importing may take some time. Please do not close your browser or refresh the page until the process is complete.', 'pmxi_plugin') ?></p>
5
+ <?php _e('<div id="processbar"><div></div><span id="import_progress"><span id="left_progress">Time Elapsed <span id="then">00:00:00</span></span><span id="center_progress"> Created 0 / Updated 0 </span><span id="right_progress">0%</span></span></div>', 'pmxi_plugin'); ?>
6
+ <div id="logbar">
7
+ <a href="javascript:void(0);" id="view_log">View Log</a><span id="download_log_separator"> | </span> <a href="javascript:void(0);" id="download_log">Download Log</a>
8
+ <p>Warnings (<span id="warnings">0</span>), Errors (<span id="errors">0</span>)</p>
9
+ </div>
10
+ <fieldset id="logwrapper" <?php if ($_SESSION['pmxi_import']['large_file']): ?> style="display:none;" <?php endif; ?>>
11
+ <legend>Log</legend>
12
+ <div id="loglist">
13
+
14
+ </div>
15
+ </fieldset>
16
+ <a href="<?php echo add_query_arg(array('page' => 'pmxi-admin-manage'), remove_query_arg(array('id','page'), $this->baseUrl)); ?>" style="float:right; display:none;" id="import_finished"><?php _e('Manage Imports', 'pmxi_plugin') ?></a>
17
  </div>
18
 
19
  <script type="text/javascript">
20
  //<![CDATA[
21
  (function($){
22
  $('#status').each(function () {
23
+
24
+ var then = $('#then');
25
+ start_date = moment().sod();
26
+ update = function(){
27
+ var duration = moment.duration({'seconds' : 1});
28
+ start_date.add(duration);
29
+
30
+ if ( ! $('#download_pmxi_log').length) then.html(start_date.format('HH:mm:ss'));
31
+ };
32
+ update();
33
+ setInterval(update, 1000);
34
+
35
  var $this = $(this);
36
  if ($this.html().match(/\.{3}$/)) {
37
  var dots = 0;
38
  var status = $this.html().replace(/\.{3}$/, '');
39
+ var interval ;
40
+ var odd = false;
41
  interval = setInterval(function () {
42
+ var percents = $('.import_percent:last').html();
43
+ if ($this.html().match(new RegExp(status + '\\.{1,3}$', ''))) {
44
+ if (percents != null && percents != ''){
45
+ $this.html(status + '...'.substr(0, dots++ % 3 + 1));
46
+ var msg = $('.import_process_bar:last').html();
47
+ if (msg != undefined) $('#center_progress').html(msg);
48
+ $('#warnings').html($('.warnings_count:last').html());
49
+ $('#errors').html($('.errors_count:last').html());
50
+ $('#right_progress').html(((parseInt(percents) > 100 || percents == undefined) ? 100 : percents) + '%');
51
+ $('#processbar div').css({'width': ((parseInt(percents) > 100 || percents == undefined) ? 100 : percents) + '%'});
52
+ }
53
+ } else {
54
+ var msg = $('.import_process_bar:last').html();
55
+ if (msg != undefined) $('#center_progress').html(msg);
56
+ $('#right_progress').html(((parseInt(percents) > 100 || percents == undefined) ? 100 : percents) + '%');
57
+ $('#warnings').html($('.warnings_count:last').html());
58
+ $('#errors').html($('.errors_count:last').html());
59
+ $('#processbar div').css({'width': ((parseInt(percents) > 100 || percents == undefined) ? 100 : percents) + '%'});
60
+ $('#process_notice').hide();
61
+ $('#import_finished').show();
62
+ clearInterval(update);
63
+ clearInterval(interval);
64
+ }
65
+ if ($('#download_pmxi_log').length){
66
+ $('#download_log').attr('href', $('#download_pmxi_log').attr('href')).show();
67
+ $('#download_log_separator').show();
68
+ }
69
+ // fill log bar
70
+ $('.progress-msg').each(function(i){
71
+ if ( ! $(this).find('.import_process_bar').length){
72
+ <?php if ($_SESSION['pmxi_import']['large_file']): ?>
73
+ if ($('#loglist').find('p').length > 100) $('#loglist').html('');
74
+ <?php endif; ?>
75
+ $('#loglist').append('<p ' + ((odd) ? 'class="odd"' : 'class="even"') + '>' + $(this).html() + '</p>');
76
+ $('#loglist').animate({ scrollTop: $('#loglist').get(0).scrollHeight }, 0);
77
+ $(this).remove();
78
+ odd = !odd;
79
+ }
80
+ });
81
+
82
  }, 1000);
83
+ $('#processbar').css({'visibility':'visible'});
84
  }
85
  });
86
  window.onbeforeunload = function () {
87
  return 'WARNING:\nImport process in under way, leaving the page will interrupt\nthe operation and most likely to cause leftovers in posts.';
88
+ };
89
  })(jQuery);
90
+
91
  //]]>
92
+ </script>
93
+
94
+ <?php if ($_SESSION['pmxi_import']['large_file']): ?>
95
+
96
+ <script type="text/javascript">
97
+ //<![CDATA[
98
+ (function($){
99
+ function parse_element(){
100
+ $.post('admin.php?page=pmxi-admin-import&action=process', {}, function (data) {
101
+ $('#loglist').append(data);
102
+ if ( ! $('#download_pmxi_log').length) parse_element();
103
+ }, 'html').fail(function() {
104
+ if ( ! $('#download_pmxi_log').length) parse_element();
105
+ });
106
+ }
107
+ parse_element();
108
+ })(jQuery);
109
+ //]]>
110
+ </script>
111
+
112
+ <?php endif; ?>
views/admin/import/tag.php CHANGED
@@ -1,12 +1,15 @@
1
  <div class="tag">
2
  <input type="hidden" name="tagno" value="<?php echo $tagno ?>" />
3
  <div class="title">
4
- <?php printf(__('Record #<strong>%s</strong> out of <strong>%s</strong>', 'pmxi_plugin'), $tagno, $elements->length) ?>
5
  <div class="navigation">
6
  <?php if ($tagno > 1): ?><a href="#prev">&lang;&lang;</a><?php else: ?><span>&lang;&lang;</span><?php endif ?>
7
- <?php if ($tagno < $elements->length): ?><a href="#next">&rang;&rang;</a><?php else: ?><span>&rang;&rang;</span><?php endif ?>
8
  </div>
9
  </div>
10
- <div class="clear"></div>
11
- <div class="xml resetable"> <?php if (!empty($elements)) $this->render_xml_element($elements->item($tagno - 1), true); ?></div>
 
 
 
12
  </div>
1
  <div class="tag">
2
  <input type="hidden" name="tagno" value="<?php echo $tagno ?>" />
3
  <div class="title">
4
+ <?php printf(__('Record #<strong>%s</strong> out of <strong>%s</strong>', 'pmxi_plugin'), $tagno, ( ! $_SESSION['pmxi_import']['large_file']) ? $elements->length : $_SESSION['pmxi_import']['count']); ?>
5
  <div class="navigation">
6
  <?php if ($tagno > 1): ?><a href="#prev">&lang;&lang;</a><?php else: ?><span>&lang;&lang;</span><?php endif ?>
7
+ <?php if ($tagno < $elements->length or ($_SESSION['pmxi_import']['large_file'] and $tagno < $_SESSION['pmxi_import']['count'])): ?><a href="#next">&rang;&rang;</a><?php else: ?><span>&rang;&rang;</span><?php endif ?>
8
  </div>
9
  </div>
10
+ <div class="clear"></div>
11
+ <div class="xml resetable"> <?php if (!empty($elements->length)) $this->render_xml_element(( ! $_SESSION['pmxi_import']['large_file']) ? $elements->item($tagno - 1) : $elements->item(0), true); ?></div>
12
+ <p class="xpath_help">
13
+ <?php _e('Operate on elements using your own PHP functions, use FOREACH loops, and more.<br />Read the <a href="http://www.wpallimport.com/portal/" target="_blank">documentation</a> to learn how.', 'pmxi_plugin') ?>
14
+ </p>
15
  </div>
views/admin/import/template.php CHANGED
@@ -1,81 +1,92 @@
1
  <form class="template <?php echo ! $this->isWizard ? 'edit' : '' ?>" method="post">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  <table class="layout">
3
- <tr>
4
- <td class="left">
5
- <h2>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  <?php $templates = new PMXI_Template_List() ?>
7
- <span class="load-template">
 
8
  <select name="load_template">
9
  <option value=""><?php _e('Load Template...', 'pmxi_plugin') ?></option>
10
  <?php foreach ($templates->getBy()->convertRecords() as $t): ?>
11
  <option value="<?php echo $t->id ?>"><?php echo $t->name ?></option>
12
  <?php endforeach ?>
13
- </select><a href="#help" class="help" title="<?php _e('Select a <b>Template</b> from the dropdown and it will be preloaded', 'pmxi_plugin') ?>">?</a>
14
- </span>
15
- <?php if ($this->isWizard): ?>
16
- <?php _e('Import XML/CSV - Step 3: Template Designer', 'pmxi_plugin') ?><br/><span class="taglines"><?php _e('arrange your data and design your posts', 'pmxi_plugin') ?></span>
17
- <?php else: ?>
18
- <?php _e('Edit Import Template', 'pmxi_plugin') ?>
19
- <?php endif ?>
20
- </h2>
21
- <hr/>
22
-
23
- <?php if ($this->errors->get_error_codes()): ?>
24
- <?php $this->error() ?>
25
- <?php endif ?>
26
-
27
- <h3>Post Title</h3>
28
- <div style="width:100%">
29
- <input id="title" class="widefat" type="text" name="title" value="<?php echo esc_attr($post['title']) ?>" />
30
- </div>
31
-
32
- <h3>
33
- <span class="header-option">
34
- <input type="hidden" name="is_keep_linebreaks" value="0" />
35
- <input type="checkbox" id="is_keep_linebreaks" name="is_keep_linebreaks" value="1" <?php echo $post['is_keep_linebreaks'] ? 'checked="checked"' : '' ?> />
36
- <label for="is_keep_linebreaks"><?php _e('Keep line breaks from XML', 'pmxi_plugin') ?></label>
37
- </span>
38
- Post Content
39
- </h3>
40
- <div id="poststuff">
41
- <div id="<?php echo user_can_richedit() ? 'postdivrich' : 'postdiv'; ?>" class="postarea">
42
-
43
- <?php the_editor($post['content']) ?>
44
- <table id="post-status-info" cellspacing="0">
45
- <tbody>
46
- <tr>
47
- <td id="wp-word-count"></td>
48
- <td class="autosave-info">
49
- <span id="autosave">&nbsp;</span>
50
- </td>
51
- </tr>
52
- </tbody>
53
- </table>
54
  </div>
55
- </div>
56
- <p>
57
- <?php wp_nonce_field('template', '_wpnonce_template') ?>
58
- <input type="hidden" name="is_submitted" value="1" />
59
- <?php if ($this->isWizard): ?>
60
- <a href="<?php echo add_query_arg('action', 'element', $this->baseUrl) ?>" class="button back"><?php _e('Back', 'pmxi_plugin') ?></a>
61
- &nbsp;
62
- <input type="submit" class="button-primary" value="<?php _e('Continue', 'pmxi_plugin') ?> &gt;&gt;" />
63
- <input type="text" name="name" title="<?php _e('Save Template As...', 'pmxi_plugin') ?>" style="vertical-align:middle" value="<?php echo esc_attr($post['name']) ?>" />
64
- &nbsp;
65
- <a href="#preview" class="button preview" title="<?php _e('Preview Post', 'pmxi_plugin') ?>"><?php _e('Preview', 'pmxi_plugin') ?></a>
66
- <?php else: ?>
67
- <input type="submit" class="button-primary" value="<?php _e('Edit', 'pmxi_plugin') ?>" />
68
- <input type="text" name="name" title="<?php _e('Save Template As...', 'pmxi_plugin') ?>" style="vertical-align:middle" value="<?php echo esc_attr($post['name']) ?>" />
69
- <?php endif ?>
70
- </p>
71
- </td>
72
- <?php if ($this->isWizard or $this->isTemplateEdit): ?>
73
- <td class="right">
74
- <p><?php _e('Drag &amp; Drop opening tag of an element for inserting corresponding XPath into template or title.', 'pmxi_plugin') ?></p>
75
- <p><?php _e('<a href="http://www.wpallimport.com/template-syntax/" target="_blank">Template Syntax Documentation</a>', 'pmxi_plugin') ?> - includes information on looping and shortcodes.</p>
76
- <?php $this->tag() ?>
77
  </td>
78
- <?php endif ?>
79
- </tr>
 
 
 
 
80
  </table>
81
  </form>
1
  <form class="template <?php echo ! $this->isWizard ? 'edit' : '' ?>" method="post">
2
+ <h2>
3
+ <?php if ($this->isWizard): ?>
4
+ <?php _e('Import XML/CSV - Step 3: Template Builder', 'pmxi_plugin') ?>
5
+ <?php else: ?>
6
+ <?php _e('Edit Import Template', 'pmxi_plugin') ?>
7
+ <?php endif ?>
8
+ </h2>
9
+
10
+ <?php if ($this->errors->get_error_codes()): ?>
11
+ <?php $this->error() ?>
12
+ <?php endif ?>
13
+
14
+ <h3>Drag-and-drop an element from the right to the left to build your template</h3>
15
+
16
  <table class="layout">
17
+ <tr>
18
+ <td class="left">
19
+ <h3>Post Title</h3>
20
+ <div style="width:100%">
21
+ <input id="title" class="widefat" type="text" name="title" value="<?php echo esc_attr($post['title']) ?>" />
22
+ </div>
23
+
24
+ <h3>
25
+ Post Content
26
+ </h3>
27
+ <div id="poststuff">
28
+ <div id="<?php echo user_can_richedit() ? 'postdivrich' : 'postdiv'; ?>" class="postarea">
29
+
30
+ <?php the_editor($post['content']) ?>
31
+ <table id="post-status-info" cellspacing="0">
32
+ <tbody>
33
+ <tr>
34
+ <td id="wp-word-count"></td>
35
+ <td class="autosave-info">
36
+ <span id="autosave">&nbsp;</span>
37
+ </td>
38
+ </tr>
39
+ </tbody>
40
+ </table>
41
+ </div>
42
+ </div>
43
+ <p>
44
+ <span class="header-option">
45
+ <input type="hidden" name="is_keep_linebreaks" value="0" />
46
+ <input type="checkbox" id="is_keep_linebreaks" name="is_keep_linebreaks" value="1" <?php echo $post['is_keep_linebreaks'] ? 'checked="checked"' : '' ?> style="position:relative; top:-3px;"/>
47
+ <label for="is_keep_linebreaks"><?php _e('Keep line breaks from XML', 'pmxi_plugin') ?></label> <br>
48
+ <input type="hidden" name="is_leave_html" value="0" />
49
+ <input type="checkbox" id="is_leave_html" name="is_leave_html" value="1" <?php echo $post['is_leave_html'] ? 'checked="checked"' : '' ?> style="position:relative; top:-3px;"/>
50
+ <label for="is_leave_html"><?php _e('Decode HTML entities with <b>html_entity_decode</b>', 'pmxi_plugin') ?></label><a class="help" href="#help" original-title="If HTML code is showing up in your posts, use this option. You can also use <br /><br /><i>[html_entity_decode({my/xpath})]</i><br /><br /> or <br /><br /><i>[htmlentities({my/xpath})]</i><br /><br /> to decode or encode HTML in your file.">?</a>
51
+ </span>
52
+ </p>
53
+ <hr>
54
+ <p style="clear:both;">
55
+ <?php wp_nonce_field('template', '_wpnonce_template'); ?>
56
+ <input type="hidden" name="is_submitted" value="1" />
57
+ <div class="input">
58
+ <input type="checkbox" id="save_template_as" name="save_template_as" value="1" <?php echo $post['save_template_as'] ? 'checked="checked"' : '' ?> style="position:relative; top:-2px;"/> <label for="save_template_as">Save template as:</label> &nbsp;<input type="text" name="name" title="<?php _e('Save Template As...', 'pmxi_plugin') ?>" style="vertical-align:middle; font-size:13px;" value="<?php echo esc_attr($post['name']) ?>" />
59
+ </div>
60
+ </p>
61
+
62
  <?php $templates = new PMXI_Template_List() ?>
63
+ <div class="load-template">
64
+ <span>Load existing template: </span>
65
  <select name="load_template">
66
  <option value=""><?php _e('Load Template...', 'pmxi_plugin') ?></option>
67
  <?php foreach ($templates->getBy()->convertRecords() as $t): ?>
68
  <option value="<?php echo $t->id ?>"><?php echo $t->name ?></option>
69
  <?php endforeach ?>
70
+ </select>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  </div>
72
+
73
+ <p>
74
+ <span class="submit-buttons" style="float:right;">
75
+ <?php if ($this->isWizard):?>
76
+ <a href="<?php echo add_query_arg('action', 'element', $this->baseUrl) ?>" class="back"><?php _e('Back', 'pmxi_plugin') ?></a>
77
+ <?php else: ?>
78
+ <a href="<?php echo remove_query_arg('id', remove_query_arg('action', $this->baseUrl)); ?>" class="back"><?php _e('Back', 'pmxi_plugin') ?></a>
79
+ <?php endif; ?>
80
+ <a href="#preview" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only large_button preview" title="<?php _e('Preview Post', 'pmxi_plugin') ?>"><?php _e('Preview', 'pmxi_plugin') ?></a>
81
+ <input type="submit" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only large_button" value="<?php _e( ($this->isWizard) ? 'Next' : 'Update', 'pmxi_plugin') ?>" />
82
+ </span>
83
+ </p>
 
 
 
 
 
 
 
 
 
 
84
  </td>
85
+ <?php if ($this->isWizard or $this->isTemplateEdit): ?>
86
+ <td class="right template-sidebar">
87
+ <?php $this->tag() ?>
88
+ </td>
89
+ <?php endif ?>
90
+ </tr>
91
  </table>
92
  </form>
views/admin/manage/delete.php CHANGED
@@ -2,11 +2,13 @@
2
 
3
  <form method="post">
4
  <p><?php printf(__('Are you sure you want to delete <strong>%s</strong> import?', 'pmxi_plugin'), $item->name) ?></p>
5
- <p><input type="checkbox" id="is_delete_posts" name="is_delete_posts" /> <label for="is_delete_posts">Delete associated posts as well</label></p>
 
 
6
  <p class="submit">
7
  <?php wp_nonce_field('delete-import', '_wpnonce_delete-import') ?>
8
  <input type="hidden" name="is_confirmed" value="1" />
9
- <input type="submit" class="button-primary" value="Delete" />
10
  </p>
11
 
12
  </form>
2
 
3
  <form method="post">
4
  <p><?php printf(__('Are you sure you want to delete <strong>%s</strong> import?', 'pmxi_plugin'), $item->name) ?></p>
5
+ <div class="input">
6
+ <input type="checkbox" id="is_delete_posts" name="is_delete_posts" /> <label for="is_delete_posts">Delete associated posts as well</label>
7
+ </div>
8
  <p class="submit">
9
  <?php wp_nonce_field('delete-import', '_wpnonce_delete-import') ?>
10
  <input type="hidden" name="is_confirmed" value="1" />
11
+ <input type="submit" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" value="Delete" />
12
  </p>
13
 
14
  </form>
views/admin/manage/index.php CHANGED
@@ -1,7 +1,7 @@
1
  <h2>
2
  <?php _e('Manage Imports', 'pmxi_plugin') ?>
3
  &nbsp;
4
- <a href="<?php echo esc_url(add_query_arg(array('page' => 'pmxi-admin-import'), admin_url('admin.php'))) ?>" class="add-new"><?php echo esc_html_x('New Import', 'pmxi_plugin'); ?></a>
5
  </h2>
6
 
7
  <?php if ($this->errors->get_error_codes()): ?>
@@ -21,16 +21,19 @@
21
  // define the columns to display, the syntax is 'internal name' => 'display name'
22
  $columns = array(
23
  'id' => __('ID', 'pmxi_plugin'),
24
- 'name' => __('XML File', 'pmxi_plugin'),
25
- 'scheduled' => __('Recurring', 'pmxi_plugin'),
26
- 'registered_on' => __('Executed On', 'pmxi_plugin'),
27
- 'post_count' => __('Posts/Pages', 'pmxi_plugin'),
 
 
 
28
  );
29
  ?>
30
  <form method="post" id="import-list" action="<?php echo remove_query_arg('pmxi_nt') ?>">
31
  <input type="hidden" name="action" value="bulk" />
32
  <?php wp_nonce_field('bulk-imports', '_wpnonce_bulk-imports') ?>
33
-
34
  <div class="tablenav">
35
  <div class="alignleft actions">
36
  <select name="bulk-action">
@@ -53,7 +56,7 @@ $columns = array(
53
  <?php endif ?>
54
  </div>
55
  <div class="clear"></div>
56
-
57
  <table class="widefat pmxi-admin-imports">
58
  <thead>
59
  <tr>
@@ -67,7 +70,7 @@ $columns = array(
67
  $order2 = 'ASC';
68
  if ($order_by == $column_id)
69
  $order2 = ($order == 'DESC') ? 'ASC' : 'DESC';
70
-
71
  $column_link .= esc_url(add_query_arg(array('order' => $order2, 'order_by' => $column_id), $this->baseUrl));
72
  $column_link .= "'>{$column_display_name}</a>";
73
  $col_html .= '<th scope="col" class="column-' . $column_id . ' ' . ($order_by == $column_id ? $order : '') . '">' . $column_link . '</th>';
@@ -89,22 +92,8 @@ $columns = array(
89
  <tr>
90
  <td colspan="<?php echo count($columns) + 1 ?>"><?php _e('No previous imports found.', 'pmxi_plugin') ?></td>
91
  </tr>
92
- <?php else: ?>
93
- <?php
94
- $periods = array( // scheduling periods
95
- '*/5 * * * *' => __('every 5 min'),
96
- '*/10 * * * *' => __('every 10 min'),
97
- '*/30 * * * *' => __('half-hourly'),
98
- '0 * * * *' => __('hourly'),
99
- '0 */4 * * *' => __('every 4 hours'),
100
- '0 */12 * * *' => __('half-daily'),
101
- '0 0 * * *' => __('daily'),
102
- '0 0 * * 1' => __('weekly'),
103
- '0 0 1 * 1' => __('monthly'),
104
- );
105
- $class = '';
106
- ?>
107
- <?php foreach ($list as $item): ?>
108
  <?php $class = ('alternate' == $class) ? '' : 'alternate'; ?>
109
  <tr class="<?php echo $class; ?>" valign="middle">
110
  <th scope="row" class="check-column">
@@ -119,11 +108,15 @@ $columns = array(
119
  <?php echo $item['id'] ?>
120
  </th>
121
  <?php
122
- break;
123
- case 'scheduled':
124
  ?>
125
  <td>
126
- <?php echo $item['scheduled'] ? $periods[$item['scheduled']] : '' ?>
 
 
 
 
127
  </td>
128
  <?php
129
  break;
@@ -138,22 +131,50 @@ $columns = array(
138
  </td>
139
  <?php
140
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  case 'name':
142
  ?>
143
  <td>
144
- <strong><?php echo $item['name'] ?></strong>
145
  <?php if ($item['path']): ?>
146
- - <em><?php echo preg_replace('%^(\w+://[^:]+:)[^@]+@%', '$1*****@', $item['path']) ?></em>
147
  <?php endif ?>
148
  <div class="row-actions">
149
- <?php if (in_array($item['type'], array('url', 'ftp', 'file'))): ?>
150
- <span class="update"><a class="update" href="<?php echo esc_url(add_query_arg(array('id' => $item['id'], 'action' => 'update'), $this->baseUrl)) ?>"><?php _e('Update', 'pmxi_plugin') ?></a></span> |
151
- <?php endif ?>
 
 
 
152
  <span class="delete"><a class="delete" href="<?php echo esc_url(add_query_arg(array('id' => $item['id'], 'action' => 'delete'), $this->baseUrl)) ?>"><?php _e('Delete', 'pmxi_plugin') ?></a></span>
 
 
 
153
  </div>
154
  </td>
155
  <?php
156
  break;
 
 
 
 
 
 
 
157
  case 'post_count':
158
  ?>
159
  <td>
@@ -176,10 +197,10 @@ $columns = array(
176
  <?php endif ?>
177
  </tbody>
178
  </table>
179
-
180
  <div class="tablenav">
181
  <?php if ($page_links): ?><div class="tablenav-pages"><?php echo $page_links_html ?></div><?php endif ?>
182
-
183
  <div class="alignleft actions">
184
  <select name="bulk-action2">
185
  <option value="" selected="selected"><?php _e('Bulk Actions', 'pmxi_plugin') ?></option>
@@ -194,5 +215,5 @@ $columns = array(
194
  </div>
195
  </div>
196
  <div class="clear"></div>
197
- <a href="http://www.wpallimport.com/upgrade-to-pro?from=mi" target="_blank">Upgrade to pro to edit import options or perform re-imports/recurring imports.</a>
198
  </form>
1
  <h2>
2
  <?php _e('Manage Imports', 'pmxi_plugin') ?>
3
  &nbsp;
4
+ <a href="<?php echo esc_url(add_query_arg(array('page' => 'pmxi-admin-import'), admin_url('admin.php'))) ?>" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" style="font-size:15px; padding:10px 20px; text-decoration:none;"><?php echo esc_html_x('New Import', 'pmxi_plugin'); ?></a>
5
  </h2>
6
 
7
  <?php if ($this->errors->get_error_codes()): ?>
21
  // define the columns to display, the syntax is 'internal name' => 'display name'
22
  $columns = array(
23
  'id' => __('ID', 'pmxi_plugin'),
24
+ 'name' => __('File', 'pmxi_plugin'),
25
+ 'xpath' => __('XPath', 'pmxi_plugin'),
26
+ 'post_count' => __('Records', 'pmxi_plugin'),
27
+ 'first_import' => __('First Import', 'pmxi_plugin'),
28
+ 'registered_on' => __('Last Import', 'pmxi_plugin'),
29
+ /*'scheduled' => __('Reimport Schedule', 'pmxi_plugin'),
30
+ 'next_import' => __('Next Import', 'pmxi_plugin'),*/
31
  );
32
  ?>
33
  <form method="post" id="import-list" action="<?php echo remove_query_arg('pmxi_nt') ?>">
34
  <input type="hidden" name="action" value="bulk" />
35
  <?php wp_nonce_field('bulk-imports', '_wpnonce_bulk-imports') ?>
36
+
37
  <div class="tablenav">
38
  <div class="alignleft actions">
39
  <select name="bulk-action">
56
  <?php endif ?>
57
  </div>
58
  <div class="clear"></div>
59
+
60
  <table class="widefat pmxi-admin-imports">
61
  <thead>
62
  <tr>
70
  $order2 = 'ASC';
71
  if ($order_by == $column_id)
72
  $order2 = ($order == 'DESC') ? 'ASC' : 'DESC';
73
+
74
  $column_link .= esc_url(add_query_arg(array('order' => $order2, 'order_by' => $column_id), $this->baseUrl));
75
  $column_link .= "'>{$column_display_name}</a>";
76
  $col_html .= '<th scope="col" class="column-' . $column_id . ' ' . ($order_by == $column_id ? $order : '') . '">' . $column_link . '</th>';
92
  <tr>
93
  <td colspan="<?php echo count($columns) + 1 ?>"><?php _e('No previous imports found.', 'pmxi_plugin') ?></td>
94
  </tr>
95
+ <?php else: ?>
96
+ <?php $class = ''; foreach ($list as $item): ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  <?php $class = ('alternate' == $class) ? '' : 'alternate'; ?>
98
  <tr class="<?php echo $class; ?>" valign="middle">
99
  <th scope="row" class="check-column">
108
  <?php echo $item['id'] ?>
109
  </th>
110
  <?php
111
+ break;
112
+ case 'first_import':
113
  ?>
114
  <td>
115
+ <?php if ('0000-00-00 00:00:00' == $item['first_import']): ?>
116
+ <em>never</em>
117
+ <?php else: ?>
118
+ <?php echo mysql2date(__('Y/m/d g:i a', 'pmxi_plugin'), $item['first_import']) ?>
119
+ <?php endif ?>
120
  </td>
121
  <?php
122
  break;
131
  </td>
132
  <?php
133
  break;
134
+ case 'next_import':
135
+ ?>
136
+ <td>
137
+ <?php if ('0000-00-00 00:00:00' == $item['registered_on'] or empty($item['scheduled'])): ?>
138
+ <em>never</em>
139
+ <?php
140
+ else:
141
+ $task = new _PMXI_Import_Record_Cron_Parser($item['scheduled']);
142
+ $task_date = $task->getNextRunDate();
143
+ echo mysql2date(__('Y/m/d g:i a', 'pmxi_plugin'), $task_date->format('Y-m-d H:i:s'));
144
+ endif;
145
+ ?>
146
+ </td>
147
+ <?php
148
+ break;
149
  case 'name':
150
  ?>
151
  <td>
152
+ <strong><?php echo (!empty($item['friendly_name'])) ? $item['friendly_name'] : $item['name']; ?></strong> <br>
153
  <?php if ($item['path']): ?>
154
+ <em><?php echo str_replace("\\", '/', preg_replace('%^(\w+://[^:]+:)[^@]+@%', '$1*****@', $item['path'])); ?></em>
155
  <?php endif ?>
156
  <div class="row-actions">
157
+
158
+ <span class="edit"><a class="edit" href="<?php echo esc_url(add_query_arg(array('id' => $item['id'], 'action' => 'edit'), $this->baseUrl)) ?>"><?php _e('Edit Template', 'pmxi_plugin') ?></a></span> |
159
+ <span class="edit"><a class="edit" href="<?php echo esc_url(add_query_arg(array('id' => $item['id'], 'action' => 'options'), $this->baseUrl)) ?>"><?php _e('Edit Options', 'pmxi_plugin') ?></a></span> |
160
+ <span class="update"><a class="update" href="<?php echo esc_url(add_query_arg(array('id' => $item['id'], 'action' => 'update'), $this->baseUrl)) ?>"><?php _e('Update', 'pmxi_plugin') ?></a></span> |
161
+ <span class="update"><a class="update" href="<?php echo esc_url(add_query_arg(array('page' => 'pmxi-admin-import', 'id' => $item['id']), admin_url('admin.php'))) ?>"><?php _e('Use New File', 'pmxi_plugin') ?></a></span> |
162
+ <span class="update"><a class="update" href="<?php echo esc_url(add_query_arg(array('id' => $item['id'], 'action' => 'log'), $this->baseUrl)) ?>"><?php _e('Download Log', 'pmxi_plugin') ?></a></span> |
163
  <span class="delete"><a class="delete" href="<?php echo esc_url(add_query_arg(array('id' => $item['id'], 'action' => 'delete'), $this->baseUrl)) ?>"><?php _e('Delete', 'pmxi_plugin') ?></a></span>
164
+ <?php if ( "Yes" == $item['large_import'] and $item['imported'] != $item['count']):?>
165
+ | <span class="update"><a class="update" href="<?php echo esc_url(add_query_arg(array('id' => $item['id'], 'action' => 'update', 'type' => 'continue'), $this->baseUrl)) ?>"><?php _e('Continue import', 'pmxi_plugin') ?></a></span>
166
+ <?php endif; ?>
167
  </div>
168
  </td>
169
  <?php
170
  break;
171
+ case 'xpath':
172
+ ?>
173
+ <td>
174
+ <?php echo $item['xpath'];?>
175
+ </td>
176
+ <?php
177
+ break;
178
  case 'post_count':
179
  ?>
180
  <td>
197
  <?php endif ?>
198
  </tbody>
199
  </table>
200
+
201
  <div class="tablenav">
202
  <?php if ($page_links): ?><div class="tablenav-pages"><?php echo $page_links_html ?></div><?php endif ?>
203
+
204
  <div class="alignleft actions">
205
  <select name="bulk-action2">
206
  <option value="" selected="selected"><?php _e('Bulk Actions', 'pmxi_plugin') ?></option>
215
  </div>
216
  </div>
217
  <div class="clear"></div>
218
+ <a href="http://www.wpallimport.com/upgrade-to-pro?from=upi" target="_blank" class="upgrade_link">Upgrade to the paid edition of WP All Import to use this feature.</a>
219
  </form>
views/admin/manage/update.php CHANGED
@@ -12,7 +12,7 @@
12
  <p class="submit">
13
  <?php wp_nonce_field('update-import', '_wpnonce_update-import') ?>
14
  <input type="hidden" name="is_confirmed" value="1" />
15
- <input type="submit" class="button-primary ajax-update" value="Create Posts" />
16
  </p>
17
 
18
  </form>
12
  <p class="submit">
13
  <?php wp_nonce_field('update-import', '_wpnonce_update-import') ?>
14
  <input type="hidden" name="is_confirmed" value="1" />
15
+ <input type="submit" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ajax-update" value="Create Posts" />
16
  </p>
17
 
18
  </form>
views/admin/settings/index.php CHANGED
@@ -37,10 +37,9 @@
37
  <div><?php printf(__('post_max_size %s', 'pmxi_plugin'), ini_get('post_max_size')) ?></div>
38
  <div><?php printf(__('max_execution_time %s', 'pmxi_plugin'), ini_get('max_execution_time')) ?></div>
39
  <div><?php printf(__('max_input_time %s', 'pmxi_plugin'), ini_get('max_input_time')) ?></div>
40
- <h3><?php _e('XML parsing filters', 'pmxi_plugin') ?></h3>
41
 
42
- <div><?php printf(__('Filter XML contains HTML entities %s', 'pmxi_plugin'), '<input type="radio" name="html_entities" value="1" '.((!empty($post['html_entities'])) ? 'checked="checked"' : '').' /> Yes <input type="radio" name="html_entities" value="0" '.((empty($post['html_entities'])) ? 'checked="checked"' : '').' /> No') ?></div>
43
- <div><?php printf(__('UTF-8 decode %s', 'pmxi_plugin'), '<input type="radio" name="utf8_decode" value="1" '.((!empty($post['utf8_decode'])) ? 'checked="checked"' : '').' /> Yes <input type="radio" name="utf8_decode" value="0" '.((empty($post['utf8_decode'])) ? 'checked="checked"' : '').' /> No') ?></div>
44
  <p class="submit-buttons">
45
  <?php wp_nonce_field('edit-settings', '_wpnonce_edit-settings') ?>
46
  <input type="hidden" name="is_settings_submitted" value="1" />
37
  <div><?php printf(__('post_max_size %s', 'pmxi_plugin'), ini_get('post_max_size')) ?></div>
38
  <div><?php printf(__('max_execution_time %s', 'pmxi_plugin'), ini_get('max_execution_time')) ?></div>
39
  <div><?php printf(__('max_input_time %s', 'pmxi_plugin'), ini_get('max_input_time')) ?></div>
 
40
 
41
+ <h3><?php _e('Recurring & Scheduled Imports', 'pmxi_plugin') ?></h3>
42
+ <a href="http://www.wpallimport.com/upgrade-to-pro?from=upi" target="_blank" class="upgrade_link">Upgrade to the paid edition of WP All Import to use this feature.</a>
43
  <p class="submit-buttons">
44
  <?php wp_nonce_field('edit-settings', '_wpnonce_edit-settings') ?>
45
  <input type="hidden" name="is_settings_submitted" value="1" />