1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.exoplatform.utils;
20
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.FileNotFoundException;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.net.URI;
27 import java.net.URISyntaxException;
28 import java.net.URLConnection;
29 import java.text.DecimalFormat;
30 import java.text.Normalizer;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.List;
34 import java.util.Locale;
35 import java.util.regex.Matcher;
36 import java.util.regex.Pattern;
37
38 import javax.xml.parsers.DocumentBuilder;
39 import javax.xml.parsers.DocumentBuilderFactory;
40 import javax.xml.parsers.ParserConfigurationException;
41
42 import org.apache.http.HttpResponse;
43 import org.apache.http.HttpStatus;
44 import org.apache.http.client.methods.HttpPut;
45 import org.apache.http.entity.FileEntity;
46 import org.w3c.dom.Document;
47 import org.w3c.dom.Element;
48 import org.w3c.dom.Node;
49 import org.w3c.dom.NodeList;
50 import org.xml.sax.SAXException;
51
52 import org.exoplatform.R;
53 import org.exoplatform.model.ExoFile;
54 import org.exoplatform.singleton.AccountSetting;
55 import org.exoplatform.singleton.DocumentHelper;
56 import org.exoplatform.ui.WebViewActivity;
57 import org.exoplatform.utils.CompatibleFileOpen.FileOpenRequest;
58 import org.exoplatform.utils.CompatibleFileOpen.FileOpenRequestResult;
59 import org.exoplatform.widget.UnreadableFileDialog;
60
61 import android.Manifest;
62 import android.annotation.TargetApi;
63 import android.app.Activity;
64 import android.content.ComponentName;
65 import android.content.ContentResolver;
66 import android.content.ContentUris;
67 import android.content.Context;
68 import android.content.Intent;
69 import android.content.SharedPreferences;
70 import android.content.pm.PackageManager;
71 import android.database.Cursor;
72 import android.graphics.Bitmap;
73 import android.graphics.Matrix;
74 import android.media.ExifInterface;
75 import android.net.Uri;
76 import android.os.Build;
77 import android.os.Bundle;
78 import android.os.Environment;
79 import android.os.StatFs;
80 import android.provider.MediaStore;
81 import android.provider.OpenableColumns;
82 import android.support.v4.app.ActivityCompat;
83 import android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback;
84 import android.support.v4.content.ContextCompat;
85 import android.text.Html;
86 import android.webkit.MimeTypeMap;
87
88 public class ExoDocumentUtils {
89
90 private static final String LOG_TAG = "____eXo____ExoDocumentUtils____";
91
92 public static final String ALL_VIDEO_TYPE = "video/*";
93
94 public static final String ALL_AUDIO_TYPE = "audio/*";
95
96 public static final String ALL_IMAGE_TYPE = "image/*";
97
98 public static final String ALL_TEXT_TYPE = "text/*";
99
100 public static final String IMAGE_TYPE = "image";
101
102 public static final String TEXT_TYPE = "text";
103
104 public static final String VIDEO_TYPE = "video";
105
106 public static final String AUDIO_TYPE = "audio";
107
108 public static final String MSWORD_TYPE = "application/msword";
109
110 public static final String OPEN_WORD_TYPE = "application/vnd.oasis.opendocument.text";
111
112 public static final String PDF_TYPE = "application/pdf";
113
114 public static final String XLS_TYPE = "application/xls";
115
116 public static final String OPEN_XLS_TYPE = "application/vnd.oasis.opendocument.spreadsheet";
117
118 public static final String POWERPOINT_TYPE = "application/vnd.ms-powerpoint";
119
120 public static final String OPEN_POWERPOINT_TYPE = "application/vnd.oasis.opendocument.presentation";
121
122 public static final String[] FORBIDDEN_TYPES = new String[] { "application/octet-stream" };
123
124 public static boolean isEnoughMemory(int fileSize) {
125 if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
126 int freeSpace = getFreeMemory(Environment.getExternalStorageDirectory().getAbsolutePath());
127 if (freeSpace > fileSize) {
128 return true;
129 } else
130 return false;
131
132 } else
133 return false;
134 }
135
136
137
138
139 public static int getFreeMemory(String path) {
140 StatFs statFs = new StatFs(path);
141 int free = (statFs.getAvailableBlocks() * statFs.getBlockSize());
142 return Math.abs(free);
143 }
144
145
146
147
148 public static String getFileSize(long fileSize) {
149 int freeUnit;
150 for (freeUnit = 0; fileSize >= 100; freeUnit++) {
151 fileSize /= 1024;
152 }
153 DecimalFormat decFormat = new DecimalFormat("0.0");
154 String doubleString = decFormat.format(fileSize);
155 StringBuffer buffer = new StringBuffer();
156 buffer.append(doubleString);
157 switch (freeUnit) {
158 case 0:
159 buffer.append("B");
160 break;
161 case 1:
162 buffer.append("KB");
163 break;
164 case 2:
165 buffer.append("MB");
166 break;
167 case 3:
168 buffer.append("GB");
169 break;
170 case 4:
171 buffer.append("TB");
172 break;
173 default:
174 buffer.append("err");
175 break;
176 }
177 return buffer.toString();
178 }
179
180
181
182
183
184
185 public static FileOpenRequest fileOpen(Context context, String fileType, String filePath, String fileName) {
186 FileOpenRequest result = new FileOpenRequest();
187 if (fileType == null) {
188 new UnreadableFileDialog(context, null).show();
189 result.mResult = FileOpenRequestResult.ERROR;
190 } else if (fileType.startsWith(IMAGE_TYPE) || fileType.startsWith(TEXT_TYPE)) {
191 Intent intent = new Intent(context, WebViewActivity.class);
192 intent.putExtra(ExoConstants.WEB_VIEW_URL, filePath);
193 intent.putExtra(ExoConstants.WEB_VIEW_TITLE, fileName);
194 intent.putExtra(ExoConstants.WEB_VIEW_MIME_TYPE, fileType);
195 intent.putExtra(ExoConstants.WEB_VIEW_ALLOW_JS, "false");
196 context.startActivity(intent);
197 result.mResult = FileOpenRequestResult.WEBVIEW;
198 } else {
199 result.mFileOpenController = new CompatibleFileOpen(context, fileType, filePath, fileName);
200 result.mResult = FileOpenRequestResult.EXTERNAL;
201 }
202 if (Log.LOGD)
203 Log.d(LOG_TAG, "File Open Result: "+result.mResult);
204 return result;
205 }
206
207
208
209
210
211
212
213
214 public static boolean isForbidden(String mimeType) {
215 return Arrays.asList(FORBIDDEN_TYPES).contains(mimeType);
216 }
217
218
219
220
221
222
223
224
225
226 public static boolean isCallable(Context context, String mimeType, String url) throws IllegalArgumentException {
227 if (context == null || mimeType == null)
228 throw new IllegalArgumentException("Context or mime-type cannot be null.");
229
230 Intent intent = new Intent(Intent.ACTION_VIEW);
231 intent.setType(mimeType.toLowerCase(Locale.US));
232 ComponentName activity = intent.resolveActivity(context.getPackageManager());
233
234 if (activity == null && url != null) {
235
236 String guessedMimeType = URLConnection.guessContentTypeFromName(url);
237 if (guessedMimeType != null) {
238 intent = new Intent(Intent.ACTION_VIEW);
239 intent.setType(guessedMimeType.toLowerCase(Locale.US));
240 activity = intent.resolveActivity(context.getPackageManager());
241 }
242 }
243
244 return activity != null;
245 }
246
247 public static String getFullFileType(String fileType) {
248 String docFileType = fileType;
249 if (fileType.startsWith(ExoDocumentUtils.AUDIO_TYPE)) {
250 docFileType = ExoDocumentUtils.ALL_AUDIO_TYPE;
251 } else if (fileType.startsWith(ExoDocumentUtils.VIDEO_TYPE)) {
252 docFileType = ExoDocumentUtils.ALL_VIDEO_TYPE;
253 } else if (fileType.startsWith(ExoDocumentUtils.IMAGE_TYPE)) {
254 docFileType = ExoDocumentUtils.ALL_IMAGE_TYPE;
255 } else if (fileType.startsWith(ExoDocumentUtils.TEXT_TYPE)) {
256 docFileType = ExoDocumentUtils.ALL_TEXT_TYPE;
257 }
258 return docFileType;
259 }
260
261 public static boolean putFileToServerFromLocal(String url, File fileManager, String fileType) {
262 try {
263 url = url.replaceAll(" ", "%20");
264
265 HttpPut put = new HttpPut(url);
266 FileEntity fileEntity = new FileEntity(fileManager, fileType);
267 put.setEntity(fileEntity);
268 fileEntity.setContentType(fileType);
269 HttpResponse response = ExoConnectionUtils.httpClient.execute(put);
270 int status = response.getStatusLine().getStatusCode();
271 if (status >= HttpStatus.SC_OK && status < HttpStatus.SC_MULTIPLE_CHOICES) {
272 return true;
273 } else {
274 return false;
275 }
276 } catch (IOException e) {
277 if (Log.LOGD)
278 Log.d(ExoDocumentUtils.class.getSimpleName(), e.getMessage(), Log.getStackTraceString(e));
279 return false;
280 } finally {
281 fileManager.delete();
282 }
283
284 }
285
286 public static void setRepositoryHomeUrl(String userName, String userHomeNodePath, String domain) {
287 String documentPath = getDocumenPath();
288 StringBuilder buffer = new StringBuilder();
289 buffer.append(domain);
290 buffer.append(documentPath);
291 buffer.append(userHomeNodePath);
292
293 try {
294 WebdavMethod copy = new WebdavMethod("HEAD", buffer.toString());
295 int status = ExoConnectionUtils.httpClient.execute(copy).getStatusLine().getStatusCode();
296
297 if (status >= 200 && status < 300) {
298 DocumentHelper.getInstance().setRepositoryHomeUrl(buffer.toString());
299 } else {
300 buffer = new StringBuilder(domain);
301 buffer.append(documentPath);
302 buffer.append("/");
303 buffer.append(userName);
304 DocumentHelper.getInstance().setRepositoryHomeUrl(buffer.toString());
305 }
306
307 } catch (Exception e) {
308
309
310 Log.e(LOG_TAG, e.getMessage(), Log.getStackTraceString(e));
311 DocumentHelper.getInstance().setRepositoryHomeUrl(null);
312 }
313 }
314
315
316
317
318
319
320
321
322
323
324 public static ExoFile getPersonalDriveContent(Context context, ExoFile file) throws IOException {
325 SharedPreferences prefs = context.getSharedPreferences(ExoConstants.EXO_PREFERENCE, 0);
326 boolean isShowHidden = prefs.getBoolean(AccountSetting.getInstance().documentKey, true);
327 ExoFile folder = file;
328 String domain = AccountSetting.getInstance().getDomainName();
329 HttpResponse response = null;
330 String urlStr = null;
331
332
333
334 if (DocumentHelper.getInstance().folderToChildrenMap == null) {
335 DocumentHelper.getInstance().folderToChildrenMap = new Bundle();
336 }
337
338
339 if ("".equals(file.name) && "".equals(file.path)) {
340
341 ArrayList<ExoFile> arrFilesTmp = new ArrayList<ExoFile>();
342 ArrayList<ExoFile> fileList = new ArrayList<ExoFile>();
343 StringBuffer buffer = new StringBuffer();
344 buffer.append(domain);
345 buffer.append(ExoConstants.DOCUMENT_DRIVE_PATH_REST);
346 buffer.append(ExoConstants.DOCUMENT_PERSONAL_DRIVER);
347 buffer.append(ExoConstants.DOCUMENT_PERSONAL_DRIVER_SHOW_PRIVATE);
348 buffer.append(isShowHidden);
349 urlStr = buffer.toString();
350 response = ExoConnectionUtils.getRequestResponse(urlStr);
351 fileList = getDrives(response);
352 if (fileList != null && fileList.size() > 0) {
353 arrFilesTmp.add(new ExoFile(ExoConstants.DOCUMENT_PERSONAL_DRIVER));
354 arrFilesTmp.addAll(fileList);
355 }
356
357 buffer = new StringBuffer();
358 buffer.append(domain);
359 buffer.append(ExoConstants.DOCUMENT_DRIVE_PATH_REST);
360 buffer.append(ExoConstants.DOCUMENT_GENERAL_DRIVER);
361 urlStr = buffer.toString();
362 response = ExoConnectionUtils.getRequestResponse(urlStr);
363 fileList = getDrives(response);
364 if (fileList != null && fileList.size() > 0) {
365 arrFilesTmp.add(new ExoFile(ExoConstants.DOCUMENT_GENERAL_DRIVER));
366 arrFilesTmp.addAll(fileList);
367 }
368
369
370 buffer = new StringBuffer();
371 buffer.append(domain);
372 buffer.append(ExoConstants.DOCUMENT_DRIVE_PATH_REST);
373 buffer.append(ExoConstants.DOCUMENT_GROUP_DRIVER);
374 urlStr = buffer.toString();
375 response = ExoConnectionUtils.getRequestResponse(urlStr);
376
377 fileList = getDrives(response, true);
378 if (fileList != null && fileList.size() > 0) {
379 arrFilesTmp.add(new ExoFile(ExoConstants.DOCUMENT_GROUP_DRIVER));
380 arrFilesTmp.addAll(fileList);
381 }
382
383
384 if (DocumentHelper.getInstance().folderToChildrenMap.containsKey(ExoConstants.DOCUMENT_JCR_PATH)) {
385 DocumentHelper.getInstance().folderToChildrenMap.remove(ExoConstants.DOCUMENT_JCR_PATH);
386 DocumentHelper.getInstance().folderToChildrenMap.putParcelableArrayList(ExoConstants.DOCUMENT_JCR_PATH, arrFilesTmp);
387 } else {
388 DocumentHelper.getInstance().folderToChildrenMap.putParcelableArrayList(ExoConstants.DOCUMENT_JCR_PATH, arrFilesTmp);
389 }
390
391
392 folder.children = arrFilesTmp;
393 } else {
394
395 urlStr = getDriverUrl(file);
396 urlStr = ExoUtils.encodeDocumentUrl(urlStr);
397 response = ExoConnectionUtils.getRequestResponse(urlStr);
398 folder = getContentOfFolder(response, file);
399
400 if (DocumentHelper.getInstance().folderToChildrenMap.containsKey(file.path)) {
401 DocumentHelper.getInstance().folderToChildrenMap.remove(file.path);
402 DocumentHelper.getInstance().folderToChildrenMap.putParcelableArrayList(file.path, new ArrayList<ExoFile>(folder.children));
403 } else
404 DocumentHelper.getInstance().folderToChildrenMap.putParcelableArrayList(file.path, new ArrayList<ExoFile>(folder.children));
405
406 }
407
408 return folder;
409
410 }
411
412 public static String fullURLofFile(String workSpaceName, String url) {
413 String domain = AccountSetting.getInstance().getDomainName();
414 StringBuffer buffer = new StringBuffer(domain);
415 buffer.append(ExoConstants.DOCUMENT_JCR_PATH);
416 buffer.append("/");
417 buffer.append(DocumentHelper.getInstance().repository);
418 buffer.append("/");
419 buffer.append(workSpaceName);
420 buffer.append(url);
421 return buffer.toString();
422
423 }
424
425 private static String getDocumenPath() {
426 StringBuilder documentPath = new StringBuilder();
427 documentPath.append(ExoConstants.DOCUMENT_JCR_PATH);
428 documentPath.append("/");
429 documentPath.append(DocumentHelper.getInstance().repository);
430 documentPath.append("/");
431 documentPath.append(ExoConstants.DOCUMENT_COLLABORATION);
432 return documentPath.toString();
433 }
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450 public static ArrayList<ExoFile> getDrives(HttpResponse response) {
451 return getDrives(response, false);
452 }
453
454
455
456
457
458
459
460
461
462
463
464
465 public static ArrayList<ExoFile> getDrives(HttpResponse response, boolean isGroupDrive) {
466
467
468 ArrayList<ExoFile> folderArray = new ArrayList<ExoFile>();
469
470 try {
471 Document obj_doc = null;
472 DocumentBuilderFactory doc_build_fact = null;
473 DocumentBuilder doc_builder = null;
474
475 doc_build_fact = DocumentBuilderFactory.newInstance();
476 doc_builder = doc_build_fact.newDocumentBuilder();
477 InputStream is = ExoConnectionUtils.sendRequest(response);
478 if (is != null) {
479 obj_doc = doc_builder.parse(is);
480
481 NodeList obj_nod_list = null;
482 if (null != obj_doc) {
483 obj_nod_list = obj_doc.getElementsByTagName("Folder");
484
485 for (int i = 0; i < obj_nod_list.getLength(); i++) {
486 Node itemNode = obj_nod_list.item(i);
487 if (itemNode.getNodeType() == Node.ELEMENT_NODE) {
488 Element itemElement = (Element) itemNode;
489 ExoFile file = new ExoFile();
490 file.name = itemElement.getAttribute("name");
491
492 Log.i(" Public file name", file.name);
493 file.workspaceName = itemElement.getAttribute("workspaceName");
494 file.driveName = file.name;
495 file.currentFolder = itemElement.getAttribute("currentFolder");
496 if (file.currentFolder == null)
497 file.currentFolder = "";
498 file.isFolder = true;
499
500
501 if (isGroupDrive)
502 file.createNaturalName();
503
504
505
506 if (file.name.equals("Public")) {
507 file.path = getRootDriverPath(file);
508 }
509
510 folderArray.add(file);
511 }
512 }
513 }
514 }
515 } catch (ParserConfigurationException e) {
516 Log.e(" ParserConfigurationException ", e.getMessage());
517 folderArray = null;
518 } catch (SAXException e) {
519 Log.e(" SAXException ", e.getMessage());
520 folderArray = null;
521 } catch (IOException e) {
522 Log.e(" IOException ", e.getMessage());
523 folderArray = null;
524 }
525
526 return folderArray;
527 }
528
529
530 private static String getDriverUrl(ExoFile file) {
531 String domain = AccountSetting.getInstance().getDomainName();
532 StringBuffer buffer = new StringBuffer(domain);
533 buffer.append(ExoConstants.DOCUMENT_FILE_PATH_REST);
534 buffer.append(file.driveName);
535 buffer.append(ExoConstants.DOCUMENT_WORKSPACE_NAME);
536 buffer.append(file.workspaceName);
537 buffer.append(ExoConstants.DOCUMENT_CURRENT_FOLDER);
538 buffer.append(file.currentFolder);
539
540 return buffer.toString();
541 }
542
543
544 private static String getRootDriverPath(ExoFile file) {
545 String path = null;
546 String urlStr = getDriverUrl(file);
547 urlStr = ExoUtils.encodeDocumentUrl(urlStr);
548 Document obj_doc = null;
549 DocumentBuilderFactory doc_build_fact = null;
550 DocumentBuilder doc_builder = null;
551 try {
552 HttpResponse response = ExoConnectionUtils.getRequestResponse(urlStr);
553 doc_build_fact = DocumentBuilderFactory.newInstance();
554 doc_builder = doc_build_fact.newDocumentBuilder();
555 InputStream is = ExoConnectionUtils.sendRequest(response);
556 if (is != null) {
557 obj_doc = doc_builder.parse(is);
558
559 if (null != obj_doc) {
560
561
562 NodeList obj_nod_list = obj_doc.getElementsByTagName("Folder");
563 Node rootNode = obj_nod_list.item(0);
564 if (rootNode.getNodeType() == Node.ELEMENT_NODE) {
565 Element itemElement = (Element) rootNode;
566 path = fullURLofFile(ExoConstants.DOCUMENT_COLLABORATION, itemElement.getAttribute("path"));
567 }
568 }
569 }
570 return path;
571 } catch (ParserConfigurationException e) {
572 return null;
573 } catch (SAXException e) {
574 return null;
575 } catch (IOException e) {
576 return null;
577 }
578 }
579
580 private static ExoFile getFileFromXMLElement(Element element, boolean isFolder) throws NullPointerException {
581 if (element == null)
582 throw new NullPointerException("Given element is null");
583
584 ExoFile file = new ExoFile();
585 if (element.hasAttribute("title")) {
586 file.name = Html.fromHtml(element.getAttribute("title")).toString();
587 } else {
588 file.name = element.getAttribute("name");
589 }
590 file.workspaceName = element.getAttribute("workspaceName");
591 file.path = fullURLofFile(file.workspaceName, element.getAttribute("path"));
592 if (element.hasAttribute("driveName"))
593 file.driveName = element.getAttribute("driveName");
594 else
595 file.driveName = file.name;
596 file.currentFolder = element.getAttribute("currentFolder");
597 if (file.currentFolder == null)
598 file.currentFolder = "";
599 file.isFolder = isFolder;
600 if (element.hasAttribute("nodeType"))
601 file.nodeType = element.getAttribute("nodeType");
602
603 String canRemove = element.getAttribute("canRemove");
604 file.canRemove = Boolean.parseBoolean(canRemove.trim());
605
606 return file;
607 }
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635 public static ExoFile getContentOfFolder(HttpResponse response, ExoFile file) {
636
637 ExoFile folder = file;
638 ArrayList<ExoFile> childrenArray = new ArrayList<ExoFile>();
639
640 Document obj_doc = null;
641 DocumentBuilderFactory doc_build_fact = null;
642 DocumentBuilder doc_builder = null;
643 try {
644 doc_build_fact = DocumentBuilderFactory.newInstance();
645 doc_builder = doc_build_fact.newDocumentBuilder();
646 InputStream is = ExoConnectionUtils.sendRequest(response);
647 if (is != null) {
648 obj_doc = doc_builder.parse(is);
649
650 NodeList obj_nod_list = null;
651 if (null != obj_doc) {
652
653
654 obj_nod_list = obj_doc.getElementsByTagName("Folder");
655 for (int i = 0; i < obj_nod_list.getLength(); i++) {
656 Node itemNode = obj_nod_list.item(i);
657 if (itemNode.getNodeType() == Node.ELEMENT_NODE) {
658 Element itemElement = (Element) itemNode;
659
660 if (i == 0) {
661
662
663
664 ExoFile tmp = getFileFromXMLElement(itemElement, true);
665
666
667
668 if ("Private".equals(tmp.name) && "".equals(tmp.currentFolder) && "Personal Documents".equals(tmp.driveName))
669 folder.name = tmp.driveName;
670 else
671 folder.name = tmp.name;
672
673 folder.workspaceName = tmp.workspaceName;
674 folder.path = tmp.path;
675 folder.driveName = tmp.driveName;
676 folder.currentFolder = tmp.currentFolder;
677 folder.isFolder = true;
678
679 if (folder.isFolder && "".equals(folder.currentFolder))
680 folder.canRemove = false;
681 else
682 folder.canRemove = tmp.canRemove;
683
684 } else {
685
686 ExoFile childFolder = getFileFromXMLElement(itemElement, true);
687 childrenArray.add(childFolder);
688 }
689 }
690 }
691
692
693 obj_nod_list = obj_doc.getElementsByTagName("File");
694 for (int i = 0; i < obj_nod_list.getLength(); i++) {
695 Node itemNode = obj_nod_list.item(i);
696 if (itemNode.getNodeType() == Node.ELEMENT_NODE) {
697 Element itemElement = (Element) itemNode;
698 ExoFile childFile = getFileFromXMLElement(itemElement, false);
699 childrenArray.add(childFile);
700 }
701 }
702
703 }
704 }
705 folder.children = childrenArray;
706 return folder;
707 } catch (ParserConfigurationException e) {
708 return null;
709 } catch (SAXException e) {
710 return null;
711 } catch (IOException e) {
712 return null;
713 }
714
715 }
716
717
718
719
720
721 public static int getIconFromType(String contentType) {
722 int id = R.drawable.documenticonforunknown;
723 if (contentType != null) {
724 if (contentType.indexOf(IMAGE_TYPE) >= 0)
725 id = R.drawable.documenticonforimage;
726 else if (contentType.indexOf(VIDEO_TYPE) >= 0)
727 id = R.drawable.documenticonforvideo;
728 else if (contentType.indexOf(AUDIO_TYPE) >= 0)
729 id = R.drawable.documenticonformusic;
730 else if (contentType.indexOf(MSWORD_TYPE) >= 0 || contentType.indexOf(OPEN_WORD_TYPE) >= 0)
731 id = R.drawable.documenticonforword;
732 else if (contentType.indexOf(PDF_TYPE) >= 0)
733 id = R.drawable.documenticonforpdf;
734 else if (contentType.indexOf(XLS_TYPE) >= 0 || contentType.indexOf(OPEN_XLS_TYPE) >= 0)
735 id = R.drawable.documenticonforxls;
736 else if (contentType.indexOf(POWERPOINT_TYPE) >= 0 || contentType.indexOf(OPEN_POWERPOINT_TYPE) >= 0)
737 id = R.drawable.documenticonforppt;
738 else if (contentType.indexOf(TEXT_TYPE) >= 0)
739 id = R.drawable.documenticonfortxt;
740 }
741
742 return id;
743 }
744
745 public static String getParentUrl(String url) {
746
747 int index = url.lastIndexOf("/");
748 if (index > 0)
749 return url.substring(0, index);
750
751 return "";
752 }
753
754 public static String getLastPathComponent(String url) {
755
756 int index = url.lastIndexOf("/");
757 if (index > 0)
758 return url.substring(url.lastIndexOf("/") + 1, url.length());
759
760 return url;
761
762 }
763
764 public static boolean isContainSpecialChar(String str, String charSet) {
765
766 Pattern patt = Pattern.compile(charSet);
767 Matcher matcher = patt.matcher(str);
768 return matcher.find();
769 }
770
771
772
773
774
775
776
777 public static boolean deleteFile(String url) {
778 HttpResponse response;
779 try {
780 url = ExoUtils.encodeDocumentUrl(url);
781 WebdavMethod delete = new WebdavMethod("DELETE", url);
782 response = ExoConnectionUtils.httpClient.execute(delete);
783 int status = response.getStatusLine().getStatusCode();
784 if (status >= HttpStatus.SC_OK && status < HttpStatus.SC_MULTIPLE_CHOICES) {
785 return true;
786 } else
787 return false;
788
789 } catch (IOException e) {
790 return false;
791 }
792
793 }
794
795
796 public static boolean copyFile(String source, String destination) {
797
798 HttpResponse response;
799 try {
800 if (source.equals(destination)) {
801 return false;
802 }
803 source = ExoUtils.encodeDocumentUrl(source);
804 destination = ExoUtils.encodeDocumentUrl(destination);
805 WebdavMethod copy = new WebdavMethod("COPY", source, destination);
806 response = ExoConnectionUtils.httpClient.execute(copy);
807 int status = response.getStatusLine().getStatusCode();
808 if (status >= HttpStatus.SC_OK && status < HttpStatus.SC_MULTIPLE_CHOICES) {
809 return true;
810 } else
811 return false;
812
813 } catch (IOException e) {
814 if (Log.LOGD)
815 Log.d(ExoDocumentUtils.class.getSimpleName(), e.getMessage(), Log.getStackTraceString(e));
816 return false;
817 }
818 }
819
820
821 public static boolean moveFile(String source, String destination) {
822 HttpResponse response;
823 try {
824 if (source.equals(destination)) {
825 return false;
826 }
827 source = ExoUtils.encodeDocumentUrl(source);
828 destination = ExoUtils.encodeDocumentUrl(destination);
829 WebdavMethod move = new WebdavMethod("MOVE", source, destination);
830 response = ExoConnectionUtils.httpClient.execute(move);
831 int status = response.getStatusLine().getStatusCode();
832 if (status >= HttpStatus.SC_OK && status < HttpStatus.SC_MULTIPLE_CHOICES) {
833 return true;
834 } else
835 return false;
836
837 } catch (IOException e) {
838 return false;
839 }
840
841 }
842
843 public static boolean renameFolder(String source, String destination) {
844 HttpResponse response;
845 try {
846 source = ExoUtils.encodeDocumentUrl(source);
847 destination = ExoUtils.encodeDocumentUrl(destination);
848 WebdavMethod create = new WebdavMethod("HEAD", destination);
849 response = ExoConnectionUtils.httpClient.execute(create);
850 int status = response.getStatusLine().getStatusCode();
851 if (status >= HttpStatus.SC_OK && status < HttpStatus.SC_MULTIPLE_CHOICES) {
852 return true;
853 } else {
854 WebdavMethod move = new WebdavMethod("MOVE", source, destination);
855 response = ExoConnectionUtils.httpClient.execute(move);
856 status = response.getStatusLine().getStatusCode();
857 if (status >= HttpStatus.SC_OK && status < HttpStatus.SC_MULTIPLE_CHOICES) {
858 return true;
859 } else {
860 return false;
861 }
862
863 }
864 } catch (IOException e) {
865 return false;
866 }
867
868 }
869
870 public static boolean createFolder(String destination) {
871 HttpResponse response;
872 try {
873
874 destination = ExoUtils.encodeDocumentUrl(destination);
875 WebdavMethod create = new WebdavMethod("HEAD", destination);
876 response = ExoConnectionUtils.httpClient.execute(create);
877 int status = response.getStatusLine().getStatusCode();
878 if (status >= HttpStatus.SC_OK && status < HttpStatus.SC_MULTIPLE_CHOICES) {
879 return true;
880 } else {
881 create = new WebdavMethod("MKCOL", destination);
882 response = ExoConnectionUtils.httpClient.execute(create);
883 status = response.getStatusLine().getStatusCode();
884
885 if (status >= HttpStatus.SC_OK && status < HttpStatus.SC_MULTIPLE_CHOICES) {
886 return true;
887 } else
888 return false;
889 }
890
891 } catch (Exception e) {
892
893
894 Log.e(LOG_TAG, e.getMessage(), e);
895 return false;
896 }
897 }
898
899
900
901
902
903
904
905
906 public static DocumentInfo documentInfoFromUri(Uri document, Context context) {
907 if (document == null)
908 return null;
909
910 if (document.toString().startsWith("content://")) {
911
912
913
914
915
916
917
918
919 String decodedUri = Uri.decode(document.toString());
920 int fileIdx = decodedUri.indexOf("file://");
921 if (fileIdx > -1) {
922 long id = -1;
923 try {
924 id = ContentUris.parseId(document);
925 } catch (NumberFormatException e) {
926 Log.e(LOG_TAG, e.getMessage(), e);
927 } catch (UnsupportedOperationException e) {
928 Log.e(LOG_TAG, e.getMessage(), e);
929 }
930 String fileUri = decodedUri.substring(fileIdx);
931 fileUri = fileUri.replaceAll("(/ACTUAL/)(" + id + ")", "");
932 return documentFromFileUri(Uri.parse(fileUri));
933 } else {
934 return documentFromContentUri(document, context);
935 }
936 } else if (document.toString().startsWith("file://")) {
937 return documentFromFileUri(document);
938 } else {
939 return null;
940 }
941 }
942
943
944
945
946
947
948
949
950 public static DocumentInfo documentFromContentUri(Uri contentUri, Context context) {
951 if (contentUri == null)
952 return null;
953
954 try {
955 ContentResolver cr = context.getContentResolver();
956 Cursor c = cr.query(contentUri, null, null, null, null);
957 int sizeIndex = c.getColumnIndex(OpenableColumns.SIZE);
958 int nameIndex = c.getColumnIndex(OpenableColumns.DISPLAY_NAME);
959 int orientIndex = c.getColumnIndex(MediaStore.Images.ImageColumns.ORIENTATION);
960 c.moveToFirst();
961
962 DocumentInfo document = new DocumentInfo();
963 document.documentName = c.getString(nameIndex);
964 document.documentSizeKb = c.getLong(sizeIndex) / 1024;
965 document.documentData = cr.openInputStream(contentUri);
966 document.documentMimeType = cr.getType(contentUri);
967 if (orientIndex != -1) {
968 document.orientationAngle = c.getInt(orientIndex);
969 }
970 return document;
971 } catch (FileNotFoundException e) {
972 Log.d(LOG_TAG, e.getClass().getSimpleName(), e.getLocalizedMessage());
973 } catch (Exception e) {
974 Log.e(LOG_TAG, "Cannot retrieve the content at " + contentUri);
975 if (Log.LOGD)
976 Log.d(LOG_TAG, e.getMessage() + "\n" + Log.getStackTraceString(e));
977 }
978 return null;
979 }
980
981
982
983
984
985
986
987 public static DocumentInfo documentFromFileUri(Uri fileUri) {
988 if (fileUri == null)
989 return null;
990
991 try {
992 URI uri = new URI(fileUri.toString());
993 File file = new File(uri);
994
995 DocumentInfo document = new DocumentInfo();
996 document.documentName = file.getName();
997 document.documentSizeKb = file.length() / 1024;
998 document.documentData = new FileInputStream(file);
999
1000 try {
1001
1002 document.documentMimeType = URLConnection.guessContentTypeFromStream(document.documentData);
1003 } catch (IOException e) {
1004 document.documentMimeType = null;
1005 }
1006 if (document.documentMimeType == null) {
1007
1008
1009 String extension = "";
1010 int dotPos = document.documentName.lastIndexOf('.');
1011 if (0 <= dotPos)
1012 extension = document.documentName.substring(dotPos + 1);
1013 document.documentMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
1014 }
1015
1016 if ("image/jpeg".equals(document.documentMimeType))
1017 document.orientationAngle = getExifOrientationAngleFromFile(file.getAbsolutePath());
1018 return document;
1019 } catch (URISyntaxException e) {
1020 Log.e(LOG_TAG, "Cannot retrieve the file at " + fileUri);
1021 if (Log.LOGD)
1022 Log.d(LOG_TAG, e.getMessage() + "\n" + Log.getStackTraceString(e));
1023 } catch (FileNotFoundException e) {
1024 Log.e(LOG_TAG, "Cannot retrieve the file at " + fileUri);
1025 if (Log.LOGD)
1026 Log.d(LOG_TAG, e.getMessage() + "\n" + Log.getStackTraceString(e));
1027 }
1028 return null;
1029 }
1030
1031
1032
1033
1034
1035
1036
1037 public static boolean deleteLocalFiles(List<String> files) {
1038 boolean result = true;
1039 if (files != null) {
1040 for (String filePath : files) {
1041 File f = new File(filePath);
1042 boolean del = f.delete();
1043 Log.d(LOG_TAG, "File " + f.getName() + " deleted: " + (del ? "YES" : "NO"));
1044 result &= del;
1045 }
1046 }
1047 return result;
1048 }
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058 public static String cleanupFilename(String originalName) {
1059 final String TILDE_HYPHENS_COLONS_SPACES = "[~_:\\s]";
1060 final String MULTIPLE_HYPHENS = "-{2,}";
1061 final String FORBIDDEN_CHARS = "[`!@#\\$%\\^&\\*\\|;\"'<>/\\\\\\[\\]\\{\\}\\(\\)\\?,=\\+\\.]+";
1062 String name = originalName;
1063 String ext = "";
1064 int lastDot = name.lastIndexOf('.');
1065 if (lastDot > 0 && lastDot < name.length()) {
1066 ext = name.substring(lastDot);
1067 name = name.substring(0, lastDot);
1068 }
1069
1070 name = Pattern.compile(TILDE_HYPHENS_COLONS_SPACES).matcher(name).replaceAll("-");
1071
1072 name = Pattern.compile(FORBIDDEN_CHARS).matcher(name).replaceAll("");
1073
1074 name = Normalizer.normalize(name, Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "");
1075
1076
1077
1078 name = name.toLowerCase(Locale.getDefault());
1079
1080 name = Pattern.compile(MULTIPLE_HYPHENS).matcher(name).replaceAll("-");
1081
1082 return (name + ext);
1083 }
1084
1085 public static final int ROTATION_0 = 0;
1086
1087 public static final int ROTATION_90 = 90;
1088
1089 public static final int ROTATION_180 = 180;
1090
1091 public static final int ROTATION_270 = 270;
1092
1093
1094
1095
1096
1097
1098
1099 public static int getExifOrientationAngleFromFile(String filePath) {
1100 int ret = ROTATION_0;
1101 try {
1102 ret = new ExifInterface(filePath).getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
1103 switch (ret) {
1104 case ExifInterface.ORIENTATION_ROTATE_90:
1105 ret = ROTATION_90;
1106 break;
1107 case ExifInterface.ORIENTATION_ROTATE_180:
1108 ret = ROTATION_180;
1109 break;
1110 case ExifInterface.ORIENTATION_ROTATE_270:
1111 ret = ROTATION_270;
1112 break;
1113 default:
1114 break;
1115 }
1116 } catch (IOException e) {
1117 if (Log.LOGD)
1118 Log.d(ExoDocumentUtils.class.getSimpleName(), e.getMessage(), Log.getStackTraceString(e));
1119 }
1120 return ret;
1121 }
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131 public static Bitmap rotateBitmapToNormal(String filePath, Bitmap source) {
1132 Bitmap ret = source;
1133
1134 int orientation = getExifOrientationAngleFromFile(filePath);
1135
1136
1137
1138 if (orientation == ROTATION_90 || orientation == ROTATION_180 || orientation == ROTATION_270) {
1139 ret = rotateBitmapByAngle(source, orientation);
1140 }
1141 return ret;
1142 }
1143
1144
1145
1146
1147
1148
1149
1150
1151 public static Bitmap rotateBitmapByAngle(Bitmap source, int angle) {
1152 Bitmap ret = source;
1153 int w, h;
1154 w = source.getWidth();
1155 h = source.getHeight();
1156 Matrix matrix = new Matrix();
1157 matrix.postRotate(angle);
1158 try {
1159 ret = Bitmap.createBitmap(source, 0, 0, w, h, matrix, true);
1160 } catch (OutOfMemoryError e) {
1161 Log.d(ExoDocumentUtils.class.getSimpleName(), "Exception : ", e, Log.getStackTraceString(e));
1162 }
1163 return ret;
1164 }
1165
1166 private static String permissionForCode(int permCode) {
1167 String permission = null;
1168 switch (permCode) {
1169 case ExoConstants.REQUEST_TAKE_PICTURE_WITH_CAMERA:
1170
1171 permission = Manifest.permission.WRITE_EXTERNAL_STORAGE;
1172 break;
1173 case ExoConstants.REQUEST_PICK_IMAGE_FROM_GALLERY:
1174 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
1175
1176 permission = permissionReadExternalStorage();
1177 else
1178
1179 permission = Manifest.permission.WRITE_EXTERNAL_STORAGE;
1180 break;
1181 default:
1182 throw new IllegalArgumentException("Given permission code is incorrect: "+permCode);
1183 }
1184 return permission;
1185 }
1186
1187 @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
1188 private static String permissionReadExternalStorage() {
1189 return Manifest.permission.READ_EXTERNAL_STORAGE;
1190 }
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201 public static boolean didRequestPermission(Activity caller, int permissionCode) {
1202 if (caller == null || !(caller instanceof OnRequestPermissionsResultCallback))
1203 throw new IllegalArgumentException("Caller activity must implement OnRequestPermissionsResultCallback");
1204
1205 boolean res = false;
1206 String permission = permissionForCode(permissionCode);
1207 int check = ContextCompat.checkSelfPermission(caller, permission);
1208 if (check != PackageManager.PERMISSION_GRANTED) {
1209 res = true;
1210 ActivityCompat.requestPermissions(caller, new String[]{permission}, permissionCode);
1211 }
1212 return res;
1213 }
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223 public static boolean shouldDisplayExplanation(Activity activity, int permCode) {
1224 if (activity == null)
1225 throw new IllegalArgumentException("Caller activity must not be null");
1226 String permission = permissionForCode(permCode);
1227 return ActivityCompat.shouldShowRequestPermissionRationale(activity, permission);
1228 }
1229
1230
1231 public static class DocumentInfo {
1232
1233 public String documentName;
1234
1235 public long documentSizeKb;
1236
1237 public InputStream documentData;
1238
1239 public String documentMimeType;
1240
1241 public int orientationAngle = ROTATION_0;
1242
1243 @Override
1244 public String toString() {
1245 return String.format(Locale.US, "File %s [%s - %s KB]", documentName, documentMimeType, documentSizeKb);
1246 }
1247
1248 public void closeDocStream() {
1249 if (documentData != null)
1250 try {
1251 documentData.close();
1252 } catch (IOException e) {
1253 if (Log.LOGD)
1254 Log.d(LOG_TAG, Log.getStackTraceString(e));
1255 }
1256 }
1257
1258
1259
1260
1261
1262
1263
1264 public void cleanupFilename(Context context) {
1265 final String TILDE_HYPHENS_COLONS_SPACES = "[~_:\\s]";
1266 final String MULTIPLE_HYPHENS = "-{2,}";
1267 final String FORBIDDEN_CHARS = "[`!@#\\$%\\^&\\*\\|;\"'<>/\\\\\\[\\]\\{\\}\\(\\)\\?,=\\+\\.]+";
1268 String name = documentName;
1269 String ext = "";
1270 int lastDot = name.lastIndexOf('.');
1271 if (lastDot > 0 && lastDot < name.length()) {
1272 ext = name.substring(lastDot);
1273 name = name.substring(0, lastDot);
1274 }
1275
1276 name = Pattern.compile(TILDE_HYPHENS_COLONS_SPACES).matcher(name).replaceAll("-");
1277
1278 name = Pattern.compile(FORBIDDEN_CHARS).matcher(name).replaceAll("");
1279
1280 name = Normalizer.normalize(name, Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "");
1281
1282 Locale loc = new Locale(SettingUtils.getPrefsLanguage(context.getApplicationContext()));
1283 name = name.toLowerCase(loc == null ? Locale.getDefault() : loc);
1284
1285 name = Pattern.compile(MULTIPLE_HYPHENS).matcher(name).replaceAll("-");
1286
1287 documentName = name + ext;
1288 }
1289 }
1290 }