diff --git a/external/Makefile b/external/Makefile index 300a465d..45bdafa8 100644 --- a/external/Makefile +++ b/external/Makefile @@ -244,6 +244,33 @@ privoxy-clean: -rm -f privoxy-build-stamp -rm -rf privoxy +#------------------------------------------------------------------------------# +# SimpleServer library # +simple/bin/simple.jar: + tar xzvf simple.tar.gz + mv simple-* simple + test -d simple/bin || mkdir simple/bin + cd simple/src && \ + javac -source 1.6 -target 1.6 org/simpleframework/http/core/ContainerServer.java -d ../bin + cd simple/src && \ + javac -source 1.6 -target 1.6 org/simpleframework/transport/connect/Connection.java -d ../bin + cd simple/src && \ + javac -source 1.6 -target 1.6 org/simpleframework/transport/connect/SocketConnection.java -d ../bin + cd simple/bin && \ + jar cvf simple.jar * + +simple-build-stamp: simple/bin/simple.jar + touch simple-build-stamp + +simple: simple-build-stamp + test -d bin || mkdir bin + cp simple/bin/simple.jar bin + +simple-clean: + - rm -f bin/simple.jar + - rm -f simple-build-stamp + - rm -rf simple + #------------------------------------------------------------------------------# # JTorControl library @@ -270,12 +297,13 @@ jtorctl-clean: #in order to stop Android OS (older devices) from trying to compress/decompress it #this is related to a bug in compression of assets and resources > 1MB -assets: tor privoxy jtorctl obfsproxy +assets: tor privoxy jtorctl obfsproxy simple install -d ../res/raw install -d ../libs install bin/privoxy ../res/raw install bin/obfsproxy ../res/raw install bin/jtorctl.jar ../libs + install bin/simple.jar ../libs cd bin && \ zip ../../res/raw/tor.mp3 tor diff --git a/external/simple.tar.gz b/external/simple.tar.gz new file mode 100644 index 00000000..069956b8 Binary files /dev/null and b/external/simple.tar.gz differ diff --git a/src/org/torproject/android/share/ShareItem.java b/src/org/torproject/android/share/ShareItem.java new file mode 100644 index 00000000..06ec2354 --- /dev/null +++ b/src/org/torproject/android/share/ShareItem.java @@ -0,0 +1,10 @@ +package org.torproject.android.share; + +import android.net.Uri; + +public class ShareItem { + + public String mContentType; + public long mContentLength; + public Uri mUriData; +} diff --git a/src/org/torproject/android/share/ShareService.java b/src/org/torproject/android/share/ShareService.java new file mode 100644 index 00000000..c34fe43e --- /dev/null +++ b/src/org/torproject/android/share/ShareService.java @@ -0,0 +1,160 @@ +package org.torproject.android.share; + +import java.io.BufferedOutputStream; +import java.io.InputStream; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.HashMap; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +import org.simpleframework.http.Path; +import org.simpleframework.http.Request; +import org.simpleframework.http.Response; +import org.simpleframework.http.core.Container; +import org.simpleframework.http.core.ContainerServer; +import org.simpleframework.transport.Server; +import org.simpleframework.transport.connect.Connection; +import org.simpleframework.transport.connect.SocketConnection; + +import android.content.ContentResolver; +import android.content.Context; +import android.content.res.AssetFileDescriptor; +import android.database.Cursor; +import android.provider.MediaStore; +import android.util.Log; + +public class ShareService implements Container { + + private final static String TAG = "OrbotShare"; + + public static class Task implements Runnable { + + private final Response response; + private final Request request; + + public Task(Request request, Response response) { + this.response = response; + this.request = request; + } + + public void run() { + try { + + Path path = request.getPath(); + String rPath = path.toString(); + if (rPath.length() > 0) + rPath = rPath.substring(1); + + ShareItem sItem = sShareItems.get(rPath); + + if (sItem != null) + { + + long time = System.currentTimeMillis(); + + response.setValue("Server", "OrbotShare/1.0 (Orbot 0.0.12-alpha)"); + response.setDate("Date", time); + response.setDate("Last-Modified", time); + response.setValue("Content-Type", sItem.mContentType); + + + ContentResolver cr = sContext.getContentResolver(); + InputStream is = cr.openInputStream(sItem.mUriData); + + AssetFileDescriptor fileDesc = cr.openAssetFileDescriptor(sItem.mUriData, "r"); + fileDesc.getLength(); + + response.setValue("Content-Length", fileDesc.getLength()+""); + + String fileName = rPath; + + String scheme = sItem.mUriData.getScheme(); + if (scheme.equals("file")) { + fileName = sItem.mUriData.getLastPathSegment(); + } + else if (scheme.equals("content")) { + String[] proj = { MediaStore.Images.Media.TITLE }; + Cursor cursor = cr.query(sItem.mUriData, proj, null, null, null); + if (cursor != null && cursor.getCount() != 0) { + int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.TITLE); + cursor.moveToFirst(); + fileName = cursor.getString(columnIndex); + } + } + + //force file to be downloaded + response.setValue("Content-Disposition","attachment; filename=" + fileName); + + BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream()); + + byte[] buffer = new byte[1024]; + int len = -1; + while ( (len = is.read(buffer)) != -1) + { + bos.write(buffer, 0, len); + } + + bos.flush(); + bos.close(); + } + else + { + response.setCode(404); + response.close(); + } + + } catch(Exception e) { + Log.e(TAG,"error handling request",e); + } + } + } + + public ShareService(int size, Context context) { + this.executor = Executors.newFixedThreadPool(size); + sContext = context; + } + + public void handle(Request request, Response response) { + Task task = new Task(request, response); + + executor.execute(task); + } + + + public void startService (int port) throws Exception { + + mServer = new ContainerServer(this); + mConnection = new SocketConnection(mServer); + SocketAddress address = new InetSocketAddress(port); + + mConnection.connect(address); + } + + public void stopService () throws Exception { + mConnection.close(); + } + + public synchronized String addShare (ShareItem sItem) + { + if (sShareItems == null) + { + sShareItems = new HashMap(); + + } + + String guid = java.util.UUID.randomUUID().toString().substring(0,6);//short guid + + sShareItems.put (guid, sItem); + + return guid; + } + + private final Executor executor; + + private Server mServer; + private Connection mConnection; + + private static HashMap sShareItems; + private static Context sContext; +} \ No newline at end of file