public static int getUriType(Uri uri) {
   assertNonRelative(uri);
   String scheme = uri.getScheme();
   if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
     return URI_TYPE_CONTENT;
   }
   if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
     return URI_TYPE_RESOURCE;
   }
   if (ContentResolver.SCHEME_FILE.equals(scheme)) {
     if (uri.getPath().startsWith("/android_asset/")) {
       return URI_TYPE_ASSET;
     }
     return URI_TYPE_FILE;
   }
   if ("data".equals(scheme)) {
     return URI_TYPE_DATA;
   }
   if ("http".equals(scheme)) {
     return URI_TYPE_HTTP;
   }
   if ("https".equals(scheme)) {
     return URI_TYPE_HTTPS;
   }
   return URI_TYPE_UNKNOWN;
 }
 /**
  * Gets a drawable by URI, without using the cache.
  *
  * @return A drawable, or {@code null} if the drawable could not be loaded.
  */
 private Drawable getDrawable(Uri uri) {
   try {
     String scheme = uri.getScheme();
     if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
       // Load drawables through Resources, to get the source density information
       OpenResourceIdResult r = mProviderContext.getContentResolver().getResourceId(uri);
       try {
         return r.r.getDrawable(r.id);
       } catch (Resources.NotFoundException ex) {
         throw new FileNotFoundException("Resource does not exist: " + uri);
       }
     } else {
       // Let the ContentResolver handle content and file URIs.
       InputStream stream = mProviderContext.getContentResolver().openInputStream(uri);
       if (stream == null) {
         throw new FileNotFoundException("Failed to open " + uri);
       }
       try {
         return Drawable.createFromStream(stream, null);
       } finally {
         try {
           stream.close();
         } catch (IOException ex) {
           Log.e(LOG_TAG, "Error closing icon stream for " + uri, ex);
         }
       }
     }
   } catch (FileNotFoundException fnfe) {
     Log.w(LOG_TAG, "Icon not found: " + uri + ", " + fnfe.getMessage());
     return null;
   }
 }
 private int openOrDownloadInner(JobContext jc) {
   String scheme = mUri.getScheme();
   if (ContentResolver.SCHEME_CONTENT.equals(scheme)
       || ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)
       || ContentResolver.SCHEME_FILE.equals(scheme)) {
     try {
       if (MIME_TYPE_JPEG.equalsIgnoreCase(mContentType)) {
         InputStream is = mApplication.getContentResolver().openInputStream(mUri);
         mRotation = Exif.getOrientation(is);
         Utils.closeSilently(is);
       }
       mFileDescriptor = mApplication.getContentResolver().openFileDescriptor(mUri, "r");
       if (jc.isCancelled()) return STATE_INIT;
       return STATE_DOWNLOADED;
     } catch (FileNotFoundException e) {
       Log.w(TAG, "fail to open: " + mUri, e);
       return STATE_ERROR;
     }
   } else {
     try {
       URL url = new URI(mUri.toString()).toURL();
       mCacheEntry = mApplication.getDownloadCache().download(jc, url);
       if (jc.isCancelled()) return STATE_INIT;
       if (mCacheEntry == null) {
         Log.w(TAG, "download failed " + url);
         return STATE_ERROR;
       }
       if (MIME_TYPE_JPEG.equalsIgnoreCase(mContentType)) {
         InputStream is = new FileInputStream(mCacheEntry.cacheFile);
         mRotation = Exif.getOrientation(is);
         Utils.closeSilently(is);
       }
       mFileDescriptor =
           ParcelFileDescriptor.open(mCacheEntry.cacheFile, ParcelFileDescriptor.MODE_READ_ONLY);
       return STATE_DOWNLOADED;
     } catch (Throwable t) {
       Log.w(TAG, "download error", t);
       return STATE_ERROR;
     }
   }
 }
  /**
   * Downloads a file form a given URL and saves it to the specified directory.
   *
   * @param source URL of the server to receive the file
   * @param target Full path of the file on the file system
   */
  private void download(
      final String source, final String target, JSONArray args, CallbackContext callbackContext)
      throws JSONException {
    Log.d(LOG_TAG, "download " + source + " to " + target);

    final boolean trustEveryone = args.optBoolean(2);
    final String objectId = args.getString(3);
    final JSONObject headers = args.optJSONObject(4);

    final URL url;
    try {
      url = new URL(source);
    } catch (MalformedURLException e) {
      JSONObject error = createFileTransferError(INVALID_URL_ERR, source, target, null, 0);
      Log.e(LOG_TAG, error.toString(), e);
      callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
      return;
    }
    final String sourceProtocol = url.getProtocol();
    final boolean useHttps = "https".equals(sourceProtocol);
    final boolean useResolvers =
        ContentResolver.SCHEME_FILE.equals(sourceProtocol)
            || ContentResolver.SCHEME_CONTENT.equals(sourceProtocol)
            || ContentResolver.SCHEME_ANDROID_RESOURCE.equals(sourceProtocol);

    // TODO: refactor to also allow resources & content:
    if (!useResolvers && !Config.isUrlWhiteListed(source)) {
      Log.w(LOG_TAG, "Source URL is not in white list: '" + source + "'");
      JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, null, 401);
      callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
      return;
    }

    final RequestContext context = new RequestContext(source, target, callbackContext);
    synchronized (activeRequests) {
      activeRequests.put(objectId, context);
    }

    cordova
        .getThreadPool()
        .execute(
            new Runnable() {
              public void run() {
                if (context.aborted) {
                  return;
                }
                URLConnection connection = null;
                HostnameVerifier oldHostnameVerifier = null;
                SSLSocketFactory oldSocketFactory = null;
                File file = null;
                PluginResult result = null;

                try {
                  UriResolver sourceResolver = null;
                  UriResolver targetResolver = webView.resolveUri(Uri.parse(target));
                  TrackingInputStream inputStream = null;

                  file = targetResolver.getLocalFile();
                  context.targetFile = file;

                  Log.d(LOG_TAG, "Download file:" + url);

                  FileProgressResult progress = new FileProgressResult();

                  if (useResolvers) {
                    sourceResolver = webView.resolveUri(Uri.parse(source));
                    long len = sourceResolver.computeLength();
                    if (len != -1) {
                      progress.setLengthComputable(true);
                      progress.setTotal(len);
                    }
                    inputStream = new SimpleTrackingInputStream(sourceResolver.getInputStream());
                  } else {
                    // connect to server
                    // Open a HTTP connection to the URL based on protocol
                    if (useHttps) {
                      // Using standard HTTPS connection. Will not allow self signed certificate
                      if (!trustEveryone) {
                        connection = (HttpsURLConnection) httpClient.open(url);
                      }
                      // Use our HTTPS connection that blindly trusts everyone.
                      // This should only be used in debug environments
                      else {
                        // Setup the HTTPS connection class to trust everyone
                        HttpsURLConnection https = (HttpsURLConnection) httpClient.open(url);
                        oldSocketFactory = trustAllHosts(https);
                        // Save the current hostnameVerifier
                        oldHostnameVerifier = https.getHostnameVerifier();
                        // Setup the connection not to verify hostnames
                        https.setHostnameVerifier(DO_NOT_VERIFY);
                        connection = https;
                      }
                    }
                    // Return a standard HTTP connection
                    else {
                      connection = httpClient.open(url);
                    }

                    if (connection instanceof HttpURLConnection) {
                      ((HttpURLConnection) connection).setRequestMethod("GET");
                    }

                    // Add cookie support
                    String cookie = CookieManager.getInstance().getCookie(source);
                    if (cookie != null) {
                      connection.setRequestProperty("cookie", cookie);
                    }

                    // This must be explicitly set for gzip progress tracking to work.
                    connection.setRequestProperty("Accept-Encoding", "gzip");

                    // Handle the other headers
                    if (headers != null) {
                      addHeadersToRequest(connection, headers);
                    }

                    connection.connect();

                    if (connection.getContentEncoding() == null
                        || connection.getContentEncoding().equalsIgnoreCase("gzip")) {
                      // Only trust content-length header if we understand
                      // the encoding -- identity or gzip
                      progress.setLengthComputable(true);
                      progress.setTotal(connection.getContentLength());
                    }
                    inputStream = getInputStream(connection);
                  }

                  OutputStream outputStream = null;

                  try {
                    outputStream = targetResolver.getOutputStream();
                    synchronized (context) {
                      if (context.aborted) {
                        return;
                      }
                      context.currentInputStream = inputStream;
                    }

                    // write bytes to file
                    byte[] buffer = new byte[MAX_BUFFER_SIZE];
                    int bytesRead = 0;
                    while ((bytesRead = inputStream.read(buffer)) > 0) {
                      outputStream.write(buffer, 0, bytesRead);
                      // Send a progress event.
                      progress.setLoaded(inputStream.getTotalRawBytesRead());
                      PluginResult progressResult =
                          new PluginResult(PluginResult.Status.OK, progress.toJSONObject());
                      progressResult.setKeepCallback(true);
                      context.sendPluginResult(progressResult);
                    }
                  } finally {
                    context.currentInputStream = null;
                    safeClose(inputStream);
                    safeClose(outputStream);
                  }

                  Log.d(LOG_TAG, "Saved file: " + target);

                  // create FileEntry object
                  JSONObject fileEntry = FileUtils.getEntry(file);

                  result = new PluginResult(PluginResult.Status.OK, fileEntry);
                } catch (FileNotFoundException e) {
                  JSONObject error =
                      createFileTransferError(FILE_NOT_FOUND_ERR, source, target, connection);
                  Log.e(LOG_TAG, error.toString(), e);
                  result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
                } catch (IOException e) {
                  JSONObject error =
                      createFileTransferError(CONNECTION_ERR, source, target, connection);
                  Log.e(LOG_TAG, error.toString(), e);
                  result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
                } catch (JSONException e) {
                  Log.e(LOG_TAG, e.getMessage(), e);
                  result = new PluginResult(PluginResult.Status.JSON_EXCEPTION);
                } catch (Throwable e) {
                  JSONObject error =
                      createFileTransferError(CONNECTION_ERR, source, target, connection);
                  Log.e(LOG_TAG, error.toString(), e);
                  result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
                } finally {
                  synchronized (activeRequests) {
                    activeRequests.remove(objectId);
                  }

                  if (connection != null) {
                    // Revert back to the proper verifier and socket factories
                    if (trustEveryone && useHttps) {
                      HttpsURLConnection https = (HttpsURLConnection) connection;
                      https.setHostnameVerifier(oldHostnameVerifier);
                      https.setSSLSocketFactory(oldSocketFactory);
                    }
                  }

                  if (result == null) {
                    result =
                        new PluginResult(
                            PluginResult.Status.ERROR,
                            createFileTransferError(CONNECTION_ERR, source, target, connection));
                  }
                  // Remove incomplete download.
                  if (result.getStatus() != PluginResult.Status.OK.ordinal() && file != null) {
                    file.delete();
                  }
                  context.sendPluginResult(result);
                }
              }
            });
  }
示例#5
0
 private boolean isLocalUri(String scheme) {
   return ContentResolver.SCHEME_FILE.equals(scheme)
       || ContentResolver.SCHEME_CONTENT.equals(scheme)
       || ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme);
 }