package com.bigpupdev.synodroid.server; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.security.SecureRandom; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import org.json.JSONObject; import com.bigpupdev.synodroid.R; import com.bigpupdev.synodroid.Synodroid; import com.bigpupdev.synodroid.data.DSMVersion; import com.bigpupdev.synodroid.protocol.DSMHandlerFactory; import com.bigpupdev.synodroid.protocol.https.AcceptAllHostNameVerifier; import com.bigpupdev.synodroid.protocol.https.AcceptAllTrustManager; import com.bigpupdev.synodroid.utils.ServiceHelper; import android.app.Activity; import android.app.IntentService; import android.app.Notification; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; import android.util.Log; public class UploadIntentService extends IntentService{ public static String URL = "URL"; public static String DEBUG = "DEBUG"; public static String DSM_VERSION = "DSM_VERSION"; public static String COOKIES = "COOKIES"; public static String DIRECTORY = "DIRECTORY"; public static String PATH = "PATH"; private int UL_ID = 43; private static final String PREFERENCE_GENERAL = "general_cat"; private static final String PREFERENCE_AUTO_DSM = "general_cat.auto_detect_DSM"; int progress = 0; static { SSLContext sc; try { sc = SSLContext.getInstance("TLS"); sc.init(null, new TrustManager[] { new AcceptAllTrustManager() }, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier(new AcceptAllHostNameVerifier()); } catch (Exception ex) { ex.printStackTrace(); } } /** * A constructor is required, and must call the super IntentService(String) * constructor with a name for the worker thread. */ public UploadIntentService() { super("UploadIntentService"); } @Override public void onDestroy() { super.onDestroy(); } /** * The IntentService calls this method from the default worker thread with * the intent that started the service. When this method returns, IntentService * stops the service, as appropriate. */ @Override protected void onHandleIntent(Intent intent) { String dsm_version = intent.getStringExtra(DSM_VERSION); String cookie = intent.getStringExtra(COOKIES); String shared = intent.getStringExtra(DIRECTORY); Uri uri = Uri.parse(intent.getStringExtra(URL)); String path = intent.getStringExtra(PATH); boolean dbg = intent.getBooleanExtra(DEBUG, false); SharedPreferences preferences = getSharedPreferences(PREFERENCE_GENERAL, Activity.MODE_PRIVATE); boolean autoDetect = preferences.getBoolean(PREFERENCE_AUTO_DSM, true); DSMVersion vers = DSMVersion.titleOf(dsm_version); if (vers == null) { vers = DSMVersion.VERSION2_2; } DSMHandlerFactory dsm = DSMHandlerFactory.getFactory(vers, null, dbg, autoDetect); String url = dsm.getDSHandler().getMultipartUri(); byte[] content = null; try { content = dsm.getDSHandler().generateMultipart(uri, shared); } catch (Exception e1) { if (dbg) Log.e(Synodroid.DS_TAG, "UploadIntentService: Error while building multipart.", e1); } if (content != null){ Notification notification = ServiceHelper.getNotificationProgress(this, uri.getPath(), progress, UL_ID, R.drawable.dl_upload); HttpURLConnection conn = null; JSONObject respJSO = null; int retry = 0; int MAX_RETRY = 2; try { while (retry <= MAX_RETRY) { try { // Create the connection conn = ServiceHelper.createConnection(url, "", "POST", dbg, cookie, path); conn.setRequestProperty("Connection", "keep-alive"); conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + dsm.getDSHandler().getBoundary()); conn.setFixedLengthStreamingMode(content.length); // Write the multipart OutputStream out = null; try{ out = conn.getOutputStream(); int offset = 0; int size = 1024; int lenBytes = Math.min(size, content.length); long lastUpdate = 0; while (content.length > offset){ lenBytes = Math.min(content.length-offset, size); out.write(content, offset, lenBytes); offset += lenBytes; progress = (int) ((float) offset / (float )content.length * 100); if (((lastUpdate + 250) < System.currentTimeMillis()) || offset == content.length){ lastUpdate = System.currentTimeMillis(); ServiceHelper.updateProgress(this, notification, progress, UL_ID); } out.flush(); } } finally{ if (out != null) { out.close(); } out = null; } // Now read the reponse and build a string with it BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); StringBuffer sb = new StringBuffer(); String line; while ((line = br.readLine()) != null) { sb.append(line); } br.close(); if (conn.getResponseCode() == -1) { retry++; if (dbg) Log.e(Synodroid.DS_TAG, "Response code is -1 (retry: " + retry + ")"); } else { if (dbg) Log.d(Synodroid.DS_TAG, "Response is: " + sb.toString()); respJSO = new JSONObject(sb.toString()); boolean success = respJSO.getBoolean("success"); // If successful then build details list if (!success) { ServiceHelper.showNotificationError(this, uri.getPath(), getString(R.string.upload_failed), R.drawable.dl_error); } return; } } catch (Exception e) { if (dbg) Log.e(Synodroid.DS_TAG, "Caught exception while contacting the server, retying...", e); retry ++; } } } finally { if (conn != null) { conn.disconnect(); } conn = null; ServiceHelper.cancelNotification(this, UL_ID); } } ServiceHelper.showNotificationError(this, uri.getPath(), getString(R.string.upload_failed), R.drawable.dl_error); } }