Dotclear

source: plugins/importExport/inc/class.dc.import.flat.php @ 3993:c402c96de044

Revision 3993:c402c96de044, 10.0 KB checked in by franck <carnet.franck.paul@…>, 6 years ago (diff)

Switching from inline JS variables to JSON script, import/export plugin

Line 
1<?php
2/**
3 * @brief importExport, a plugin for Dotclear 2
4 *
5 * @package Dotclear
6 * @subpackage Plugins
7 *
8 * @copyright Olivier Meunier & Association Dotclear
9 * @copyright GPL-2.0-only
10 */
11
12if (!defined('DC_RC_PATH')) {return;}
13
14class dcImportFlat extends dcIeModule
15{
16    protected $status = false;
17
18    public function setInfo()
19    {
20        $this->type        = 'import';
21        $this->name        = __('Flat file import');
22        $this->description = __('Imports a blog or a full Dotclear installation from flat file.');
23    }
24
25    public function process($do)
26    {
27        if ($do == 'single' || $do == 'full') {
28            $this->status = $do;
29            return;
30        }
31
32        $to_unlink = false;
33
34        # Single blog import
35        $files      = $this->getPublicFiles();
36        $single_upl = null;
37        if (!empty($_POST['public_single_file']) && in_array($_POST['public_single_file'], $files)) {
38            $single_upl = false;
39        } elseif (!empty($_FILES['up_single_file'])) {
40            $single_upl = true;
41        }
42
43        if ($single_upl !== null) {
44            if ($single_upl) {
45                files::uploadStatus($_FILES['up_single_file']);
46                $file = DC_TPL_CACHE . '/' . md5(uniqid());
47                if (!move_uploaded_file($_FILES['up_single_file']['tmp_name'], $file)) {
48                    throw new Exception(__('Unable to move uploaded file.'));
49                }
50                $to_unlink = true;
51            } else {
52                $file = $_POST['public_single_file'];
53            }
54
55            try {
56                # Try to unzip file
57                $unzip_file = $this->unzip($file);
58                if (false !== $unzip_file) {
59                    $bk = new flatImport($this->core, $unzip_file);
60                }
61                # Else this is a normal file
62                else {
63                    $bk = new flatImport($this->core, $file);
64                }
65
66                $bk->importSingle();
67            } catch (Exception $e) {
68                @unlink($unzip_file);
69                if ($to_unlink) {
70                    @unlink($file);
71                }
72                throw $e;
73            }
74            @unlink($unzip_file);
75            if ($to_unlink) {
76                @unlink($file);
77            }
78            http::redirect($this->getURL() . '&do=single');
79        }
80
81        # Full import
82        $full_upl = null;
83        if (!empty($_POST['public_full_file']) && in_array($_POST['public_full_file'], $files)) {
84            $full_upl = false;
85        } elseif (!empty($_FILES['up_full_file'])) {
86            $full_upl = true;
87        }
88
89        if ($full_upl !== null && $this->core->auth->isSuperAdmin()) {
90            if (empty($_POST['your_pwd']) || !$this->core->auth->checkPassword($_POST['your_pwd'])) {
91                throw new Exception(__('Password verification failed'));
92            }
93
94            if ($full_upl) {
95                files::uploadStatus($_FILES['up_full_file']);
96                $file = DC_TPL_CACHE . '/' . md5(uniqid());
97                if (!move_uploaded_file($_FILES['up_full_file']['tmp_name'], $file)) {
98                    throw new Exception(__('Unable to move uploaded file.'));
99                }
100                $to_unlink = true;
101            } else {
102                $file = $_POST['public_full_file'];
103            }
104
105            try {
106                # Try to unzip file
107                $unzip_file = $this->unzip($file);
108                if (false !== $unzip_file) {
109                    $bk = new flatImport($this->core, $unzip_file);
110                }
111                # Else this is a normal file
112                else {
113                    $bk = new flatImport($this->core, $file);
114                }
115
116                $bk->importFull();
117            } catch (Exception $e) {
118                @unlink($unzip_file);
119                if ($to_unlink) {
120                    @unlink($file);
121                }
122                throw $e;
123            }
124            @unlink($unzip_file);
125            if ($to_unlink) {
126                @unlink($file);
127            }
128            http::redirect($this->getURL() . '&do=full');
129        }
130
131        header('content-type:text/plain');
132        var_dump($_POST);
133        exit;
134
135        $this->status = true;
136    }
137
138    public function gui()
139    {
140        if ($this->status == 'single') {
141            dcPage::success(__('Single blog successfully imported.'));
142            return;
143        }
144        if ($this->status == 'full') {
145            dcPage::success(__('Content successfully imported.'));
146            return;
147        }
148
149        $public_files = array_merge(['-' => ''], $this->getPublicFiles());
150        $has_files    = (boolean) (count($public_files) - 1);
151
152        echo
153        dcPage::jsJson('ie_import_flat_msg',
154            ['confirm_full_import' => __('Are you sure you want to import a full backup file?')]) .
155        dcPage::jsLoad(dcPage::getPF('importExport/js/import_flat.js'));
156        echo
157        '<form action="' . $this->getURL(true) . '" method="post" enctype="multipart/form-data" class="fieldset">' .
158        '<h3>' . __('Single blog') . '</h3>' .
159        '<p>' . sprintf(__('This will import a single blog backup as new content in the current blog: <strong>%s</strong>.'), html::escapeHTML($this->core->blog->name)) . '</p>' .
160
161        '<p><label for="up_single_file">' . __('Upload a backup file') .
162        ' (' . sprintf(__('maximum size %s'), files::size(DC_MAX_UPLOAD_SIZE)) . ')' . ' </label>' .
163            ' <input type="file" id="up_single_file" name="up_single_file" size="20" />' .
164            '</p>';
165
166        if ($has_files) {
167            echo
168            '<p><label for="public_single_file" class="">' . __('or pick up a local file in your public directory') . ' </label> ' .
169            form::combo('public_single_file', $public_files) .
170                '</p>';
171        }
172
173        echo
174        '<p>' .
175        $this->core->formNonce() .
176        form::hidden(['do'], 1) .
177        form::hidden(['MAX_FILE_SIZE'], DC_MAX_UPLOAD_SIZE) .
178        '<input type="submit" value="' . __('Import') . '" /></p>' .
179
180            '</form>';
181
182        if ($this->core->auth->isSuperAdmin()) {
183            echo
184            '<form action="' . $this->getURL(true) . '" method="post" enctype="multipart/form-data" id="formfull" class="fieldset">' .
185            '<h3>' . __('Multiple blogs') . '</h3>' .
186            '<p class="warning">' . __('This will reset all the content of your database, except users.') . '</p>' .
187
188            '<p><label for="up_full_file">' . __('Upload a backup file') . ' ' .
189            ' (' . sprintf(__('maximum size %s'), files::size(DC_MAX_UPLOAD_SIZE)) . ')' . ' </label>' .
190                '<input type="file" id="up_full_file" name="up_full_file" size="20" />' .
191                '</p>';
192
193            if ($has_files) {
194                echo
195                '<p><label for="public_full_file">' . __('or pick up a local file in your public directory') . ' </label>' .
196                form::combo('public_full_file', $public_files) .
197                    '</p>';
198            }
199
200            echo
201            '<p><label for="your_pwd" class="required"><abbr title="' . __('Required field') . '">*</abbr> ' . __('Your password:') . '</label>' .
202            form::password('your_pwd', 20, 255,
203                [
204                    'extra_html'   => 'required placeholder="' . __('Password') . '"',
205                    'autocomplete' => 'current-password'
206                ]
207            ) . '</p>' .
208
209            '<p>' .
210            $this->core->formNonce() .
211            form::hidden(['do'], 1) .
212            form::hidden(['MAX_FILE_SIZE'], DC_MAX_UPLOAD_SIZE) .
213            '<input type="submit" value="' . __('Import') . '" /></p>' .
214
215                '</form>';
216        }
217    }
218
219    protected function getPublicFiles()
220    {
221        $public_files = [];
222        $dir          = @dir($this->core->blog->public_path);
223        if ($dir) {
224            while (($entry = $dir->read()) !== false) {
225                $entry_path = $dir->path . '/' . $entry;
226
227                if (is_file($entry_path) && is_readable($entry_path)) {
228                    # Do not test each zip file content here, its too long
229                    if (substr($entry_path, -4) == '.zip') {
230                        $public_files[$entry] = $entry_path;
231                    } elseif (self::checkFileContent($entry_path)) {
232                        $public_files[$entry] = $entry_path;
233                    }
234                }
235            }
236        }
237        return $public_files;
238    }
239
240    protected static function checkFileContent($entry_path)
241    {
242        $ret = false;
243
244        $fp  = fopen($entry_path, 'rb');
245        $ret = strpos(fgets($fp), '///DOTCLEAR|') === 0;
246        fclose($fp);
247
248        return $ret;
249    }
250
251    private function unzip($file)
252    {
253        $zip = new fileUnzip($file);
254
255        if ($zip->isEmpty()) {
256            $zip->close();
257            return false; //throw new Exception(__('File is empty or not a compressed file.'));
258        }
259
260        foreach ($zip->getFilesList() as $zip_file) {
261            # Check zipped file name
262            if (substr($zip_file, -4) != '.txt') {
263                continue;
264            }
265
266            # Check zipped file contents
267            $content = $zip->unzip($zip_file);
268            if (strpos($content, '///DOTCLEAR|') !== 0) {
269                unset($content);
270                continue;
271            }
272
273            $target = path::fullFromRoot($zip_file, dirname($file));
274
275            # Check existing files with same name
276            if (file_exists($target)) {
277                $zip->close();
278                unset($content);
279                throw new Exception(__('Another file with same name exists.'));
280            }
281
282            # Extract backup content
283            if (file_put_contents($target, $content) === false) {
284                $zip->close();
285                unset($content);
286                throw new Exception(__('Failed to extract backup file.'));
287            }
288
289            $zip->close();
290            unset($content);
291
292            # Return extracted file name
293            return $target;
294        }
295
296        $zip->close();
297        throw new Exception(__('No backup in compressed file.'));
298    }
299}
Note: See TracBrowser for help on using the repository browser.

Sites map