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

RevLine 
[0]1<?php
[3731]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
[3699]12if (!defined('DC_RC_PATH')) {return;}
[0]13
14class dcImportFlat extends dcIeModule
15{
[3699]16    protected $status = false;
[2485]17
[3699]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    }
[2485]24
[3699]25    public function process($do)
26    {
27        if ($do == 'single' || $do == 'full') {
28            $this->status = $do;
29            return;
30        }
[2485]31
[3699]32        $to_unlink = false;
[2485]33
[3699]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        }
[2485]42
[3699]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            }
[2485]54
[3699]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                }
[2485]65
[3699]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        }
[2485]80
[3699]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        }
[2485]88
[3699]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            }
[2485]93
[3699]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            }
[2485]104
[3699]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                }
[2485]115
[3699]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        }
[2485]130
[3699]131        header('content-type:text/plain');
132        var_dump($_POST);
133        exit;
[2485]134
[3699]135        $this->status = true;
136    }
[2485]137
[3699]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        }
[2485]148
[3874]149        $public_files = array_merge(['-' => ''], $this->getPublicFiles());
[3699]150        $has_files    = (boolean) (count($public_files) - 1);
[2485]151
[3699]152        echo
[3993]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'));
[3699]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>' .
[2485]160
[3699]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>';
[2485]165
[3699]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        }
[2485]172
[3699]173        echo
174        '<p>' .
175        $this->core->formNonce() .
[3874]176        form::hidden(['do'], 1) .
177        form::hidden(['MAX_FILE_SIZE'], DC_MAX_UPLOAD_SIZE) .
[3699]178        '<input type="submit" value="' . __('Import') . '" /></p>' .
[2485]179
[3699]180            '</form>';
[2485]181
[3699]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>' .
[2485]187
[3699]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>';
[2485]192
[3699]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            }
[2485]199
[3699]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,
[3874]203                [
[3699]204                    'extra_html'   => 'required placeholder="' . __('Password') . '"',
205                    'autocomplete' => 'current-password'
[3874]206                ]
[3699]207            ) . '</p>' .
[2485]208
[3699]209            '<p>' .
210            $this->core->formNonce() .
[3874]211            form::hidden(['do'], 1) .
212            form::hidden(['MAX_FILE_SIZE'], DC_MAX_UPLOAD_SIZE) .
[3699]213            '<input type="submit" value="' . __('Import') . '" /></p>' .
[2485]214
[3699]215                '</form>';
216        }
217    }
[2485]218
[3699]219    protected function getPublicFiles()
220    {
[3874]221        $public_files = [];
[3699]222        $dir          = @dir($this->core->blog->public_path);
223        if ($dir) {
224            while (($entry = $dir->read()) !== false) {
225                $entry_path = $dir->path . '/' . $entry;
[2485]226
[3699]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    }
[2485]239
[3699]240    protected static function checkFileContent($entry_path)
241    {
242        $ret = false;
[2485]243
[3699]244        $fp  = fopen($entry_path, 'rb');
245        $ret = strpos(fgets($fp), '///DOTCLEAR|') === 0;
246        fclose($fp);
[2485]247
[3699]248        return $ret;
249    }
[2485]250
[3699]251    private function unzip($file)
252    {
253        $zip = new fileUnzip($file);
[2485]254
[3699]255        if ($zip->isEmpty()) {
256            $zip->close();
257            return false; //throw new Exception(__('File is empty or not a compressed file.'));
258        }
[2485]259
[3699]260        foreach ($zip->getFilesList() as $zip_file) {
261            # Check zipped file name
262            if (substr($zip_file, -4) != '.txt') {
263                continue;
264            }
[2485]265
[3699]266            # Check zipped file contents
267            $content = $zip->unzip($zip_file);
268            if (strpos($content, '///DOTCLEAR|') !== 0) {
269                unset($content);
270                continue;
271            }
[2485]272
[3699]273            $target = path::fullFromRoot($zip_file, dirname($file));
[2485]274
[3699]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            }
[2485]281
[3699]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            }
[2485]288
[3699]289            $zip->close();
290            unset($content);
[2485]291
[3699]292            # Return extracted file name
293            return $target;
294        }
[2485]295
[3699]296        $zip->close();
297        throw new Exception(__('No backup in compressed file.'));
298    }
[0]299}
Note: See TracBrowser for help on using the repository browser.

Sites map