importdelicious.php 11 KB
Newer Older
1 2 3 4 5 6
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2010, StatusNet, Inc.
 *
 * Import del.icio.us bookmarks backups
Siebrand Mazeland's avatar
Siebrand Mazeland committed
7
 *
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
 * PHP version 5
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Bookmark
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2010 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */

if (!defined('STATUSNET')) {
    // This check helps protect against security problems;
    // your code file can't be executed directly from the web.
    exit(1);
}

/**
 * UI for importing del.icio.us bookmark backups
 *
 * @category  Bookmark
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2010 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */
class ImportdeliciousAction extends Action
{
    protected $success = false;
50
    private $inprogress = false;
51

Evan Prodromou's avatar
Evan Prodromou committed
52 53 54 55 56
    /**
     * Return the title of the page
     *
     * @return string page title
     */
57 58
    function title()
    {
Siebrand Mazeland's avatar
Siebrand Mazeland committed
59
        // TRANS: Title for page to import del.icio.us bookmark backups on.
60
        return _m("Import del.icio.us bookmarks");
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
    }

    /**
     * For initializing members of the class.
     *
     * @param array $argarray misc. arguments
     *
     * @return boolean true
     */
    function prepare($argarray)
    {
        parent::prepare($argarray);

        $cur = common_current_user();

        if (empty($cur)) {
Siebrand Mazeland's avatar
Siebrand Mazeland committed
77
            // TRANS: Client exception thrown when trying to import bookmarks without being logged in.
78
            throw new ClientException(_m('Only logged-in users can '.
Evan Prodromou's avatar
Evan Prodromou committed
79 80
                                        'import del.icio.us backups.'),
                                      403);
81 82 83
        }

        if (!$cur->hasRight(BookmarkPlugin::IMPORTDELICIOUS)) {
Siebrand Mazeland's avatar
Siebrand Mazeland committed
84
            // TRANS: Client exception thrown when trying to import bookmarks without having the rights to do so.
85
            throw new ClientException(_m('You may not restore your account.'), 403);
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
        }

        return true;
    }

    /**
     * Handler method
     *
     * @param array $argarray is ignored since it's now passed in in prepare()
     *
     * @return void
     */
    function handle($argarray=null)
    {
        parent::handle($argarray);

        if ($this->isPost()) {
            $this->importDelicious();
        } else {
            $this->showPage();
        }
        return;
    }

