public static final String PATH_MANUAL_BOOKMARK_ID = "MBMID/";
public static final String PATH_HOSTNAME = "HOST/";
public static final String PATH_PLACEHOLDER = "PLCHLD/";
+ public static final String PATH_FILE = "FILE/";
public static String getManualBookmarkReference(long bookmarkId) {
return (PATH_MANUAL_BOOKMARK_ID + bookmarkId);
return (PATH_PLACEHOLDER + name);
}
+ public static String getFileReference(String uri) {
+ return (PATH_FILE + uri);
+ }
+
public static boolean isBookmarkReference(String refStr) {
return refStr.startsWith(PATH_MANUAL_BOOKMARK_ID);
}
return refStr.startsWith(PATH_PLACEHOLDER);
}
+ public static boolean isFileReference(String refStr) {
+ return refStr.startsWith(PATH_FILE);
+ }
+
public static long getManualBookmarkId(String refStr) {
return Integer.parseInt(refStr.substring(PATH_MANUAL_BOOKMARK_ID.length()));
}
public static String getPlaceholder(String refStr) {
return refStr.substring(PATH_PLACEHOLDER.length());
}
+
+ public static String getFile(String refStr) {
+ return refStr.substring(PATH_FILE.length());
+ }
}
package com.freerdp.freerdpcore.presentation;
+import java.io.File;
+import java.io.IOException;
+
import com.freerdp.freerdpcore.R;
import com.freerdp.freerdpcore.application.GlobalApp;
import com.freerdp.freerdpcore.domain.BookmarkBase;
import com.freerdp.freerdpcore.domain.ConnectionReference;
import com.freerdp.freerdpcore.domain.ManualBookmark;
import com.freerdp.freerdpcore.services.BookmarkBaseGateway;
+import com.freerdp.freerdpcore.utils.RDPFileParser;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
+import android.util.Log;
public class BookmarkActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener
{
public static final String PARAM_CONNECTION_REFERENCE = "conRef";
+ private static final String TAG = "BookmarkActivity";
+
private int current_preferences;
private static final int PREFERENCES_BOOKMARK = 1;
private static final int PREFERENCES_CREDENTIALS = 2;
bookmark.<ManualBookmark>get().setHostname(ConnectionReference.getHostname(refStr));
new_bookmark = true;
}
+ else if (ConnectionReference.isFileReference(refStr))
+ {
+ String file = ConnectionReference.getFile(refStr);
+
+ bookmark = new ManualBookmark();
+ bookmark.setLabel(file);
+
+ try
+ {
+ RDPFileParser rdpFile = new RDPFileParser(file);
+ updateBookmarkFromFile((ManualBookmark)bookmark, rdpFile);
+
+ bookmark.setLabel(new File(file).getName());
+ new_bookmark = true;
+ }
+ catch (IOException e)
+ {
+ Log.e(TAG, "Failed reading RDP file", e);
+ }
+ }
}
}
setIntentComponentNames();
}
+ private void updateBookmarkFromFile(ManualBookmark bookmark, RDPFileParser rdpFile)
+ {
+ String s;
+ Integer i;
+
+ s = rdpFile.getString("full address");
+ if (s != null)
+ {
+ // this gets complicated as it can include port
+ if (s.lastIndexOf(":") > s.lastIndexOf("]"))
+ {
+ try
+ {
+ String port = s.substring(s.lastIndexOf(":") + 1);
+ bookmark.setPort(Integer.parseInt(port));
+ }
+ catch (NumberFormatException e)
+ {
+ Log.e(TAG, "Malformed address");
+ }
+
+ s = s.substring(0, s.lastIndexOf(":"));
+ }
+
+ // or even be an ipv6 address
+ if (s.startsWith("[") && s.endsWith("]"))
+ s = s.substring(1, s.length() - 1);
+
+ bookmark.setHostname(s);
+ }
+
+ i = rdpFile.getInteger("server port");
+ if (i != null)
+ bookmark.setPort(i);
+
+ s = rdpFile.getString("username");
+ if (s != null)
+ bookmark.setUsername(s);
+
+ s = rdpFile.getString("domain");
+ if (s != null)
+ bookmark.setDomain(s);
+
+ i = rdpFile.getInteger("connect to console");
+ if (i != null)
+ bookmark.getAdvancedSettings().setConsoleMode(i == 1);
+ }
+
private void setIntentComponentNames()
{
// we set the component name for our sub-activity calls here because we don't know the package
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
+import android.net.Uri;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
-import android.view.ContextMenu;
import android.view.View.OnClickListener;
-import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnCreateContextMenuListener;
import android.webkit.WebView;
import android.webkit.WebViewClient;
+import android.widget.AdapterView;
+import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ListView;
-import android.widget.AdapterView;
-import android.widget.AdapterView.AdapterContextMenuInfo;
public class HomeActivity extends Activity
{
addBookmarkPlaceholder.setName(ADD_BOOKMARK_PLACEHOLDER);
addBookmarkPlaceholder.setLabel(getResources().getString(R.string.list_placeholder_add_bookmark));
+ // check for passed .rdp file and open it in a new bookmark
+ Intent caller = getIntent();
+ Uri callParameter = caller.getData();
+
+ if (Intent.ACTION_VIEW.equals(caller.getAction()) && callParameter != null)
+ {
+ String refStr = ConnectionReference.getFileReference(callParameter.getPath());
+ Bundle bundle = new Bundle();
+ bundle.putString(BookmarkActivity.PARAM_CONNECTION_REFERENCE, refStr);
+
+ Intent bookmarkIntent = new Intent(this.getApplicationContext(), BookmarkActivity.class);
+ bookmarkIntent.putExtras(bundle);
+ startActivity(bookmarkIntent);
+ }
+
// load views
clearTextButton = (Button) findViewById(R.id.clear_search_btn);
superBarEditText = (EditText) findViewById(R.id.superBarEditText);
--- /dev/null
+/*
+ Simple .RDP file parser
+
+ Copyright 2013 Blaz Bacnik
+
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+*/
+
+package com.freerdp.freerdpcore.utils;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Locale;
+
+public class RDPFileParser {
+
+ private static final int MAX_ERRORS = 20;
+ private static final int MAX_LINES = 500;
+
+ private HashMap<String, Object> options;
+
+ private void init()
+ {
+ options = new HashMap<String, Object>();
+ }
+
+ public RDPFileParser()
+ {
+ init();
+ }
+
+ public RDPFileParser(String filename) throws IOException
+ {
+ init();
+ parse(filename);
+ }
+
+ public void parse(String filename) throws IOException
+ {
+ BufferedReader br = new BufferedReader(new FileReader(filename));
+ String line = null;
+
+ int errors = 0;
+ int lines = 0;
+ boolean ok;
+
+ while ((line = br.readLine()) != null)
+ {
+ lines++; ok = false;
+
+ if (errors > MAX_ERRORS || lines > MAX_LINES)
+ throw new IOException("Parsing limits exceeded");
+
+ String[] fields = line.split(":", 3);
+
+ if (fields.length == 3)
+ {
+ if (fields[1].equals("s"))
+ {
+ options.put(fields[0].toLowerCase(Locale.ENGLISH), fields[2]);
+ ok = true;
+ }
+ else if (fields[1].equals("i"))
+ {
+ try
+ {
+ Integer i = Integer.parseInt(fields[2]);
+ options.put(fields[0].toLowerCase(Locale.ENGLISH), i);
+ ok = true;
+ }
+ catch (NumberFormatException e) { }
+ }
+ else if (fields[1].equals("b"))
+ {
+ ok = true;
+ }
+ }
+
+ if (!ok) errors++;
+ }
+ }
+
+ public String getString(String optionName)
+ {
+ if (options.get(optionName) instanceof String)
+ return (String) options.get(optionName);
+ else
+ return null;
+ }
+
+ public Integer getInteger(String optionName)
+ {
+ if (options.get(optionName) instanceof Integer)
+ return (Integer) options.get(optionName);
+ else
+ return null;
+ }
+}
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data
+ android:scheme="file"
+ android:mimeType="application/x-rdp" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data
+ android:scheme="file"
+ android:pathPattern=".*\\.rdp"
+ android:mimeType="*/*" />
+ </intent-filter>
</activity>
<!-- Session request handler activity - used for search and internally to start sessions -->