2013-05-02 20:41:26 +02:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* @author Thomas Tanghus
|
|
|
|
* Copyright (c) 2013 Thomas Tanghus (thomas@tanghus.net)
|
|
|
|
* This file is licensed under the Affero General Public License version 3 or
|
|
|
|
* later.
|
|
|
|
* See the COPYING-README file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace OCA\Contacts\Controller;
|
|
|
|
|
2013-09-24 13:39:45 +02:00
|
|
|
use OCA\Contacts\App,
|
2013-09-17 18:46:59 +02:00
|
|
|
OCA\Contacts\JSONResponse,
|
|
|
|
OCA\Contacts\Controller,
|
|
|
|
Sabre\VObject;
|
2013-05-02 20:41:26 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Controller importing contacts
|
|
|
|
*/
|
2013-09-17 18:46:59 +02:00
|
|
|
class ImportController extends Controller {
|
2013-05-02 20:41:26 +02:00
|
|
|
|
|
|
|
/**
|
2013-09-24 13:39:45 +02:00
|
|
|
* @NoAdminRequired
|
2013-05-02 20:41:26 +02:00
|
|
|
*/
|
|
|
|
public function upload() {
|
|
|
|
$request = $this->request;
|
|
|
|
$params = $this->request->urlParams;
|
|
|
|
$response = new JSONResponse();
|
|
|
|
|
|
|
|
$view = \OCP\Files::getStorage('contacts');
|
|
|
|
if(!$view->file_exists('imports')) {
|
|
|
|
$view->mkdir('imports');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isset($request->files['file'])) {
|
|
|
|
$response->bailOut(App::$l10n->t('No file was uploaded. Unknown error'));
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
|
|
|
|
$file=$request->files['file'];
|
|
|
|
|
|
|
|
if($file['error'] !== UPLOAD_ERR_OK) {
|
|
|
|
$errors = array(
|
|
|
|
UPLOAD_ERR_OK => App::$l10n->t("There is no error, the file uploaded with success"),
|
|
|
|
UPLOAD_ERR_INI_SIZE => App::$l10n->t("The uploaded file exceeds the upload_max_filesize directive in php.ini")
|
|
|
|
.ini_get('upload_max_filesize'),
|
|
|
|
UPLOAD_ERR_FORM_SIZE => App::$l10n->t("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form"),
|
|
|
|
UPLOAD_ERR_PARTIAL => App::$l10n->t("The uploaded file was only partially uploaded"),
|
|
|
|
UPLOAD_ERR_NO_FILE => App::$l10n->t("No file was uploaded"),
|
|
|
|
UPLOAD_ERR_NO_TMP_DIR => App::$l10n->t('Missing a temporary folder'),
|
|
|
|
UPLOAD_ERR_CANT_WRITE => App::$l10n->t('Failed to write to disk'),
|
|
|
|
);
|
|
|
|
$response->bailOut($errors[$error]);
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
|
|
|
|
$maxUploadFilesize = \OCP\Util::maxUploadFilesize('/');
|
|
|
|
$maxHumanFilesize = \OCP\Util::humanFileSize($maxUploadFilesize);
|
|
|
|
|
|
|
|
$totalSize = $file['size'];
|
|
|
|
if ($maxUploadFilesize >= 0 and $totalSize > $maxUploadFilesize) {
|
|
|
|
$response->bailOut(App::$l10n->t('Not enough storage available'));
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
|
|
|
|
$tmpname = $file['tmp_name'];
|
|
|
|
$filename = strtr($file['name'], array('/' => '', "\\" => ''));
|
|
|
|
if(is_uploaded_file($tmpname)) {
|
|
|
|
if(\OC\Files\Filesystem::isFileBlacklisted($filename)) {
|
|
|
|
$response->bailOut(App::$l10n->t('Attempt to upload blacklisted file:') . $filename);
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
$content = file_get_contents($tmpname);
|
2013-08-15 20:11:10 +02:00
|
|
|
$proxyStatus = \OC_FileProxy::$enabled;
|
|
|
|
\OC_FileProxy::$enabled = false;
|
2013-05-02 20:41:26 +02:00
|
|
|
if($view->file_put_contents('/imports/'.$filename, $content)) {
|
2013-08-15 20:11:10 +02:00
|
|
|
\OC_FileProxy::$enabled = $proxyStatus;
|
2013-05-02 20:41:26 +02:00
|
|
|
$count = substr_count($content, 'BEGIN:');
|
|
|
|
$progresskey = 'contacts-import-' . rand();
|
|
|
|
$response->setParams(
|
|
|
|
array(
|
|
|
|
'filename'=>$filename,
|
|
|
|
'count' => $count,
|
|
|
|
'progresskey' => $progresskey,
|
|
|
|
'backend' => $params['backend'],
|
|
|
|
'addressbookid' => $params['addressbookid']
|
|
|
|
)
|
|
|
|
);
|
|
|
|
\OC_Cache::set($progresskey, '10', 300);
|
|
|
|
} else {
|
2013-08-15 20:11:10 +02:00
|
|
|
\OC_FileProxy::$enabled = $proxyStatus;
|
2013-05-02 20:41:26 +02:00
|
|
|
$response->bailOut(App::$l10n->t('Error uploading contacts to storage.'));
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$response->bailOut('Temporary file: \''.$tmpname.'\' has gone AWOL?');
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
|
2013-09-10 00:28:16 +02:00
|
|
|
/**
|
2013-09-24 13:39:45 +02:00
|
|
|
* @NoAdminRequired
|
2013-09-10 00:28:16 +02:00
|
|
|
*/
|
|
|
|
public function prepare() {
|
|
|
|
$request = $this->request;
|
|
|
|
$params = $this->request->urlParams;
|
|
|
|
$response = new JSONResponse();
|
|
|
|
$filename = $request->post['filename'];
|
|
|
|
$path = $request->post['path'];
|
|
|
|
|
|
|
|
$view = \OCP\Files::getStorage('contacts');
|
|
|
|
if(!$view->file_exists('imports')) {
|
|
|
|
$view->mkdir('imports');
|
|
|
|
}
|
|
|
|
|
|
|
|
$proxyStatus = \OC_FileProxy::$enabled;
|
|
|
|
\OC_FileProxy::$enabled = false;
|
|
|
|
$content = \OC_Filesystem::file_get_contents($path . '/' . $filename);
|
|
|
|
if($view->file_put_contents('/imports/' . $filename, $content)) {
|
|
|
|
\OC_FileProxy::$enabled = $proxyStatus;
|
|
|
|
$count = substr_count($content, 'BEGIN:');
|
|
|
|
$progresskey = 'contacts-import-' . rand();
|
|
|
|
$response->setParams(
|
|
|
|
array(
|
|
|
|
'filename'=>$filename,
|
|
|
|
'count' => $count,
|
|
|
|
'progresskey' => $progresskey,
|
|
|
|
'backend' => $params['backend'],
|
|
|
|
'addressbookid' => $params['addressbookid']
|
|
|
|
)
|
|
|
|
);
|
|
|
|
\OC_Cache::set($progresskey, '10', 300);
|
|
|
|
} else {
|
|
|
|
\OC_FileProxy::$enabled = $proxyStatus;
|
|
|
|
$response->bailOut(App::$l10n->t('Error moving file to imports folder.'));
|
|
|
|
}
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
|
2013-05-02 20:41:26 +02:00
|
|
|
/**
|
2013-09-24 13:39:45 +02:00
|
|
|
* @NoAdminRequired
|
2013-05-02 20:41:26 +02:00
|
|
|
*/
|
|
|
|
public function start() {
|
|
|
|
$request = $this->request;
|
|
|
|
$response = new JSONResponse();
|
|
|
|
$params = $this->request->urlParams;
|
|
|
|
$app = new App($this->api->getUserId());
|
|
|
|
|
|
|
|
$addressBook = $app->getAddressBook($params['backend'], $params['addressbookid']);
|
2013-05-20 23:36:49 +02:00
|
|
|
if(!$addressBook->hasPermission(\OCP\PERMISSION_CREATE)) {
|
2013-05-18 00:07:58 +02:00
|
|
|
$response->setStatus('403');
|
|
|
|
$response->bailOut(App::$l10n->t('You do not have permissions to import into this address book.'));
|
|
|
|
return $response;
|
|
|
|
}
|
2013-05-02 20:41:26 +02:00
|
|
|
|
|
|
|
$filename = isset($request->post['filename']) ? $request->post['filename'] : null;
|
|
|
|
$progresskey = isset($request->post['progresskey']) ? $request->post['progresskey'] : null;
|
|
|
|
|
|
|
|
if(is_null($filename)) {
|
|
|
|
$response->bailOut(App::$l10n->t('File name missing from request.'));
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(is_null($progresskey)) {
|
|
|
|
$response->bailOut(App::$l10n->t('Progress key missing from request.'));
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
|
|
|
|
$filename = strtr($filename, array('/' => '', "\\" => ''));
|
|
|
|
if(\OC\Files\Filesystem::isFileBlacklisted($filename)) {
|
|
|
|
$response->bailOut(App::$l10n->t('Attempt to access blacklisted file:') . $filename);
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
$view = \OCP\Files::getStorage('contacts');
|
2013-08-15 20:11:10 +02:00
|
|
|
$proxyStatus = \OC_FileProxy::$enabled;
|
|
|
|
\OC_FileProxy::$enabled = false;
|
2013-05-02 20:41:26 +02:00
|
|
|
$file = $view->file_get_contents('/imports/' . $filename);
|
2013-08-15 20:11:10 +02:00
|
|
|
\OC_FileProxy::$enabled = $proxyStatus;
|
2013-05-02 20:41:26 +02:00
|
|
|
|
|
|
|
$writeProgress = function($pct) use ($progresskey) {
|
|
|
|
\OC_Cache::set($progresskey, $pct, 300);
|
|
|
|
};
|
|
|
|
|
|
|
|
$cleanup = function() use ($view, $filename, $progresskey) {
|
|
|
|
if(!$view->unlink('/imports/' . $filename)) {
|
|
|
|
$response->debug('Unable to unlink /imports/' . $filename);
|
|
|
|
}
|
|
|
|
\OC_Cache::remove($progresskey);
|
|
|
|
};
|
|
|
|
|
|
|
|
$writeProgress('20');
|
|
|
|
$nl = "\n";
|
|
|
|
$file = str_replace(array("\r","\n\n"), array("\n","\n"), $file);
|
|
|
|
$lines = explode($nl, $file);
|
|
|
|
|
|
|
|
$inelement = false;
|
|
|
|
$parts = array();
|
|
|
|
$card = array();
|
|
|
|
foreach($lines as $line) {
|
|
|
|
if(strtoupper(trim($line)) == 'BEGIN:VCARD') {
|
|
|
|
$inelement = true;
|
|
|
|
} elseif (strtoupper(trim($line)) == 'END:VCARD') {
|
|
|
|
$card[] = $line;
|
|
|
|
$parts[] = implode($nl, $card);
|
|
|
|
$card = array();
|
|
|
|
$inelement = false;
|
|
|
|
}
|
|
|
|
if ($inelement === true && trim($line) != '') {
|
|
|
|
$card[] = $line;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(count($parts) === 0) {
|
|
|
|
$response->bailOut(App::$l10n->t('No contacts found in: ') . $filename);
|
|
|
|
$cleanup();
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
//import the contacts
|
|
|
|
$writeProgress('40');
|
|
|
|
$imported = 0;
|
|
|
|
$failed = 0;
|
2013-05-18 00:08:23 +02:00
|
|
|
$partially = 0;
|
2013-05-02 20:41:26 +02:00
|
|
|
|
2013-06-22 08:49:37 +02:00
|
|
|
// TODO: Add a new group: "Imported at {date}"
|
2013-05-02 20:41:26 +02:00
|
|
|
foreach($parts as $part) {
|
|
|
|
try {
|
|
|
|
$vcard = VObject\Reader::read($part);
|
|
|
|
} catch (VObject\ParseException $e) {
|
|
|
|
try {
|
|
|
|
$vcard = VObject\Reader::read($part, VObject\Reader::OPTION_IGNORE_INVALID_LINES);
|
2013-05-18 00:08:23 +02:00
|
|
|
$partially += 1;
|
2013-05-02 20:41:26 +02:00
|
|
|
$response->debug('Import: Retrying reading card. Error parsing VCard: ' . $e->getMessage());
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
$failed += 1;
|
|
|
|
$response->debug('Import: skipping card. Error parsing VCard: ' . $e->getMessage());
|
|
|
|
continue; // Ditch cards that can't be parsed by Sabre.
|
|
|
|
}
|
|
|
|
}
|
2013-08-03 14:37:51 +02:00
|
|
|
/**
|
|
|
|
* TODO
|
|
|
|
* - Check if a contact with identical UID exists.
|
|
|
|
* - If so, fetch that contact and call $contact->mergeFromVCard($vcard);
|
|
|
|
* - Increment $updated var (not present yet.)
|
|
|
|
* - continue
|
|
|
|
*/
|
2013-05-02 20:41:26 +02:00
|
|
|
try {
|
|
|
|
if($addressBook->addChild($vcard)) {
|
|
|
|
$imported += 1;
|
|
|
|
$writeProgress($imported);
|
|
|
|
} else {
|
|
|
|
$failed += 1;
|
|
|
|
}
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
$response->debug('Error importing vcard: ' . $e->getMessage() . $nl . $vcard->serialize());
|
|
|
|
$failed += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//done the import
|
|
|
|
sleep(3); // Give client side a chance to read the progress.
|
|
|
|
$response->setParams(
|
|
|
|
array(
|
2013-05-08 06:47:36 +02:00
|
|
|
'backend' => $params['backend'],
|
|
|
|
'addressbookid' => $params['addressbookid'],
|
2013-05-02 20:41:26 +02:00
|
|
|
'imported' => $imported,
|
2013-05-18 00:08:23 +02:00
|
|
|
'partially' => $partially,
|
2013-05-02 20:41:26 +02:00
|
|
|
'failed' => $failed,
|
|
|
|
)
|
|
|
|
);
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-09-24 13:39:45 +02:00
|
|
|
* @NoAdminRequired
|
2013-05-02 20:41:26 +02:00
|
|
|
*/
|
|
|
|
public function status() {
|
|
|
|
$request = $this->request;
|
|
|
|
$response = new JSONResponse();
|
|
|
|
|
2013-06-25 21:44:23 +02:00
|
|
|
$progresskey = isset($request->get['progresskey']) ? $request->get['progresskey'] : null;
|
2013-05-02 20:41:26 +02:00
|
|
|
if(is_null($progresskey)) {
|
|
|
|
$response->bailOut(App::$l10n->t('Progress key missing from request.'));
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
|
|
|
|
$response->setParams(array('progress' => \OC_Cache::get($progresskey)));
|
|
|
|
return $response;
|
|
|
|
}
|
|
|
|
}
|