    /**
     * Queue a file for importation
Siebrand Mazeland's avatar
Siebrand Mazeland committed
112
     *
113 114 115 116 117 118 119 120 121
     * Uses the DeliciousBackupImporter class; may take a long time!
     *
     * @return void
     */
    function importDelicious()
    {
        $this->checkSessionToken();

        if (!isset($_FILES[ImportDeliciousForm::FILEINPUT]['error'])) {
Siebrand Mazeland's avatar
Siebrand Mazeland committed
122
            // TRANS: Client exception thrown when trying to import bookmarks and upload fails.
123
            throw new ClientException(_m('No uploaded file.'));
124 125 126 127 128 129
        }

        switch ($_FILES[ImportDeliciousForm::FILEINPUT]['error']) {
        case UPLOAD_ERR_OK: // success, jump out
            break;
        case UPLOAD_ERR_INI_SIZE:
Evan Prodromou's avatar
Evan Prodromou committed
130
            // TRANS: Client exception thrown when an uploaded file is too large.
131
            throw new ClientException(_m('The uploaded file exceeds the ' .
132 133 134 135
                'upload_max_filesize directive in php.ini.'));
            return;
        case UPLOAD_ERR_FORM_SIZE:
            throw new ClientException(
Siebrand Mazeland's avatar
Siebrand Mazeland committed
136
            // TRANS: Client exception thrown when an uploaded file is too large.
137
                _m('The uploaded file exceeds the MAX_FILE_SIZE directive' .
138 139 140 141
                ' that was specified in the HTML form.'));
            return;
        case UPLOAD_ERR_PARTIAL:
            @unlink($_FILES[ImportDeliciousForm::FILEINPUT]['tmp_name']);
Siebrand Mazeland's avatar
Siebrand Mazeland committed
142
            // TRANS: Client exception thrown when a file was only partially uploaded.
143
            throw new ClientException(_m('The uploaded file was only' .
144 145 146 147
                ' partially uploaded.'));
            return;
        case UPLOAD_ERR_NO_FILE:
            // No file; probably just a non-AJAX submission.
Siebrand Mazeland's avatar
Siebrand Mazeland committed
148
            // TRANS: Client exception thrown when a file upload has failed.
149
            throw new ClientException(_m('No uploaded file.'));
150 151
            return;
        case UPLOAD_ERR_NO_TMP_DIR:
Siebrand Mazeland's avatar
Siebrand Mazeland committed
152
            // TRANS: Client exception thrown when a temporary folder is not present.
153
            throw new ClientException(_m('Missing a temporary folder.'));
154 155
            return;
        case UPLOAD_ERR_CANT_WRITE:
Siebrand Mazeland's avatar
Siebrand Mazeland committed
156
            // TRANS: Client exception thrown when writing to disk is not possible.
157
            throw new ClientException(_m('Failed to write file to disk.'));
158 159
            return;
        case UPLOAD_ERR_EXTENSION:
Siebrand Mazeland's avatar
Siebrand Mazeland committed
160
            // TRANS: Client exception thrown when a file upload has been stopped.
161
            throw new ClientException(_m('File upload stopped by extension.'));
162 163 164 165
            return;
        default:
            common_log(LOG_ERR, __METHOD__ . ": Unknown upload error " .
                $_FILES[ImportDeliciousForm::FILEINPUT]['error']);
Siebrand Mazeland's avatar
Siebrand Mazeland committed
166
            // TRANS: Client exception thrown when a file upload operation has failed.
167
            throw new ClientException(_m('System error uploading file.'));
168 169 170 171 172 173 174
            return;
        }

        $filename = $_FILES[ImportDeliciousForm::FILEINPUT]['tmp_name'];

        try {
            if (!file_exists($filename)) {
Siebrand Mazeland's avatar
Siebrand Mazeland committed
175 176 177
                // TRANS: Server exception thrown when a file upload cannot be found.
                // TRANS: %s is the file that could not be found.
                throw new ServerException(sprintf(_m('No such file "%s".'),$filename));
178
            }
Siebrand Mazeland's avatar
Siebrand Mazeland committed
179

180
            if (!is_file($filename)) {
Siebrand Mazeland's avatar
Siebrand Mazeland committed
181 182 183
                // TRANS: Server exception thrown when a file upload is incorrect.
                // TRANS: %s is the irregular file.
                throw new ServerException(sprintf(_m('Not a regular file: "%s".'),$filename));
184
            }
Siebrand Mazeland's avatar
Siebrand Mazeland committed
185

186
            if (!is_readable($filename)) {
Siebrand Mazeland's avatar
Siebrand Mazeland committed
187 188 189
                // TRANS: Server exception thrown when a file upload is not readable.
                // TRANS: %s is the file that could not be read.
                throw new ServerException(sprintf(_m('File "%s" not readable.'),$filename));
190
            }
Siebrand Mazeland's avatar
Siebrand Mazeland committed
191 192

            common_debug(sprintf("Getting backup from file '%s'.", $filename));
193 194 195 196 197 198 199 200

            $html = file_get_contents($filename);

            // Enqueue for processing.

            $qm = QueueManager::get();
            $qm->enqueue(array(common_current_user(), $html), 'dlcsback');

201 202 203 204 205 206 207
            if ($qm instanceof UnQueueManager) {
                // No active queuing means we've actually just completed the job!
                $this->success = true;
            } else {
                // We've fed data into background queues, and it's probably still running.
                $this->inprogress = true;
            }
208 209 210 211 212 213 214 215 216 217

            $this->showPage();

        } catch (Exception $e) {
            // Delete the file and re-throw
            @unlink($_FILES[ImportDeliciousForm::FILEINPUT]['tmp_name']);
            throw $e;
        }
    }

Evan Prodromou's avatar
Evan Prodromou committed
218 219 220 221 222
    /**
     * Show the content of the page
     *
     * @return void
     */
223 224 225 226
    function showContent()
    {
        if ($this->success) {
            $this->element('p', null,
Siebrand Mazeland's avatar
Siebrand Mazeland committed
227
                           // TRANS: Success message after importing bookmarks.
228
                           _m('Bookmarks have been imported. Your bookmarks should now appear in search and your profile page.'));
229 230
        } else if ($this->inprogress) {
            $this->element('p', null,
Siebrand Mazeland's avatar
Siebrand Mazeland committed
231
                           // TRANS: Busy message for importing bookmarks.
232
                           _m('Bookmarks are being imported. Please wait a few minutes for results.'));
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
        } else {
            $form = new ImportDeliciousForm($this);
            $form->show();
        }
    }

