Blame view

sources/apps/contacts/lib/controller/importcontroller.php 9.66 KB
d1bafeea1   Kload   [fix] Upgrade to ...
1
2
3
  <?php
  /**
   * @author Thomas Tanghus
6d9380f96   Cédric Dupont   Update sources OC...
4
5
   * @copyright 2013-2014 Thomas Tanghus (thomas@tanghus.net)
   *
d1bafeea1   Kload   [fix] Upgrade to ...
6
7
8
9
10
11
12
13
14
15
   * This file is licensed under the Affero General Public License version 3 or
   * later.
   * See the COPYING-README file.
   */
  
  namespace OCA\Contacts\Controller;
  
  use OCA\Contacts\App,
  	OCA\Contacts\JSONResponse,
  	OCA\Contacts\Controller,
6d9380f96   Cédric Dupont   Update sources OC...
16
  	Sabre\VObject,
d1bafeea1   Kload   [fix] Upgrade to ...
17
  	OCA\Contacts\VObject\VCard as MyVCard,
6d9380f96   Cédric Dupont   Update sources OC...
18
19
20
21
  	OCA\Contacts\ImportManager,
  	OCP\IRequest,
  	OCP\ICache,
  	OCP\ITags;
d1bafeea1   Kload   [fix] Upgrade to ...
22
23
24
25
26
  
  /**
   * Controller importing contacts
   */
  class ImportController extends Controller {
6d9380f96   Cédric Dupont   Update sources OC...
27
28
29
30
  	public function __construct($appName, IRequest $request, App $app, ICache $cache) {
  		parent::__construct($appName, $request, $app);
  		$this->cache = $cache;
  	}
d1bafeea1   Kload   [fix] Upgrade to ...
31
32
33
34
35
36
  	/**
  	 * @NoAdminRequired
  	 */
  	public function upload() {
  		$request = $this->request;
  		$params = $this->request->urlParams;
6d9380f96   Cédric Dupont   Update sources OC...
37
38
  		$addressBookId = $params['addressBookId'];
  		$format = $params['importType'];
d1bafeea1   Kload   [fix] Upgrade to ...
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  		$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) {
  			$error = $file['error'];
  			$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);
6d9380f96   Cédric Dupont   Update sources OC...
83
  				return $response;
d1bafeea1   Kload   [fix] Upgrade to ...
84
85
86
87
88
89
  			}
  			$content = file_get_contents($tmpname);
  			$proxyStatus = \OC_FileProxy::$enabled;
  			\OC_FileProxy::$enabled = false;
  			if($view->file_put_contents('/imports/'.$filename, $content)) {
  				\OC_FileProxy::$enabled = $proxyStatus;
d1bafeea1   Kload   [fix] Upgrade to ...
90
91
92
93
  				$progresskey = 'contacts-import-' . rand();
  				$response->setParams(
  					array(
  						'filename'=>$filename,
d1bafeea1   Kload   [fix] Upgrade to ...
94
95
  						'progresskey' => $progresskey,
  						'backend' => $params['backend'],
6d9380f96   Cédric Dupont   Update sources OC...
96
97
  						'addressBookId' => $params['addressBookId'],
  						'importType' => $format
d1bafeea1   Kload   [fix] Upgrade to ...
98
99
  					)
  				);
d1bafeea1   Kload   [fix] Upgrade to ...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
  			} else {
  				\OC_FileProxy::$enabled = $proxyStatus;
  				$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;
  	}
  
  	/**
  	 * @NoAdminRequired
  	 */
  	public function prepare() {
  		$request = $this->request;
  		$params = $this->request->urlParams;
6d9380f96   Cédric Dupont   Update sources OC...
118
119
  		$addressBookId = $params['addressBookId'];
  		$format = $params['importType'];
d1bafeea1   Kload   [fix] Upgrade to ...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  		$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);
  		//$content = file_get_contents('oc://' . $path . '/' . $filename);
  		if($view->file_put_contents('/imports/' . $filename, $content)) {
  			\OC_FileProxy::$enabled = $proxyStatus;
d1bafeea1   Kload   [fix] Upgrade to ...
135
136
137
138
  			$progresskey = 'contacts-import-' . rand();
  			$response->setParams(
  				array(
  					'filename'=>$filename,
d1bafeea1   Kload   [fix] Upgrade to ...
139
140
  					'progresskey' => $progresskey,
  					'backend' => $params['backend'],
6d9380f96   Cédric Dupont   Update sources OC...
141
142
  					'addressBookId' => $params['addressBookId'],
  					'importType' => $params['importType']
d1bafeea1   Kload   [fix] Upgrade to ...
143
144
  				)
  			);
d1bafeea1   Kload   [fix] Upgrade to ...
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  		} else {
  			\OC_FileProxy::$enabled = $proxyStatus;
  			$response->bailOut(App::$l10n->t('Error moving file to imports folder.'));
  		}
  		return $response;
  	}
  
  	/**
  	 * @NoAdminRequired
  	 */
  	public function start() {
  		$request = $this->request;
  		$response = new JSONResponse();
  		$params = $this->request->urlParams;
6d9380f96   Cédric Dupont   Update sources OC...
159
160
161
  		$app = new App(\OCP\User::getUser());
  		$addressBookId = $params['addressBookId'];
  		$format = $params['importType'];
d1bafeea1   Kload   [fix] Upgrade to ...
162

6d9380f96   Cédric Dupont   Update sources OC...
163
  		$addressBook = $app->getAddressBook($params['backend'], $addressBookId);
d1bafeea1   Kload   [fix] Upgrade to ...
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
  		if(!$addressBook->hasPermission(\OCP\PERMISSION_CREATE)) {
  			$response->setStatus('403');
  			$response->bailOut(App::$l10n->t('You do not have permissions to import into this address book.'));
  			return $response;
  		}
  
  		$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');
  		$proxyStatus = \OC_FileProxy::$enabled;
  		\OC_FileProxy::$enabled = false;
  		$file = $view->file_get_contents('/imports/' . $filename);
  		\OC_FileProxy::$enabled = $proxyStatus;
6d9380f96   Cédric Dupont   Update sources OC...
193
194
195
196
197
  		$importManager = new ImportManager();
  		
  		$formatList = $importManager->getTypes();
  		
  		$found = false;
d1bafeea1   Kload   [fix] Upgrade to ...
198
  		$parts = array();
6d9380f96   Cédric Dupont   Update sources OC...
199
200
201
202
  		foreach ($formatList as $formatName => $formatDisplayName) {
  			if ($formatName == $format) {
  				$parts = $importManager->importFile($view->getLocalFile('/imports/' . $filename), $formatName);
  				$found = true;
d1bafeea1   Kload   [fix] Upgrade to ...
203
204
  			}
  		}
6d9380f96   Cédric Dupont   Update sources OC...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
  		
  		if (!$found) {
  			// detect file type
  			$mostLikelyName = "";
  			$mostLikelyValue = 0;
  			$probability = $importManager->detectFileType($view->getLocalFile('/imports/' . $filename));
  			foreach ($probability as $probName => $probValue) {
  				if ($probValue > $mostLikelyValue) {
  					$mostLikelyName = $probName;
  					$mostLikelyValue = $probValue;
  				}
  			}
  			
  			if ($mostLikelyValue > 0) {
  				// found one (most likely...)
  				$parts = $importManager->importFile($view->getLocalFile('/imports/' . $filename), $mostLikelyName);
  			}
d1bafeea1   Kload   [fix] Upgrade to ...
222
  		}
6d9380f96   Cédric Dupont   Update sources OC...
223
224
225
226
227
228
229
  		
  		if ($parts) {
  			//import the contacts
  			$imported = 0;
  			$failed = 0;
  			$processed = 0;
  			$total = count($parts);
d1bafeea1   Kload   [fix] Upgrade to ...
230

6d9380f96   Cédric Dupont   Update sources OC...
231
232
233
234
235
236
237
238
  			foreach($parts as $part) {
  				/**
  				 * TODO
  				 * - Check if a contact with identical UID exists.
  				 * - If so, fetch that contact and call $contact->mergeFromVCard($part);
  				 * - Increment $updated var (not present yet.)
  				 * - continue
  				 */
d1bafeea1   Kload   [fix] Upgrade to ...
239
  				try {
6d9380f96   Cédric Dupont   Update sources OC...
240
241
242
243
244
245
246
247
248
249
250
251
252
  					$id = $addressBook->addChild($part);
  					if($id) {
  						$imported++;
  						$favourites = $part->select('X-FAVOURITES');
  						foreach ($favourites as $favourite) {
  							if ($favourite->getValue() == 'yes') {
  								$tagMgr = $this->server->getTagManager()->load('contact');
  								$tagMgr->addToFavorites($id);
  							}
  						}
  					} else {
  						$failed++;
  					}
d1bafeea1   Kload   [fix] Upgrade to ...
253
  				} catch (\Exception $e) {
6d9380f96   Cédric Dupont   Update sources OC...
254
255
  					$response->debug('Error importing vcard: ' . $e->getMessage() . $nl . $part->serialize());
  					$failed++;
d1bafeea1   Kload   [fix] Upgrade to ...
256
  				}
6d9380f96   Cédric Dupont   Update sources OC...
257
258
  				$processed++;
  				$this->writeProcess($processed, $total, $progresskey);
d1bafeea1   Kload   [fix] Upgrade to ...
259
  			}
6d9380f96   Cédric Dupont   Update sources OC...
260
261
262
263
264
  		} else {
  			$imported = 0;
  			$failed = 0;
  			$processed = 0;
  			$total = 0;
d1bafeea1   Kload   [fix] Upgrade to ...
265
  		}
6d9380f96   Cédric Dupont   Update sources OC...
266
267
  
  		$this->cleanup($view, $filename, $progresskey, $response);
d1bafeea1   Kload   [fix] Upgrade to ...
268
269
270
271
272
273
  		//done the import
  		sleep(3); // Give client side a chance to read the progress.
  		$response->setParams(
  			array(
  				'backend' => $params['backend'],
  				'addressBookId' => $params['addressBookId'],
6d9380f96   Cédric Dupont   Update sources OC...
274
  				'importType' => $params['importType'],
d1bafeea1   Kload   [fix] Upgrade to ...
275
  				'imported' => $imported,
6d9380f96   Cédric Dupont   Update sources OC...
276
277
  				'count' => $processed,
  				'total' => $total,
d1bafeea1   Kload   [fix] Upgrade to ...
278
279
280
281
282
283
284
  				'failed' => $failed,
  			)
  		);
  		return $response;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
  	 * @param $pct
  	 * @param $total
  	 * @param $progresskey
  	 */
  	protected function writeProcess($pct, $total, $progresskey) {
  		$this->cache->set($progresskey, $pct, 300);
  		$this->cache->set($progresskey . '_total', $total, 300);
  	}
  
  	/**
  	 * @param $view
  	 * @param $filename
  	 * @param $progresskey
  	 * @param $response
  	 */
  	protected function cleanup($view, $filename, $progresskey, $response) {
  		if (!$view->unlink('/imports/' . $filename)) {
  			$response->debug('Unable to unlink /imports/' . $filename);
  		}
  		$this->cache->remove($progresskey);
  		$this->cache->remove($progresskey . '_total');
  	}
  
  	/**
d1bafeea1   Kload   [fix] Upgrade to ...
309
310
311
312
313
314
315
316
317
318
319
  	 * @NoAdminRequired
  	 */
  	public function status() {
  		$request = $this->request;
  		$response = new JSONResponse();
  
  		$progresskey = isset($request->get['progresskey']) ? $request->get['progresskey'] : null;
  		if(is_null($progresskey)) {
  			$response->bailOut(App::$l10n->t('Progress key missing from request.'));
  			return $response;
  		}
6d9380f96   Cédric Dupont   Update sources OC...
320
321
  		error_log("progresskey: ".$this->cache->get($progresskey)." total: ".$this->cache->get($progresskey.'_total') );
  		$response->setParams(array('progress' => $this->cache->get($progresskey), 'total' => $this->cache->get($progresskey.'_total') ));
d1bafeea1   Kload   [fix] Upgrade to ...
322
323
  		return $response;
  	}
6d9380f96   Cédric Dupont   Update sources OC...
324
  }