    /**
     * Return true if read only.
     *
     * MAY override
     *
     * @param array $args other arguments
     *
     * @return boolean is read only action?
     */
    function isReadOnly($args)
    {
        return !$this->isPost();
    }
}

/**
 * A form for backing up the account.
 *
 * @category  Account
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2010 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */
class ImportDeliciousForm extends Form
{
    const FILEINPUT = 'deliciousbackupfile';

Evan Prodromou's avatar
Evan Prodromou committed
268 269
    /**
     * Constructor
Siebrand Mazeland's avatar
Siebrand Mazeland committed
270
     *
Evan Prodromou's avatar
Evan Prodromou committed
271 272 273 274 275 276 277 278
     * Set the encoding type, since this is a file upload.
     *
     * @param HTMLOutputter $out output channel
     *
     * @return ImportDeliciousForm this
     */
    function __construct($out=null)
    {
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
        parent::__construct($out);
        $this->enctype = 'multipart/form-data';
    }

    /**
     * Class of the form.
     *
     * @return string the form's class
     */
    function formClass()
    {
        return 'form_import_delicious';
    }

    /**
     * URL the form posts to
     *
     * @return string the form's action URL
     */
    function action()
    {
        return common_local_url('importdelicious');
    }

    /**
     * Output form data
Siebrand Mazeland's avatar
Siebrand Mazeland committed
305
     *
306 307 308 309 310 311 312 313
     * Really, just instructions for doing a backup.
     *
     * @return void
     */
    function formData()
    {
        $this->out->elementStart('p', 'instructions');

Siebrand Mazeland's avatar
Siebrand Mazeland committed
314
        // TRANS: Form instructions for importing bookmarks.
315
        $this->out->raw(_m('You can upload a backed-up '.
Evan Prodromou's avatar
Evan Prodromou committed
316
                          'delicious.com bookmarks file.'));
Siebrand Mazeland's avatar
Siebrand Mazeland committed
317

318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
        $this->out->elementEnd('p');

        $this->out->elementStart('ul', 'form_data');

        $this->out->elementStart('li', array ('id' => 'settings_attach'));
        $this->out->element('input', array('name' => self::FILEINPUT,
                                           'type' => 'file',
                                           'id' => self::FILEINPUT));
        $this->out->elementEnd('li');

        $this->out->elementEnd('ul');
    }

    /**
     * Buttons for the form
Siebrand Mazeland's avatar
Siebrand Mazeland committed
333
     *
334 335 336 337 338 339 340 341
     * In this case, a single submit button
     *
     * @return void
     */

    function formActions()
    {
        $this->out->submit('submit',
Siebrand Mazeland's avatar
Siebrand Mazeland committed
342
                           // TRANS: Button text on form to import bookmarks.
343 344 345
                           _m('BUTTON', 'Upload'),
                           'submit',
                           null,
Siebrand Mazeland's avatar
Siebrand Mazeland committed
346 347
                           // TRANS: Button title on form to import bookmarks.
                           _m('Upload the file.'));
348 349
    }
}