Milestone 5: deliver embedded RDP sessions and lifecycle hardening
51
third_party/FreeRDP/client/Android/Studio/aFreeRDP/build.gradle
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
plugins {
|
||||
id 'com.gladed.androidgitversion' version '0.4.14'
|
||||
}
|
||||
|
||||
androidGitVersion {
|
||||
abis = ['armeabi':1, 'armeabi-v7a':2, 'arm64-v8a':3, 'mips':5, 'mips64':6, 'x86':8, 'x86_64':9 ]
|
||||
prefix ''
|
||||
}
|
||||
|
||||
println 'Version Name: ' + androidGitVersion.name()
|
||||
println 'Version Code: ' + androidGitVersion.code()
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
android {
|
||||
compileSdkVersion = rootProject.ext.compileApi
|
||||
buildToolsVersion = rootProject.ext.toolsVersion
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.freerdp.afreerdp"
|
||||
minSdkVersion rootProject.ext.minApi
|
||||
targetSdkVersion rootProject.ext.targetApi
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
versionName = androidGitVersion.name()
|
||||
versionCode = androidGitVersion.code()
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
release {
|
||||
storeFile file(RELEASE_STORE_FILE)
|
||||
storePassword RELEASE_STORE_PASSWORD
|
||||
keyAlias RELEASE_KEY_ALIAS
|
||||
keyPassword RELEASE_KEY_PASSWORD
|
||||
storeType "jks"
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
signingConfig signingConfigs.release
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
}
|
||||
debug {
|
||||
jniDebuggable true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':freeRDPCore')
|
||||
}
|
||||
2
third_party/FreeRDP/client/Android/Studio/aFreeRDP/lint.xml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<lint></lint>
|
||||
107
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/AndroidManifest.xml
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:installLocation="auto">
|
||||
|
||||
<application
|
||||
android:name="com.freerdp.afreerdp.application.GlobalApp"
|
||||
android:icon="@drawable/icon_launcher_freerdp"
|
||||
android:label="aFreeRDP"
|
||||
android:resizeableActivity="true">
|
||||
|
||||
<!-- Main activity -->
|
||||
<activity
|
||||
android:exported="true"
|
||||
android:name="com.freerdp.freerdpcore.presentation.HomeActivity"
|
||||
android:alwaysRetainTaskState="true"
|
||||
android:label="@string/app_title"
|
||||
android:theme="@style/Theme.Main"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|screenLayout">
|
||||
|
||||
<intent-filter android:label="@string/app_title">
|
||||
<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" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:mimeType="application/rdp" />
|
||||
<data android:mimeType="application/x-rdp" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="rdp" />
|
||||
<data android:scheme="Rdp" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="file" />
|
||||
<data android:scheme="http" />
|
||||
<data android:scheme="https" />
|
||||
<data android:scheme="content" />
|
||||
<data android:host="*" />
|
||||
|
||||
<!-- Ugly hack to match all files with a dot in its name.
|
||||
Remove if a better way is found / supported.
|
||||
https://stackoverflow.com/questions/3400072/pathpattern-to-match-file-extension-does-not-work-if-a-period-exists-elsewhere-i/8599921#8599921
|
||||
-->
|
||||
<data android:pathPattern=".*\\.rdp" />
|
||||
<data android:pathPattern=".*\\..*\\.rdp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\.rdp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\.rdp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.rdp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.rdp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.rdp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.rdp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.rdp" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- Session request handler activity - used for search and internally to start sessions -->
|
||||
<!-- This should actually be defined in FreeRDPCore lib but Android manifest merging will -->
|
||||
<!-- append the libs manifest to the apps manifest and therefore aliasing is not possible -->
|
||||
<activity
|
||||
android:exported="true"
|
||||
android:name="com.freerdp.freerdpcore.services.SessionRequestHandlerActivity"
|
||||
android:excludeFromRecents="true"
|
||||
android:noHistory="true"
|
||||
android:theme="@android:style/Theme.NoDisplay">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity-alias
|
||||
android:exported="true"
|
||||
android:name=".services.SessionRequestHandlerActivity"
|
||||
android:targetActivity="com.freerdp.freerdpcore.services.SessionRequestHandlerActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEARCH" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.searchable"
|
||||
android:resource="@xml/searchable" />
|
||||
</activity-alias>
|
||||
|
||||
<provider
|
||||
android:name="com.freerdp.freerdpcore.services.FreeRDPSuggestionProvider"
|
||||
android:authorities="com.freerdp.afreerdp.services.freerdpsuggestionprovider"
|
||||
android:exported="false"></provider>
|
||||
|
||||
<meta-data android:name="com.samsung.android.keepalive.density" android:value="true"/>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/FreeRDP_Logo.png
vendored
Normal file
|
After Width: | Height: | Size: 30 KiB |
147
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/about.css
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
p {
|
||||
border: none;
|
||||
padding: 0in;
|
||||
font-variant: normal;
|
||||
font-family: "Helvetica";
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
line-height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
td p {
|
||||
border: none;
|
||||
padding: 0in;
|
||||
font-variant: normal;
|
||||
font-family: "Helvetica";
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
line-height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h2 {
|
||||
border: none;
|
||||
padding: 0in;
|
||||
direction: inherit;
|
||||
font-variant: normal;
|
||||
color: #ffffff;
|
||||
line-height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h2.western {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
h2.cjk {
|
||||
font-family: "AR PL SungtiL GB";
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
h2.ctl {
|
||||
font-family: "Lohit Devanagari";
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
h3 {
|
||||
border: none;
|
||||
padding: 0in;
|
||||
direction: inherit;
|
||||
font-variant: normal;
|
||||
color: #ffffff;
|
||||
line-height: 100%;
|
||||
text-align: center;
|
||||
page-break-before: auto;
|
||||
page-break-after: auto;
|
||||
}
|
||||
|
||||
h3.western {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
h3.cjk {
|
||||
font-family: "AR PL SungtiL GB";
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
h3.ctl {
|
||||
font-family: "Lohit Devanagari";
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
h4 {
|
||||
border: none;
|
||||
padding: 0in;
|
||||
direction: inherit;
|
||||
font-variant: normal;
|
||||
color: #ffffff;
|
||||
line-height: 100%;
|
||||
text-align: center;
|
||||
page-break-before: auto;
|
||||
page-break-after: auto;
|
||||
}
|
||||
|
||||
h4.western {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
h4.cjk {
|
||||
font-family: "AR PL SungtiL GB";
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
h4.ctl {
|
||||
font-family: "Lohit Devanagari";
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
pre {
|
||||
direction: inherit;
|
||||
font-variant: normal;
|
||||
line-height: 100%;
|
||||
text-align: center;
|
||||
page-break-before: auto;
|
||||
white-space: pre-wrap; /* css-3 */
|
||||
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
}
|
||||
|
||||
pre.western {
|
||||
font-size: 8pt;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
white-space: pre-wrap; /* css-3 */
|
||||
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
}
|
||||
|
||||
pre.cjk {
|
||||
font-family: "AR PL SungtiL GB", monospace;
|
||||
font-size: 8pt;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
white-space: pre-wrap; /* css-3 */
|
||||
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
}
|
||||
|
||||
pre.ctl {
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
white-space: pre-wrap; /* css-3 */
|
||||
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
}
|
||||
|
||||
a:link {
|
||||
color: #0000ff
|
||||
}
|
||||
397
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/about_page/about.html
vendored
Normal file
@@ -0,0 +1,397 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
|
||||
<title></title>
|
||||
<meta name="" content=""/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../about.css">
|
||||
</head>
|
||||
<body lang="en-US" link="#0000ff" bgcolor="#e9ebf8" dir="ltr">
|
||||
<div id="container" dir="ltr">
|
||||
<h2 class="western"><br/>
|
||||
<br/>
|
||||
|
||||
</h2>
|
||||
<div id="introduction_headline" dir="ltr" style="background: #353639">
|
||||
<h2 class="western"><font color="#ffffff">aFreeRDP <br/>
|
||||
Remote
|
||||
Desktop Client</font></h2>
|
||||
</div>
|
||||
<p><img src="../FreeRDP_Logo.png" name="Image1" align="bottom" width="25%" border="0"/>
|
||||
|
||||
</p>
|
||||
<div id="introduction" dir="ltr" style="background: #ffffff">
|
||||
<p><font color="#000000"><b>aFreeRDP</b> is an open source client
|
||||
capable of natively using<br/>
|
||||
Remote Desktop Protocol (RDP) in
|
||||
order to remotely access your Windows desktop. </font>
|
||||
</p>
|
||||
</div>
|
||||
<div id="article" dir="ltr" style="background: #ffffff">
|
||||
<p style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
</p>
|
||||
<div id="headline" dir="ltr" style="background: #353639">
|
||||
<h3 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
Version Information</h3>
|
||||
</div>
|
||||
<table cellpadding="3" cellspacing="1" align="center">
|
||||
<tr>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p><b>aFreeRDP</b> Version</p>
|
||||
</td>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>%AFREERDP_VERSION%</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>System Version</p>
|
||||
</td>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>%SYSTEM_VERSION%</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>Model</p>
|
||||
</td>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>%DEVICE_MODEL%</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div id="Section1" dir="ltr" style="background: #353639">
|
||||
<h3 class="western" align="center" style="margin-left: 0.1in; margin-right: 0.1in"><a
|
||||
name="headline"></a>
|
||||
Credits</h3>
|
||||
</div>
|
||||
<p style="margin-top: 0.1in; margin-bottom: 0.1in"><font
|
||||
color="#000000"><b>aFreeRDP</b></font><font color="#000000">
|
||||
is a part of <a href="http://www.freerdp.com/">FreeRDP</a> </font>
|
||||
</p>
|
||||
<div id="Section2" dir="ltr" style="background: #353639">
|
||||
<h3 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline1"></a>
|
||||
Data protection</h3>
|
||||
</div>
|
||||
<p style="margin-top: 0.1in; margin-bottom: 0.1in"><font color="#000000">Details
|
||||
about data collection and usage by <b>aFreeRDP</b> are available at</font></p>
|
||||
<p><a href="http://www.freerdp.com/privacy">http://www.freerdp.com/privacy</a>
|
||||
</p>
|
||||
<div id="Section3" dir="ltr" style="background: #353639">
|
||||
<h3 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline2"></a>
|
||||
Licenses</h3>
|
||||
</div>
|
||||
<div id="Section4" dir="ltr" style="background: #353639">
|
||||
<h4 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline3"></a>
|
||||
<font color="#ffffff">aFreeRDP</font></h4>
|
||||
</div>
|
||||
<pre class="western">This program is free software;
|
||||
|
||||
you can redistribute it and/or modify it under the terms
|
||||
|
||||
of the Mozilla Public License, v. 2.0.
|
||||
|
||||
You can obtain an online version of the License from
|
||||
|
||||
<a href="http://mozilla.org/MPL/2.0/">http://mozilla.org/MPL/2.0/</a>.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
A copy of the product's source code can be obtained from the FreeRDP GitHub repository at
|
||||
|
||||
<a href="https://github.com/FreeRDP/FreeRDP">https://github.com/FreeRDP/FreeRDP</a>.</pre>
|
||||
<p style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
</p>
|
||||
<div id="Section5" dir="ltr" style="background: #353639">
|
||||
<h4 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline4"></a>
|
||||
FreeRDP</h4>
|
||||
</div>
|
||||
<pre class="western">Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
You may obtain a copy of the License at
|
||||
|
||||
<a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
See the License for the specific language governing permissions and
|
||||
|
||||
limitations under the License.
|
||||
A copy of the product's source code can be obtained from the FreeRDP GitHub repository at
|
||||
|
||||
<a href="https://github.com/FreeRDP/FreeRDP">https://github.com/FreeRDP/FreeRDP</a>.</pre>
|
||||
<div id="Section6" dir="ltr" style="background: #353639">
|
||||
<h4 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline5"></a>
|
||||
OpenSSL</h4>
|
||||
</div>
|
||||
<pre class="western">LICENSE ISSUES
|
||||
|
||||
==============
|
||||
|
||||
|
||||
The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
|
||||
|
||||
the OpenSSL License and the original SSLeay license apply to the toolkit.
|
||||
|
||||
See below for the actual license texts.
|
||||
|
||||
|
||||
OpenSSL License
|
||||
|
||||
---------------
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
* Copyright (c) 1998-2016 The OpenSSL Project. All rights reserved.
|
||||
|
||||
*
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
||||
* are met:
|
||||
|
||||
*
|
||||
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
|
||||
*
|
||||
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
|
||||
* the documentation and/or other materials provided with the
|
||||
|
||||
* distribution.
|
||||
|
||||
*
|
||||
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
|
||||
* software must display the following acknowledgment:
|
||||
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
|
||||
*
|
||||
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
|
||||
* endorse or promote products derived from this software without
|
||||
|
||||
* prior written permission. For written permission, please contact
|
||||
|
||||
* openssl-core@openssl.org.
|
||||
|
||||
*
|
||||
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
|
||||
* permission of the OpenSSL Project.
|
||||
|
||||
*
|
||||
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
|
||||
* acknowledgment:
|
||||
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
|
||||
*
|
||||
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
* ====================================================================
|
||||
|
||||
*
|
||||
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
|
||||
*
|
||||
|
||||
*/
|
||||
|
||||
|
||||
Original SSLeay License
|
||||
|
||||
-----------------------
|
||||
|
||||
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
|
||||
* All rights reserved.
|
||||
|
||||
*
|
||||
|
||||
* This package is an SSL implementation written
|
||||
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
|
||||
*
|
||||
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
|
||||
* the following conditions are adhered to. The following conditions
|
||||
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
|
||||
*
|
||||
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
|
||||
* the code are not to be removed.
|
||||
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
|
||||
* as the author of the parts of the library used.
|
||||
|
||||
* This can be in the form of a textual message at program startup or
|
||||
|
||||
* in documentation (online or textual) provided with the package.
|
||||
|
||||
*
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
||||
* are met:
|
||||
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
|
||||
* must display the following acknowledgement:
|
||||
|
||||
* "This product includes cryptographic software written by
|
||||
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
|
||||
* The word 'cryptographic' can be left out if the routines from the library
|
||||
|
||||
* being used are not cryptographic related :-).
|
||||
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
|
||||
*
|
||||
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
|
||||
* SUCH DAMAGE.
|
||||
|
||||
*
|
||||
|
||||
* The licence and distribution terms for any publicly available version or
|
||||
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
|
||||
* copied and put under another distribution licence
|
||||
|
||||
* [including the GNU Public Licence.]
|
||||
|
||||
*/
|
||||
A copy of the product's source code can be obtained from the project page at
|
||||
|
||||
<a href="https://www.openssl.org/">https://www.openssl.org/</a>.</pre>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
397
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/about_page/about_phone.html
vendored
Normal file
@@ -0,0 +1,397 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
|
||||
<title></title>
|
||||
<meta name="" content=""/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../about.css">
|
||||
</head>
|
||||
<body lang="en-US" link="#0000ff" bgcolor="#e9ebf8" dir="ltr">
|
||||
<div id="container" dir="ltr">
|
||||
<h2 class="western"><br/>
|
||||
<br/>
|
||||
|
||||
</h2>
|
||||
<div id="introduction_headline" dir="ltr" style="background: #353639">
|
||||
<h2 class="western"><font color="#ffffff">aFreeRDP <br/>
|
||||
Remote
|
||||
Desktop Client</font></h2>
|
||||
</div>
|
||||
<p><img src="../FreeRDP_Logo.png" name="Image1" align="bottom" width="25%" border="0"/>
|
||||
|
||||
</p>
|
||||
<div id="introduction" dir="ltr" style="background: #ffffff">
|
||||
<p><font color="#000000"><b>aFreeRDP</b> is an open source client
|
||||
capable of natively using<br/>
|
||||
Remote Desktop Protocol (RDP) in
|
||||
order to remotely access your Windows desktop. </font>
|
||||
</p>
|
||||
</div>
|
||||
<div id="article" dir="ltr" style="background: #ffffff">
|
||||
<p style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
</p>
|
||||
<div id="headline" dir="ltr" style="background: #353639">
|
||||
<h3 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
Version Information</h3>
|
||||
</div>
|
||||
<table cellpadding="3" cellspacing="1" align="center">
|
||||
<tr>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p><b>aFreeRDP</b> Version</p>
|
||||
</td>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>%AFREERDP_VERSION%</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>System Version</p>
|
||||
</td>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>%SYSTEM_VERSION%</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>Model</p>
|
||||
</td>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>%DEVICE_MODEL%</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div id="Section1" dir="ltr" style="background: #353639">
|
||||
<h3 class="western" align="center" style="margin-left: 0.1in; margin-right: 0.1in"><a
|
||||
name="headline"></a>
|
||||
Credits</h3>
|
||||
</div>
|
||||
<p style="margin-top: 0.1in; margin-bottom: 0.1in"><font
|
||||
color="#000000"><b>aFreeRDP</b></font><font color="#000000">
|
||||
is a part of <a href="http://www.freerdp.com/">FreeRDP</a> </font>
|
||||
</p>
|
||||
<div id="Section2" dir="ltr" style="background: #353639">
|
||||
<h3 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline1"></a>
|
||||
Data protection</h3>
|
||||
</div>
|
||||
<p style="margin-top: 0.1in; margin-bottom: 0.1in"><font color="#000000">Details
|
||||
about data collection and usage by <b>aFreeRDP</b> are available at</font></p>
|
||||
<p><a href="http://www.freerdp.com/privacy">http://www.freerdp.com/privacy</a>
|
||||
</p>
|
||||
<div id="Section3" dir="ltr" style="background: #353639">
|
||||
<h3 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline2"></a>
|
||||
Licenses</h3>
|
||||
</div>
|
||||
<div id="Section4" dir="ltr" style="background: #353639">
|
||||
<h4 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline3"></a>
|
||||
<font color="#ffffff">aFreeRDP</font></h4>
|
||||
</div>
|
||||
<pre class="western">This program is free software;
|
||||
|
||||
you can redistribute it and/or modify it under the terms
|
||||
|
||||
of the Mozilla Public License, v. 2.0.
|
||||
|
||||
You can obtain an online version of the License from
|
||||
|
||||
<a href="http://mozilla.org/MPL/2.0/">http://mozilla.org/MPL/2.0/</a>.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
A copy of the product's source code can be obtained from the FreeRDP GitHub repository at
|
||||
|
||||
<a href="https://github.com/FreeRDP/FreeRDP">https://github.com/FreeRDP/FreeRDP</a>.</pre>
|
||||
<p style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
</p>
|
||||
<div id="Section5" dir="ltr" style="background: #353639">
|
||||
<h4 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline4"></a>
|
||||
FreeRDP</h4>
|
||||
</div>
|
||||
<pre class="western">Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
You may obtain a copy of the License at
|
||||
|
||||
<a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
See the License for the specific language governing permissions and
|
||||
|
||||
limitations under the License.
|
||||
A copy of the product's source code can be obtained from the FreeRDP GitHub repository at
|
||||
|
||||
<a href="https://github.com/FreeRDP/FreeRDP">https://github.com/FreeRDP/FreeRDP</a>.</pre>
|
||||
<div id="Section6" dir="ltr" style="background: #353639">
|
||||
<h4 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline5"></a>
|
||||
OpenSSL</h4>
|
||||
</div>
|
||||
<pre class="western">LICENSE ISSUES
|
||||
|
||||
==============
|
||||
|
||||
|
||||
The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
|
||||
|
||||
the OpenSSL License and the original SSLeay license apply to the toolkit.
|
||||
|
||||
See below for the actual license texts.
|
||||
|
||||
|
||||
OpenSSL License
|
||||
|
||||
---------------
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
* Copyright (c) 1998-2016 The OpenSSL Project. All rights reserved.
|
||||
|
||||
*
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
||||
* are met:
|
||||
|
||||
*
|
||||
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
|
||||
*
|
||||
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
|
||||
* the documentation and/or other materials provided with the
|
||||
|
||||
* distribution.
|
||||
|
||||
*
|
||||
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
|
||||
* software must display the following acknowledgment:
|
||||
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
|
||||
*
|
||||
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
|
||||
* endorse or promote products derived from this software without
|
||||
|
||||
* prior written permission. For written permission, please contact
|
||||
|
||||
* openssl-core@openssl.org.
|
||||
|
||||
*
|
||||
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
|
||||
* permission of the OpenSSL Project.
|
||||
|
||||
*
|
||||
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
|
||||
* acknowledgment:
|
||||
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
|
||||
*
|
||||
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
* ====================================================================
|
||||
|
||||
*
|
||||
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
|
||||
*
|
||||
|
||||
*/
|
||||
|
||||
|
||||
Original SSLeay License
|
||||
|
||||
-----------------------
|
||||
|
||||
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
|
||||
* All rights reserved.
|
||||
|
||||
*
|
||||
|
||||
* This package is an SSL implementation written
|
||||
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
|
||||
*
|
||||
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
|
||||
* the following conditions are adhered to. The following conditions
|
||||
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
|
||||
*
|
||||
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
|
||||
* the code are not to be removed.
|
||||
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
|
||||
* as the author of the parts of the library used.
|
||||
|
||||
* This can be in the form of a textual message at program startup or
|
||||
|
||||
* in documentation (online or textual) provided with the package.
|
||||
|
||||
*
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
||||
* are met:
|
||||
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
|
||||
* must display the following acknowledgement:
|
||||
|
||||
* "This product includes cryptographic software written by
|
||||
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
|
||||
* The word 'cryptographic' can be left out if the routines from the library
|
||||
|
||||
* being used are not cryptographic related :-).
|
||||
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
|
||||
*
|
||||
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
|
||||
* SUCH DAMAGE.
|
||||
|
||||
*
|
||||
|
||||
* The licence and distribution terms for any publicly available version or
|
||||
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
|
||||
* copied and put under another distribution licence
|
||||
|
||||
* [including the GNU Public Licence.]
|
||||
|
||||
*/
|
||||
A copy of the product's source code can be obtained from the project page at
|
||||
|
||||
<a href="https://www.openssl.org/">https://www.openssl.org/</a>.</pre>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/background.jpg
vendored
Normal file
|
After Width: | Height: | Size: 115 KiB |
410
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/de_about_page/about.html
vendored
Normal file
@@ -0,0 +1,410 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
|
||||
<title></title>
|
||||
<meta name="" content=""/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../about.css">
|
||||
</head>
|
||||
<body lang="de-AT" link="#0000ff" bgcolor="#e9ebf8" dir="ltr">
|
||||
<div id="container" dir="ltr">
|
||||
<p><br/>
|
||||
<br/>
|
||||
|
||||
</p>
|
||||
<div id="introduction_headline" dir="ltr" style="background: #353639">
|
||||
<h2 class="western"><font color="#ffffff">aFreeRDP<br/>
|
||||
Remote
|
||||
Desktop Client</font>
|
||||
</h2>
|
||||
</div>
|
||||
<div id="introduction" dir="ltr" style="background: #ffffff">
|
||||
<p align="center"><font color="#000000"><img src="FreeRDP_Logo.png" name="FreeRDP-Logo"
|
||||
align="top" hspace="6" vspace="6" width="10%"
|
||||
border="0"/>
|
||||
|
||||
</font>
|
||||
</p>
|
||||
</div>
|
||||
<div id="article" dir="ltr" style="background: #ffffff">
|
||||
<p align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<font color="#000000"><b>aFreeRDP</b> ist ein Open Source Programm
|
||||
mit nativer Unterstützung des Remote Desktop Protocol (RDP)<br/>
|
||||
um
|
||||
einen entfernten Zugriff auf Windows Desktops zu ermöglichen. </font>
|
||||
</p>
|
||||
<div id="headline" dir="ltr" style="background: #353639">
|
||||
<h3 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
Versions Information</h3>
|
||||
</div>
|
||||
<table cellpadding="3" cellspacing="1" align="center">
|
||||
<tr>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p><b>aFreeRDP</b> Version</p>
|
||||
</td>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>%AFREERDP_VERSION%</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>System Version</p>
|
||||
</td>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>%SYSTEM_VERSION%</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>Model</p>
|
||||
</td>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>%DEVICE_MODEL%</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div id="Section1" dir="ltr" style="background: #ffffff">
|
||||
<p style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="article"></a>
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
</p>
|
||||
<div id="Section2" dir="ltr" style="background: #353639">
|
||||
<h3 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline"></a>
|
||||
Credits</h3>
|
||||
</div>
|
||||
<p style="margin-top: 0.1in; margin-bottom: 0.1in"><font
|
||||
color="#000000"><b>aFreeRDP</b></font><font color="#000000">
|
||||
ist ein Teil von <a href="http://www.freerdp.com/">FreeRDP</a> </font>
|
||||
</p>
|
||||
</div>
|
||||
<div id="Section3" dir="ltr" style="background: #ffffff">
|
||||
<p style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="article1"></a>
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
</p>
|
||||
<div id="Section4" dir="ltr" style="background: #353639">
|
||||
<h3 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline1"></a>
|
||||
Datenschutz</h3>
|
||||
</div>
|
||||
<p style="margin-top: 0.1in; margin-bottom: 0.1in"><font color="#000000">Details
|
||||
zu den Daten die aFreeRDP sammelt und verarbeitet sind unter</font></p>
|
||||
<p style="margin-top: 0.1in; margin-bottom: 0.1in"><font color="#000000"><a
|
||||
href="http://www.freerdp.com/privacy">http://www.freerdp.com/privacy</a>
|
||||
zu finden.</font></p>
|
||||
<div id="Section5" dir="ltr" style="background: #353639">
|
||||
<h3 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline2"></a>
|
||||
Lizenzen</h3>
|
||||
</div>
|
||||
<div id="Section6" dir="ltr" style="background: #353639">
|
||||
<h4 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline3"></a>
|
||||
<font color="#000000">aFreeRDP</font></h4>
|
||||
</div>
|
||||
<pre class="western">This program is free software;
|
||||
|
||||
you can redistribute it and/or modify it under the terms
|
||||
|
||||
of the Mozilla Public License, v. 2.0.
|
||||
|
||||
You can obtain an online version of the License from
|
||||
|
||||
<a href="http://mozilla.org/MPL/2.0/">http://mozilla.org/MPL/2.0/</a>.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
A copy of the product's source code can be obtained from the FreeRDP GitHub repository at
|
||||
|
||||
<a href="https://github.com/FreeRDP/FreeRDP">https://github.com/FreeRDP/FreeRDP</a>.</pre>
|
||||
<div id="Section7" dir="ltr" style="background: #353639">
|
||||
<h4 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline4"></a>
|
||||
FreeRDP</h4>
|
||||
</div>
|
||||
<pre class="western">Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
You may obtain a copy of the License at
|
||||
<a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
See the License for the specific language governing permissions and
|
||||
|
||||
limitations under the License.
|
||||
A copy of the product's source code can be obtained from the FreeRDP GitHub repository at
|
||||
|
||||
<a href="https://github.com/FreeRDP/FreeRDP">https://github.com/FreeRDP/FreeRDP</a>.</pre>
|
||||
<div id="Section8" dir="ltr" style="background: #353639">
|
||||
<h4 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline5"></a>
|
||||
OpenSSL</h4>
|
||||
</div>
|
||||
<pre class="western">LICENSE ISSUES
|
||||
|
||||
==============
|
||||
|
||||
|
||||
The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
|
||||
|
||||
the OpenSSL License and the original SSLeay license apply to the toolkit.
|
||||
|
||||
See below for the actual license texts.
|
||||
|
||||
|
||||
OpenSSL License
|
||||
|
||||
---------------
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
* Copyright (c) 1998-2016 The OpenSSL Project. All rights reserved.
|
||||
|
||||
*
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
||||
* are met:
|
||||
|
||||
*
|
||||
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
|
||||
*
|
||||
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
|
||||
* the documentation and/or other materials provided with the
|
||||
|
||||
* distribution.
|
||||
|
||||
*
|
||||
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
|
||||
* software must display the following acknowledgment:
|
||||
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
|
||||
*
|
||||
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
|
||||
* endorse or promote products derived from this software without
|
||||
|
||||
* prior written permission. For written permission, please contact
|
||||
|
||||
* openssl-core@openssl.org.
|
||||
|
||||
*
|
||||
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
|
||||
* permission of the OpenSSL Project.
|
||||
|
||||
*
|
||||
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
|
||||
* acknowledgment:
|
||||
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
|
||||
*
|
||||
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
* ====================================================================
|
||||
|
||||
*
|
||||
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
|
||||
*
|
||||
|
||||
*/
|
||||
|
||||
|
||||
Original SSLeay License
|
||||
|
||||
-----------------------
|
||||
|
||||
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
|
||||
* All rights reserved.
|
||||
|
||||
*
|
||||
|
||||
* This package is an SSL implementation written
|
||||
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
|
||||
*
|
||||
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
|
||||
* the following conditions are aheared to. The following conditions
|
||||
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
|
||||
*
|
||||
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
|
||||
* the code are not to be removed.
|
||||
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
|
||||
* as the author of the parts of the library used.
|
||||
|
||||
* This can be in the form of a textual message at program startup or
|
||||
|
||||
* in documentation (online or textual) provided with the package.
|
||||
|
||||
*
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
||||
* are met:
|
||||
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
|
||||
* must display the following acknowledgement:
|
||||
|
||||
* "This product includes cryptographic software written by
|
||||
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
|
||||
* being used are not cryptographic related :-).
|
||||
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
|
||||
*
|
||||
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
|
||||
* SUCH DAMAGE.
|
||||
|
||||
*
|
||||
|
||||
* The licence and distribution terms for any publically available version or
|
||||
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
|
||||
* copied and put under another distribution licence
|
||||
|
||||
* [including the GNU Public Licence.]
|
||||
|
||||
*/
|
||||
A copy of the product's source code can be obtained from the project page at
|
||||
|
||||
<a href="https://www.openssl.org/">https://www.openssl.org/</a>.</pre>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
412
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/de_about_page/about_phone.html
vendored
Normal file
@@ -0,0 +1,412 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
|
||||
<title></title>
|
||||
<meta name="" content=""/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
|
||||
|
||||
<meta name="changed" content="2017-02-23T09:47:39.760769965">
|
||||
<link rel="stylesheet" type="text/css" href="../about.css">
|
||||
</head>
|
||||
<body lang="de-AT" link="#0000ff" bgcolor="#e9ebf8" dir="ltr">
|
||||
<div id="container" dir="ltr">
|
||||
<p><br/>
|
||||
<br/>
|
||||
|
||||
</p>
|
||||
<div id="introduction_headline" dir="ltr" style="background: #353639">
|
||||
<h2 class="western"><font color="#ffffff">aFreeRDP<br/>
|
||||
Remote
|
||||
Desktop Client</font>
|
||||
</h2>
|
||||
</div>
|
||||
<div id="introduction" dir="ltr" style="background: #ffffff">
|
||||
<p align="center"><font color="#000000"><img src="../FreeRDP_Logo.png" name="FreeRDP-Logo"
|
||||
align="top" hspace="6" vspace="6" width="25%"
|
||||
border="0"/>
|
||||
|
||||
</font>
|
||||
</p>
|
||||
</div>
|
||||
<div id="article" dir="ltr" style="background: #ffffff">
|
||||
<p align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<font color="#000000"><b>aFreeRDP</b> ist ein Open Source Programm
|
||||
mit nativer Unterstützung des Remote Desktop Protocol (RDP)<br/>
|
||||
um
|
||||
einen entfernten Zugriff auf Windows Desktops zu ermöglichen. </font>
|
||||
</p>
|
||||
<div id="headline" dir="ltr" style="background: #353639">
|
||||
<h3 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
Versions Information</h3>
|
||||
</div>
|
||||
<table cellpadding="3" cellspacing="1" align="center">
|
||||
<tr>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p><b>aFreeRDP</b> Version</p>
|
||||
</td>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>%AFREERDP_VERSION%</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>System Version</p>
|
||||
</td>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>%SYSTEM_VERSION%</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>Model</p>
|
||||
</td>
|
||||
<td style="border: none; padding: 0in">
|
||||
<p>%DEVICE_MODEL%</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div id="Section1" dir="ltr" style="background: #ffffff">
|
||||
<p style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="article"></a>
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
</p>
|
||||
<div id="Section2" dir="ltr" style="background: #353639">
|
||||
<h3 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline"></a>
|
||||
Credits</h3>
|
||||
</div>
|
||||
<p style="margin-top: 0.1in; margin-bottom: 0.1in"><font
|
||||
color="#000000"><b>aFreeRDP</b></font><font color="#000000">
|
||||
ist ein Teil von <a href="http://www.freerdp.com/">FreeRDP</a> </font>
|
||||
</p>
|
||||
</div>
|
||||
<div id="Section3" dir="ltr" style="background: #ffffff">
|
||||
<p style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="article1"></a>
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
</p>
|
||||
<div id="Section4" dir="ltr" style="background: #353639">
|
||||
<h3 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline1"></a>
|
||||
Datenschutz</h3>
|
||||
</div>
|
||||
<p style="margin-top: 0.1in; margin-bottom: 0.1in"><font color="#000000">Details
|
||||
zu den Daten die aFreeRDP sammelt und verarbeitet sind unter</font></p>
|
||||
<p style="margin-top: 0.1in; margin-bottom: 0.1in"><font color="#000000"><a
|
||||
href="http://www.freerdp.com/privacy">http://www.freerdp.com/privacy</a>
|
||||
zu finden.</font></p>
|
||||
<div id="Section5" dir="ltr" style="background: #353639">
|
||||
<h3 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline2"></a>
|
||||
Lizenzen</h3>
|
||||
</div>
|
||||
<div id="Section6" dir="ltr" style="background: #353639">
|
||||
<h4 class="western"><a name="headline3"></a>aFreeRDP</h4>
|
||||
</div>
|
||||
<pre class="western">This program is free software;
|
||||
|
||||
you can redistribute it and/or modify it under the terms
|
||||
|
||||
of the Mozilla Public License, v. 2.0.
|
||||
|
||||
You can obtain an online version of the License from
|
||||
|
||||
<a href="http://mozilla.org/MPL/2.0/">http://mozilla.org/MPL/2.0/</a>.
|
||||
This program is distributed in the hope
|
||||
that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
|
||||
without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
A copy of the product's source code can be
|
||||
obtained from the FreeRDP GitHub repository at
|
||||
|
||||
<a href="https://github.com/FreeRDP/FreeRDP">https://github.com/FreeRDP/FreeRDP</a>.</pre>
|
||||
<div id="Section7" dir="ltr" style="background: #353639">
|
||||
<h4 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline4"></a>
|
||||
FreeRDP</h4>
|
||||
</div>
|
||||
<pre class="western">Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
You may obtain a copy of the License at
|
||||
<a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
See the License for the specific language governing permissions and
|
||||
|
||||
limitations under the License.
|
||||
A copy of the product's source code can be obtained
|
||||
from the FreeRDP GitHub repository at
|
||||
|
||||
<a href="https://github.com/FreeRDP/FreeRDP">https://github.com/FreeRDP/FreeRDP</a>.</pre>
|
||||
<div id="Section8" dir="ltr" style="background: #353639">
|
||||
<h4 class="western" align="center"
|
||||
style="margin-left: 0.1in; margin-right: 0.1in; margin-top: 0.1in; margin-bottom: 0.1in">
|
||||
<a name="headline5"></a>
|
||||
OpenSSL</h4>
|
||||
</div>
|
||||
<pre class="western">LICENSE ISSUES
|
||||
|
||||
==============
|
||||
|
||||
|
||||
The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
|
||||
|
||||
the OpenSSL License and the original SSLeay license apply to the toolkit.
|
||||
|
||||
See below for the actual license texts.
|
||||
|
||||
|
||||
OpenSSL License
|
||||
|
||||
---------------
|
||||
|
||||
|
||||
/* ====================================================================
|
||||
|
||||
* Copyright (c) 1998-2016 The OpenSSL Project. All rights reserved.
|
||||
|
||||
*
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
||||
* are met:
|
||||
|
||||
*
|
||||
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
|
||||
*
|
||||
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
|
||||
* the documentation and/or other materials provided with the
|
||||
|
||||
* distribution.
|
||||
|
||||
*
|
||||
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
|
||||
* software must display the following acknowledgment:
|
||||
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
|
||||
*
|
||||
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
|
||||
* endorse or promote products derived from this software without
|
||||
|
||||
* prior written permission. For written permission, please contact
|
||||
|
||||
* openssl-core@openssl.org.
|
||||
|
||||
*
|
||||
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
|
||||
* permission of the OpenSSL Project.
|
||||
|
||||
*
|
||||
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
|
||||
* acknowledgment:
|
||||
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
|
||||
*
|
||||
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
* ====================================================================
|
||||
|
||||
*
|
||||
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
|
||||
*
|
||||
|
||||
*/
|
||||
|
||||
|
||||
Original SSLeay License
|
||||
|
||||
-----------------------
|
||||
|
||||
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
|
||||
* All rights reserved.
|
||||
|
||||
*
|
||||
|
||||
* This package is an SSL implementation written
|
||||
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
|
||||
*
|
||||
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
|
||||
* the following conditions are aheared to. The following conditions
|
||||
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
|
||||
*
|
||||
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
|
||||
* the code are not to be removed.
|
||||
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
|
||||
* as the author of the parts of the library used.
|
||||
|
||||
* This can be in the form of a textual message at program startup or
|
||||
|
||||
* in documentation (online or textual) provided with the package.
|
||||
|
||||
*
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
||||
* are met:
|
||||
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
|
||||
* must display the following acknowledgement:
|
||||
|
||||
* "This product includes cryptographic software written by
|
||||
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
|
||||
* being used are not cryptographic related :-).
|
||||
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
|
||||
*
|
||||
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
|
||||
* SUCH DAMAGE.
|
||||
|
||||
*
|
||||
|
||||
* The licence and distribution terms for any publicly available version or
|
||||
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
|
||||
* copied and put under another distribution licence
|
||||
|
||||
* [including the GNU Public Licence.]
|
||||
|
||||
*/
|
||||
A copy of the product's source code can be obtained from the project page at
|
||||
|
||||
<a href="https://www.openssl.org/">https://www.openssl.org/</a>.</pre>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
33
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/de_help_page/gestures.html
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;"/>
|
||||
<title>Help</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../help.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<center>
|
||||
<div id="header">
|
||||
<a href="gestures.html"><img src="nav_gestures.png"></a>
|
||||
<a href="toolbar.html"><img src="nav_toolbar.png"></a>
|
||||
<a href="touch_pointer.html"><img src="nav_touch_pointer.png"></a>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<h1>Gesten</h1>
|
||||
<p>
|
||||
aFreeRDP ist für Touch Geräte entwickelt worden.
|
||||
Diese Gesten lassen sie die häufigsten Operationen mit ihren Fingern
|
||||
durchführen.</p>
|
||||
<p><img src="gestures.png"></p>
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/de_help_page/gestures.png
vendored
Normal file
|
After Width: | Height: | Size: 43 KiB |
@@ -0,0 +1,38 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;"/>
|
||||
<title>Help</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../help-phone.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<center>
|
||||
<div id="header">
|
||||
|
||||
<a href="gestures_phone.html"><img src="nav_gestures.png" height="90%"></a>
|
||||
<a href="toolbar_phone.html"><img src="nav_toolbar.png" height="90%"></a>
|
||||
<a href="touch_pointer_phone.html"><img src="nav_touch_pointer.png" height="90%""></a>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<h2>Gesten</h2>
|
||||
<p>
|
||||
aFreeRDP ist für Touch Geräte entwickelt worden.
|
||||
Diese Gesten lassen sie die häufigsten Operationen mit ihren Fingern
|
||||
durchführen.</p>
|
||||
<p><img src="gestures_phone.png"></p>
|
||||
|
||||
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/de_help_page/gestures_phone.png
vendored
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/de_help_page/nav_gestures.png
vendored
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/de_help_page/nav_toolbar.png
vendored
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
49
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/de_help_page/toolbar.html
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;"/>
|
||||
<title>Help</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../help.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<center>
|
||||
<div id="header">
|
||||
<a href="gestures.html"><img src="nav_gestures.png"></a>
|
||||
<a href="toolbar.html"><img src="nav_toolbar.png"></a>
|
||||
<a href="touch_pointer.html"><img src="nav_touch_pointer.png"></a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<h1>Toolbar</h1>
|
||||
<p>
|
||||
With the toolbar you'll be able to display and hide the main tools in your session.
|
||||
This allows together with the touch pointer and the gestures an intuitiv workflow
|
||||
for remote computing on touch sensitive screens.
|
||||
</p>
|
||||
<p><img src="toolbar.png"></p>
|
||||
|
||||
<div id="article">
|
||||
<div id="headline">
|
||||
<h3><span style="color:white">Tastatur</span></h3></div>
|
||||
Zeige/verstecke die standard und die erweiterte Tastatur mit Funktionstasten
|
||||
</div>
|
||||
<div id="article">
|
||||
<div id="headline"><h3><span style="color:white">Touch Zeiger</span></h3></div>
|
||||
Zeige/verstecke den gesten gesteuerten Zeiger
|
||||
</div>
|
||||
<div id="article">
|
||||
<div id="headline"><h3><span style="color:white">Beenden</span></h3></div>
|
||||
Beende die aktuelle Sitzung. Seihen sie sich bewusst, dass das Beenden kein Logout
|
||||
ist.
|
||||
</div>
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/de_help_page/toolbar.png
vendored
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
@@ -0,0 +1,49 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;"/>
|
||||
<title>Help</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../help-phone.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<center>
|
||||
<div id="header">
|
||||
<a href="gestures_phone.html"><img src="nav_gestures.png" height="90%"></a>
|
||||
<a href="toolbar_phone.html"><img src="nav_toolbar.png" height="90%"></a>
|
||||
<a href="touch_pointer_phone.html"><img src="nav_touch_pointer.png" height="90%""></a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<h2>Toolbar</h2>
|
||||
<p>
|
||||
With the toolbar you'll be able to display and hide the main tools in your session.
|
||||
This allows together with the touch pointer and the gestures an intuitiv workflow
|
||||
for remote computing on touch sensitive screens.
|
||||
</p>
|
||||
<p><img src="toolbar_phone.png"></p>
|
||||
|
||||
<div id="article">
|
||||
<div id="headline">
|
||||
<h4><span style="color:white">Tastatur</h4></span></div>
|
||||
Zeige/verstecke die standard und die erweiterte Tastatur mit Funktionstasten
|
||||
</div>
|
||||
<div id="article">
|
||||
<div id="headline"><h4><span style="color:white">Touch Zeiger</h4></div>
|
||||
Zeige/verstecke den gesten gesteuerten Zeiger
|
||||
</div>
|
||||
<div id="article">
|
||||
<div id="headline"><h4><span style="color:white">Beenden</span></h4></div>
|
||||
Beende die aktuelle Sitzung. Seihen sie sich bewusst, dass das Beenden kein Logout
|
||||
ist.
|
||||
</div>
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/de_help_page/toolbar_phone.png
vendored
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
@@ -0,0 +1,29 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;"/>
|
||||
<title>Help</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../help.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<center>
|
||||
<div id="header">
|
||||
<a href="gestures.html"><img src="nav_gestures.png"></a>
|
||||
<a href="toolbar.html"><img src="nav_toolbar.png"></a>
|
||||
<a href="touch_pointer.html"><img src="nav_touch_pointer.png"></a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<h1>Touch Pointer</h1>
|
||||
<p><img src="touch_pointer.png">
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/de_help_page/touch_pointer.png
vendored
Normal file
|
After Width: | Height: | Size: 108 KiB |
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;"/>
|
||||
<title>Help</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../help-phone.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<center>
|
||||
<div id="header">
|
||||
<a href="gestures_phone.html"><img src="nav_gestures.png" height="90%"></a>
|
||||
<a href="toolbar_phone.html"><img src="nav_toolbar.png" height="90%"></a>
|
||||
<a href="touch_pointer_phone.html"><img src="nav_touch_pointer.png" height="90%""></a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<h2>Touch Pointer</h2>
|
||||
<p><img src="touch_pointer_phone.png">
|
||||
</p>
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 86 KiB |
100
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/help.css
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
<style type="text/css">
|
||||
|
||||
@charset "utf-8";
|
||||
|
||||
#container{
|
||||
text-align:center;
|
||||
color:#FFFFFF;
|
||||
}
|
||||
|
||||
body {
|
||||
margin:0;
|
||||
padding:<length> 0 0 0;
|
||||
font: 100%/1.4 Helvetica;
|
||||
background-image:url(../background.jpg);
|
||||
background-position:center;
|
||||
}
|
||||
|
||||
#headline {
|
||||
background-color:#353639;
|
||||
opacity:0.9;
|
||||
color:FFF;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
#article {
|
||||
background-color:#FFFFFF;
|
||||
opacity: 0.8;
|
||||
z-index:0;
|
||||
margin-bottom:3%;
|
||||
padding-bottom:0.1%;
|
||||
border-radius: 15px;
|
||||
border-top-left-radius:0px;
|
||||
border-top-right-radius:0px;
|
||||
color:#000;
|
||||
margin: 10px auto;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
#header {
|
||||
height:auto;
|
||||
width:100%;
|
||||
background-color:#353639;
|
||||
padding-bottom:5px;
|
||||
padding-left:5px;
|
||||
padding-right:5px;
|
||||
padding-top:10px;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height:40px;
|
||||
overflow:visible;
|
||||
min-width:400px;
|
||||
z-index:20;
|
||||
}
|
||||
|
||||
#content {
|
||||
padding-top:70px;
|
||||
z-index:-20;
|
||||
max-width:420px;
|
||||
}
|
||||
|
||||
/* ~~ Element/tag selectors ~~ */
|
||||
ul, ol, dl { /* Due to variations between browsers, it's best practices to zero padding and margin on lists. For consistency, you can either specify the amounts you want here, or on the list items (LI, DT, DD) they contain. Remember that what you do here will cascade to the .nav list unless you write a more specific selector. */
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6, p {
|
||||
margin-top: 0; /* removing the top margin gets around an issue where margins can escape from their containing div. The remaining bottom margin will hold it away from any elements that follow. */
|
||||
padding-right: 1px;
|
||||
padding-left: 1px; /* adding the padding to the sides of the elements within the divs, instead of the divs themselves, gets rid of any box model math. A nested div with side padding can also be used as an alternate method.
|
||||
*/
|
||||
color:#000;
|
||||
}
|
||||
|
||||
a img { /* this selector removes the default blue border displayed in some browsers around an image when it is surrounded by a link */
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* ~~ Styling for your site's links must remain in this order - including the group of selectors that create the hover effect. ~~ */
|
||||
/*a:link {
|
||||
color:#414958;
|
||||
text-decoration: underline; unless you style your links to look extremely unique, it's best to provide underlines for quick visual identification */
|
||||
|
||||
a:hover, a:active, a:focus { /* this group of selectors will give a keyboard navigator the same hover experience as the person using a mouse. */
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
* {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none; /* Disable selection/Copy of UIWebView */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
32
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/help_page/gestures.html
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;"/>
|
||||
<title>Help</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../help.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<center>
|
||||
<div id="header">
|
||||
<a href="gestures.html"><img src="nav_gestures.png"></a>
|
||||
<a href="toolbar.html"><img src="nav_toolbar.png"></a>
|
||||
<a href="touch_pointer.html"><img src="nav_touch_pointer.png"></a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<h1>Gestures</h1>
|
||||
<p>
|
||||
aFreeRDP is designed for touch sensitive devices.
|
||||
These gestures let you do the most usual operations with your fingers.</p>
|
||||
<p><img src="gestures.png"></p>
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/help_page/gestures.png
vendored
Normal file
|
After Width: | Height: | Size: 43 KiB |
33
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/help_page/gestures_phone.html
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;"/>
|
||||
<title>Help</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../help-phone.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<center>
|
||||
<div id="header">
|
||||
<a href="gestures_phone.html"><img src="nav_gestures.png" height="90%"></a>
|
||||
<a href="toolbar_phone.html"><img src="nav_toolbar.png" height="90%"></a>
|
||||
<a href="touch_pointer_phone.html"><img src="nav_touch_pointer.png" height="90%""></a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<h2> Gestures</h2>
|
||||
<p>
|
||||
aFreeRDP is designed for touch sensitive devices.
|
||||
These gestures let you do the most usual operations with your fingers.</p>
|
||||
<p><img src="gestures_phone.png"></p>
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/help_page/gestures_phone.png
vendored
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/help_page/nav_gestures.png
vendored
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/help_page/nav_toolbar.png
vendored
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/help_page/nav_touch_pointer.png
vendored
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
49
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/help_page/toolbar.html
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;"/>
|
||||
<title>Help</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../help.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<center>
|
||||
<div id="header">
|
||||
<a href="gestures.html"><img src="nav_gestures.png"></a>
|
||||
<a href="toolbar.html"><img src="nav_toolbar.png"></a>
|
||||
<a href="touch_pointer.html"><img src="nav_touch_pointer.png"></a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<h1>Toolbar</h1>
|
||||
<p>
|
||||
With the toolbar you'll be able to display and hide the main tools in your session.
|
||||
This allows together with the touch pointer and the gestures an intuitiv workflow
|
||||
for remote computing on touch sensitive screens.
|
||||
</p>
|
||||
<p><img src="toolbar.png"></p>
|
||||
|
||||
<div id="article">
|
||||
<div id="headline">
|
||||
<h3><span style="color:white">Keyboards</span></h3></div>
|
||||
Display/hide the default keyboard as well as an extended keyboard with function keys
|
||||
</div>
|
||||
<div id="article">
|
||||
<div id="headline"><h3><span style="color:white">Touch Pointer</span></h3></div>
|
||||
Display/hide the gesture controlled cursor
|
||||
</div>
|
||||
<div id="article">
|
||||
<div id="headline"><h3><span style="color:white">Disconnect</span></h3></div>
|
||||
Disconnect your current session. Please be aware that a disconnect is not the same
|
||||
as a log out.
|
||||
</div>
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/help_page/toolbar.png
vendored
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
50
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/help_page/toolbar_phone.html
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;"/>
|
||||
<title>Help</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../help-phone.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<center>
|
||||
<div id="header">
|
||||
<a href="gestures_phone.html"><img src="nav_gestures.png" height="90%"></a>
|
||||
<a href="toolbar_phone.html"><img src="nav_toolbar.png" height="90%"></a>
|
||||
<a href="touch_pointer_phone.html"><img src="nav_touch_pointer.png" height="90%""></a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<h2>Toolbar</h2>
|
||||
<p>
|
||||
With the toolbar you'll be able to display and hide the main tools in your session.
|
||||
This allows together with the touch pointer and the gestures an intuitiv workflow
|
||||
for remote computing on touch sensitive screens.
|
||||
</p>
|
||||
<p><img src="toolbar_phone.png"></p>
|
||||
|
||||
<div id="article">
|
||||
<div id="headline">
|
||||
<h4><span style="color:white">Keyboards</h4></span></div>
|
||||
Display/hide the default keyboard as well as an extended keyboard with function keys
|
||||
</div>
|
||||
<div id="article">
|
||||
<div id="headline"><h4><span style="color:white">Touch Pointer</h4></div>
|
||||
Display/hide the gesture controlled cursor
|
||||
</div>
|
||||
</span>
|
||||
<div id="article">
|
||||
<div id="headline"><h4><span style="color:white">Disconnect</span></h4></div>
|
||||
Disconnect your current session. Please be aware that a disconnect is not the same
|
||||
as a log out.
|
||||
</div>
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/help_page/toolbar_phone.png
vendored
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
29
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/help_page/touch_pointer.html
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;"/>
|
||||
<title>Help</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../help.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<center>
|
||||
<div id="header">
|
||||
<a href="gestures.html"><img src="nav_gestures.png"></a>
|
||||
<a href="toolbar.html"><img src="nav_toolbar.png"></a>
|
||||
<a href="touch_pointer.html"><img src="nav_touch_pointer.png"></a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<h1>Touch Pointer</h1>
|
||||
<p><img src="touch_pointer.png">
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/help_page/touch_pointer.png
vendored
Normal file
|
After Width: | Height: | Size: 108 KiB |
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;"/>
|
||||
<title>Help</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../help-phone.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
<center>
|
||||
<div id="header">
|
||||
<a href="gestures_phone.html"><img src="nav_gestures.png" height="90%"></a>
|
||||
<a href="toolbar_phone.html"><img src="nav_toolbar.png" height="90%"></a>
|
||||
<a href="touch_pointer_phone.html"><img src="nav_touch_pointer.png" height="90%""></a>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<h2>Touch Pointer</h2>
|
||||
<p><img src="touch_pointer_phone.png">
|
||||
</p>
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/assets/help_page/touch_pointer_phone.png
vendored
Normal file
|
After Width: | Height: | Size: 86 KiB |
@@ -0,0 +1,5 @@
|
||||
package com.freerdp.afreerdp.application;
|
||||
|
||||
public class GlobalApp extends com.freerdp.freerdpcore.application.GlobalApp
|
||||
{
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
31
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/res/drawable/button_background.xml
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:state_pressed="true">
|
||||
<shape>
|
||||
<solid android:color="#99D4FF" />
|
||||
<stroke android:width="1dp" android:color="#A7A7A7" />
|
||||
<corners android:radius="3dp" />
|
||||
<padding android:bottom="3dp" android:left="3dp" android:right="3dp" android:top="3dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:state_focused="true">
|
||||
<shape>
|
||||
<solid android:color="#E3E3E3" />
|
||||
<stroke android:width="1dp" android:color="#585858" />
|
||||
<corners android:radius="3dp" />
|
||||
<padding android:bottom="3dp" android:left="3dp" android:right="3dp" android:top="3dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<shape>
|
||||
<solid android:color="#E3E3E3" />
|
||||
<stroke android:width="1dp" android:color="#585858" />
|
||||
<corners android:radius="3dp" />
|
||||
<padding android:bottom="3dp" android:left="3dp" android:right="3dp" android:top="3dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
||||
BIN
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/res/drawable/icon_launcher_freerdp.png
vendored
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<solid android:color="@color/separator_background_color" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/separator_frame_color" />
|
||||
<padding
|
||||
android:bottom="1dp"
|
||||
android:left="1dp"
|
||||
android:right="1dp"
|
||||
android:top="1dp" />
|
||||
<!--
|
||||
<color xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="#C2D6E6"
|
||||
/>
|
||||
-->
|
||||
|
||||
</shape>
|
||||
4
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/res/values-de/strings.xml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="search_settings_description">Entfernte Rechner</string>
|
||||
</resources>
|
||||
4
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/res/values-es/strings.xml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="search_settings_description">Remote Computers</string>
|
||||
</resources>
|
||||
4
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/res/values-fr/strings.xml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="search_settings_description">L\'ordinateur distant</string>
|
||||
</resources>
|
||||
4
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/res/values-ko/strings.xml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="search_settings_description">원격 컴퓨터</string>
|
||||
</resources>
|
||||
4
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/res/values-nl/strings.xml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="search_settings_description">Remote Computers</string>
|
||||
</resources>
|
||||
5
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/res/values-zh-rTW/strings.xml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Search strings -->
|
||||
<string name="search_settings_description">遠端電腦</string>
|
||||
</resources>
|
||||
4
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/res/values-zh/strings.xml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="search_settings_description">远程计算机</string>
|
||||
</resources>
|
||||
7
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/res/values/strings.xml
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_title" translatable="false">aFreeRDP</string>
|
||||
<!-- Search strings -->
|
||||
<string name="search_label" translatable="false">aFreeRDP</string>
|
||||
<string name="search_settings_description">Remote Computers</string>
|
||||
</resources>
|
||||
22
third_party/FreeRDP/client/Android/Studio/aFreeRDP/src/main/res/xml/searchable.xml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
/*
|
||||
Bookmark searchable definition
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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/.
|
||||
*/
|
||||
-->
|
||||
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:hint="@string/search_hint"
|
||||
android:imeOptions="actionGo"
|
||||
android:includeInGlobalSearch="true"
|
||||
android:label="@string/search_label"
|
||||
|
||||
android:searchMode="queryRewriteFromText"
|
||||
android:searchSettingsDescription="@string/search_settings_description"
|
||||
android:searchSuggestAuthority="com.freerdp.afreerdp.services.freerdpsuggestionprovider"
|
||||
|
||||
android:searchSuggestIntentAction="android.intent.action.VIEW"
|
||||
android:searchSuggestSelection=" ? "></searchable>
|
||||
70
third_party/FreeRDP/client/Android/Studio/build.gradle
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
Properties releaseProperties = new Properties()
|
||||
File file = new File('release.properties')
|
||||
if (file.canRead()) {
|
||||
releaseProperties.load(new FileInputStream(file))
|
||||
}
|
||||
|
||||
if (!hasProperty('RELEASE_STORE_FILE')) {
|
||||
RELEASE_STORE_FILE=releaseProperties.get('RELEASE_STORE_FILE', '~/.android/debug.keystore')
|
||||
}
|
||||
if (!hasProperty('RELEASE_KEY_ALIAS')) {
|
||||
RELEASE_KEY_ALIAS=releaseProperties.get('RELEASE_KEY_ALIAS', 'androiddebugkey')
|
||||
}
|
||||
if (!hasProperty('RELEASE_KEY_PASSWORD')) {
|
||||
RELEASE_KEY_PASSWORD=releaseProperties.get('RELEASE_KEY_PASSWORD', 'android')
|
||||
}
|
||||
if (!hasProperty('RELEASE_STORE_PASSWORD')) {
|
||||
RELEASE_STORE_PASSWORD=releaseProperties.get('RELEASE_STORE_PASSWORD', 'android')
|
||||
}
|
||||
|
||||
ext {
|
||||
compileApi = releaseProperties.get('COMPILE_API', 35)
|
||||
targetApi = releaseProperties.get('TARGET_API', 35)
|
||||
minApi = releaseProperties.get('MIN_API', 23)
|
||||
toolsVersion = releaseProperties.get('TOOLS_VERSION', '35.0.0')
|
||||
|
||||
println '----------------- Project configuration -------------------'
|
||||
println 'RELEASE_STORE_FILE: ' + RELEASE_STORE_FILE
|
||||
println 'RELEASE_KEY_ALIAS: ' + RELEASE_KEY_ALIAS
|
||||
println 'compile API: ' + compileApi
|
||||
println 'target API: ' + targetApi
|
||||
println 'min API: ' + minApi
|
||||
println 'tools version: ' + toolsVersion
|
||||
println '-----------------------------------------------------------'
|
||||
}
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
google()
|
||||
maven {
|
||||
url 'https://maven.google.com'
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.13.0'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
google()
|
||||
maven {
|
||||
url 'https://maven.google.com'
|
||||
}
|
||||
}
|
||||
|
||||
subprojects {
|
||||
afterEvaluate { project ->
|
||||
if (project.hasProperty('android')) {
|
||||
project.android {
|
||||
if (namespace == null) {
|
||||
namespace 'com.freerdp.' + project.name.toLowerCase()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
66
third_party/FreeRDP/client/Android/Studio/freeRDPCore/build.gradle
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion = rootProject.ext.compileApi
|
||||
buildToolsVersion = rootProject.ext.toolsVersion
|
||||
packagingOptions {
|
||||
jniLibs {
|
||||
pickFirsts += ['lib/arm64-v8a/libfreerdp3.so', 'lib/armeabi-v7a/libfreerdp3.so', 'lib/x86/libfreerdp3.so', 'lib/x86_64/libfreerdp3.so', 'lib/arm64-v8a/libfreerdp-client3.so', 'lib/armeabi-v7a/libfreerdp-client3.so', 'lib/x86/libfreerdp-client3.so', 'lib/x86_64/libfreerdp-client3.so', 'lib/arm64-v8a/libwinpr3.so', 'lib/armeabi-v7a/libwinpr3.so', 'lib/x86/libwinpr3.so', 'lib/x86_64/libwinpr3.so']
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.minApi
|
||||
targetSdkVersion rootProject.ext.targetApi
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
ndkVersion = "29.0.13113456"
|
||||
|
||||
ndk {
|
||||
File jniLibsDirectory = new File(project.projectDir, "src/main/jniLibs")
|
||||
ArrayList<String> abiFiltersList = new ArrayList<String>()
|
||||
if (new File(jniLibsDirectory, "arm64-v8a/libfreerdp3.so").exists())
|
||||
abiFiltersList.add("arm64-v8a")
|
||||
if (new File(jniLibsDirectory, "armeabi-v7a/libfreerdp3.so").exists())
|
||||
abiFiltersList.add("armeabi-v7a")
|
||||
if (new File(jniLibsDirectory, "x86_64/libfreerdp3.so").exists())
|
||||
abiFiltersList.add("x86_64")
|
||||
if (new File(jniLibsDirectory, "x86/libfreerdp3.so").exists())
|
||||
abiFiltersList.add("x86")
|
||||
|
||||
//noinspection ChromeOsAbiSupport
|
||||
abiFilters = abiFiltersList
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments "-DWITH_CLIENT_CHANNELS=ON"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
}
|
||||
debug {
|
||||
jniDebuggable true
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path file('src/main/cpp/CMakeLists.txt')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.android.support:appcompat-v7:28.0.0'
|
||||
implementation 'com.android.support:support-v4:28.0.0'
|
||||
implementation 'com.android.support:support-vector-drawable:28.0.0'
|
||||
}
|
||||
2
third_party/FreeRDP/client/Android/Studio/freeRDPCore/lint.xml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<lint></lint>
|
||||
116
third_party/FreeRDP/client/Android/Studio/freeRDPCore/src/main/AndroidManifest.xml
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:installLocation="auto">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="32" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="32" />
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
|
||||
<supports-screens
|
||||
android:anyDensity="true"
|
||||
android:largeScreens="true"
|
||||
android:normalScreens="true"
|
||||
android:smallScreens="true"
|
||||
android:xlargeScreens="true" />
|
||||
|
||||
<application
|
||||
android:theme="@style/Theme.Main"
|
||||
android:resizeableActivity="true"
|
||||
>
|
||||
<meta-data android:name="com.samsung.android.keepalive.density" android:value="true"/>
|
||||
<!-- Activity to create shortcuts -->
|
||||
<activity
|
||||
android:exported="true"
|
||||
android:name=".presentation.ShortcutsActivity"
|
||||
android:label="@string/title_create_shortcut"
|
||||
android:theme="@style/Theme.Main">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- It is recommended that you use an activity-alias to provide the "CREATE_SHORTCUT" -->
|
||||
<!-- intent-filter. This gives you a way to set the text (and optionally the -->
|
||||
<!-- icon) that will be seen in the launcher's create-shortcut user interface. -->
|
||||
<activity-alias
|
||||
android:exported="true"
|
||||
android:name=".presentation.CreateShortcuts"
|
||||
android:label="@string/title_create_shortcut"
|
||||
android:targetActivity=".presentation.ShortcutsActivity">
|
||||
|
||||
<!-- This intent-filter allows your shortcuts to be created in the launcher. -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.CREATE_SHORTCUT" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity
|
||||
android:exported="false"
|
||||
android:name=".presentation.BookmarkActivity"
|
||||
android:label="@string/title_bookmark_settings"
|
||||
android:theme="@style/Theme.Settings">
|
||||
<intent-filter>
|
||||
<action android:name="freerdp.intent.action.BOOKMARK" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
<data android:scheme="preferences" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:exported="true"
|
||||
android:name=".presentation.ApplicationSettingsActivity"
|
||||
android:label="@string/title_application_settings"
|
||||
android:theme="@style/Theme.Settings"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
<activity
|
||||
android:exported="true"
|
||||
android:name=".presentation.SessionActivity"
|
||||
android:theme="@style/Theme.Main"
|
||||
android:configChanges="orientation|keyboard|keyboardHidden|screenSize|smallestScreenSize|density|screenLayout|navigation"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!--android:configChanges="orientation|keyboardHidden|screenSize|keyboard"-->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="*"
|
||||
android:scheme="freerdp" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:exported="true"
|
||||
android:name=".presentation.AboutActivity"
|
||||
android:label="@string/title_about"
|
||||
android:theme="@style/Theme.Main" />
|
||||
<activity
|
||||
android:exported="true"
|
||||
android:name=".presentation.HelpActivity"
|
||||
android:label="@string/title_help"
|
||||
android:theme="@style/Theme.Main" />
|
||||
|
||||
<receiver
|
||||
android:exported="true"
|
||||
android:name=".application.NetworkStateReceiver"
|
||||
android:enabled="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
83
third_party/FreeRDP/client/Android/Studio/freeRDPCore/src/main/cpp/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# Android Client
|
||||
#
|
||||
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
# Copyright 2013 Bernhard Miklautz <bernhard.miklautz@thincast.com>
|
||||
# Copyright 2022 Ely Ronnen <elyronnen@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
if(NOT FREERDP_DEFAULT_PROJECT_VERSION)
|
||||
set(FREERDP_DEFAULT_PROJECT_VERSION "1.0.0.0")
|
||||
endif()
|
||||
|
||||
project("freerdp-android" LANGUAGES C VERSION ${FREERDP_DEFAULT_PROJECT_VERSION})
|
||||
|
||||
message("project ${PROJECT_NAME} is using version ${PROJECT_VERSION}")
|
||||
|
||||
set(MODULE_NAME "freerdp-android")
|
||||
set(MODULE_PREFIX "FREERDP_CLIENT_ANDROID")
|
||||
|
||||
set(FREERDP_IMPORT_DIR_RELATIVE ../jniLibs/${CMAKE_ANDROID_ARCH_ABI})
|
||||
get_filename_component(FREERDP_IMPORT_DIR ${FREERDP_IMPORT_DIR_RELATIVE} ABSOLUTE)
|
||||
|
||||
include_directories(
|
||||
SYSTEM ${FREERDP_IMPORT_DIR}/include/freerdp3 ${FREERDP_IMPORT_DIR}/include/winpr3
|
||||
${FREERDP_IMPORT_DIR}/include/openssl
|
||||
)
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
android_event.c
|
||||
android_event.h
|
||||
android_freerdp.c
|
||||
android_freerdp.h
|
||||
android_jni_utils.c
|
||||
android_jni_utils.h
|
||||
android_jni_callback.c
|
||||
android_jni_callback.h
|
||||
)
|
||||
|
||||
if(WITH_CLIENT_CHANNELS)
|
||||
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} android_cliprdr.c android_cliprdr.h)
|
||||
endif()
|
||||
|
||||
add_library(${MODULE_NAME} SHARED ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
add_library(freerdp3-lib SHARED IMPORTED)
|
||||
set_property(TARGET freerdp3-lib PROPERTY IMPORTED_LOCATION ${FREERDP_IMPORT_DIR}/libfreerdp3.so)
|
||||
|
||||
add_library(freerdp-client3-lib SHARED IMPORTED)
|
||||
set_property(TARGET freerdp-client3-lib PROPERTY IMPORTED_LOCATION ${FREERDP_IMPORT_DIR}/libfreerdp-client3.so)
|
||||
|
||||
add_library(winpr3-lib SHARED IMPORTED)
|
||||
set_property(TARGET winpr3-lib PROPERTY IMPORTED_LOCATION ${FREERDP_IMPORT_DIR}/libwinpr3.so)
|
||||
|
||||
find_library(log-lib log)
|
||||
find_library(dl-lib dl)
|
||||
find_library(jnigraphics-lib jnigraphics)
|
||||
|
||||
# Specifies libraries CMake should link to your target library. You
|
||||
# can link multiple libraries, such as libraries you define in this
|
||||
# build script, prebuilt third-party libraries, or system libraries.
|
||||
|
||||
target_link_libraries(
|
||||
${MODULE_NAME}
|
||||
freerdp3-lib
|
||||
freerdp-client3-lib
|
||||
winpr3-lib
|
||||
${log-lib}
|
||||
${dl-lib}
|
||||
${jnigraphics-lib}
|
||||
)
|
||||
501
third_party/FreeRDP/client/Android/Studio/freeRDPCore/src/main/cpp/android_cliprdr.c
vendored
Normal file
@@ -0,0 +1,501 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Android Clipboard Redirection
|
||||
*
|
||||
* Copyright 2013 Felix Long
|
||||
* Copyright 2015 Thincast Technologies GmbH
|
||||
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include <freerdp/client/channels.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
|
||||
#include "android_cliprdr.h"
|
||||
#include "android_jni_utils.h"
|
||||
#include "android_jni_callback.h"
|
||||
|
||||
UINT android_cliprdr_send_client_format_list(CliprdrClientContext* cliprdr)
|
||||
{
|
||||
UINT rc = ERROR_INTERNAL_ERROR;
|
||||
UINT32 formatId;
|
||||
UINT32 numFormats;
|
||||
UINT32* pFormatIds;
|
||||
const char* formatName;
|
||||
CLIPRDR_FORMAT* formats;
|
||||
CLIPRDR_FORMAT_LIST formatList = WINPR_C_ARRAY_INIT;
|
||||
|
||||
if (!cliprdr)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
androidContext* afc = (androidContext*)cliprdr->custom;
|
||||
|
||||
if (!afc || !afc->cliprdr)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
pFormatIds = nullptr;
|
||||
numFormats = ClipboardGetFormatIds(afc->clipboard, &pFormatIds);
|
||||
formats = (CLIPRDR_FORMAT*)calloc(numFormats, sizeof(CLIPRDR_FORMAT));
|
||||
|
||||
if (!formats)
|
||||
goto fail;
|
||||
|
||||
for (UINT32 index = 0; index < numFormats; index++)
|
||||
{
|
||||
formatId = pFormatIds[index];
|
||||
formatName = ClipboardGetFormatName(afc->clipboard, formatId);
|
||||
formats[index].formatId = formatId;
|
||||
formats[index].formatName = nullptr;
|
||||
|
||||
if ((formatId > CF_MAX) && formatName)
|
||||
{
|
||||
formats[index].formatName = _strdup(formatName);
|
||||
|
||||
if (!formats[index].formatName)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
formatList.common.msgFlags = 0;
|
||||
formatList.numFormats = numFormats;
|
||||
formatList.formats = formats;
|
||||
formatList.common.msgType = CB_FORMAT_LIST;
|
||||
|
||||
if (!afc->cliprdr->ClientFormatList)
|
||||
goto fail;
|
||||
|
||||
rc = afc->cliprdr->ClientFormatList(afc->cliprdr, &formatList);
|
||||
fail:
|
||||
free(pFormatIds);
|
||||
free(formats);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static UINT android_cliprdr_send_client_format_data_request(CliprdrClientContext* cliprdr,
|
||||
UINT32 formatId)
|
||||
{
|
||||
UINT rc = ERROR_INVALID_PARAMETER;
|
||||
CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest = WINPR_C_ARRAY_INIT;
|
||||
androidContext* afc;
|
||||
|
||||
if (!cliprdr)
|
||||
goto fail;
|
||||
|
||||
afc = (androidContext*)cliprdr->custom;
|
||||
|
||||
if (!afc || !afc->clipboardRequestEvent || !cliprdr->ClientFormatDataRequest)
|
||||
goto fail;
|
||||
|
||||
formatDataRequest.common.msgType = CB_FORMAT_DATA_REQUEST;
|
||||
formatDataRequest.common.msgFlags = 0;
|
||||
formatDataRequest.requestedFormatId = formatId;
|
||||
afc->requestedFormatId = formatId;
|
||||
(void)ResetEvent(afc->clipboardRequestEvent);
|
||||
rc = cliprdr->ClientFormatDataRequest(cliprdr, &formatDataRequest);
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static UINT android_cliprdr_send_client_capabilities(CliprdrClientContext* cliprdr)
|
||||
{
|
||||
CLIPRDR_CAPABILITIES capabilities;
|
||||
CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet;
|
||||
|
||||
if (!cliprdr || !cliprdr->ClientCapabilities)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
capabilities.cCapabilitiesSets = 1;
|
||||
capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*)&(generalCapabilitySet);
|
||||
generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
|
||||
generalCapabilitySet.capabilitySetLength = 12;
|
||||
generalCapabilitySet.version = CB_CAPS_VERSION_2;
|
||||
generalCapabilitySet.generalFlags = CB_USE_LONG_FORMAT_NAMES;
|
||||
return cliprdr->ClientCapabilities(cliprdr, &capabilities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT android_cliprdr_monitor_ready(CliprdrClientContext* cliprdr,
|
||||
const CLIPRDR_MONITOR_READY* monitorReady)
|
||||
{
|
||||
UINT rc;
|
||||
androidContext* afc;
|
||||
|
||||
if (!cliprdr || !monitorReady)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
afc = (androidContext*)cliprdr->custom;
|
||||
|
||||
if (!afc)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if ((rc = android_cliprdr_send_client_capabilities(cliprdr)) != CHANNEL_RC_OK)
|
||||
return rc;
|
||||
|
||||
if ((rc = android_cliprdr_send_client_format_list(cliprdr)) != CHANNEL_RC_OK)
|
||||
return rc;
|
||||
|
||||
afc->clipboardSync = TRUE;
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT android_cliprdr_server_capabilities(CliprdrClientContext* cliprdr,
|
||||
const CLIPRDR_CAPABILITIES* capabilities)
|
||||
{
|
||||
CLIPRDR_CAPABILITY_SET* capabilitySet;
|
||||
androidContext* afc;
|
||||
|
||||
if (!cliprdr || !capabilities)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
afc = (androidContext*)cliprdr->custom;
|
||||
|
||||
if (!afc)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
for (UINT32 index = 0; index < capabilities->cCapabilitiesSets; index++)
|
||||
{
|
||||
capabilitySet = &(capabilities->capabilitySets[index]);
|
||||
|
||||
if ((capabilitySet->capabilitySetType == CB_CAPSTYPE_GENERAL) &&
|
||||
(capabilitySet->capabilitySetLength >= CB_CAPSTYPE_GENERAL_LEN))
|
||||
{
|
||||
CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet =
|
||||
(CLIPRDR_GENERAL_CAPABILITY_SET*)capabilitySet;
|
||||
afc->clipboardCapabilities = generalCapabilitySet->generalFlags;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT android_cliprdr_server_format_list(CliprdrClientContext* cliprdr,
|
||||
const CLIPRDR_FORMAT_LIST* formatList)
|
||||
{
|
||||
UINT rc;
|
||||
CLIPRDR_FORMAT* format;
|
||||
androidContext* afc;
|
||||
|
||||
if (!cliprdr || !formatList)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
afc = (androidContext*)cliprdr->custom;
|
||||
|
||||
if (!afc)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if (afc->serverFormats)
|
||||
{
|
||||
for (UINT32 index = 0; index < afc->numServerFormats; index++)
|
||||
free(afc->serverFormats[index].formatName);
|
||||
|
||||
free(afc->serverFormats);
|
||||
afc->serverFormats = nullptr;
|
||||
afc->numServerFormats = 0;
|
||||
}
|
||||
|
||||
if (formatList->numFormats < 1)
|
||||
return CHANNEL_RC_OK;
|
||||
|
||||
afc->numServerFormats = formatList->numFormats;
|
||||
afc->serverFormats = (CLIPRDR_FORMAT*)calloc(afc->numServerFormats, sizeof(CLIPRDR_FORMAT));
|
||||
|
||||
if (!afc->serverFormats)
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
|
||||
for (UINT32 index = 0; index < afc->numServerFormats; index++)
|
||||
{
|
||||
afc->serverFormats[index].formatId = formatList->formats[index].formatId;
|
||||
afc->serverFormats[index].formatName = nullptr;
|
||||
|
||||
if (formatList->formats[index].formatName)
|
||||
{
|
||||
afc->serverFormats[index].formatName = _strdup(formatList->formats[index].formatName);
|
||||
|
||||
if (!afc->serverFormats[index].formatName)
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
for (UINT32 index = 0; index < afc->numServerFormats; index++)
|
||||
{
|
||||
format = &(afc->serverFormats[index]);
|
||||
|
||||
if (format->formatId == CF_UNICODETEXT)
|
||||
{
|
||||
if ((rc = android_cliprdr_send_client_format_data_request(cliprdr, CF_UNICODETEXT)) !=
|
||||
CHANNEL_RC_OK)
|
||||
return rc;
|
||||
|
||||
break;
|
||||
}
|
||||
else if (format->formatId == CF_TEXT)
|
||||
{
|
||||
if ((rc = android_cliprdr_send_client_format_data_request(cliprdr, CF_TEXT)) !=
|
||||
CHANNEL_RC_OK)
|
||||
return rc;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT
|
||||
android_cliprdr_server_format_list_response(CliprdrClientContext* cliprdr,
|
||||
const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
|
||||
{
|
||||
if (!cliprdr || !formatListResponse)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT
|
||||
android_cliprdr_server_lock_clipboard_data(CliprdrClientContext* cliprdr,
|
||||
const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
|
||||
{
|
||||
if (!cliprdr || !lockClipboardData)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT android_cliprdr_server_unlock_clipboard_data(
|
||||
CliprdrClientContext* cliprdr, const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
|
||||
{
|
||||
if (!cliprdr || !unlockClipboardData)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT
|
||||
android_cliprdr_server_format_data_request(CliprdrClientContext* cliprdr,
|
||||
const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
||||
{
|
||||
UINT rc;
|
||||
BYTE* data;
|
||||
UINT32 size;
|
||||
UINT32 formatId;
|
||||
CLIPRDR_FORMAT_DATA_RESPONSE response = WINPR_C_ARRAY_INIT;
|
||||
androidContext* afc;
|
||||
|
||||
if (!cliprdr || !formatDataRequest || !cliprdr->ClientFormatDataResponse)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
afc = (androidContext*)cliprdr->custom;
|
||||
|
||||
if (!afc)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
formatId = formatDataRequest->requestedFormatId;
|
||||
data = (BYTE*)ClipboardGetData(afc->clipboard, formatId, &size);
|
||||
response.common.msgFlags = CB_RESPONSE_OK;
|
||||
response.common.dataLen = size;
|
||||
response.requestedFormatData = data;
|
||||
|
||||
if (!data)
|
||||
{
|
||||
response.common.msgFlags = CB_RESPONSE_FAIL;
|
||||
response.common.dataLen = 0;
|
||||
response.requestedFormatData = nullptr;
|
||||
}
|
||||
|
||||
rc = cliprdr->ClientFormatDataResponse(cliprdr, &response);
|
||||
free(data);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT
|
||||
android_cliprdr_server_format_data_response(CliprdrClientContext* cliprdr,
|
||||
const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
|
||||
{
|
||||
CLIPRDR_FORMAT* format = nullptr;
|
||||
|
||||
if (!cliprdr || !formatDataResponse)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
androidContext* afc = (androidContext*)cliprdr->custom;
|
||||
|
||||
if (!afc)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
freerdp* instance = ((rdpContext*)afc)->instance;
|
||||
|
||||
if (!instance)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
for (UINT32 index = 0; index < afc->numServerFormats; index++)
|
||||
{
|
||||
if (afc->requestedFormatId == afc->serverFormats[index].formatId)
|
||||
format = &(afc->serverFormats[index]);
|
||||
}
|
||||
|
||||
if (!format)
|
||||
{
|
||||
(void)SetEvent(afc->clipboardRequestEvent);
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
UINT32 formatId = format->formatId;
|
||||
if (format->formatName)
|
||||
formatId = ClipboardRegisterFormat(afc->clipboard, format->formatName);
|
||||
|
||||
uint32_t size = formatDataResponse->common.dataLen;
|
||||
|
||||
if (!ClipboardSetData(afc->clipboard, formatId, formatDataResponse->requestedFormatData, size))
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
(void)SetEvent(afc->clipboardRequestEvent);
|
||||
|
||||
if ((formatId == CF_TEXT) || (formatId == CF_UNICODETEXT))
|
||||
{
|
||||
JNIEnv* env = nullptr;
|
||||
formatId = ClipboardRegisterFormat(afc->clipboard, "text/plain");
|
||||
char* data = (char*)ClipboardGetData(afc->clipboard, formatId, &size);
|
||||
jboolean attached = jni_attach_thread(&env);
|
||||
size = strnlen(data, size);
|
||||
jstring jdata = jniNewStringUTF(env, data, size);
|
||||
freerdp_callback("OnRemoteClipboardChanged", "(JLjava/lang/String;)V", (jlong)instance,
|
||||
jdata);
|
||||
(*env)->DeleteLocalRef(env, jdata);
|
||||
|
||||
if (attached == JNI_TRUE)
|
||||
jni_detach_thread();
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT android_cliprdr_server_file_contents_request(
|
||||
CliprdrClientContext* cliprdr, const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
|
||||
{
|
||||
if (!cliprdr || !fileContentsRequest)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT android_cliprdr_server_file_contents_response(
|
||||
CliprdrClientContext* cliprdr, const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
|
||||
{
|
||||
if (!cliprdr || !fileContentsResponse)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
BOOL android_cliprdr_init(androidContext* afc, CliprdrClientContext* cliprdr)
|
||||
{
|
||||
wClipboard* clipboard;
|
||||
HANDLE hevent;
|
||||
|
||||
if (!afc || !cliprdr)
|
||||
return FALSE;
|
||||
|
||||
if (!(hevent = CreateEvent(nullptr, TRUE, FALSE, nullptr)))
|
||||
return FALSE;
|
||||
|
||||
if (!(clipboard = ClipboardCreate()))
|
||||
{
|
||||
(void)CloseHandle(hevent);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
afc->cliprdr = cliprdr;
|
||||
afc->clipboard = clipboard;
|
||||
afc->clipboardRequestEvent = hevent;
|
||||
cliprdr->custom = (void*)afc;
|
||||
cliprdr->MonitorReady = android_cliprdr_monitor_ready;
|
||||
cliprdr->ServerCapabilities = android_cliprdr_server_capabilities;
|
||||
cliprdr->ServerFormatList = android_cliprdr_server_format_list;
|
||||
cliprdr->ServerFormatListResponse = android_cliprdr_server_format_list_response;
|
||||
cliprdr->ServerLockClipboardData = android_cliprdr_server_lock_clipboard_data;
|
||||
cliprdr->ServerUnlockClipboardData = android_cliprdr_server_unlock_clipboard_data;
|
||||
cliprdr->ServerFormatDataRequest = android_cliprdr_server_format_data_request;
|
||||
cliprdr->ServerFormatDataResponse = android_cliprdr_server_format_data_response;
|
||||
cliprdr->ServerFileContentsRequest = android_cliprdr_server_file_contents_request;
|
||||
cliprdr->ServerFileContentsResponse = android_cliprdr_server_file_contents_response;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL android_cliprdr_uninit(androidContext* afc, CliprdrClientContext* cliprdr)
|
||||
{
|
||||
if (!afc || !cliprdr)
|
||||
return FALSE;
|
||||
|
||||
cliprdr->custom = nullptr;
|
||||
afc->cliprdr = nullptr;
|
||||
ClipboardDestroy(afc->clipboard);
|
||||
(void)CloseHandle(afc->clipboardRequestEvent);
|
||||
return TRUE;
|
||||
}
|
||||
33
third_party/FreeRDP/client/Android/Studio/freeRDPCore/src/main/cpp/android_cliprdr.h
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Android Clipboard Redirection
|
||||
*
|
||||
* Copyright 2013 Felix Long
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CLIENT_ANDROID_CLIPRDR_H
|
||||
#define FREERDP_CLIENT_ANDROID_CLIPRDR_H
|
||||
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include "android_freerdp.h"
|
||||
|
||||
FREERDP_LOCAL UINT android_cliprdr_send_client_format_list(CliprdrClientContext* cliprdr);
|
||||
|
||||
FREERDP_LOCAL BOOL android_cliprdr_init(androidContext* afc, CliprdrClientContext* cliprdr);
|
||||
FREERDP_LOCAL BOOL android_cliprdr_uninit(androidContext* afc, CliprdrClientContext* cliprdr);
|
||||
|
||||
#endif /* FREERDP_CLIENT_ANDROID_CLIPRDR_H */
|
||||
404
third_party/FreeRDP/client/Android/Studio/freeRDPCore/src/main/cpp/android_event.c
vendored
Normal file
@@ -0,0 +1,404 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Android Event System
|
||||
*
|
||||
* Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#define TAG CLIENT_TAG("android")
|
||||
|
||||
#include "android_freerdp.h"
|
||||
#include "android_cliprdr.h"
|
||||
|
||||
BOOL android_push_event(freerdp* inst, ANDROID_EVENT* event)
|
||||
{
|
||||
androidContext* aCtx = (androidContext*)inst->context;
|
||||
|
||||
if (aCtx->event_queue->count >= aCtx->event_queue->size)
|
||||
{
|
||||
size_t new_size = aCtx->event_queue->size;
|
||||
do
|
||||
{
|
||||
if (new_size >= SIZE_MAX - 128ull)
|
||||
return FALSE;
|
||||
|
||||
new_size += 128ull;
|
||||
} while (new_size <= aCtx->event_queue->count);
|
||||
void* new_events =
|
||||
realloc((void*)aCtx->event_queue->events, sizeof(ANDROID_EVENT*) * new_size);
|
||||
|
||||
if (!new_events)
|
||||
return FALSE;
|
||||
|
||||
aCtx->event_queue->events = new_events;
|
||||
aCtx->event_queue->size = new_size;
|
||||
}
|
||||
|
||||
aCtx->event_queue->events[(aCtx->event_queue->count)++] = event;
|
||||
return SetEvent(aCtx->event_queue->isSet);
|
||||
}
|
||||
|
||||
static ANDROID_EVENT* android_peek_event(ANDROID_EVENT_QUEUE* queue)
|
||||
{
|
||||
ANDROID_EVENT* event;
|
||||
|
||||
if (queue->count < 1)
|
||||
return nullptr;
|
||||
|
||||
event = queue->events[0];
|
||||
return event;
|
||||
}
|
||||
|
||||
static ANDROID_EVENT* android_pop_event(ANDROID_EVENT_QUEUE* queue)
|
||||
{
|
||||
ANDROID_EVENT* event;
|
||||
|
||||
if (queue->count < 1)
|
||||
return nullptr;
|
||||
|
||||
event = queue->events[0];
|
||||
(queue->count)--;
|
||||
|
||||
for (size_t i = 0; i < queue->count; i++)
|
||||
{
|
||||
queue->events[i] = queue->events[i + 1];
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
static BOOL android_process_event(ANDROID_EVENT_QUEUE* queue, freerdp* inst)
|
||||
{
|
||||
rdpContext* context;
|
||||
|
||||
WINPR_ASSERT(queue);
|
||||
WINPR_ASSERT(inst);
|
||||
|
||||
context = inst->context;
|
||||
WINPR_ASSERT(context);
|
||||
|
||||
while (android_peek_event(queue))
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
androidContext* afc = (androidContext*)context;
|
||||
ANDROID_EVENT* event = android_pop_event(queue);
|
||||
|
||||
WINPR_ASSERT(event);
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case EVENT_TYPE_KEY:
|
||||
{
|
||||
ANDROID_EVENT_KEY* key_event = (ANDROID_EVENT_KEY*)event;
|
||||
|
||||
rc = freerdp_input_send_keyboard_event(context->input, key_event->flags,
|
||||
key_event->scancode);
|
||||
}
|
||||
break;
|
||||
|
||||
case EVENT_TYPE_KEY_UNICODE:
|
||||
{
|
||||
ANDROID_EVENT_KEY* key_event = (ANDROID_EVENT_KEY*)event;
|
||||
|
||||
rc = freerdp_input_send_unicode_keyboard_event(context->input, key_event->flags,
|
||||
key_event->scancode);
|
||||
}
|
||||
break;
|
||||
|
||||
case EVENT_TYPE_CURSOR:
|
||||
{
|
||||
ANDROID_EVENT_CURSOR* cursor_event = (ANDROID_EVENT_CURSOR*)event;
|
||||
|
||||
rc = freerdp_input_send_mouse_event(context->input, cursor_event->flags,
|
||||
cursor_event->x, cursor_event->y);
|
||||
}
|
||||
break;
|
||||
|
||||
case EVENT_TYPE_CLIPBOARD:
|
||||
{
|
||||
ANDROID_EVENT_CLIPBOARD* clipboard_event = (ANDROID_EVENT_CLIPBOARD*)event;
|
||||
UINT32 formatId = ClipboardRegisterFormat(afc->clipboard, "text/plain");
|
||||
UINT32 size = clipboard_event->data_length;
|
||||
|
||||
if (size)
|
||||
ClipboardSetData(afc->clipboard, formatId, clipboard_event->data, size);
|
||||
else
|
||||
ClipboardEmpty(afc->clipboard);
|
||||
|
||||
rc = (android_cliprdr_send_client_format_list(afc->cliprdr) == CHANNEL_RC_OK);
|
||||
}
|
||||
break;
|
||||
|
||||
case EVENT_TYPE_DISCONNECT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
android_event_free(event);
|
||||
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HANDLE android_get_handle(freerdp* inst)
|
||||
{
|
||||
androidContext* aCtx;
|
||||
|
||||
if (!inst || !inst->context)
|
||||
return nullptr;
|
||||
|
||||
aCtx = (androidContext*)inst->context;
|
||||
|
||||
if (!aCtx->event_queue || !aCtx->event_queue->isSet)
|
||||
return nullptr;
|
||||
|
||||
return aCtx->event_queue->isSet;
|
||||
}
|
||||
|
||||
BOOL android_check_handle(freerdp* inst)
|
||||
{
|
||||
androidContext* aCtx;
|
||||
|
||||
if (!inst || !inst->context)
|
||||
return FALSE;
|
||||
|
||||
aCtx = (androidContext*)inst->context;
|
||||
|
||||
if (!aCtx->event_queue || !aCtx->event_queue->isSet)
|
||||
return FALSE;
|
||||
|
||||
if (WaitForSingleObject(aCtx->event_queue->isSet, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
if (!ResetEvent(aCtx->event_queue->isSet))
|
||||
return FALSE;
|
||||
|
||||
if (!android_process_event(aCtx->event_queue, inst))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ANDROID_EVENT_KEY* android_event_key_new(int flags, UINT16 scancode)
|
||||
{
|
||||
ANDROID_EVENT_KEY* event = (ANDROID_EVENT_KEY*)calloc(1, sizeof(ANDROID_EVENT_KEY));
|
||||
|
||||
if (!event)
|
||||
return nullptr;
|
||||
|
||||
event->type = EVENT_TYPE_KEY;
|
||||
event->flags = flags;
|
||||
event->scancode = scancode;
|
||||
return event;
|
||||
}
|
||||
|
||||
static void android_event_key_free(ANDROID_EVENT_KEY* event)
|
||||
{
|
||||
free(event);
|
||||
}
|
||||
|
||||
ANDROID_EVENT_KEY* android_event_unicodekey_new(UINT16 flags, UINT16 key)
|
||||
{
|
||||
ANDROID_EVENT_KEY* event;
|
||||
event = (ANDROID_EVENT_KEY*)calloc(1, sizeof(ANDROID_EVENT_KEY));
|
||||
|
||||
if (!event)
|
||||
return nullptr;
|
||||
|
||||
event->type = EVENT_TYPE_KEY_UNICODE;
|
||||
event->flags = flags;
|
||||
event->scancode = key;
|
||||
return event;
|
||||
}
|
||||
|
||||
static void android_event_unicodekey_free(ANDROID_EVENT_KEY* event)
|
||||
{
|
||||
free(event);
|
||||
}
|
||||
|
||||
ANDROID_EVENT_CURSOR* android_event_cursor_new(UINT16 flags, UINT16 x, UINT16 y)
|
||||
{
|
||||
ANDROID_EVENT_CURSOR* event;
|
||||
event = (ANDROID_EVENT_CURSOR*)calloc(1, sizeof(ANDROID_EVENT_CURSOR));
|
||||
|
||||
if (!event)
|
||||
return nullptr;
|
||||
|
||||
event->type = EVENT_TYPE_CURSOR;
|
||||
event->x = x;
|
||||
event->y = y;
|
||||
event->flags = flags;
|
||||
return event;
|
||||
}
|
||||
|
||||
static void android_event_cursor_free(ANDROID_EVENT_CURSOR* event)
|
||||
{
|
||||
free(event);
|
||||
}
|
||||
|
||||
ANDROID_EVENT* android_event_disconnect_new(void)
|
||||
{
|
||||
ANDROID_EVENT* event;
|
||||
event = (ANDROID_EVENT*)calloc(1, sizeof(ANDROID_EVENT));
|
||||
|
||||
if (!event)
|
||||
return nullptr;
|
||||
|
||||
event->type = EVENT_TYPE_DISCONNECT;
|
||||
return event;
|
||||
}
|
||||
|
||||
static void android_event_disconnect_free(ANDROID_EVENT* event)
|
||||
{
|
||||
free(event);
|
||||
}
|
||||
|
||||
ANDROID_EVENT_CLIPBOARD* android_event_clipboard_new(const void* data, size_t data_length)
|
||||
{
|
||||
ANDROID_EVENT_CLIPBOARD* event;
|
||||
event = (ANDROID_EVENT_CLIPBOARD*)calloc(1, sizeof(ANDROID_EVENT_CLIPBOARD));
|
||||
|
||||
if (!event)
|
||||
return nullptr;
|
||||
|
||||
event->type = EVENT_TYPE_CLIPBOARD;
|
||||
|
||||
if (data)
|
||||
{
|
||||
event->data = calloc(data_length + 1, sizeof(char));
|
||||
|
||||
if (!event->data)
|
||||
{
|
||||
free(event);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
memcpy(event->data, data, data_length);
|
||||
event->data_length = data_length + 1;
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
static void android_event_clipboard_free(ANDROID_EVENT_CLIPBOARD* event)
|
||||
{
|
||||
if (event)
|
||||
{
|
||||
free(event->data);
|
||||
free(event);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL android_event_queue_init(freerdp* inst)
|
||||
{
|
||||
androidContext* aCtx = (androidContext*)inst->context;
|
||||
ANDROID_EVENT_QUEUE* queue;
|
||||
queue = (ANDROID_EVENT_QUEUE*)calloc(1, sizeof(ANDROID_EVENT_QUEUE));
|
||||
|
||||
if (!queue)
|
||||
{
|
||||
WLog_ERR(TAG, "android_event_queue_init: memory allocation failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
queue->size = 16;
|
||||
queue->count = 0;
|
||||
queue->isSet = CreateEventA(nullptr, TRUE, FALSE, nullptr);
|
||||
|
||||
if (!queue->isSet)
|
||||
{
|
||||
free(queue);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
queue->events = (ANDROID_EVENT**)calloc(queue->size, sizeof(ANDROID_EVENT*));
|
||||
|
||||
if (!queue->events)
|
||||
{
|
||||
WLog_ERR(TAG, "android_event_queue_init: memory allocation failed");
|
||||
(void)CloseHandle(queue->isSet);
|
||||
free(queue);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
aCtx->event_queue = queue;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void android_event_queue_uninit(freerdp* inst)
|
||||
{
|
||||
androidContext* aCtx;
|
||||
ANDROID_EVENT_QUEUE* queue;
|
||||
|
||||
if (!inst || !inst->context)
|
||||
return;
|
||||
|
||||
aCtx = (androidContext*)inst->context;
|
||||
queue = aCtx->event_queue;
|
||||
|
||||
if (queue)
|
||||
{
|
||||
if (queue->isSet)
|
||||
{
|
||||
(void)CloseHandle(queue->isSet);
|
||||
queue->isSet = nullptr;
|
||||
}
|
||||
|
||||
if (queue->events)
|
||||
{
|
||||
free(queue->events);
|
||||
queue->events = nullptr;
|
||||
queue->size = 0;
|
||||
queue->count = 0;
|
||||
}
|
||||
|
||||
free(queue);
|
||||
}
|
||||
}
|
||||
|
||||
void android_event_free(ANDROID_EVENT* event)
|
||||
{
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case EVENT_TYPE_KEY:
|
||||
android_event_key_free((ANDROID_EVENT_KEY*)event);
|
||||
break;
|
||||
|
||||
case EVENT_TYPE_KEY_UNICODE:
|
||||
android_event_unicodekey_free((ANDROID_EVENT_KEY*)event);
|
||||
break;
|
||||
|
||||
case EVENT_TYPE_CURSOR:
|
||||
android_event_cursor_free((ANDROID_EVENT_CURSOR*)event);
|
||||
break;
|
||||
|
||||
case EVENT_TYPE_DISCONNECT:
|
||||
android_event_disconnect_free((ANDROID_EVENT*)event);
|
||||
break;
|
||||
|
||||
case EVENT_TYPE_CLIPBOARD:
|
||||
android_event_clipboard_free((ANDROID_EVENT_CLIPBOARD*)event);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
75
third_party/FreeRDP/client/Android/Studio/freeRDPCore/src/main/cpp/android_event.h
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Android Event System
|
||||
*
|
||||
* Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CLIENT_ANDROID_EVENT_H
|
||||
#define FREERDP_CLIENT_ANDROID_EVENT_H
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#define EVENT_TYPE_KEY 1
|
||||
#define EVENT_TYPE_CURSOR 2
|
||||
#define EVENT_TYPE_DISCONNECT 3
|
||||
#define EVENT_TYPE_KEY_UNICODE 4
|
||||
#define EVENT_TYPE_CLIPBOARD 5
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int type;
|
||||
} ANDROID_EVENT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int type;
|
||||
int flags;
|
||||
UINT16 scancode;
|
||||
} ANDROID_EVENT_KEY;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int type;
|
||||
UINT16 flags;
|
||||
UINT16 x;
|
||||
UINT16 y;
|
||||
} ANDROID_EVENT_CURSOR;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int type;
|
||||
void* data;
|
||||
int data_length;
|
||||
} ANDROID_EVENT_CLIPBOARD;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int size;
|
||||
int count;
|
||||
HANDLE isSet;
|
||||
ANDROID_EVENT** events;
|
||||
} ANDROID_EVENT_QUEUE;
|
||||
|
||||
FREERDP_LOCAL BOOL android_push_event(freerdp* inst, ANDROID_EVENT* event);
|
||||
|
||||
FREERDP_LOCAL HANDLE android_get_handle(freerdp* inst);
|
||||
FREERDP_LOCAL BOOL android_check_handle(freerdp* inst);
|
||||
|
||||
FREERDP_LOCAL ANDROID_EVENT_KEY* android_event_key_new(int flags, UINT16 scancode);
|
||||
FREERDP_LOCAL ANDROID_EVENT_KEY* android_event_unicodekey_new(UINT16 flags, UINT16 key);
|
||||
FREERDP_LOCAL ANDROID_EVENT_CURSOR* android_event_cursor_new(UINT16 flags, UINT16 x, UINT16 y);
|
||||
FREERDP_LOCAL ANDROID_EVENT* android_event_disconnect_new(void);
|
||||
FREERDP_LOCAL ANDROID_EVENT_CLIPBOARD* android_event_clipboard_new(const void* data,
|
||||
size_t data_length);
|
||||
|
||||
FREERDP_LOCAL void android_event_free(ANDROID_EVENT* event);
|
||||
|
||||
FREERDP_LOCAL BOOL android_event_queue_init(freerdp* inst);
|
||||
FREERDP_LOCAL void android_event_queue_uninit(freerdp* inst);
|
||||
|
||||
#endif /* FREERDP_CLIENT_ANDROID_EVENT_H */
|
||||
1039
third_party/FreeRDP/client/Android/Studio/freeRDPCore/src/main/cpp/android_freerdp.c
vendored
Normal file
43
third_party/FreeRDP/client/Android/Studio/freeRDPCore/src/main/cpp/android_freerdp.h
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Android JNI Client Layer
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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/.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CLIENT_ANDROID_FREERDP_H
|
||||
#define FREERDP_CLIENT_ANDROID_FREERDP_H
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/clipboard.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
|
||||
#include "android_event.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rdpClientContext common;
|
||||
|
||||
ANDROID_EVENT_QUEUE* event_queue;
|
||||
HANDLE thread;
|
||||
|
||||
BOOL is_connected;
|
||||
|
||||
BOOL clipboardSync;
|
||||
wClipboard* clipboard;
|
||||
UINT32 numServerFormats;
|
||||
UINT32 requestedFormatId;
|
||||
HANDLE clipboardRequestEvent;
|
||||
CLIPRDR_FORMAT* serverFormats;
|
||||
CliprdrClientContext* cliprdr;
|
||||
UINT32 clipboardCapabilities;
|
||||
} androidContext;
|
||||
|
||||
#endif /* FREERDP_CLIENT_ANDROID_FREERDP_H */
|
||||
27
third_party/FreeRDP/client/Android/Studio/freeRDPCore/src/main/cpp/android_freerdp_jni.h
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
FreeRDP: A Remote Desktop Protocol client.
|
||||
Android FreeRDP JNI Definitions
|
||||
|
||||
Copyright 2010 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CLIENT_ANDROID_FREERDP_JNI_H
|
||||
#define FREERDP_CLIENT_ANDROID_FREERDP_JNI_H
|
||||
|
||||
#define JAVA_LIBFREERDP_CLASS "com/freerdp/freerdpcore/services/LibFreeRDP"
|
||||
#define JAVA_CONTEXT_CLASS "android/content/Context"
|
||||
#define JAVA_FILE_CLASS "java/io/File"
|
||||
|
||||
#endif /* FREERDP_CLIENT_ANDROID_FREERDP_JNI_H */
|
||||
226
third_party/FreeRDP/client/Android/Studio/freeRDPCore/src/main/cpp/android_jni_callback.c
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Android JNI Callback Helpers
|
||||
*
|
||||
* Copyright 2011-2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "android_jni_callback.h"
|
||||
#include "android_freerdp_jni.h"
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#define TAG CLIENT_TAG("android.callback")
|
||||
|
||||
static JavaVM* jVM;
|
||||
static jobject jLibFreeRDPObject;
|
||||
|
||||
static const char* jLibFreeRDPPath = JAVA_LIBFREERDP_CLASS;
|
||||
|
||||
static void jni_load_class(JNIEnv* env, const char* path, jobject* objptr)
|
||||
{
|
||||
jclass class;
|
||||
jmethodID method;
|
||||
jobject object;
|
||||
WLog_DBG(TAG, "jni_load_class: %s", path);
|
||||
class = (*env)->FindClass(env, path);
|
||||
|
||||
if (!class)
|
||||
{
|
||||
WLog_ERR(TAG, "jni_load_class: failed to find class %s", path);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
method = (*env)->GetMethodID(env, class, "<init>", "()V");
|
||||
|
||||
if (!method)
|
||||
{
|
||||
WLog_ERR(TAG, "jni_load_class: failed to find class constructor of %s", path);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
object = (*env)->NewObject(env, class, method);
|
||||
|
||||
if (!object)
|
||||
{
|
||||
WLog_ERR(TAG, "jni_load_class: failed create new object of %s", path);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
(*objptr) = (*env)->NewGlobalRef(env, object);
|
||||
finish:
|
||||
|
||||
while (0)
|
||||
;
|
||||
}
|
||||
|
||||
jint init_callback_environment(JavaVM* vm, JNIEnv* env)
|
||||
{
|
||||
jVM = vm;
|
||||
jni_load_class(env, jLibFreeRDPPath, &jLibFreeRDPObject);
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
/* attach current thread to jvm */
|
||||
jboolean jni_attach_thread(JNIEnv** env)
|
||||
{
|
||||
if ((*jVM)->GetEnv(jVM, (void**)env, JNI_VERSION_1_4) != JNI_OK)
|
||||
{
|
||||
WLog_DBG(TAG, "android_java_callback: attaching current thread");
|
||||
(*jVM)->AttachCurrentThread(jVM, env, nullptr);
|
||||
|
||||
if ((*jVM)->GetEnv(jVM, (void**)env, JNI_VERSION_1_4) != JNI_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "android_java_callback: failed to obtain current JNI environment");
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
/* attach current thread to JVM */
|
||||
void jni_detach_thread()
|
||||
{
|
||||
(*jVM)->DetachCurrentThread(jVM);
|
||||
}
|
||||
|
||||
/* callback with void result */
|
||||
static void java_callback_void(jobject obj, const char* callback, const char* signature,
|
||||
va_list args)
|
||||
{
|
||||
jclass jObjClass;
|
||||
jmethodID jCallback;
|
||||
jboolean attached;
|
||||
JNIEnv* env;
|
||||
WLog_DBG(TAG, "java_callback: %s (%s)", callback, signature);
|
||||
attached = jni_attach_thread(&env);
|
||||
jObjClass = (*env)->GetObjectClass(env, obj);
|
||||
|
||||
if (!jObjClass)
|
||||
{
|
||||
WLog_ERR(TAG, "android_java_callback: failed to get class reference");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
jCallback = (*env)->GetStaticMethodID(env, jObjClass, callback, signature);
|
||||
|
||||
if (!jCallback)
|
||||
{
|
||||
WLog_ERR(TAG, "android_java_callback: failed to get method id");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
(*env)->CallStaticVoidMethodV(env, jObjClass, jCallback, args);
|
||||
finish:
|
||||
|
||||
if (attached == JNI_TRUE)
|
||||
jni_detach_thread();
|
||||
}
|
||||
|
||||
/* callback with bool result */
|
||||
static jboolean java_callback_bool(jobject obj, const char* callback, const char* signature,
|
||||
va_list args)
|
||||
{
|
||||
jclass jObjClass;
|
||||
jmethodID jCallback;
|
||||
jboolean attached;
|
||||
jboolean res = JNI_FALSE;
|
||||
JNIEnv* env;
|
||||
WLog_DBG(TAG, "java_callback: %s (%s)", callback, signature);
|
||||
attached = jni_attach_thread(&env);
|
||||
jObjClass = (*env)->GetObjectClass(env, obj);
|
||||
|
||||
if (!jObjClass)
|
||||
{
|
||||
WLog_ERR(TAG, "android_java_callback: failed to get class reference");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
jCallback = (*env)->GetStaticMethodID(env, jObjClass, callback, signature);
|
||||
|
||||
if (!jCallback)
|
||||
{
|
||||
WLog_ERR(TAG, "android_java_callback: failed to get method id");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
res = (*env)->CallStaticBooleanMethodV(env, jObjClass, jCallback, args);
|
||||
finish:
|
||||
|
||||
if (attached == JNI_TRUE)
|
||||
jni_detach_thread();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* callback with int result */
|
||||
static jint java_callback_int(jobject obj, const char* callback, const char* signature,
|
||||
va_list args)
|
||||
{
|
||||
jclass jObjClass;
|
||||
jmethodID jCallback;
|
||||
jboolean attached;
|
||||
jint res = -1;
|
||||
JNIEnv* env;
|
||||
WLog_DBG(TAG, "java_callback: %s (%s)", callback, signature);
|
||||
attached = jni_attach_thread(&env);
|
||||
jObjClass = (*env)->GetObjectClass(env, obj);
|
||||
|
||||
if (!jObjClass)
|
||||
{
|
||||
WLog_ERR(TAG, "android_java_callback: failed to get class reference");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
jCallback = (*env)->GetStaticMethodID(env, jObjClass, callback, signature);
|
||||
|
||||
if (!jCallback)
|
||||
{
|
||||
WLog_ERR(TAG, "android_java_callback: failed to get method id");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
res = (*env)->CallStaticIntMethodV(env, jObjClass, jCallback, args);
|
||||
finish:
|
||||
|
||||
if (attached == JNI_TRUE)
|
||||
jni_detach_thread();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* callback to freerdp class */
|
||||
void freerdp_callback(const char* callback, const char* signature, ...)
|
||||
{
|
||||
va_list vl = WINPR_C_ARRAY_INIT;
|
||||
va_start(vl, signature);
|
||||
java_callback_void(jLibFreeRDPObject, callback, signature, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
jboolean freerdp_callback_bool_result(const char* callback, const char* signature, ...)
|
||||
{
|
||||
va_list vl = WINPR_C_ARRAY_INIT;
|
||||
va_start(vl, signature);
|
||||
jboolean res = java_callback_bool(jLibFreeRDPObject, callback, signature, vl);
|
||||
va_end(vl);
|
||||
return res;
|
||||
}
|
||||
|
||||
jint freerdp_callback_int_result(const char* callback, const char* signature, ...)
|
||||
{
|
||||
va_list vl = WINPR_C_ARRAY_INIT;
|
||||
va_start(vl, signature);
|
||||
jint res = java_callback_int(jLibFreeRDPObject, callback, signature, vl);
|
||||
va_end(vl);
|
||||
return res;
|
||||
}
|
||||
28
third_party/FreeRDP/client/Android/Studio/freeRDPCore/src/main/cpp/android_jni_callback.h
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Android JNI Callback Helpers
|
||||
*
|
||||
* Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2011-2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CLIENT_ANDROID_JNI_CALLBACK_H
|
||||
#define FREERDP_CLIENT_ANDROID_JNI_CALLBACK_H
|
||||
|
||||
#include <jni.h>
|
||||
#include <stdarg.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
FREERDP_LOCAL jint init_callback_environment(JavaVM* vm, JNIEnv* env);
|
||||
FREERDP_LOCAL jboolean jni_attach_thread(JNIEnv** env);
|
||||
FREERDP_LOCAL void jni_detach_thread(void);
|
||||
FREERDP_LOCAL void freerdp_callback(const char* callback, const char* signature, ...);
|
||||
FREERDP_LOCAL jboolean freerdp_callback_bool_result(const char* callback, const char* signature,
|
||||
...);
|
||||
FREERDP_LOCAL jint freerdp_callback_int_result(const char* callback, const char* signature, ...);
|
||||
|
||||
#endif /* FREERDP_CLIENT_ANDROID_JNI_CALLBACK_H */
|
||||
191
third_party/FreeRDP/client/Android/Studio/freeRDPCore/src/main/cpp/android_jni_utils.c
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Android Event System
|
||||
*
|
||||
* Copyright 2013 Felix Long
|
||||
* Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#include "android_jni_utils.h"
|
||||
|
||||
#include <locale.h>
|
||||
#include <freerdp/channels/channels.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "android_jni_callback.h"
|
||||
|
||||
#define TAG CLIENT_TAG("android.utils")
|
||||
|
||||
JavaVM* g_JavaVm;
|
||||
|
||||
JavaVM* getJavaVM()
|
||||
{
|
||||
return g_JavaVm;
|
||||
}
|
||||
|
||||
JNIEnv* getJNIEnv()
|
||||
{
|
||||
JNIEnv* env = nullptr;
|
||||
if ((*g_JavaVm)->GetEnv(g_JavaVm, (void**)&env, JNI_VERSION_1_4) != JNI_OK)
|
||||
{
|
||||
WLog_FATAL(TAG, "Failed to obtain JNIEnv");
|
||||
return nullptr;
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
jobject create_string_builder(JNIEnv* env, char* initialStr)
|
||||
{
|
||||
jclass cls;
|
||||
jmethodID methodId;
|
||||
jobject obj;
|
||||
|
||||
// get class
|
||||
cls = (*env)->FindClass(env, "java/lang/StringBuilder");
|
||||
if (!cls)
|
||||
return nullptr;
|
||||
|
||||
if (initialStr)
|
||||
{
|
||||
// get method id for constructor
|
||||
methodId = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V");
|
||||
if (!methodId)
|
||||
return nullptr;
|
||||
|
||||
// create string that holds our initial string
|
||||
jstring jstr = (*env)->NewStringUTF(env, initialStr);
|
||||
|
||||
// construct new StringBuilder
|
||||
obj = (*env)->NewObject(env, cls, methodId, jstr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// get method id for constructor
|
||||
methodId = (*env)->GetMethodID(env, cls, "<init>", "()V");
|
||||
if (!methodId)
|
||||
return nullptr;
|
||||
|
||||
// construct new StringBuilder
|
||||
obj = (*env)->NewObject(env, cls, methodId);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
char* get_string_from_string_builder(JNIEnv* env, jobject strBuilder)
|
||||
{
|
||||
jclass cls;
|
||||
jmethodID methodId;
|
||||
jstring strObj;
|
||||
const char* native_str;
|
||||
char* result;
|
||||
|
||||
// get class
|
||||
cls = (*env)->FindClass(env, "java/lang/StringBuilder");
|
||||
if (!cls)
|
||||
return nullptr;
|
||||
|
||||
// get method id for constructor
|
||||
methodId = (*env)->GetMethodID(env, cls, "toString", "()Ljava/lang/String;");
|
||||
if (!methodId)
|
||||
return nullptr;
|
||||
|
||||
// get jstring representation of our buffer
|
||||
strObj = (*env)->CallObjectMethod(env, strBuilder, methodId);
|
||||
|
||||
// read string
|
||||
native_str = (*env)->GetStringUTFChars(env, strObj, nullptr);
|
||||
if (!native_str)
|
||||
return nullptr;
|
||||
result = _strdup(native_str);
|
||||
(*env)->ReleaseStringUTFChars(env, strObj, native_str);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
jstring jniNewStringUTF(JNIEnv* env, const char* in, int len)
|
||||
{
|
||||
jstring out = nullptr;
|
||||
jchar* unicode = nullptr;
|
||||
jint result_size = 0;
|
||||
unsigned char* utf8 = (unsigned char*)in;
|
||||
|
||||
if (!in)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
if (len < 0)
|
||||
len = strlen(in);
|
||||
|
||||
unicode = (jchar*)malloc(sizeof(jchar) * (len + 1));
|
||||
if (!unicode)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (jint i = 0; i < len; i++)
|
||||
{
|
||||
unsigned char one = utf8[i];
|
||||
switch (one >> 4)
|
||||
{
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
unicode[result_size++] = one;
|
||||
break;
|
||||
case 0x08:
|
||||
case 0x09:
|
||||
case 0x0a:
|
||||
case 0x0b:
|
||||
// case 0x0f:
|
||||
/*
|
||||
* Bit pattern 10xx or 1111, which are illegal start bytes.
|
||||
* Note: 1111 is valid for normal UTF-8, but not the
|
||||
* modified UTF-8 used here.
|
||||
*/
|
||||
break;
|
||||
case 0x0f:
|
||||
case 0x0e:
|
||||
// Bit pattern 111x, so there are two additional bytes.
|
||||
if (i < (len - 2))
|
||||
{
|
||||
unsigned char two = utf8[i + 1];
|
||||
unsigned char three = utf8[i + 2];
|
||||
if ((two & 0xc0) == 0x80 && (three & 0xc0) == 0x80)
|
||||
{
|
||||
i += 2;
|
||||
unicode[result_size++] =
|
||||
((one & 0x0f) << 12) | ((two & 0x3f) << 6) | (three & 0x3f);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x0c:
|
||||
case 0x0d:
|
||||
// Bit pattern 110x, so there is one additional byte.
|
||||
if (i < (len - 1))
|
||||
{
|
||||
unsigned char two = utf8[i + 1];
|
||||
if ((two & 0xc0) == 0x80)
|
||||
{
|
||||
i += 1;
|
||||
unicode[result_size++] = ((one & 0x1f) << 6) | (two & 0x3f);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out = (*env)->NewString(env, unicode, result_size);
|
||||
free(unicode);
|
||||
|
||||
return out;
|
||||
}
|
||||
36
third_party/FreeRDP/client/Android/Studio/freeRDPCore/src/main/cpp/android_jni_utils.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Android Event System
|
||||
*
|
||||
* Copyright 2013 Felix Long
|
||||
* Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
*
|
||||
* 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/.
|
||||
*/
|
||||
#ifndef FREERDP_CLIENT_ANDROID_JNI_UTILS_H
|
||||
#define FREERDP_CLIENT_ANDROID_JNI_UTILS_H
|
||||
|
||||
#include <jni.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
FREERDP_LOCAL JNIEnv* getJNIEnv();
|
||||
FREERDP_LOCAL JavaVM* getJavaVM();
|
||||
|
||||
FREERDP_LOCAL char* get_string_from_string_builder(JNIEnv* env, jobject strBuilder);
|
||||
FREERDP_LOCAL jobject create_string_builder(JNIEnv* env, char* initialStr);
|
||||
FREERDP_LOCAL jstring jniNewStringUTF(JNIEnv* env, const char* in, int len);
|
||||
|
||||
FREERDP_LOCAL extern JavaVM* g_JavaVm;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_CLIENT_ANDROID_JNI_UTILS_H */
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
Android Main Application
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.application;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import com.freerdp.freerdpcore.domain.BookmarkBase;
|
||||
import com.freerdp.freerdpcore.presentation.ApplicationSettingsActivity;
|
||||
import com.freerdp.freerdpcore.services.BookmarkDB;
|
||||
import com.freerdp.freerdpcore.services.HistoryDB;
|
||||
import com.freerdp.freerdpcore.services.LibFreeRDP;
|
||||
import com.freerdp.freerdpcore.services.ManualBookmarkGateway;
|
||||
import com.freerdp.freerdpcore.services.QuickConnectHistoryGateway;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class GlobalApp extends Application implements LibFreeRDP.EventListener
|
||||
{
|
||||
// event notification defines
|
||||
public static final String EVENT_TYPE = "EVENT_TYPE";
|
||||
public static final String EVENT_PARAM = "EVENT_PARAM";
|
||||
public static final String EVENT_STATUS = "EVENT_STATUS";
|
||||
public static final String EVENT_ERROR = "EVENT_ERROR";
|
||||
public static final String ACTION_EVENT_FREERDP = "com.freerdp.freerdp.event.freerdp";
|
||||
public static final int FREERDP_EVENT_CONNECTION_SUCCESS = 1;
|
||||
public static final int FREERDP_EVENT_CONNECTION_FAILURE = 2;
|
||||
public static final int FREERDP_EVENT_DISCONNECTED = 3;
|
||||
private static final String TAG = "GlobalApp";
|
||||
public static boolean ConnectedTo3G = false;
|
||||
private static Map<Long, SessionState> sessionMap;
|
||||
private static BookmarkDB bookmarkDB;
|
||||
private static ManualBookmarkGateway manualBookmarkGateway;
|
||||
|
||||
private static HistoryDB historyDB;
|
||||
private static QuickConnectHistoryGateway quickConnectHistoryGateway;
|
||||
|
||||
// timer for disconnecting sessions after the screen was turned off
|
||||
private static Timer disconnectTimer = null;
|
||||
|
||||
public static ManualBookmarkGateway getManualBookmarkGateway()
|
||||
{
|
||||
return manualBookmarkGateway;
|
||||
}
|
||||
|
||||
public static QuickConnectHistoryGateway getQuickConnectHistoryGateway()
|
||||
{
|
||||
return quickConnectHistoryGateway;
|
||||
}
|
||||
|
||||
// Disconnect handling for Screen on/off events
|
||||
public void startDisconnectTimer()
|
||||
{
|
||||
final int timeoutMinutes = ApplicationSettingsActivity.getDisconnectTimeout(this);
|
||||
if (timeoutMinutes > 0)
|
||||
{
|
||||
// start disconnect timeout...
|
||||
disconnectTimer = new Timer();
|
||||
disconnectTimer.schedule(new DisconnectTask(), (long)timeoutMinutes * 60 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
static public void cancelDisconnectTimer()
|
||||
{
|
||||
// cancel any pending timer events
|
||||
if (disconnectTimer != null)
|
||||
{
|
||||
disconnectTimer.cancel();
|
||||
disconnectTimer.purge();
|
||||
disconnectTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
// RDP session handling
|
||||
static public SessionState createSession(BookmarkBase bookmark, Context context)
|
||||
{
|
||||
SessionState session = new SessionState(LibFreeRDP.newInstance(context), bookmark);
|
||||
sessionMap.put(session.getInstance(), session);
|
||||
return session;
|
||||
}
|
||||
|
||||
static public SessionState createSession(Uri openUri, Context context)
|
||||
{
|
||||
SessionState session = new SessionState(LibFreeRDP.newInstance(context), openUri);
|
||||
sessionMap.put(session.getInstance(), session);
|
||||
return session;
|
||||
}
|
||||
|
||||
static public SessionState getSession(long instance)
|
||||
{
|
||||
return sessionMap.get(instance);
|
||||
}
|
||||
|
||||
static public Collection<SessionState> getSessions()
|
||||
{
|
||||
// return a copy of the session items
|
||||
return new ArrayList<>(sessionMap.values());
|
||||
}
|
||||
|
||||
static public void freeSession(long instance)
|
||||
{
|
||||
if (GlobalApp.sessionMap.containsKey(instance))
|
||||
{
|
||||
GlobalApp.sessionMap.remove(instance);
|
||||
LibFreeRDP.freeInstance(instance);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onCreate()
|
||||
{
|
||||
super.onCreate();
|
||||
|
||||
/* Initialize preferences. */
|
||||
ApplicationSettingsActivity.get(this);
|
||||
|
||||
sessionMap = Collections.synchronizedMap(new HashMap<Long, SessionState>());
|
||||
|
||||
LibFreeRDP.setEventListener(this);
|
||||
|
||||
bookmarkDB = new BookmarkDB(this);
|
||||
|
||||
manualBookmarkGateway = new ManualBookmarkGateway(bookmarkDB);
|
||||
|
||||
historyDB = new HistoryDB(this);
|
||||
quickConnectHistoryGateway = new QuickConnectHistoryGateway(historyDB);
|
||||
|
||||
ConnectedTo3G = NetworkStateReceiver.isConnectedTo3G(this);
|
||||
|
||||
// init screen receiver here (this can't be declared in AndroidManifest - refer to:
|
||||
// http://thinkandroid.wordpress.com/2010/01/24/handling-screen-off-and-screen-on-intents/
|
||||
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
|
||||
filter.addAction(Intent.ACTION_SCREEN_OFF);
|
||||
registerReceiver(new ScreenReceiver(), filter, RECEIVER_EXPORTED);
|
||||
}
|
||||
|
||||
// helper to send FreeRDP notifications
|
||||
private void sendRDPNotification(int type, long param)
|
||||
{
|
||||
// send broadcast
|
||||
Intent intent = new Intent(ACTION_EVENT_FREERDP);
|
||||
intent.putExtra(EVENT_TYPE, type);
|
||||
intent.putExtra(EVENT_PARAM, param);
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
|
||||
@Override public void OnPreConnect(long instance)
|
||||
{
|
||||
Log.v(TAG, "OnPreConnect");
|
||||
}
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// Implementation of LibFreeRDP.EventListener
|
||||
public void OnConnectionSuccess(long instance)
|
||||
{
|
||||
Log.v(TAG, "OnConnectionSuccess");
|
||||
sendRDPNotification(FREERDP_EVENT_CONNECTION_SUCCESS, instance);
|
||||
}
|
||||
|
||||
public void OnConnectionFailure(long instance)
|
||||
{
|
||||
Log.v(TAG, "OnConnectionFailure");
|
||||
|
||||
// send notification to session activity
|
||||
sendRDPNotification(FREERDP_EVENT_CONNECTION_FAILURE, instance);
|
||||
}
|
||||
|
||||
public void OnDisconnecting(long instance)
|
||||
{
|
||||
Log.v(TAG, "OnDisconnecting");
|
||||
}
|
||||
|
||||
public void OnDisconnected(long instance)
|
||||
{
|
||||
Log.v(TAG, "OnDisconnected");
|
||||
sendRDPNotification(FREERDP_EVENT_DISCONNECTED, instance);
|
||||
}
|
||||
|
||||
// TimerTask for disconnecting sessions after screen was turned off
|
||||
private static class DisconnectTask extends TimerTask
|
||||
{
|
||||
@Override public void run()
|
||||
{
|
||||
Log.v("DisconnectTask", "Doing action");
|
||||
|
||||
// disconnect any running rdp session
|
||||
Collection<SessionState> sessions = GlobalApp.getSessions();
|
||||
for (SessionState session : sessions)
|
||||
{
|
||||
LibFreeRDP.disconnect(session.getInstance());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Network State Receiver
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.application;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class NetworkStateReceiver extends BroadcastReceiver
|
||||
{
|
||||
|
||||
public static boolean isConnectedTo3G(Context context)
|
||||
{
|
||||
ConnectivityManager connectivity =
|
||||
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo info = connectivity.getActiveNetworkInfo();
|
||||
|
||||
// no connection or background data disabled
|
||||
if (info == null || !info.isConnected())
|
||||
return false;
|
||||
|
||||
return (info.getType() != ConnectivityManager.TYPE_WIFI &&
|
||||
info.getType() != ConnectivityManager.TYPE_WIMAX);
|
||||
}
|
||||
|
||||
@Override public void onReceive(@NonNull Context context, @NonNull Intent intent)
|
||||
{
|
||||
String action = intent.getAction();
|
||||
if (!action.equals("android.net.conn.CONNECTIVITY_CHANGE"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// check if we are connected via 3g or wlan
|
||||
if (intent.getExtras() != null)
|
||||
{
|
||||
NetworkInfo info =
|
||||
(NetworkInfo)intent.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);
|
||||
|
||||
// are we connected at all?
|
||||
if (info != null)
|
||||
{
|
||||
if (info.isConnected())
|
||||
{
|
||||
// see if we are connected through 3G or WiFi
|
||||
Log.d("app", "Connected via type " + info.getTypeName());
|
||||
GlobalApp.ConnectedTo3G = (info.getType() != ConnectivityManager.TYPE_WIFI &&
|
||||
info.getType() != ConnectivityManager.TYPE_WIMAX);
|
||||
}
|
||||
|
||||
Log.v("NetworkState", info.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Helper class to receive notifications when the screen is turned on/off
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.application;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
public class ScreenReceiver extends BroadcastReceiver
|
||||
{
|
||||
|
||||
@Override public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
GlobalApp app = (GlobalApp)context.getApplicationContext();
|
||||
Log.v("ScreenReceiver", "Received action: " + intent.getAction());
|
||||
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF))
|
||||
app.startDisconnectTimer();
|
||||
else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON))
|
||||
GlobalApp.cancelDisconnectTimer();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
Session State class
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.application;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.freerdp.freerdpcore.domain.BookmarkBase;
|
||||
import com.freerdp.freerdpcore.services.LibFreeRDP;
|
||||
|
||||
public class SessionState implements Parcelable
|
||||
{
|
||||
public static final Parcelable.Creator<SessionState> CREATOR =
|
||||
new Parcelable.Creator<SessionState>() {
|
||||
public SessionState createFromParcel(Parcel in)
|
||||
{
|
||||
return new SessionState(in);
|
||||
}
|
||||
|
||||
@Override public SessionState[] newArray(int size)
|
||||
{
|
||||
return new SessionState[size];
|
||||
}
|
||||
};
|
||||
private final long instance;
|
||||
private final BookmarkBase bookmark;
|
||||
private final Uri openUri;
|
||||
private BitmapDrawable surface;
|
||||
private LibFreeRDP.UIEventListener uiEventListener;
|
||||
|
||||
public SessionState(Parcel parcel)
|
||||
{
|
||||
instance = parcel.readLong();
|
||||
bookmark = parcel.readParcelable(null);
|
||||
openUri = parcel.readParcelable(null);
|
||||
|
||||
Bitmap bitmap = parcel.readParcelable(null);
|
||||
surface = new BitmapDrawable(bitmap);
|
||||
}
|
||||
|
||||
public SessionState(long instance, BookmarkBase bookmark)
|
||||
{
|
||||
this.instance = instance;
|
||||
this.bookmark = bookmark;
|
||||
this.openUri = null;
|
||||
this.uiEventListener = null;
|
||||
}
|
||||
|
||||
public SessionState(long instance, Uri openUri)
|
||||
{
|
||||
this.instance = instance;
|
||||
this.bookmark = null;
|
||||
this.openUri = openUri;
|
||||
this.uiEventListener = null;
|
||||
}
|
||||
|
||||
public void connect(Context context)
|
||||
{
|
||||
if (bookmark != null)
|
||||
{
|
||||
LibFreeRDP.setConnectionInfo(context, instance, bookmark);
|
||||
}
|
||||
else
|
||||
{
|
||||
LibFreeRDP.setConnectionInfo(context, instance, openUri);
|
||||
}
|
||||
LibFreeRDP.connect(instance);
|
||||
}
|
||||
|
||||
public long getInstance()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
public BookmarkBase getBookmark()
|
||||
{
|
||||
return bookmark;
|
||||
}
|
||||
|
||||
public Uri getOpenUri()
|
||||
{
|
||||
return openUri;
|
||||
}
|
||||
|
||||
public LibFreeRDP.UIEventListener getUIEventListener()
|
||||
{
|
||||
return uiEventListener;
|
||||
}
|
||||
|
||||
public void setUIEventListener(LibFreeRDP.UIEventListener uiEventListener)
|
||||
{
|
||||
this.uiEventListener = uiEventListener;
|
||||
}
|
||||
|
||||
public BitmapDrawable getSurface()
|
||||
{
|
||||
return surface;
|
||||
}
|
||||
|
||||
public void setSurface(BitmapDrawable surface)
|
||||
{
|
||||
this.surface = surface;
|
||||
}
|
||||
|
||||
@Override public int describeContents()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override public void writeToParcel(Parcel out, int flags)
|
||||
{
|
||||
out.writeLong(instance);
|
||||
out.writeParcelable(bookmark, flags);
|
||||
out.writeParcelable(openUri, flags);
|
||||
out.writeParcelable(surface.getBitmap(), flags);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
A RDP connection reference. References can use bookmark ids or hostnames to connect to a RDP
|
||||
server.
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.domain;
|
||||
|
||||
public class ConnectionReference
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
public static String getHostnameReference(String hostname)
|
||||
{
|
||||
return (PATH_HOSTNAME + hostname);
|
||||
}
|
||||
|
||||
public static String getPlaceholderReference(String name)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
public static boolean isManualBookmarkReference(String refStr)
|
||||
{
|
||||
return refStr.startsWith(PATH_MANUAL_BOOKMARK_ID);
|
||||
}
|
||||
|
||||
public static boolean isHostnameReference(String refStr)
|
||||
{
|
||||
return refStr.startsWith(PATH_HOSTNAME);
|
||||
}
|
||||
|
||||
public static boolean isPlaceholderReference(String refStr)
|
||||
{
|
||||
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 getHostname(String refStr)
|
||||
{
|
||||
return refStr.substring(PATH_HOSTNAME.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());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
Manual Bookmark implementation
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.domain;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class ManualBookmark extends BookmarkBase
|
||||
{
|
||||
public static final Parcelable.Creator<ManualBookmark> CREATOR =
|
||||
new Parcelable.Creator<ManualBookmark>() {
|
||||
public ManualBookmark createFromParcel(Parcel in)
|
||||
{
|
||||
return new ManualBookmark(in);
|
||||
}
|
||||
|
||||
@Override public ManualBookmark[] newArray(int size)
|
||||
{
|
||||
return new ManualBookmark[size];
|
||||
}
|
||||
};
|
||||
private String hostname;
|
||||
private int port;
|
||||
private boolean enableGatewaySettings;
|
||||
private GatewaySettings gatewaySettings;
|
||||
|
||||
public ManualBookmark(Parcel parcel)
|
||||
{
|
||||
super(parcel);
|
||||
type = TYPE_MANUAL;
|
||||
hostname = parcel.readString();
|
||||
port = parcel.readInt();
|
||||
|
||||
enableGatewaySettings = (parcel.readInt() == 1);
|
||||
gatewaySettings = parcel.readParcelable(GatewaySettings.class.getClassLoader());
|
||||
}
|
||||
|
||||
public ManualBookmark()
|
||||
{
|
||||
super();
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
type = TYPE_MANUAL;
|
||||
hostname = "";
|
||||
port = 3389;
|
||||
enableGatewaySettings = false;
|
||||
gatewaySettings = new GatewaySettings();
|
||||
}
|
||||
|
||||
public String getHostname()
|
||||
{
|
||||
return hostname;
|
||||
}
|
||||
|
||||
public void setHostname(String hostname)
|
||||
{
|
||||
this.hostname = hostname;
|
||||
}
|
||||
|
||||
public int getPort()
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port)
|
||||
{
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public boolean getEnableGatewaySettings()
|
||||
{
|
||||
return enableGatewaySettings;
|
||||
}
|
||||
|
||||
public void setEnableGatewaySettings(boolean enableGatewaySettings)
|
||||
{
|
||||
this.enableGatewaySettings = enableGatewaySettings;
|
||||
}
|
||||
|
||||
public GatewaySettings getGatewaySettings()
|
||||
{
|
||||
return gatewaySettings;
|
||||
}
|
||||
|
||||
public void setGatewaySettings(GatewaySettings gatewaySettings)
|
||||
{
|
||||
this.gatewaySettings = gatewaySettings;
|
||||
}
|
||||
|
||||
@Override public int describeContents()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override public void writeToParcel(Parcel out, int flags)
|
||||
{
|
||||
super.writeToParcel(out, flags);
|
||||
out.writeString(hostname);
|
||||
out.writeInt(port);
|
||||
out.writeInt(enableGatewaySettings ? 1 : 0);
|
||||
out.writeParcelable(gatewaySettings, flags);
|
||||
}
|
||||
|
||||
@Override public void writeToSharedPreferences(SharedPreferences sharedPrefs)
|
||||
{
|
||||
super.writeToSharedPreferences(sharedPrefs);
|
||||
|
||||
SharedPreferences.Editor editor = sharedPrefs.edit();
|
||||
editor.putString("bookmark.hostname", hostname);
|
||||
editor.putInt("bookmark.port", port);
|
||||
editor.putBoolean("bookmark.enable_gateway_settings", enableGatewaySettings);
|
||||
editor.putString("bookmark.gateway_hostname", gatewaySettings.getHostname());
|
||||
editor.putInt("bookmark.gateway_port", gatewaySettings.getPort());
|
||||
editor.putString("bookmark.gateway_username", gatewaySettings.getUsername());
|
||||
editor.putString("bookmark.gateway_password", gatewaySettings.getPassword());
|
||||
editor.putString("bookmark.gateway_domain", gatewaySettings.getDomain());
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
@Override public void readFromSharedPreferences(SharedPreferences sharedPrefs)
|
||||
{
|
||||
super.readFromSharedPreferences(sharedPrefs);
|
||||
|
||||
hostname = sharedPrefs.getString("bookmark.hostname", "");
|
||||
port = sharedPrefs.getInt("bookmark.port", 3389);
|
||||
enableGatewaySettings = sharedPrefs.getBoolean("bookmark.enable_gateway_settings", false);
|
||||
gatewaySettings.setHostname(sharedPrefs.getString("bookmark.gateway_hostname", ""));
|
||||
gatewaySettings.setPort(sharedPrefs.getInt("bookmark.gateway_port", 443));
|
||||
gatewaySettings.setUsername(sharedPrefs.getString("bookmark.gateway_username", ""));
|
||||
gatewaySettings.setPassword(sharedPrefs.getString("bookmark.gateway_password", ""));
|
||||
gatewaySettings.setDomain(sharedPrefs.getString("bookmark.gateway_domain", ""));
|
||||
}
|
||||
|
||||
// Cloneable
|
||||
public Object clone()
|
||||
{
|
||||
return super.clone();
|
||||
}
|
||||
|
||||
// Gateway Settings class
|
||||
public static class GatewaySettings implements Parcelable
|
||||
{
|
||||
public static final Parcelable.Creator<GatewaySettings> CREATOR =
|
||||
new Parcelable.Creator<GatewaySettings>() {
|
||||
public GatewaySettings createFromParcel(Parcel in)
|
||||
{
|
||||
return new GatewaySettings(in);
|
||||
}
|
||||
|
||||
@Override public GatewaySettings[] newArray(int size)
|
||||
{
|
||||
return new GatewaySettings[size];
|
||||
}
|
||||
};
|
||||
private String hostname;
|
||||
private int port;
|
||||
private String username;
|
||||
private String password;
|
||||
private String domain;
|
||||
|
||||
public GatewaySettings()
|
||||
{
|
||||
hostname = "";
|
||||
port = 443;
|
||||
username = "";
|
||||
password = "";
|
||||
domain = "";
|
||||
}
|
||||
|
||||
public GatewaySettings(Parcel parcel)
|
||||
{
|
||||
hostname = parcel.readString();
|
||||
port = parcel.readInt();
|
||||
username = parcel.readString();
|
||||
password = parcel.readString();
|
||||
domain = parcel.readString();
|
||||
}
|
||||
|
||||
public String getHostname()
|
||||
{
|
||||
return hostname;
|
||||
}
|
||||
|
||||
public void setHostname(String hostname)
|
||||
{
|
||||
this.hostname = hostname;
|
||||
}
|
||||
|
||||
public int getPort()
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port)
|
||||
{
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getUsername()
|
||||
{
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username)
|
||||
{
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword()
|
||||
{
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password)
|
||||
{
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getDomain()
|
||||
{
|
||||
return domain;
|
||||
}
|
||||
|
||||
public void setDomain(String domain)
|
||||
{
|
||||
this.domain = domain;
|
||||
}
|
||||
|
||||
@Override public int describeContents()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override public void writeToParcel(Parcel out, int flags)
|
||||
{
|
||||
out.writeString(hostname);
|
||||
out.writeInt(port);
|
||||
out.writeString(username);
|
||||
out.writeString(password);
|
||||
out.writeString(domain);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
Placeholder for bookmark items with a special purpose (i.e. just displaying some text)
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.domain;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class PlaceholderBookmark extends BookmarkBase
|
||||
{
|
||||
|
||||
public static final Parcelable.Creator<PlaceholderBookmark> CREATOR =
|
||||
new Parcelable.Creator<PlaceholderBookmark>() {
|
||||
public PlaceholderBookmark createFromParcel(Parcel in)
|
||||
{
|
||||
return new PlaceholderBookmark(in);
|
||||
}
|
||||
|
||||
@Override public PlaceholderBookmark[] newArray(int size)
|
||||
{
|
||||
return new PlaceholderBookmark[size];
|
||||
}
|
||||
};
|
||||
private String name;
|
||||
|
||||
public PlaceholderBookmark(Parcel parcel)
|
||||
{
|
||||
super(parcel);
|
||||
type = TYPE_PLACEHOLDER;
|
||||
name = parcel.readString();
|
||||
}
|
||||
|
||||
public PlaceholderBookmark()
|
||||
{
|
||||
super();
|
||||
type = TYPE_PLACEHOLDER;
|
||||
name = "";
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override public int describeContents()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override public void writeToParcel(Parcel out, int flags)
|
||||
{
|
||||
super.writeToParcel(out, flags);
|
||||
out.writeString(name);
|
||||
}
|
||||
|
||||
@Override public void writeToSharedPreferences(SharedPreferences sharedPrefs)
|
||||
{
|
||||
super.writeToSharedPreferences(sharedPrefs);
|
||||
}
|
||||
|
||||
@Override public void readFromSharedPreferences(SharedPreferences sharedPrefs)
|
||||
{
|
||||
super.readFromSharedPreferences(sharedPrefs);
|
||||
}
|
||||
|
||||
// Cloneable
|
||||
public Object clone()
|
||||
{
|
||||
return super.clone();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
Quick Connect bookmark (used for quick connects using just a hostname)
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.domain;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class QuickConnectBookmark extends ManualBookmark
|
||||
{
|
||||
|
||||
public static final Parcelable.Creator<QuickConnectBookmark> CREATOR =
|
||||
new Parcelable.Creator<QuickConnectBookmark>() {
|
||||
public QuickConnectBookmark createFromParcel(Parcel in)
|
||||
{
|
||||
return new QuickConnectBookmark(in);
|
||||
}
|
||||
|
||||
@Override public QuickConnectBookmark[] newArray(int size)
|
||||
{
|
||||
return new QuickConnectBookmark[size];
|
||||
}
|
||||
};
|
||||
|
||||
public QuickConnectBookmark(Parcel parcel)
|
||||
{
|
||||
super(parcel);
|
||||
type = TYPE_QUICKCONNECT;
|
||||
}
|
||||
|
||||
public QuickConnectBookmark()
|
||||
{
|
||||
super();
|
||||
type = TYPE_QUICKCONNECT;
|
||||
}
|
||||
|
||||
@Override public int describeContents()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override public void writeToParcel(Parcel out, int flags)
|
||||
{
|
||||
super.writeToParcel(out, flags);
|
||||
}
|
||||
|
||||
@Override public void writeToSharedPreferences(SharedPreferences sharedPrefs)
|
||||
{
|
||||
super.writeToSharedPreferences(sharedPrefs);
|
||||
}
|
||||
|
||||
@Override public void readFromSharedPreferences(SharedPreferences sharedPrefs)
|
||||
{
|
||||
super.readFromSharedPreferences(sharedPrefs);
|
||||
}
|
||||
|
||||
// Cloneable
|
||||
public Object clone()
|
||||
{
|
||||
return super.clone();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package com.freerdp.freerdpcore.presentation;
|
||||
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.nfc.FormatException;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import androidx.core.text.TextUtilsCompat;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import com.freerdp.freerdpcore.R;
|
||||
import com.freerdp.freerdpcore.services.LibFreeRDP;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Formatter;
|
||||
import java.util.IllegalFormatException;
|
||||
import java.util.Locale;
|
||||
|
||||
public class AboutActivity extends AppCompatActivity
|
||||
{
|
||||
private static final String TAG = AboutActivity.class.toString();
|
||||
private WebView mWebView;
|
||||
|
||||
@Override protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_about);
|
||||
mWebView = findViewById(R.id.activity_about_webview);
|
||||
}
|
||||
|
||||
@Override protected void onResume()
|
||||
{
|
||||
populate();
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
private void populate()
|
||||
{
|
||||
StringBuilder total = new StringBuilder();
|
||||
|
||||
String filename = "about_phone.html";
|
||||
if ((getResources().getConfiguration().screenLayout &
|
||||
Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE)
|
||||
{
|
||||
filename = "about.html";
|
||||
}
|
||||
Locale def = Locale.getDefault();
|
||||
String prefix = def.getLanguage().toLowerCase(def);
|
||||
|
||||
String dir = prefix + "_about_page/";
|
||||
String file = dir + filename;
|
||||
InputStream is;
|
||||
try
|
||||
{
|
||||
is = getAssets().open(file);
|
||||
is.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Log.e(TAG, "Missing localized asset " + file, e);
|
||||
dir = "about_page/";
|
||||
file = dir + filename;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try (BufferedReader r =
|
||||
new BufferedReader(new InputStreamReader(getAssets().open(file))))
|
||||
{
|
||||
String line;
|
||||
while ((line = r.readLine()) != null)
|
||||
{
|
||||
total.append(line);
|
||||
total.append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Log.e(TAG, "Could not read about page " + file, e);
|
||||
}
|
||||
|
||||
// append FreeRDP core version to app version
|
||||
// get app version
|
||||
String version;
|
||||
try
|
||||
{
|
||||
version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
|
||||
}
|
||||
catch (PackageManager.NameNotFoundException e)
|
||||
{
|
||||
version = "unknown";
|
||||
}
|
||||
version = version + " (" + LibFreeRDP.getVersion() + ")";
|
||||
|
||||
WebSettings settings = mWebView.getSettings();
|
||||
settings.setDomStorageEnabled(true);
|
||||
settings.setUseWideViewPort(true);
|
||||
settings.setLoadWithOverviewMode(true);
|
||||
settings.setSupportZoom(true);
|
||||
|
||||
final String base = "file:///android_asset/" + dir;
|
||||
|
||||
final String rawHtml = total.toString();
|
||||
final String html = rawHtml.replaceAll("%AFREERDP_VERSION%", version)
|
||||
.replaceAll("%SYSTEM_VERSION%", Build.VERSION.RELEASE)
|
||||
.replaceAll("%DEVICE_MODEL%", Build.MODEL);
|
||||
|
||||
mWebView.loadDataWithBaseURL(base, html, "text/html", null, "about:blank");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
Application Settings Activity
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.presentation;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.preference.PreferenceScreen;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.freerdp.freerdpcore.R;
|
||||
import com.freerdp.freerdpcore.utils.AppCompatPreferenceActivity;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ApplicationSettingsActivity extends AppCompatPreferenceActivity
|
||||
{
|
||||
private static boolean isXLargeTablet(Context context)
|
||||
{
|
||||
return (context.getResources().getConfiguration().screenLayout &
|
||||
Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
|
||||
}
|
||||
|
||||
@Override protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setupActionBar();
|
||||
}
|
||||
|
||||
private void setupActionBar()
|
||||
{
|
||||
android.app.ActionBar actionBar = getActionBar();
|
||||
if (actionBar != null)
|
||||
{
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean onIsMultiPane()
|
||||
{
|
||||
return isXLargeTablet(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public void onBuildHeaders(List<Header> target)
|
||||
{
|
||||
loadHeadersFromResource(R.xml.settings_app_headers, target);
|
||||
}
|
||||
|
||||
protected boolean isValidFragment(String fragmentName)
|
||||
{
|
||||
return PreferenceFragment.class.getName().equals(fragmentName) ||
|
||||
ClientPreferenceFragment.class.getName().equals(fragmentName) ||
|
||||
UiPreferenceFragment.class.getName().equals(fragmentName) ||
|
||||
PowerPreferenceFragment.class.getName().equals(fragmentName) ||
|
||||
SecurityPreferenceFragment.class.getName().equals(fragmentName);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public static class ClientPreferenceFragment
|
||||
extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener
|
||||
{
|
||||
@Override public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.settings_app_client);
|
||||
SharedPreferences preferences = get(getActivity());
|
||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
|
||||
{
|
||||
if (isAdded())
|
||||
{
|
||||
final String clientNameKey = getString(R.string.preference_key_client_name);
|
||||
|
||||
get(getActivity());
|
||||
if (key.equals(clientNameKey))
|
||||
{
|
||||
final String clientNameValue = sharedPreferences.getString(clientNameKey, "");
|
||||
EditTextPreference pref = (EditTextPreference)findPreference(clientNameKey);
|
||||
pref.setText(clientNameValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public static class UiPreferenceFragment extends PreferenceFragment
|
||||
{
|
||||
@Override public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.settings_app_ui);
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public static class PowerPreferenceFragment extends PreferenceFragment
|
||||
{
|
||||
@Override public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.settings_app_power);
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public static class SecurityPreferenceFragment extends PreferenceFragment
|
||||
{
|
||||
@Override public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.settings_app_security);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
|
||||
Preference preference)
|
||||
{
|
||||
final String clear =
|
||||
getString(R.string.preference_key_security_clear_certificate_cache);
|
||||
if (preference.getKey().equals(clear))
|
||||
{
|
||||
showDialog();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return super.onPreferenceTreeClick(preferenceScreen, preference);
|
||||
}
|
||||
}
|
||||
|
||||
private void showDialog()
|
||||
{
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.dlg_title_clear_cert_cache)
|
||||
.setMessage(R.string.dlg_msg_clear_cert_cache)
|
||||
.setPositiveButton(android.R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
clearCertificateCache();
|
||||
dialog.dismiss();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
dialog.dismiss();
|
||||
}
|
||||
})
|
||||
.setIcon(android.R.drawable.ic_delete)
|
||||
.show();
|
||||
}
|
||||
|
||||
private boolean deleteDirectory(File dir)
|
||||
{
|
||||
if (dir.isDirectory())
|
||||
{
|
||||
String[] children = dir.list();
|
||||
for (String file : children)
|
||||
{
|
||||
if (!deleteDirectory(new File(dir, file)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return dir.delete();
|
||||
}
|
||||
|
||||
private void clearCertificateCache()
|
||||
{
|
||||
Context context = getActivity();
|
||||
if ((new File(context.getFilesDir() + "/.freerdp")).exists())
|
||||
{
|
||||
if (deleteDirectory(new File(context.getFilesDir() + "/.freerdp")))
|
||||
Toast.makeText(context, R.string.info_reset_success, Toast.LENGTH_LONG).show();
|
||||
else
|
||||
Toast.makeText(context, R.string.info_reset_failed, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
else
|
||||
Toast.makeText(context, R.string.info_reset_success, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
public static SharedPreferences get(Context context)
|
||||
{
|
||||
Context appContext = context.getApplicationContext();
|
||||
PreferenceManager.setDefaultValues(appContext, R.xml.settings_app_client, false);
|
||||
PreferenceManager.setDefaultValues(appContext, R.xml.settings_app_power, false);
|
||||
PreferenceManager.setDefaultValues(appContext, R.xml.settings_app_security, false);
|
||||
PreferenceManager.setDefaultValues(appContext, R.xml.settings_app_ui, false);
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(appContext);
|
||||
|
||||
final String key = context.getString(R.string.preference_key_client_name);
|
||||
final String value = preferences.getString(key, "");
|
||||
if (value.isEmpty())
|
||||
{
|
||||
final String android_id = UUID.randomUUID().toString();
|
||||
final String defaultValue = context.getString(R.string.preference_default_client_name);
|
||||
final String name = defaultValue + "-" + android_id;
|
||||
preferences.edit().putString(key, name.substring(0, 31)).apply();
|
||||
}
|
||||
|
||||
return preferences;
|
||||
}
|
||||
|
||||
public static int getDisconnectTimeout(Context context)
|
||||
{
|
||||
SharedPreferences preferences = get(context);
|
||||
return preferences.getInt(
|
||||
context.getString(R.string.preference_key_power_disconnect_timeout), 0);
|
||||
}
|
||||
|
||||
public static boolean getHideStatusBar(Context context)
|
||||
{
|
||||
SharedPreferences preferences = get(context);
|
||||
return preferences.getBoolean(context.getString(R.string.preference_key_ui_hide_status_bar),
|
||||
false);
|
||||
}
|
||||
|
||||
public static boolean getHideActionBar(Context context)
|
||||
{
|
||||
SharedPreferences preferences = get(context);
|
||||
return preferences.getBoolean(context.getString(R.string.preference_key_ui_hide_action_bar),
|
||||
false);
|
||||
}
|
||||
|
||||
public static boolean getUseBackAsAltf4(Context context)
|
||||
{
|
||||
SharedPreferences preferences = get(context);
|
||||
return preferences.getBoolean(
|
||||
context.getString(R.string.preference_key_ui_use_back_as_altf4), true);
|
||||
}
|
||||
|
||||
public static boolean getAcceptAllCertificates(Context context)
|
||||
{
|
||||
SharedPreferences preferences = get(context);
|
||||
return preferences.getBoolean(
|
||||
context.getString(R.string.preference_key_accept_certificates), false);
|
||||
}
|
||||
|
||||
public static boolean getHideZoomControls(Context context)
|
||||
{
|
||||
SharedPreferences preferences = get(context);
|
||||
return preferences.getBoolean(
|
||||
context.getString(R.string.preference_key_ui_hide_zoom_controls), false);
|
||||
}
|
||||
|
||||
public static boolean getSwapMouseButtons(Context context)
|
||||
{
|
||||
SharedPreferences preferences = get(context);
|
||||
return preferences.getBoolean(
|
||||
context.getString(R.string.preference_key_ui_swap_mouse_buttons), false);
|
||||
}
|
||||
|
||||
public static boolean getInvertScrolling(Context context)
|
||||
{
|
||||
SharedPreferences preferences = get(context);
|
||||
return preferences.getBoolean(
|
||||
context.getString(R.string.preference_key_ui_invert_scrolling), true);
|
||||
}
|
||||
|
||||
public static boolean getAskOnExit(Context context)
|
||||
{
|
||||
SharedPreferences preferences = get(context);
|
||||
return preferences.getBoolean(context.getString(R.string.preference_key_ui_ask_on_exit),
|
||||
false);
|
||||
}
|
||||
|
||||
public static boolean getAutoScrollTouchPointer(Context context)
|
||||
{
|
||||
SharedPreferences preferences = get(context);
|
||||
return preferences.getBoolean(
|
||||
context.getString(R.string.preference_key_ui_auto_scroll_touchpointer), false);
|
||||
}
|
||||
|
||||
public static String getClientName(Context context)
|
||||
{
|
||||
SharedPreferences preferences = get(context);
|
||||
return preferences.getString(context.getString(R.string.preference_key_client_name), "");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,732 @@
|
||||
/*
|
||||
Bookmark editing activity
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.presentation;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.ComponentName;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.os.Bundle;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
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.services.LibFreeRDP;
|
||||
import com.freerdp.freerdpcore.utils.RDPFileParser;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class BookmarkActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener
|
||||
{
|
||||
public static final String PARAM_CONNECTION_REFERENCE = "conRef";
|
||||
|
||||
private static final String TAG = "BookmarkActivity";
|
||||
private static final int PREFERENCES_BOOKMARK = 1;
|
||||
private static final int PREFERENCES_CREDENTIALS = 2;
|
||||
private static final int PREFERENCES_SCREEN = 3;
|
||||
private static final int PREFERENCES_PERFORMANCE = 4;
|
||||
private static final int PREFERENCES_ADVANCED = 5;
|
||||
private static final int PREFERENCES_SCREEN3G = 6;
|
||||
private static final int PREFERENCES_PERFORMANCE3G = 7;
|
||||
private static final int PREFERENCES_GATEWAY = 8;
|
||||
private static final int PREFERENCES_DEBUG = 9;
|
||||
// bookmark needs to be static because the activity is started for each
|
||||
// subview
|
||||
// (we have to do this because Android has a bug where the style for
|
||||
// Preferences
|
||||
// is only applied to the first PreferenceScreen but not to subsequent ones)
|
||||
private static BookmarkBase bookmark = null;
|
||||
private static boolean settings_changed = false;
|
||||
private static boolean new_bookmark = false;
|
||||
private int current_preferences;
|
||||
|
||||
@Override public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
PreferenceManager mgr = getPreferenceManager();
|
||||
// init shared preferences for activity
|
||||
mgr.setSharedPreferencesName("TEMP");
|
||||
mgr.setSharedPreferencesMode(MODE_PRIVATE);
|
||||
|
||||
if (bookmark == null)
|
||||
{
|
||||
// if we have a bookmark id set in the extras we are in edit mode
|
||||
Bundle bundle = getIntent().getExtras();
|
||||
if (bundle != null)
|
||||
{
|
||||
// See if we got a connection reference to a bookmark
|
||||
if (bundle.containsKey(PARAM_CONNECTION_REFERENCE))
|
||||
{
|
||||
String refStr = bundle.getString(PARAM_CONNECTION_REFERENCE);
|
||||
if (ConnectionReference.isManualBookmarkReference(refStr))
|
||||
{
|
||||
bookmark = GlobalApp.getManualBookmarkGateway().findById(
|
||||
ConnectionReference.getManualBookmarkId(refStr));
|
||||
new_bookmark = false;
|
||||
}
|
||||
else if (ConnectionReference.isHostnameReference(refStr))
|
||||
{
|
||||
bookmark = new ManualBookmark();
|
||||
bookmark.<ManualBookmark>get().setLabel(
|
||||
ConnectionReference.getHostname(refStr));
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// last chance - ensure we really have a valid bookmark
|
||||
if (bookmark == null)
|
||||
bookmark = new ManualBookmark();
|
||||
|
||||
// hide gateway settings if we edit a non-manual bookmark
|
||||
if (current_preferences == PREFERENCES_ADVANCED &&
|
||||
bookmark.getType() != ManualBookmark.TYPE_MANUAL)
|
||||
{
|
||||
PreferenceScreen screen = getPreferenceScreen();
|
||||
screen.removePreference(findPreference("bookmark.enable_gateway"));
|
||||
screen.removePreference(findPreference("bookmark.gateway"));
|
||||
}
|
||||
|
||||
updateH264Preferences();
|
||||
|
||||
// update preferences from bookmark
|
||||
bookmark.writeToSharedPreferences(mgr.getSharedPreferences());
|
||||
|
||||
// no settings changed yet
|
||||
settings_changed = false;
|
||||
}
|
||||
|
||||
// load the requested settings resource
|
||||
if (getIntent() == null || getIntent().getData() == null)
|
||||
{
|
||||
addPreferencesFromResource(R.xml.bookmark_settings);
|
||||
current_preferences = PREFERENCES_BOOKMARK;
|
||||
}
|
||||
else if (getIntent().getData().toString().equals("preferences://screen_settings"))
|
||||
{
|
||||
addPreferencesFromResource(R.xml.screen_settings);
|
||||
current_preferences = PREFERENCES_SCREEN;
|
||||
}
|
||||
else if (getIntent().getData().toString().equals("preferences://performance_flags"))
|
||||
{
|
||||
addPreferencesFromResource(R.xml.performance_flags);
|
||||
current_preferences = PREFERENCES_PERFORMANCE;
|
||||
}
|
||||
else if (getIntent().getData().toString().equals("preferences://screen_settings_3g"))
|
||||
{
|
||||
addPreferencesFromResource(R.xml.screen_settings_3g);
|
||||
current_preferences = PREFERENCES_SCREEN3G;
|
||||
}
|
||||
else if (getIntent().getData().toString().equals("preferences://performance_flags_3g"))
|
||||
{
|
||||
addPreferencesFromResource(R.xml.performance_flags_3g);
|
||||
current_preferences = PREFERENCES_PERFORMANCE3G;
|
||||
}
|
||||
else if (getIntent().getData().toString().equals("preferences://advanced_settings"))
|
||||
{
|
||||
addPreferencesFromResource(R.xml.advanced_settings);
|
||||
current_preferences = PREFERENCES_ADVANCED;
|
||||
}
|
||||
else if (getIntent().getData().toString().equals("preferences://credentials_settings"))
|
||||
{
|
||||
addPreferencesFromResource(R.xml.credentials_settings);
|
||||
current_preferences = PREFERENCES_CREDENTIALS;
|
||||
}
|
||||
else if (getIntent().getData().toString().equals("preferences://gateway_settings"))
|
||||
{
|
||||
addPreferencesFromResource(R.xml.gateway_settings);
|
||||
current_preferences = PREFERENCES_GATEWAY;
|
||||
}
|
||||
else if (getIntent().getData().toString().equals("preferences://debug_settings"))
|
||||
{
|
||||
addPreferencesFromResource(R.xml.debug_settings);
|
||||
current_preferences = PREFERENCES_DEBUG;
|
||||
}
|
||||
else
|
||||
{
|
||||
addPreferencesFromResource(R.xml.bookmark_settings);
|
||||
current_preferences = PREFERENCES_BOOKMARK;
|
||||
}
|
||||
|
||||
// update UI with bookmark data
|
||||
SharedPreferences spref = mgr.getSharedPreferences();
|
||||
initSettings(spref);
|
||||
|
||||
// register for preferences changed notification
|
||||
mgr.getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
// set the correct component names in our preferencescreen settings
|
||||
setIntentComponentNames();
|
||||
|
||||
updateH264Preferences();
|
||||
}
|
||||
|
||||
private void updateH264Preferences()
|
||||
{
|
||||
if (!LibFreeRDP.hasH264Support())
|
||||
{
|
||||
final int[] preferenceIdList = { R.string.preference_key_h264,
|
||||
R.string.preference_key_h264_3g };
|
||||
|
||||
PreferenceManager mgr = getPreferenceManager();
|
||||
for (int id : preferenceIdList)
|
||||
{
|
||||
final String key = getString(id);
|
||||
Preference preference = mgr.findPreference(key);
|
||||
if (preference != null)
|
||||
{
|
||||
preference.setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// name of the main app in our library project.
|
||||
ComponentName compName =
|
||||
new ComponentName(getPackageName(), BookmarkActivity.class.getName());
|
||||
ArrayList<String> prefKeys = new ArrayList<>();
|
||||
|
||||
prefKeys.add("bookmark.credentials");
|
||||
prefKeys.add("bookmark.screen");
|
||||
prefKeys.add("bookmark.performance");
|
||||
prefKeys.add("bookmark.advanced");
|
||||
prefKeys.add("bookmark.screen_3g");
|
||||
prefKeys.add("bookmark.performance_3g");
|
||||
prefKeys.add("bookmark.gateway_settings");
|
||||
prefKeys.add("bookmark.debug");
|
||||
|
||||
for (String p : prefKeys)
|
||||
{
|
||||
Preference pref = findPreference(p);
|
||||
if (pref != null)
|
||||
pref.getIntent().setComponent(compName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
|
||||
{
|
||||
settings_changed = true;
|
||||
switch (current_preferences)
|
||||
{
|
||||
case PREFERENCES_DEBUG:
|
||||
debugSettingsChanged(sharedPreferences, key);
|
||||
break;
|
||||
|
||||
case PREFERENCES_BOOKMARK:
|
||||
bookmarkSettingsChanged(sharedPreferences, key);
|
||||
break;
|
||||
|
||||
case PREFERENCES_ADVANCED:
|
||||
advancedSettingsChanged(sharedPreferences, key);
|
||||
break;
|
||||
|
||||
case PREFERENCES_CREDENTIALS:
|
||||
credentialsSettingsChanged(sharedPreferences, key);
|
||||
break;
|
||||
|
||||
case PREFERENCES_SCREEN:
|
||||
case PREFERENCES_SCREEN3G:
|
||||
screenSettingsChanged(sharedPreferences, key);
|
||||
break;
|
||||
|
||||
case PREFERENCES_GATEWAY:
|
||||
gatewaySettingsChanged(sharedPreferences, key);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void initSettings(SharedPreferences sharedPreferences)
|
||||
{
|
||||
switch (current_preferences)
|
||||
{
|
||||
case PREFERENCES_BOOKMARK:
|
||||
initBookmarkSettings(sharedPreferences);
|
||||
break;
|
||||
|
||||
case PREFERENCES_ADVANCED:
|
||||
initAdvancedSettings(sharedPreferences);
|
||||
break;
|
||||
|
||||
case PREFERENCES_CREDENTIALS:
|
||||
initCredentialsSettings(sharedPreferences);
|
||||
break;
|
||||
|
||||
case PREFERENCES_SCREEN:
|
||||
initScreenSettings(sharedPreferences);
|
||||
break;
|
||||
|
||||
case PREFERENCES_SCREEN3G:
|
||||
initScreenSettings3G(sharedPreferences);
|
||||
break;
|
||||
|
||||
case PREFERENCES_GATEWAY:
|
||||
initGatewaySettings(sharedPreferences);
|
||||
break;
|
||||
|
||||
case PREFERENCES_DEBUG:
|
||||
initDebugSettings(sharedPreferences);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void initBookmarkSettings(SharedPreferences sharedPreferences)
|
||||
{
|
||||
bookmarkSettingsChanged(sharedPreferences, "bookmark.label");
|
||||
bookmarkSettingsChanged(sharedPreferences, "bookmark.hostname");
|
||||
bookmarkSettingsChanged(sharedPreferences, "bookmark.port");
|
||||
bookmarkSettingsChanged(sharedPreferences, "bookmark.username");
|
||||
bookmarkSettingsChanged(sharedPreferences, "bookmark.resolution");
|
||||
}
|
||||
|
||||
private void bookmarkSettingsChanged(SharedPreferences sharedPreferences, String key)
|
||||
{
|
||||
if (key.equals("bookmark.label") && findPreference(key) != null)
|
||||
findPreference(key).setSummary(sharedPreferences.getString(key, ""));
|
||||
else if (key.equals("bookmark.hostname") && findPreference(key) != null)
|
||||
findPreference(key).setSummary(sharedPreferences.getString(key, ""));
|
||||
else if (key.equals("bookmark.port") && findPreference(key) != null)
|
||||
findPreference(key).setSummary(String.valueOf(sharedPreferences.getInt(key, -1)));
|
||||
else if (key.equals("bookmark.username"))
|
||||
{
|
||||
String username = sharedPreferences.getString(key, "<none>");
|
||||
if (username.length() == 0)
|
||||
username = "<none>";
|
||||
findPreference("bookmark.credentials").setSummary(username);
|
||||
}
|
||||
else if (key.equals("bookmark.resolution") || key.equals("bookmark.colors") ||
|
||||
key.equals("bookmark.width") || key.equals("bookmark.height"))
|
||||
{
|
||||
String resolution = sharedPreferences.getString("bookmark.resolution", "800x600");
|
||||
// compare english string from resolutions_values_array array,
|
||||
// decode to localized
|
||||
// text for display
|
||||
if (resolution.equals("automatic"))
|
||||
{
|
||||
resolution = getResources().getString(R.string.resolution_automatic);
|
||||
}
|
||||
if (resolution.equals("custom"))
|
||||
{
|
||||
resolution = getResources().getString(R.string.resolution_custom);
|
||||
}
|
||||
if (resolution.equals("fitscreen"))
|
||||
{
|
||||
resolution = getResources().getString(R.string.resolution_fit);
|
||||
}
|
||||
resolution += "@" + sharedPreferences.getInt("bookmark.colors", 16);
|
||||
findPreference("bookmark.screen").setSummary(resolution);
|
||||
}
|
||||
}
|
||||
|
||||
private void initAdvancedSettings(SharedPreferences sharedPreferences)
|
||||
{
|
||||
advancedSettingsChanged(sharedPreferences, "bookmark.enable_gateway_settings");
|
||||
advancedSettingsChanged(sharedPreferences, "bookmark.enable_3g_settings");
|
||||
advancedSettingsChanged(sharedPreferences, "bookmark.security");
|
||||
advancedSettingsChanged(sharedPreferences, "bookmark.resolution_3g");
|
||||
advancedSettingsChanged(sharedPreferences, "bookmark.remote_program");
|
||||
advancedSettingsChanged(sharedPreferences, "bookmark.work_dir");
|
||||
}
|
||||
|
||||
private void advancedSettingsChanged(SharedPreferences sharedPreferences, String key)
|
||||
{
|
||||
if (key.equals("bookmark.enable_gateway_settings"))
|
||||
{
|
||||
boolean enabled = sharedPreferences.getBoolean(key, false);
|
||||
findPreference("bookmark.gateway_settings").setEnabled(enabled);
|
||||
}
|
||||
else if (key.equals("bookmark.enable_3g_settings"))
|
||||
{
|
||||
boolean enabled = sharedPreferences.getBoolean(key, false);
|
||||
findPreference("bookmark.screen_3g").setEnabled(enabled);
|
||||
findPreference("bookmark.performance_3g").setEnabled(enabled);
|
||||
}
|
||||
else if (key.equals("bookmark.security"))
|
||||
{
|
||||
ListPreference listPreference = (ListPreference)findPreference(key);
|
||||
CharSequence security = listPreference.getEntries()[sharedPreferences.getInt(key, 0)];
|
||||
listPreference.setSummary(security);
|
||||
}
|
||||
else if (key.equals("bookmark.resolution_3g") || key.equals("bookmark.colors_3g") ||
|
||||
key.equals("bookmark.width_3g") || key.equals("bookmark.height_3g"))
|
||||
{
|
||||
String resolution = sharedPreferences.getString("bookmark.resolution_3g", "800x600");
|
||||
if (resolution.equals("automatic"))
|
||||
resolution = getResources().getString(R.string.resolution_automatic);
|
||||
else if (resolution.equals("custom"))
|
||||
resolution = getResources().getString(R.string.resolution_custom);
|
||||
resolution += "@" + sharedPreferences.getInt("bookmark.colors_3g", 16);
|
||||
findPreference("bookmark.screen_3g").setSummary(resolution);
|
||||
}
|
||||
else if (key.equals("bookmark.remote_program"))
|
||||
findPreference(key).setSummary(sharedPreferences.getString(key, ""));
|
||||
else if (key.equals("bookmark.work_dir"))
|
||||
findPreference(key).setSummary(sharedPreferences.getString(key, ""));
|
||||
}
|
||||
|
||||
private void initCredentialsSettings(SharedPreferences sharedPreferences)
|
||||
{
|
||||
credentialsSettingsChanged(sharedPreferences, "bookmark.username");
|
||||
credentialsSettingsChanged(sharedPreferences, "bookmark.password");
|
||||
credentialsSettingsChanged(sharedPreferences, "bookmark.domain");
|
||||
}
|
||||
|
||||
private void credentialsSettingsChanged(SharedPreferences sharedPreferences, String key)
|
||||
{
|
||||
if (key.equals("bookmark.username"))
|
||||
findPreference(key).setSummary(sharedPreferences.getString(key, ""));
|
||||
else if (key.equals("bookmark.password"))
|
||||
{
|
||||
if (sharedPreferences.getString(key, "").length() == 0)
|
||||
findPreference(key).setSummary(
|
||||
getResources().getString(R.string.settings_password_empty));
|
||||
else
|
||||
findPreference(key).setSummary(
|
||||
getResources().getString(R.string.settings_password_present));
|
||||
}
|
||||
else if (key.equals("bookmark.domain"))
|
||||
findPreference(key).setSummary(sharedPreferences.getString(key, ""));
|
||||
}
|
||||
|
||||
private void initScreenSettings(SharedPreferences sharedPreferences)
|
||||
{
|
||||
screenSettingsChanged(sharedPreferences, "bookmark.colors");
|
||||
screenSettingsChanged(sharedPreferences, "bookmark.resolution");
|
||||
screenSettingsChanged(sharedPreferences, "bookmark.width");
|
||||
screenSettingsChanged(sharedPreferences, "bookmark.height");
|
||||
}
|
||||
|
||||
private void initScreenSettings3G(SharedPreferences sharedPreferences)
|
||||
{
|
||||
screenSettingsChanged(sharedPreferences, "bookmark.colors_3g");
|
||||
screenSettingsChanged(sharedPreferences, "bookmark.resolution_3g");
|
||||
screenSettingsChanged(sharedPreferences, "bookmark.width_3g");
|
||||
screenSettingsChanged(sharedPreferences, "bookmark.height_3g");
|
||||
}
|
||||
|
||||
private void screenSettingsChanged(SharedPreferences sharedPreferences, String key)
|
||||
{
|
||||
// could happen during initialization because 3g and non-3g settings
|
||||
// share this routine - just skip
|
||||
if (findPreference(key) == null)
|
||||
return;
|
||||
|
||||
if (key.equals("bookmark.colors") || key.equals("bookmark.colors_3g"))
|
||||
{
|
||||
ListPreference listPreference = (ListPreference)findPreference(key);
|
||||
listPreference.setSummary(listPreference.getEntry());
|
||||
}
|
||||
else if (key.equals("bookmark.resolution") || key.equals("bookmark.resolution_3g"))
|
||||
{
|
||||
ListPreference listPreference = (ListPreference)findPreference(key);
|
||||
listPreference.setSummary(listPreference.getEntry());
|
||||
|
||||
String value = listPreference.getValue();
|
||||
boolean enabled = value.equalsIgnoreCase("custom");
|
||||
if (key.equals("bookmark.resolution"))
|
||||
{
|
||||
findPreference("bookmark.width").setEnabled(enabled);
|
||||
findPreference("bookmark.height").setEnabled(enabled);
|
||||
}
|
||||
else
|
||||
{
|
||||
findPreference("bookmark.width_3g").setEnabled(enabled);
|
||||
findPreference("bookmark.height_3g").setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
else if (key.equals("bookmark.width") || key.equals("bookmark.width_3g"))
|
||||
findPreference(key).setSummary(String.valueOf(sharedPreferences.getInt(key, 800)));
|
||||
else if (key.equals("bookmark.height") || key.equals("bookmark.height_3g"))
|
||||
findPreference(key).setSummary(String.valueOf(sharedPreferences.getInt(key, 600)));
|
||||
}
|
||||
|
||||
private void initDebugSettings(SharedPreferences sharedPreferences)
|
||||
{
|
||||
debugSettingsChanged(sharedPreferences, "bookmark.debug_level");
|
||||
debugSettingsChanged(sharedPreferences, "bookmark.async_channel");
|
||||
debugSettingsChanged(sharedPreferences, "bookmark.async_update");
|
||||
}
|
||||
|
||||
private void initGatewaySettings(SharedPreferences sharedPreferences)
|
||||
{
|
||||
gatewaySettingsChanged(sharedPreferences, "bookmark.gateway_hostname");
|
||||
gatewaySettingsChanged(sharedPreferences, "bookmark.gateway_port");
|
||||
gatewaySettingsChanged(sharedPreferences, "bookmark.gateway_username");
|
||||
gatewaySettingsChanged(sharedPreferences, "bookmark.gateway_password");
|
||||
gatewaySettingsChanged(sharedPreferences, "bookmark.gateway_domain");
|
||||
}
|
||||
|
||||
private void debugSettingsChanged(SharedPreferences sharedPreferences, String key)
|
||||
{
|
||||
if (key.equals("bookmark.debug_level"))
|
||||
{
|
||||
String level = sharedPreferences.getString(key, "INFO");
|
||||
Preference pref = findPreference("bookmark.debug_level");
|
||||
pref.setDefaultValue(level);
|
||||
}
|
||||
else if (key.equals("bookmark.async_channel"))
|
||||
{
|
||||
boolean enabled = sharedPreferences.getBoolean(key, false);
|
||||
Preference pref = findPreference("bookmark.async_channel");
|
||||
pref.setDefaultValue(enabled);
|
||||
}
|
||||
else if (key.equals("bookmark.async_update"))
|
||||
{
|
||||
boolean enabled = sharedPreferences.getBoolean(key, false);
|
||||
Preference pref = findPreference("bookmark.async_update");
|
||||
pref.setDefaultValue(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
private void gatewaySettingsChanged(SharedPreferences sharedPreferences, String key)
|
||||
{
|
||||
if (key.equals("bookmark.gateway_hostname"))
|
||||
{
|
||||
findPreference(key).setSummary(sharedPreferences.getString(key, ""));
|
||||
}
|
||||
else if (key.equals("bookmark.gateway_port"))
|
||||
{
|
||||
findPreference(key).setSummary(String.valueOf(sharedPreferences.getInt(key, 443)));
|
||||
}
|
||||
else if (key.equals("bookmark.gateway_username"))
|
||||
{
|
||||
findPreference(key).setSummary(sharedPreferences.getString(key, ""));
|
||||
}
|
||||
else if (key.equals("bookmark.gateway_password"))
|
||||
{
|
||||
if (sharedPreferences.getString(key, "").length() == 0)
|
||||
findPreference(key).setSummary(
|
||||
getResources().getString(R.string.settings_password_empty));
|
||||
else
|
||||
findPreference(key).setSummary(
|
||||
getResources().getString(R.string.settings_password_present));
|
||||
}
|
||||
else if (key.equals("bookmark.gateway_domain"))
|
||||
findPreference(key).setSummary(sharedPreferences.getString(key, ""));
|
||||
}
|
||||
|
||||
private boolean verifySettings(SharedPreferences sharedPreferences)
|
||||
{
|
||||
|
||||
boolean verifyFailed = sharedPreferences.getString("bookmark.label", "").length() == 0;
|
||||
// perform sanity checks on settings
|
||||
// Label set
|
||||
|
||||
// Server and port specified
|
||||
if (!verifyFailed && sharedPreferences.getString("bookmark.hostname", "").length() == 0)
|
||||
verifyFailed = true;
|
||||
|
||||
// Server and port specified
|
||||
if (!verifyFailed && sharedPreferences.getInt("bookmark.port", -1) <= 0)
|
||||
verifyFailed = true;
|
||||
|
||||
// if an error occurred - display toast and return false
|
||||
return (!verifyFailed);
|
||||
}
|
||||
|
||||
private void finishAndResetBookmark()
|
||||
{
|
||||
bookmark = null;
|
||||
getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(
|
||||
this);
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override public void onBackPressed()
|
||||
{
|
||||
// only proceed if we are in the main preferences screen
|
||||
if (current_preferences != PREFERENCES_BOOKMARK)
|
||||
{
|
||||
super.onBackPressed();
|
||||
getPreferenceManager()
|
||||
.getSharedPreferences()
|
||||
.unregisterOnSharedPreferenceChangeListener(this);
|
||||
return;
|
||||
}
|
||||
|
||||
SharedPreferences sharedPreferences = getPreferenceManager().getSharedPreferences();
|
||||
if (!verifySettings(sharedPreferences))
|
||||
{
|
||||
// ask the user if he wants to cancel or continue editing
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.error_bookmark_incomplete_title)
|
||||
.setMessage(R.string.error_bookmark_incomplete)
|
||||
.setPositiveButton(R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
finishAndResetBookmark();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cont,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
dialog.cancel();
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
else
|
||||
{
|
||||
// ask the user if he wants to save or cancel editing if a setting
|
||||
// has changed
|
||||
if (new_bookmark || settings_changed)
|
||||
{
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.dlg_title_save_bookmark)
|
||||
.setMessage(R.string.dlg_save_bookmark)
|
||||
.setPositiveButton(
|
||||
R.string.yes,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
// read shared prefs back to bookmark
|
||||
bookmark.readFromSharedPreferences(
|
||||
getPreferenceManager().getSharedPreferences());
|
||||
|
||||
BookmarkBaseGateway bookmarkGateway;
|
||||
if (bookmark.getType() == BookmarkBase.TYPE_MANUAL)
|
||||
{
|
||||
bookmarkGateway = GlobalApp.getManualBookmarkGateway();
|
||||
// remove any history entry for this
|
||||
// bookmark
|
||||
GlobalApp.getQuickConnectHistoryGateway().removeHistoryItem(
|
||||
bookmark.<ManualBookmark>get().getHostname());
|
||||
}
|
||||
else
|
||||
{
|
||||
assert false;
|
||||
return;
|
||||
}
|
||||
|
||||
// insert or update bookmark and leave
|
||||
// activity
|
||||
if (bookmark.getId() > 0)
|
||||
bookmarkGateway.update(bookmark);
|
||||
else
|
||||
bookmarkGateway.insert(bookmark);
|
||||
|
||||
finishAndResetBookmark();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.no,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
finishAndResetBookmark();
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
else
|
||||
{
|
||||
finishAndResetBookmark();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
Activity that displays the help pages
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.presentation;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Locale;
|
||||
|
||||
public class HelpActivity extends AppCompatActivity
|
||||
{
|
||||
|
||||
private static final String TAG = HelpActivity.class.toString();
|
||||
|
||||
@Override public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
WebView webview = new WebView(this);
|
||||
setContentView(webview);
|
||||
|
||||
String filename;
|
||||
if ((getResources().getConfiguration().screenLayout &
|
||||
Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE)
|
||||
filename = "gestures.html";
|
||||
else
|
||||
filename = "gestures_phone.html";
|
||||
|
||||
WebSettings settings = webview.getSettings();
|
||||
settings.setDomStorageEnabled(true);
|
||||
settings.setUseWideViewPort(true);
|
||||
settings.setLoadWithOverviewMode(true);
|
||||
settings.setSupportZoom(true);
|
||||
settings.setJavaScriptEnabled(true);
|
||||
|
||||
settings.setAllowContentAccess(true);
|
||||
settings.setAllowFileAccess(true);
|
||||
|
||||
final Locale def = Locale.getDefault();
|
||||
final String prefix = def.getLanguage().toLowerCase(def);
|
||||
|
||||
final String base = "file:///android_asset/";
|
||||
final String baseName = "help_page";
|
||||
String dir = prefix + "_" + baseName + "/";
|
||||
String file = dir + filename;
|
||||
InputStream is;
|
||||
try
|
||||
{
|
||||
is = getAssets().open(file);
|
||||
is.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Log.e(TAG, "Missing localized asset " + file, e);
|
||||
dir = baseName + "/";
|
||||
file = dir + filename;
|
||||
}
|
||||
|
||||
webview.loadUrl(base + file);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,399 @@
|
||||
/*
|
||||
Main/Home Activity
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.presentation;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
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.View.OnClickListener;
|
||||
import android.view.View.OnCreateContextMenuListener;
|
||||
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 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.PlaceholderBookmark;
|
||||
import com.freerdp.freerdpcore.domain.QuickConnectBookmark;
|
||||
import com.freerdp.freerdpcore.utils.BookmarkArrayAdapter;
|
||||
import com.freerdp.freerdpcore.utils.SeparatedListAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class HomeActivity extends AppCompatActivity
|
||||
{
|
||||
private final static String ADD_BOOKMARK_PLACEHOLDER = "add_bookmark";
|
||||
private static final String TAG = "HomeActivity";
|
||||
private static final String PARAM_SUPERBAR_TEXT = "superbar_text";
|
||||
private ListView listViewBookmarks;
|
||||
private Button clearTextButton;
|
||||
private EditText superBarEditText;
|
||||
private BookmarkArrayAdapter manualBookmarkAdapter;
|
||||
private SeparatedListAdapter separatedListAdapter;
|
||||
private PlaceholderBookmark addBookmarkPlaceholder;
|
||||
private String sectionLabelBookmarks;
|
||||
|
||||
View mDecor;
|
||||
|
||||
@Override public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
setTitle(R.string.title_home);
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.home);
|
||||
|
||||
mDecor = getWindow().getDecorView();
|
||||
mDecor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
|
||||
|
||||
long heapSize = Runtime.getRuntime().maxMemory();
|
||||
Log.i(TAG, "Max HeapSize: " + heapSize);
|
||||
Log.i(TAG, "App data folder: " + getFilesDir().toString());
|
||||
|
||||
// load strings
|
||||
sectionLabelBookmarks = getResources().getString(R.string.section_bookmarks);
|
||||
|
||||
// create add bookmark/quick connect bookmark placeholder
|
||||
addBookmarkPlaceholder = new PlaceholderBookmark();
|
||||
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 = findViewById(R.id.clear_search_btn);
|
||||
superBarEditText = findViewById(R.id.superBarEditText);
|
||||
|
||||
listViewBookmarks = findViewById(R.id.listViewBookmarks);
|
||||
|
||||
// set listeners for the list view
|
||||
listViewBookmarks.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
|
||||
{
|
||||
String curSection = separatedListAdapter.getSectionForPosition(position);
|
||||
Log.v(TAG, "Clicked on item id " + separatedListAdapter.getItemId(position) +
|
||||
" in section " + curSection);
|
||||
if (curSection.equals(sectionLabelBookmarks))
|
||||
{
|
||||
String refStr = view.getTag().toString();
|
||||
if (ConnectionReference.isManualBookmarkReference(refStr) ||
|
||||
ConnectionReference.isHostnameReference(refStr))
|
||||
{
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(SessionActivity.PARAM_CONNECTION_REFERENCE, refStr);
|
||||
|
||||
Intent sessionIntent = new Intent(view.getContext(), SessionActivity.class);
|
||||
sessionIntent.putExtras(bundle);
|
||||
startActivity(sessionIntent);
|
||||
|
||||
// clear any search text
|
||||
superBarEditText.setText("");
|
||||
superBarEditText.clearFocus();
|
||||
}
|
||||
else if (ConnectionReference.isPlaceholderReference(refStr))
|
||||
{
|
||||
// is this the add bookmark placeholder?
|
||||
if (ConnectionReference.getPlaceholder(refStr).equals(
|
||||
ADD_BOOKMARK_PLACEHOLDER))
|
||||
{
|
||||
Intent bookmarkIntent =
|
||||
new Intent(view.getContext(), BookmarkActivity.class);
|
||||
startActivity(bookmarkIntent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
listViewBookmarks.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)
|
||||
{
|
||||
// if the selected item is not a session item (tag == null) and not a quick connect
|
||||
// entry (not a hostname connection reference) inflate the context menu
|
||||
View itemView = ((AdapterContextMenuInfo)menuInfo).targetView;
|
||||
String refStr = itemView.getTag() != null ? itemView.getTag().toString() : null;
|
||||
if (refStr != null && !ConnectionReference.isHostnameReference(refStr) &&
|
||||
!ConnectionReference.isPlaceholderReference(refStr))
|
||||
{
|
||||
getMenuInflater().inflate(R.menu.bookmark_context_menu, menu);
|
||||
menu.setHeaderTitle(getResources().getString(R.string.menu_title_bookmark));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
superBarEditText.addTextChangedListener(new SuperBarTextWatcher());
|
||||
|
||||
clearTextButton.setOnClickListener(new OnClickListener() {
|
||||
@Override public void onClick(View v)
|
||||
{
|
||||
superBarEditText.setText("");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override public void onConfigurationChanged(Configuration newConfig)
|
||||
{
|
||||
// ignore orientation/keyboard change
|
||||
super.onConfigurationChanged(newConfig);
|
||||
mDecor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
|
||||
}
|
||||
|
||||
@Override public boolean onSearchRequested()
|
||||
{
|
||||
superBarEditText.requestFocus();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public boolean onContextItemSelected(MenuItem aItem)
|
||||
{
|
||||
|
||||
// get connection reference
|
||||
AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo)aItem.getMenuInfo();
|
||||
String refStr = menuInfo.targetView.getTag().toString();
|
||||
|
||||
// refer to http://tools.android.com/tips/non-constant-fields why we can't use switch/case
|
||||
// here ..
|
||||
int itemId = aItem.getItemId();
|
||||
if (itemId == R.id.bookmark_connect)
|
||||
{
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(SessionActivity.PARAM_CONNECTION_REFERENCE, refStr);
|
||||
Intent sessionIntent = new Intent(this, SessionActivity.class);
|
||||
sessionIntent.putExtras(bundle);
|
||||
|
||||
startActivity(sessionIntent);
|
||||
return true;
|
||||
}
|
||||
else if (itemId == R.id.bookmark_edit)
|
||||
{
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(BookmarkActivity.PARAM_CONNECTION_REFERENCE, refStr);
|
||||
|
||||
Intent bookmarkIntent =
|
||||
new Intent(this.getApplicationContext(), BookmarkActivity.class);
|
||||
bookmarkIntent.putExtras(bundle);
|
||||
startActivity(bookmarkIntent);
|
||||
return true;
|
||||
}
|
||||
else if (itemId == R.id.bookmark_delete)
|
||||
{
|
||||
if (ConnectionReference.isManualBookmarkReference(refStr))
|
||||
{
|
||||
long id = ConnectionReference.getManualBookmarkId(refStr);
|
||||
GlobalApp.getManualBookmarkGateway().delete(id);
|
||||
manualBookmarkAdapter.remove(id);
|
||||
separatedListAdapter.notifyDataSetChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
assert false;
|
||||
}
|
||||
|
||||
// clear super bar text
|
||||
superBarEditText.setText("");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override protected void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
Log.v(TAG, "HomeActivity.onResume");
|
||||
|
||||
// create bookmark cursor adapter
|
||||
manualBookmarkAdapter = new BookmarkArrayAdapter(
|
||||
this, R.layout.bookmark_list_item, GlobalApp.getManualBookmarkGateway().findAll());
|
||||
|
||||
// add add bookmark item to manual adapter
|
||||
manualBookmarkAdapter.insert(addBookmarkPlaceholder, 0);
|
||||
|
||||
// attach all adapters to the separatedListView adapter and assign it to the list view
|
||||
separatedListAdapter = new SeparatedListAdapter(this);
|
||||
separatedListAdapter.addSection(sectionLabelBookmarks, manualBookmarkAdapter);
|
||||
listViewBookmarks.setAdapter(separatedListAdapter);
|
||||
|
||||
// if we have a filter text entered cause an update to be caused here
|
||||
String filter = superBarEditText.getText().toString();
|
||||
if (filter.length() > 0)
|
||||
superBarEditText.setText(filter);
|
||||
}
|
||||
|
||||
@Override protected void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
Log.v(TAG, "HomeActivity.onPause");
|
||||
|
||||
// reset adapters
|
||||
listViewBookmarks.setAdapter(null);
|
||||
separatedListAdapter = null;
|
||||
manualBookmarkAdapter = null;
|
||||
}
|
||||
|
||||
@Override public void onBackPressed()
|
||||
{
|
||||
// if back was pressed - ask the user if he really wants to exit
|
||||
if (ApplicationSettingsActivity.getAskOnExit(this))
|
||||
{
|
||||
final CheckBox cb = new CheckBox(this);
|
||||
cb.setChecked(!ApplicationSettingsActivity.getAskOnExit(this));
|
||||
cb.setText(R.string.dlg_dont_show_again);
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.dlg_title_exit)
|
||||
.setMessage(R.string.dlg_msg_exit)
|
||||
.setView(cb)
|
||||
.setPositiveButton(R.string.yes,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
finish();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.no,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
dialog.dismiss();
|
||||
}
|
||||
})
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
else
|
||||
{
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
@Override protected void onSaveInstanceState(Bundle outState)
|
||||
{
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putString(PARAM_SUPERBAR_TEXT, superBarEditText.getText().toString());
|
||||
}
|
||||
|
||||
@Override protected void onRestoreInstanceState(Bundle inState)
|
||||
{
|
||||
super.onRestoreInstanceState(inState);
|
||||
superBarEditText.setText(inState.getString(PARAM_SUPERBAR_TEXT));
|
||||
}
|
||||
|
||||
@Override public boolean onCreateOptionsMenu(Menu menu)
|
||||
{
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.home_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
|
||||
// refer to http://tools.android.com/tips/non-constant-fields why we can't use switch/case
|
||||
// here ..
|
||||
int itemId = item.getItemId();
|
||||
if (itemId == R.id.newBookmark)
|
||||
{
|
||||
Intent bookmarkIntent = new Intent(this, BookmarkActivity.class);
|
||||
startActivity(bookmarkIntent);
|
||||
}
|
||||
else if (itemId == R.id.appSettings)
|
||||
{
|
||||
Intent settingsIntent = new Intent(this, ApplicationSettingsActivity.class);
|
||||
startActivity(settingsIntent);
|
||||
}
|
||||
else if (itemId == R.id.help)
|
||||
{
|
||||
Intent helpIntent = new Intent(this, HelpActivity.class);
|
||||
startActivity(helpIntent);
|
||||
}
|
||||
else if (itemId == R.id.about)
|
||||
{
|
||||
Intent aboutIntent = new Intent(this, AboutActivity.class);
|
||||
startActivity(aboutIntent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private class SuperBarTextWatcher implements TextWatcher
|
||||
{
|
||||
@Override public void afterTextChanged(Editable s)
|
||||
{
|
||||
if (separatedListAdapter != null)
|
||||
{
|
||||
String text = s.toString();
|
||||
if (text.length() > 0)
|
||||
{
|
||||
ArrayList<BookmarkBase> computers_list =
|
||||
GlobalApp.getQuickConnectHistoryGateway().findHistory(text);
|
||||
computers_list.addAll(
|
||||
GlobalApp.getManualBookmarkGateway().findByLabelOrHostnameLike(text));
|
||||
manualBookmarkAdapter.replaceItems(computers_list);
|
||||
QuickConnectBookmark qcBm = new QuickConnectBookmark();
|
||||
qcBm.setLabel(text);
|
||||
qcBm.setHostname(text);
|
||||
manualBookmarkAdapter.insert(qcBm, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
manualBookmarkAdapter.replaceItems(
|
||||
GlobalApp.getManualBookmarkGateway().findAll());
|
||||
manualBookmarkAdapter.insert(addBookmarkPlaceholder, 0);
|
||||
}
|
||||
|
||||
separatedListAdapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after)
|
||||
{
|
||||
}
|
||||
|
||||
@Override public void onTextChanged(CharSequence s, int start, int before, int count)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,445 @@
|
||||
/*
|
||||
Android Session view
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.presentation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.text.InputType;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ScaleGestureDetector;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.freerdp.freerdpcore.application.SessionState;
|
||||
import com.freerdp.freerdpcore.services.LibFreeRDP;
|
||||
import com.freerdp.freerdpcore.utils.DoubleGestureDetector;
|
||||
import com.freerdp.freerdpcore.utils.GestureDetector;
|
||||
import com.freerdp.freerdpcore.utils.Mouse;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
public class SessionView extends View
|
||||
{
|
||||
public static final float MAX_SCALE_FACTOR = 3.0f;
|
||||
public static final float MIN_SCALE_FACTOR = 1.0f;
|
||||
private static final String TAG = "SessionView";
|
||||
private static final float SCALE_FACTOR_DELTA = 0.0001f;
|
||||
private static final float TOUCH_SCROLL_DELTA = 10.0f;
|
||||
private int width;
|
||||
private int height;
|
||||
private BitmapDrawable surface;
|
||||
private Stack<Rect> invalidRegions;
|
||||
private int touchPointerPaddingWidth = 0;
|
||||
private int touchPointerPaddingHeight = 0;
|
||||
private SessionViewListener sessionViewListener = null;
|
||||
// helpers for scaling gesture handling
|
||||
private float scaleFactor = 1.0f;
|
||||
private Matrix scaleMatrix;
|
||||
private Matrix invScaleMatrix;
|
||||
private RectF invalidRegionF;
|
||||
private GestureDetector gestureDetector;
|
||||
private SessionState currentSession;
|
||||
|
||||
// private static final String TAG = "FreeRDP.SessionView";
|
||||
private DoubleGestureDetector doubleGestureDetector;
|
||||
public SessionView(Context context)
|
||||
{
|
||||
super(context);
|
||||
initSessionView(context);
|
||||
}
|
||||
|
||||
public SessionView(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
initSessionView(context);
|
||||
}
|
||||
|
||||
public SessionView(Context context, AttributeSet attrs, int defStyle)
|
||||
{
|
||||
super(context, attrs, defStyle);
|
||||
initSessionView(context);
|
||||
}
|
||||
|
||||
private void initSessionView(Context context)
|
||||
{
|
||||
invalidRegions = new Stack<>();
|
||||
gestureDetector = new GestureDetector(context, new SessionGestureListener(), null, true);
|
||||
doubleGestureDetector =
|
||||
new DoubleGestureDetector(context, null, new SessionDoubleGestureListener());
|
||||
|
||||
scaleFactor = 1.0f;
|
||||
scaleMatrix = new Matrix();
|
||||
invScaleMatrix = new Matrix();
|
||||
invalidRegionF = new RectF();
|
||||
|
||||
setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
|
||||
}
|
||||
|
||||
/* External Mouse Hover */
|
||||
@Override public boolean onHoverEvent(MotionEvent event)
|
||||
{
|
||||
if (event.getAction() == MotionEvent.ACTION_HOVER_MOVE)
|
||||
{
|
||||
// Handle hover move event
|
||||
float x = event.getX();
|
||||
float y = event.getY();
|
||||
// Perform actions based on the hover position (x, y)
|
||||
MotionEvent mappedEvent = mapTouchEvent(event);
|
||||
LibFreeRDP.sendCursorEvent(currentSession.getInstance(), (int)mappedEvent.getX(),
|
||||
(int)mappedEvent.getY(), Mouse.getMoveEvent());
|
||||
}
|
||||
// Return true to indicate that you've handled the event
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setScaleGestureDetector(ScaleGestureDetector scaleGestureDetector)
|
||||
{
|
||||
doubleGestureDetector.setScaleGestureDetector(scaleGestureDetector);
|
||||
}
|
||||
|
||||
public void setSessionViewListener(SessionViewListener sessionViewListener)
|
||||
{
|
||||
this.sessionViewListener = sessionViewListener;
|
||||
}
|
||||
|
||||
public void addInvalidRegion(Rect invalidRegion)
|
||||
{
|
||||
// correctly transform invalid region depending on current scaling
|
||||
invalidRegionF.set(invalidRegion);
|
||||
scaleMatrix.mapRect(invalidRegionF);
|
||||
invalidRegionF.roundOut(invalidRegion);
|
||||
|
||||
invalidRegions.add(invalidRegion);
|
||||
}
|
||||
|
||||
public void invalidateRegion()
|
||||
{
|
||||
invalidate(invalidRegions.pop());
|
||||
}
|
||||
|
||||
public void onSurfaceChange(SessionState session)
|
||||
{
|
||||
surface = session.getSurface();
|
||||
Bitmap bitmap = surface.getBitmap();
|
||||
width = bitmap.getWidth();
|
||||
height = bitmap.getHeight();
|
||||
surface.setBounds(0, 0, width, height);
|
||||
|
||||
setMinimumWidth(width);
|
||||
setMinimumHeight(height);
|
||||
|
||||
requestLayout();
|
||||
currentSession = session;
|
||||
}
|
||||
|
||||
public float getZoom()
|
||||
{
|
||||
return scaleFactor;
|
||||
}
|
||||
|
||||
public void setZoom(float factor)
|
||||
{
|
||||
// calc scale matrix and inverse scale matrix (to correctly transform the view and moues
|
||||
// coordinates)
|
||||
scaleFactor = factor;
|
||||
scaleMatrix.setScale(scaleFactor, scaleFactor);
|
||||
invScaleMatrix.setScale(1.0f / scaleFactor, 1.0f / scaleFactor);
|
||||
|
||||
// update layout
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
public boolean isAtMaxZoom()
|
||||
{
|
||||
return (scaleFactor > (MAX_SCALE_FACTOR - SCALE_FACTOR_DELTA));
|
||||
}
|
||||
|
||||
public boolean isAtMinZoom()
|
||||
{
|
||||
return (scaleFactor < (MIN_SCALE_FACTOR + SCALE_FACTOR_DELTA));
|
||||
}
|
||||
|
||||
public boolean zoomIn(float factor)
|
||||
{
|
||||
boolean res = true;
|
||||
scaleFactor += factor;
|
||||
if (scaleFactor > (MAX_SCALE_FACTOR - SCALE_FACTOR_DELTA))
|
||||
{
|
||||
scaleFactor = MAX_SCALE_FACTOR;
|
||||
res = false;
|
||||
}
|
||||
setZoom(scaleFactor);
|
||||
return res;
|
||||
}
|
||||
|
||||
public boolean zoomOut(float factor)
|
||||
{
|
||||
boolean res = true;
|
||||
scaleFactor -= factor;
|
||||
if (scaleFactor < (MIN_SCALE_FACTOR + SCALE_FACTOR_DELTA))
|
||||
{
|
||||
scaleFactor = MIN_SCALE_FACTOR;
|
||||
res = false;
|
||||
}
|
||||
setZoom(scaleFactor);
|
||||
return res;
|
||||
}
|
||||
|
||||
public void setTouchPointerPadding(int width, int height)
|
||||
{
|
||||
touchPointerPaddingWidth = width;
|
||||
touchPointerPaddingHeight = height;
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
public int getTouchPointerPaddingWidth()
|
||||
{
|
||||
return touchPointerPaddingWidth;
|
||||
}
|
||||
|
||||
public int getTouchPointerPaddingHeight()
|
||||
{
|
||||
return touchPointerPaddingHeight;
|
||||
}
|
||||
|
||||
@Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
|
||||
{
|
||||
Log.v(TAG, width + "x" + height);
|
||||
this.setMeasuredDimension((int)(width * scaleFactor) + touchPointerPaddingWidth,
|
||||
(int)(height * scaleFactor) + touchPointerPaddingHeight);
|
||||
}
|
||||
|
||||
@Override public void onDraw(@NonNull Canvas canvas)
|
||||
{
|
||||
super.onDraw(canvas);
|
||||
|
||||
canvas.save();
|
||||
canvas.concat(scaleMatrix);
|
||||
canvas.drawColor(Color.BLACK);
|
||||
if (surface != null)
|
||||
{
|
||||
surface.draw(canvas);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
// dirty hack: we call back to our activity and call onBackPressed as this doesn't reach us when
|
||||
// the soft keyboard is shown ...
|
||||
@Override public boolean dispatchKeyEventPreIme(KeyEvent event)
|
||||
{
|
||||
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK &&
|
||||
event.getAction() == KeyEvent.ACTION_DOWN)
|
||||
((SessionActivity)this.getContext()).onBackPressed();
|
||||
return super.dispatchKeyEventPreIme(event);
|
||||
}
|
||||
|
||||
// perform mapping on the touch event's coordinates according to the current scaling
|
||||
private MotionEvent mapTouchEvent(MotionEvent event)
|
||||
{
|
||||
MotionEvent mappedEvent = MotionEvent.obtain(event);
|
||||
float[] coordinates = { mappedEvent.getX(), mappedEvent.getY() };
|
||||
invScaleMatrix.mapPoints(coordinates);
|
||||
mappedEvent.setLocation(coordinates[0], coordinates[1]);
|
||||
return mappedEvent;
|
||||
}
|
||||
|
||||
// perform mapping on the double touch event's coordinates according to the current scaling
|
||||
private MotionEvent mapDoubleTouchEvent(MotionEvent event)
|
||||
{
|
||||
MotionEvent mappedEvent = MotionEvent.obtain(event);
|
||||
float[] coordinates = { (mappedEvent.getX(0) + mappedEvent.getX(1)) / 2,
|
||||
(mappedEvent.getY(0) + mappedEvent.getY(1)) / 2 };
|
||||
invScaleMatrix.mapPoints(coordinates);
|
||||
mappedEvent.setLocation(coordinates[0], coordinates[1]);
|
||||
return mappedEvent;
|
||||
}
|
||||
|
||||
@Override public boolean onTouchEvent(MotionEvent event)
|
||||
{
|
||||
boolean res = gestureDetector.onTouchEvent(event);
|
||||
res |= doubleGestureDetector.onTouchEvent(event);
|
||||
return res;
|
||||
}
|
||||
|
||||
public interface SessionViewListener {
|
||||
void onSessionViewBeginTouch();
|
||||
|
||||
void onSessionViewEndTouch();
|
||||
|
||||
void onSessionViewLeftTouch(int x, int y, boolean down);
|
||||
|
||||
void onSessionViewRightTouch(int x, int y, boolean down);
|
||||
|
||||
void onSessionViewMove(int x, int y);
|
||||
|
||||
void onSessionViewScroll(boolean down);
|
||||
}
|
||||
|
||||
private class SessionGestureListener extends GestureDetector.SimpleOnGestureListener
|
||||
{
|
||||
boolean longPressInProgress = false;
|
||||
|
||||
public boolean onDown(MotionEvent e)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean onUp(MotionEvent e)
|
||||
{
|
||||
sessionViewListener.onSessionViewEndTouch();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onLongPress(MotionEvent e)
|
||||
{
|
||||
MotionEvent mappedEvent = mapTouchEvent(e);
|
||||
sessionViewListener.onSessionViewBeginTouch();
|
||||
sessionViewListener.onSessionViewLeftTouch((int)mappedEvent.getX(),
|
||||
(int)mappedEvent.getY(), true);
|
||||
longPressInProgress = true;
|
||||
}
|
||||
|
||||
public void onLongPressUp(MotionEvent e)
|
||||
{
|
||||
MotionEvent mappedEvent = mapTouchEvent(e);
|
||||
sessionViewListener.onSessionViewLeftTouch((int)mappedEvent.getX(),
|
||||
(int)mappedEvent.getY(), false);
|
||||
longPressInProgress = false;
|
||||
sessionViewListener.onSessionViewEndTouch();
|
||||
}
|
||||
|
||||
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
|
||||
{
|
||||
if (longPressInProgress)
|
||||
{
|
||||
MotionEvent mappedEvent = mapTouchEvent(e2);
|
||||
sessionViewListener.onSessionViewMove((int)mappedEvent.getX(),
|
||||
(int)mappedEvent.getY());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onDoubleTap(MotionEvent e)
|
||||
{
|
||||
// send 2nd click for double click
|
||||
MotionEvent mappedEvent = mapTouchEvent(e);
|
||||
sessionViewListener.onSessionViewLeftTouch((int)mappedEvent.getX(),
|
||||
(int)mappedEvent.getY(), true);
|
||||
sessionViewListener.onSessionViewLeftTouch((int)mappedEvent.getX(),
|
||||
(int)mappedEvent.getY(), false);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean onSingleTapUp(MotionEvent e)
|
||||
{
|
||||
// send single click
|
||||
MotionEvent mappedEvent = mapTouchEvent(e);
|
||||
sessionViewListener.onSessionViewBeginTouch();
|
||||
switch (e.getButtonState())
|
||||
{
|
||||
case MotionEvent.BUTTON_PRIMARY:
|
||||
sessionViewListener.onSessionViewLeftTouch((int)mappedEvent.getX(),
|
||||
(int)mappedEvent.getY(), true);
|
||||
sessionViewListener.onSessionViewLeftTouch((int)mappedEvent.getX(),
|
||||
(int)mappedEvent.getY(), false);
|
||||
break;
|
||||
case MotionEvent.BUTTON_SECONDARY:
|
||||
sessionViewListener.onSessionViewRightTouch((int)mappedEvent.getX(),
|
||||
(int)mappedEvent.getY(), true);
|
||||
sessionViewListener.onSessionViewRightTouch((int)mappedEvent.getX(),
|
||||
(int)mappedEvent.getY(), false);
|
||||
sessionViewListener.onSessionViewLeftTouch((int)mappedEvent.getX(),
|
||||
(int)mappedEvent.getY(), true);
|
||||
sessionViewListener.onSessionViewLeftTouch((int)mappedEvent.getX(),
|
||||
(int)mappedEvent.getY(), false);
|
||||
break;
|
||||
}
|
||||
sessionViewListener.onSessionViewEndTouch();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class SessionDoubleGestureListener
|
||||
implements DoubleGestureDetector.OnDoubleGestureListener
|
||||
{
|
||||
private MotionEvent prevEvent = null;
|
||||
|
||||
public boolean onDoubleTouchDown(MotionEvent e)
|
||||
{
|
||||
sessionViewListener.onSessionViewBeginTouch();
|
||||
prevEvent = MotionEvent.obtain(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean onDoubleTouchUp(MotionEvent e)
|
||||
{
|
||||
if (prevEvent != null)
|
||||
{
|
||||
prevEvent.recycle();
|
||||
prevEvent = null;
|
||||
}
|
||||
sessionViewListener.onSessionViewEndTouch();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean onDoubleTouchScroll(MotionEvent e1, MotionEvent e2)
|
||||
{
|
||||
// calc if user scrolled up or down (or if any scrolling happened at all)
|
||||
float deltaY = e2.getY() - prevEvent.getY();
|
||||
if (deltaY > TOUCH_SCROLL_DELTA)
|
||||
{
|
||||
sessionViewListener.onSessionViewScroll(true);
|
||||
prevEvent.recycle();
|
||||
prevEvent = MotionEvent.obtain(e2);
|
||||
}
|
||||
else if (deltaY < -TOUCH_SCROLL_DELTA)
|
||||
{
|
||||
sessionViewListener.onSessionViewScroll(false);
|
||||
prevEvent.recycle();
|
||||
prevEvent = MotionEvent.obtain(e2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean onDoubleTouchSingleTap(MotionEvent e)
|
||||
{
|
||||
// send single click
|
||||
MotionEvent mappedEvent = mapDoubleTouchEvent(e);
|
||||
sessionViewListener.onSessionViewRightTouch((int)mappedEvent.getX(),
|
||||
(int)mappedEvent.getY(), true);
|
||||
sessionViewListener.onSessionViewRightTouch((int)mappedEvent.getX(),
|
||||
(int)mappedEvent.getY(), false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public InputConnection onCreateInputConnection(EditorInfo outAttrs)
|
||||
{
|
||||
super.onCreateInputConnection(outAttrs);
|
||||
outAttrs.inputType = InputType.TYPE_CLASS_TEXT;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
Android Shortcut activity
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.presentation;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.ListActivity;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.freerdp.freerdpcore.R;
|
||||
import com.freerdp.freerdpcore.application.GlobalApp;
|
||||
import com.freerdp.freerdpcore.domain.BookmarkBase;
|
||||
import com.freerdp.freerdpcore.services.SessionRequestHandlerActivity;
|
||||
import com.freerdp.freerdpcore.utils.BookmarkArrayAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ShortcutsActivity extends ListActivity
|
||||
{
|
||||
|
||||
public static final String TAG = "ShortcutsActivity";
|
||||
|
||||
@Override public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Intent intent = getIntent();
|
||||
if (Intent.ACTION_CREATE_SHORTCUT.equals(intent.getAction()))
|
||||
{
|
||||
// set listeners for the list view
|
||||
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
|
||||
{
|
||||
String refStr = view.getTag().toString();
|
||||
String defLabel =
|
||||
((TextView)(view.findViewById(R.id.bookmark_text1))).getText().toString();
|
||||
setupShortcut(refStr, defLabel);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// just exit
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
// create bookmark cursor adapter
|
||||
ArrayList<BookmarkBase> bookmarks = GlobalApp.getManualBookmarkGateway().findAll();
|
||||
BookmarkArrayAdapter bookmarkAdapter =
|
||||
new BookmarkArrayAdapter(this, android.R.layout.simple_list_item_2, bookmarks);
|
||||
getListView().setAdapter(bookmarkAdapter);
|
||||
}
|
||||
|
||||
public void onPause()
|
||||
{
|
||||
super.onPause();
|
||||
getListView().setAdapter(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function creates a shortcut and returns it to the caller. There are actually two
|
||||
* intents that you will send back.
|
||||
* <p>
|
||||
* The first intent serves as a container for the shortcut and is returned to the launcher by
|
||||
* setResult(). This intent must contain three fields:
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>{@link android.content.Intent#EXTRA_SHORTCUT_INTENT} The shortcut intent.</li>
|
||||
* <li>{@link android.content.Intent#EXTRA_SHORTCUT_NAME} The text that will be displayed with
|
||||
* the shortcut.</li>
|
||||
* <li>{@link android.content.Intent#EXTRA_SHORTCUT_ICON} The shortcut's icon, if provided as a
|
||||
* bitmap, <i>or</i> {@link android.content.Intent#EXTRA_SHORTCUT_ICON_RESOURCE} if provided as
|
||||
* a drawable resource.</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* If you use a simple drawable resource, note that you must wrapper it using
|
||||
* {@link android.content.Intent.ShortcutIconResource}, as shown below. This is required so
|
||||
* that the launcher can access resources that are stored in your application's .apk file. If
|
||||
* you return a bitmap, such as a thumbnail, you can simply put the bitmap into the extras
|
||||
* bundle using {@link android.content.Intent#EXTRA_SHORTCUT_ICON}.
|
||||
* <p>
|
||||
* The shortcut intent can be any intent that you wish the launcher to send, when the user
|
||||
* clicks on the shortcut. Typically this will be {@link android.content.Intent#ACTION_VIEW}
|
||||
* with an appropriate Uri for your content, but any Intent will work here as long as it
|
||||
* triggers the desired action within your Activity.
|
||||
*/
|
||||
|
||||
private void setupShortcut(String strRef, String defaultLabel)
|
||||
{
|
||||
final String paramStrRef = strRef;
|
||||
final String paramDefaultLabel = defaultLabel;
|
||||
final Context paramContext = this;
|
||||
|
||||
// display edit dialog to the user so he can specify the shortcut name
|
||||
final EditText input = new EditText(this);
|
||||
input.setText(defaultLabel);
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.dlg_title_create_shortcut)
|
||||
.setMessage(R.string.dlg_msg_create_shortcut)
|
||||
.setView(input)
|
||||
.setPositiveButton(
|
||||
android.R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
String label = input.getText().toString();
|
||||
if (label.length() == 0)
|
||||
label = paramDefaultLabel;
|
||||
|
||||
Intent shortcutIntent = new Intent(Intent.ACTION_VIEW);
|
||||
shortcutIntent.setClassName(paramContext,
|
||||
SessionRequestHandlerActivity.class.getName());
|
||||
shortcutIntent.setData(Uri.parse(paramStrRef));
|
||||
|
||||
// Then, set up the container intent (the response to the caller)
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, label);
|
||||
Parcelable iconResource = Intent.ShortcutIconResource.fromContext(
|
||||
paramContext, R.drawable.icon_launcher_freerdp);
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);
|
||||
|
||||
// Now, return the result to the launcher
|
||||
setResult(RESULT_OK, intent);
|
||||
finish();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
dialog.dismiss();
|
||||
}
|
||||
})
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
Android Touch Pointer view
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.presentation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.freerdp.freerdpcore.R;
|
||||
import com.freerdp.freerdpcore.utils.GestureDetector;
|
||||
|
||||
public class TouchPointerView extends ImageView
|
||||
{
|
||||
|
||||
private static final int POINTER_ACTION_CURSOR = 0;
|
||||
private static final int POINTER_ACTION_CLOSE = 3;
|
||||
|
||||
// the touch pointer consists of 9 quadrants with the following functionality:
|
||||
//
|
||||
// -------------
|
||||
// | 0 | 1 | 2 |
|
||||
// -------------
|
||||
// | 3 | 4 | 5 |
|
||||
// -------------
|
||||
// | 6 | 7 | 8 |
|
||||
// -------------
|
||||
//
|
||||
// 0 ... contains the actual pointer (the tip must be centered in the quadrant)
|
||||
// 1 ... is left empty
|
||||
// 2, 3, 5, 6, 7, 8 ... function quadrants that issue a callback
|
||||
// 4 ... pointer center used for left clicks and to drag the pointer
|
||||
private static final int POINTER_ACTION_RCLICK = 2;
|
||||
private static final int POINTER_ACTION_LCLICK = 4;
|
||||
private static final int POINTER_ACTION_MOVE = 4;
|
||||
private static final int POINTER_ACTION_SCROLL = 5;
|
||||
private static final int POINTER_ACTION_RESET = 6;
|
||||
private static final int POINTER_ACTION_KEYBOARD = 7;
|
||||
private static final int POINTER_ACTION_EXTKEYBOARD = 8;
|
||||
private static final float SCROLL_DELTA = 10.0f;
|
||||
private static final int DEFAULT_TOUCH_POINTER_RESTORE_DELAY = 150;
|
||||
private RectF pointerRect;
|
||||
private final RectF[] pointerAreaRects = new RectF[9];
|
||||
private Matrix translationMatrix;
|
||||
private boolean pointerMoving = false;
|
||||
private boolean pointerScrolling = false;
|
||||
private TouchPointerListener listener = null;
|
||||
private final UIHandler uiHandler = new UIHandler();
|
||||
// gesture detection
|
||||
private GestureDetector gestureDetector;
|
||||
public TouchPointerView(Context context)
|
||||
{
|
||||
super(context);
|
||||
initTouchPointer(context);
|
||||
}
|
||||
|
||||
public TouchPointerView(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
initTouchPointer(context);
|
||||
}
|
||||
|
||||
public TouchPointerView(Context context, AttributeSet attrs, int defStyle)
|
||||
{
|
||||
super(context, attrs, defStyle);
|
||||
initTouchPointer(context);
|
||||
}
|
||||
|
||||
private void initTouchPointer(Context context)
|
||||
{
|
||||
gestureDetector =
|
||||
new GestureDetector(context, new TouchPointerGestureListener(), null, true);
|
||||
gestureDetector.setLongPressTimeout(500);
|
||||
translationMatrix = new Matrix();
|
||||
setScaleType(ScaleType.MATRIX);
|
||||
setImageMatrix(translationMatrix);
|
||||
|
||||
// init rects
|
||||
final float rectSizeWidth = (float)getDrawable().getIntrinsicWidth() / 3.0f;
|
||||
final float rectSizeHeight = (float)getDrawable().getIntrinsicWidth() / 3.0f;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
int left = (int)(j * rectSizeWidth);
|
||||
int top = (int)(i * rectSizeHeight);
|
||||
int right = left + (int)rectSizeWidth;
|
||||
int bottom = top + (int)rectSizeHeight;
|
||||
pointerAreaRects[i * 3 + j] = new RectF(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
pointerRect =
|
||||
new RectF(0, 0, getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());
|
||||
}
|
||||
|
||||
public void setTouchPointerListener(TouchPointerListener listener)
|
||||
{
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public int getPointerWidth()
|
||||
{
|
||||
return getDrawable().getIntrinsicWidth();
|
||||
}
|
||||
|
||||
public int getPointerHeight()
|
||||
{
|
||||
return getDrawable().getIntrinsicHeight();
|
||||
}
|
||||
|
||||
public float[] getPointerPosition()
|
||||
{
|
||||
float[] curPos = new float[2];
|
||||
translationMatrix.mapPoints(curPos);
|
||||
return curPos;
|
||||
}
|
||||
|
||||
private void movePointer(float deltaX, float deltaY)
|
||||
{
|
||||
translationMatrix.postTranslate(deltaX, deltaY);
|
||||
setImageMatrix(translationMatrix);
|
||||
}
|
||||
|
||||
private void ensureVisibility(int screen_width, int screen_height)
|
||||
{
|
||||
float[] curPos = new float[2];
|
||||
translationMatrix.mapPoints(curPos);
|
||||
|
||||
if (curPos[0] > (screen_width - pointerRect.width()))
|
||||
curPos[0] = screen_width - pointerRect.width();
|
||||
if (curPos[0] < 0)
|
||||
curPos[0] = 0;
|
||||
if (curPos[1] > (screen_height - pointerRect.height()))
|
||||
curPos[1] = screen_height - pointerRect.height();
|
||||
if (curPos[1] < 0)
|
||||
curPos[1] = 0;
|
||||
|
||||
translationMatrix.setTranslate(curPos[0], curPos[1]);
|
||||
setImageMatrix(translationMatrix);
|
||||
}
|
||||
|
||||
private void displayPointerImageAction(int resId)
|
||||
{
|
||||
setPointerImage(resId);
|
||||
uiHandler.sendEmptyMessageDelayed(0, DEFAULT_TOUCH_POINTER_RESTORE_DELAY);
|
||||
}
|
||||
|
||||
private void setPointerImage(int resId)
|
||||
{
|
||||
setImageResource(resId);
|
||||
}
|
||||
|
||||
// returns the pointer area with the current translation matrix applied
|
||||
private RectF getCurrentPointerArea(int area)
|
||||
{
|
||||
RectF transRect = new RectF(pointerAreaRects[area]);
|
||||
translationMatrix.mapRect(transRect);
|
||||
return transRect;
|
||||
}
|
||||
|
||||
private boolean pointerAreaTouched(MotionEvent event, int area)
|
||||
{
|
||||
RectF transRect = new RectF(pointerAreaRects[area]);
|
||||
translationMatrix.mapRect(transRect);
|
||||
return transRect.contains(event.getX(), event.getY());
|
||||
}
|
||||
|
||||
private boolean pointerTouched(MotionEvent event)
|
||||
{
|
||||
RectF transRect = new RectF(pointerRect);
|
||||
translationMatrix.mapRect(transRect);
|
||||
return transRect.contains(event.getX(), event.getY());
|
||||
}
|
||||
|
||||
@Override public boolean onTouchEvent(MotionEvent event)
|
||||
{
|
||||
// check if pointer is being moved or if we are in scroll mode or if the pointer is touched
|
||||
if (!pointerMoving && !pointerScrolling && !pointerTouched(event))
|
||||
return false;
|
||||
return gestureDetector.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override protected void onLayout(boolean changed, int left, int top, int right, int bottom)
|
||||
{
|
||||
// ensure touch pointer is visible
|
||||
if (changed)
|
||||
ensureVisibility(right - left, bottom - top);
|
||||
}
|
||||
|
||||
// touch pointer listener - is triggered if an action field is
|
||||
public interface TouchPointerListener {
|
||||
void onTouchPointerClose();
|
||||
|
||||
void onTouchPointerLeftClick(int x, int y, boolean down);
|
||||
|
||||
void onTouchPointerRightClick(int x, int y, boolean down);
|
||||
|
||||
void onTouchPointerMove(int x, int y);
|
||||
|
||||
void onTouchPointerScroll(boolean down);
|
||||
|
||||
void onTouchPointerToggleKeyboard();
|
||||
|
||||
void onTouchPointerToggleExtKeyboard();
|
||||
|
||||
void onTouchPointerResetScrollZoom();
|
||||
}
|
||||
|
||||
private class UIHandler extends Handler
|
||||
{
|
||||
|
||||
UIHandler()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
@Override public void handleMessage(Message msg)
|
||||
{
|
||||
setPointerImage(R.drawable.touch_pointer_default);
|
||||
}
|
||||
}
|
||||
|
||||
private class TouchPointerGestureListener extends GestureDetector.SimpleOnGestureListener
|
||||
{
|
||||
|
||||
private MotionEvent prevEvent = null;
|
||||
|
||||
public boolean onDown(MotionEvent e)
|
||||
{
|
||||
if (pointerAreaTouched(e, POINTER_ACTION_MOVE))
|
||||
{
|
||||
prevEvent = MotionEvent.obtain(e);
|
||||
pointerMoving = true;
|
||||
}
|
||||
else if (pointerAreaTouched(e, POINTER_ACTION_SCROLL))
|
||||
{
|
||||
prevEvent = MotionEvent.obtain(e);
|
||||
pointerScrolling = true;
|
||||
setPointerImage(R.drawable.touch_pointer_scroll);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean onUp(MotionEvent e)
|
||||
{
|
||||
if (prevEvent != null)
|
||||
{
|
||||
prevEvent.recycle();
|
||||
prevEvent = null;
|
||||
}
|
||||
|
||||
if (pointerScrolling)
|
||||
setPointerImage(R.drawable.touch_pointer_default);
|
||||
|
||||
pointerMoving = false;
|
||||
pointerScrolling = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onLongPress(MotionEvent e)
|
||||
{
|
||||
if (pointerAreaTouched(e, POINTER_ACTION_LCLICK))
|
||||
{
|
||||
setPointerImage(R.drawable.touch_pointer_active);
|
||||
pointerMoving = true;
|
||||
RectF rect = getCurrentPointerArea(POINTER_ACTION_CURSOR);
|
||||
listener.onTouchPointerLeftClick((int)rect.centerX(), (int)rect.centerY(), true);
|
||||
}
|
||||
}
|
||||
|
||||
public void onLongPressUp(MotionEvent e)
|
||||
{
|
||||
if (pointerMoving)
|
||||
{
|
||||
setPointerImage(R.drawable.touch_pointer_default);
|
||||
pointerMoving = false;
|
||||
RectF rect = getCurrentPointerArea(POINTER_ACTION_CURSOR);
|
||||
listener.onTouchPointerLeftClick((int)rect.centerX(), (int)rect.centerY(), false);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
|
||||
{
|
||||
if (pointerMoving)
|
||||
{
|
||||
// move pointer graphics
|
||||
movePointer((int)(e2.getX() - prevEvent.getX()),
|
||||
(int)(e2.getY() - prevEvent.getY()));
|
||||
prevEvent.recycle();
|
||||
prevEvent = MotionEvent.obtain(e2);
|
||||
|
||||
// send move notification
|
||||
RectF rect = getCurrentPointerArea(POINTER_ACTION_CURSOR);
|
||||
listener.onTouchPointerMove((int)rect.centerX(), (int)rect.centerY());
|
||||
return true;
|
||||
}
|
||||
else if (pointerScrolling)
|
||||
{
|
||||
// calc if user scrolled up or down (or if any scrolling happened at all)
|
||||
float deltaY = e2.getY() - prevEvent.getY();
|
||||
if (deltaY > SCROLL_DELTA)
|
||||
{
|
||||
listener.onTouchPointerScroll(true);
|
||||
prevEvent.recycle();
|
||||
prevEvent = MotionEvent.obtain(e2);
|
||||
}
|
||||
else if (deltaY < -SCROLL_DELTA)
|
||||
{
|
||||
listener.onTouchPointerScroll(false);
|
||||
prevEvent.recycle();
|
||||
prevEvent = MotionEvent.obtain(e2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onSingleTapUp(MotionEvent e)
|
||||
{
|
||||
// look what area got touched and fire actions accordingly
|
||||
if (pointerAreaTouched(e, POINTER_ACTION_CLOSE))
|
||||
listener.onTouchPointerClose();
|
||||
else if (pointerAreaTouched(e, POINTER_ACTION_LCLICK))
|
||||
{
|
||||
displayPointerImageAction(R.drawable.touch_pointer_lclick);
|
||||
RectF rect = getCurrentPointerArea(POINTER_ACTION_CURSOR);
|
||||
listener.onTouchPointerLeftClick((int)rect.centerX(), (int)rect.centerY(), true);
|
||||
listener.onTouchPointerLeftClick((int)rect.centerX(), (int)rect.centerY(), false);
|
||||
}
|
||||
else if (pointerAreaTouched(e, POINTER_ACTION_RCLICK))
|
||||
{
|
||||
displayPointerImageAction(R.drawable.touch_pointer_rclick);
|
||||
RectF rect = getCurrentPointerArea(POINTER_ACTION_CURSOR);
|
||||
listener.onTouchPointerRightClick((int)rect.centerX(), (int)rect.centerY(), true);
|
||||
listener.onTouchPointerRightClick((int)rect.centerX(), (int)rect.centerY(), false);
|
||||
}
|
||||
else if (pointerAreaTouched(e, POINTER_ACTION_KEYBOARD))
|
||||
{
|
||||
displayPointerImageAction(R.drawable.touch_pointer_keyboard);
|
||||
listener.onTouchPointerToggleKeyboard();
|
||||
}
|
||||
else if (pointerAreaTouched(e, POINTER_ACTION_EXTKEYBOARD))
|
||||
{
|
||||
displayPointerImageAction(R.drawable.touch_pointer_extkeyboard);
|
||||
listener.onTouchPointerToggleExtKeyboard();
|
||||
}
|
||||
else if (pointerAreaTouched(e, POINTER_ACTION_RESET))
|
||||
{
|
||||
displayPointerImageAction(R.drawable.touch_pointer_reset);
|
||||
listener.onTouchPointerResetScrollZoom();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean onDoubleTap(MotionEvent e)
|
||||
{
|
||||
// issue a double click notification if performed in center quadrant
|
||||
if (pointerAreaTouched(e, POINTER_ACTION_LCLICK))
|
||||
{
|
||||
RectF rect = getCurrentPointerArea(POINTER_ACTION_CURSOR);
|
||||
listener.onTouchPointerLeftClick((int)rect.centerX(), (int)rect.centerY(), true);
|
||||
listener.onTouchPointerLeftClick((int)rect.centerX(), (int)rect.centerY(), false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,610 @@
|
||||
/*
|
||||
Helper class to access bookmark database
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.services;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.database.sqlite.SQLiteQueryBuilder;
|
||||
import android.util.Log;
|
||||
|
||||
import com.freerdp.freerdpcore.domain.BookmarkBase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public abstract class BookmarkBaseGateway
|
||||
{
|
||||
private final static String TAG = "BookmarkBaseGateway";
|
||||
private final SQLiteOpenHelper bookmarkDB;
|
||||
|
||||
private static final String JOIN_PREFIX = "join_";
|
||||
private static final String KEY_BOOKMARK_ID = "bookmarkId";
|
||||
private static final String KEY_SCREEN_COLORS = "screenColors";
|
||||
private static final String KEY_SCREEN_COLORS_3G = "screenColors3G";
|
||||
private static final String KEY_SCREEN_RESOLUTION = "screenResolution";
|
||||
private static final String KEY_SCREEN_RESOLUTION_3G = "screenResolution3G";
|
||||
private static final String KEY_SCREEN_WIDTH = "screenWidth";
|
||||
private static final String KEY_SCREEN_WIDTH_3G = "screenWidth3G";
|
||||
private static final String KEY_SCREEN_HEIGHT = "screenHeight";
|
||||
private static final String KEY_SCREEN_HEIGHT_3G = "screenHeight3G";
|
||||
|
||||
private static final String KEY_PERFORMANCE_RFX = "performanceRemoteFX";
|
||||
private static final String KEY_PERFORMANCE_RFX_3G = "performanceRemoteFX3G";
|
||||
private static final String KEY_PERFORMANCE_GFX = "performanceGfx";
|
||||
private static final String KEY_PERFORMANCE_GFX_3G = "performanceGfx3G";
|
||||
private static final String KEY_PERFORMANCE_H264 = "performanceGfxH264";
|
||||
private static final String KEY_PERFORMANCE_H264_3G = "performanceGfxH2643G";
|
||||
private static final String KEY_PERFORMANCE_WALLPAPER = "performanceWallpaper";
|
||||
private static final String KEY_PERFORMANCE_WALLPAPER_3G = "performanceWallpaper3G";
|
||||
private static final String KEY_PERFORMANCE_THEME = "performanceTheming";
|
||||
private static final String KEY_PERFORMANCE_THEME_3G = "performanceTheming3G";
|
||||
|
||||
private static final String KEY_PERFORMANCE_DRAG = "performanceFullWindowDrag";
|
||||
private static final String KEY_PERFORMANCE_DRAG_3G = "performanceFullWindowDrag3G";
|
||||
private static final String KEY_PERFORMANCE_MENU_ANIMATIONS = "performanceMenuAnimations";
|
||||
private static final String KEY_PERFORMANCE_MENU_ANIMATIONS_3G = "performanceMenuAnimations3G";
|
||||
private static final String KEY_PERFORMANCE_FONTS = "performanceFontSmoothing";
|
||||
private static final String KEY_PERFORMANCE_FONTS_3G = "performanceFontSmoothing3G";
|
||||
private static final String KEY_PERFORMANCE_COMPOSITION = "performanceDesktopComposition";
|
||||
private static final String KEY_PERFORMANCE_COMPOSITION_3G = "performanceDesktopComposition3G";
|
||||
|
||||
public BookmarkBaseGateway(SQLiteOpenHelper bookmarkDB)
|
||||
{
|
||||
this.bookmarkDB = bookmarkDB;
|
||||
}
|
||||
|
||||
protected abstract BookmarkBase createBookmark();
|
||||
|
||||
protected abstract String getBookmarkTableName();
|
||||
|
||||
protected abstract void addBookmarkSpecificColumns(ArrayList<String> columns);
|
||||
|
||||
protected abstract void addBookmarkSpecificColumns(BookmarkBase bookmark,
|
||||
ContentValues columns);
|
||||
|
||||
protected abstract void readBookmarkSpecificColumns(BookmarkBase bookmark, Cursor cursor);
|
||||
|
||||
public void insert(BookmarkBase bookmark)
|
||||
{
|
||||
// begin transaction
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.beginTransaction();
|
||||
|
||||
long rowid;
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_LABEL, bookmark.getLabel());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_USERNAME, bookmark.getUsername());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_PASSWORD, bookmark.getPassword());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_DOMAIN, bookmark.getDomain());
|
||||
// insert screen and performance settings
|
||||
rowid = insertScreenSettings(db, bookmark.getScreenSettings());
|
||||
values.put(BookmarkDB.DB_KEY_SCREEN_SETTINGS, rowid);
|
||||
rowid = insertPerformanceFlags(db, bookmark.getPerformanceFlags());
|
||||
values.put(BookmarkDB.DB_KEY_PERFORMANCE_FLAGS, rowid);
|
||||
|
||||
// advanced settings
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_3G_ENABLE,
|
||||
bookmark.getAdvancedSettings().getEnable3GSettings());
|
||||
// insert 3G screen and 3G performance settings
|
||||
rowid = insertScreenSettings(db, bookmark.getAdvancedSettings().getScreen3G());
|
||||
values.put(BookmarkDB.DB_KEY_SCREEN_SETTINGS_3G, rowid);
|
||||
rowid = insertPerformanceFlags(db, bookmark.getAdvancedSettings().getPerformance3G());
|
||||
values.put(BookmarkDB.DB_KEY_PERFORMANCE_FLAGS_3G, rowid);
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_REDIRECT_SDCARD,
|
||||
bookmark.getAdvancedSettings().getRedirectSDCard());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_REDIRECT_SOUND,
|
||||
bookmark.getAdvancedSettings().getRedirectSound());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_REDIRECT_MICROPHONE,
|
||||
bookmark.getAdvancedSettings().getRedirectMicrophone());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_SECURITY,
|
||||
bookmark.getAdvancedSettings().getSecurity());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_CONSOLE_MODE,
|
||||
bookmark.getAdvancedSettings().getConsoleMode());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_REMOTE_PROGRAM,
|
||||
bookmark.getAdvancedSettings().getRemoteProgram());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_WORK_DIR,
|
||||
bookmark.getAdvancedSettings().getWorkDir());
|
||||
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_ASYNC_CHANNEL,
|
||||
bookmark.getDebugSettings().getAsyncChannel());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_ASYNC_UPDATE,
|
||||
bookmark.getDebugSettings().getAsyncUpdate());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_DEBUG_LEVEL,
|
||||
bookmark.getDebugSettings().getDebugLevel());
|
||||
|
||||
// add any special columns
|
||||
addBookmarkSpecificColumns(bookmark, values);
|
||||
|
||||
// insert bookmark and end transaction
|
||||
db.insertOrThrow(getBookmarkTableName(), null, values);
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
public boolean update(BookmarkBase bookmark)
|
||||
{
|
||||
// start a transaction
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.beginTransaction();
|
||||
|
||||
// bookmark settings
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_LABEL, bookmark.getLabel());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_USERNAME, bookmark.getUsername());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_PASSWORD, bookmark.getPassword());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_DOMAIN, bookmark.getDomain());
|
||||
// update screen and performance settings settings
|
||||
updateScreenSettings(db, bookmark);
|
||||
updatePerformanceFlags(db, bookmark);
|
||||
|
||||
// advanced settings
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_3G_ENABLE,
|
||||
bookmark.getAdvancedSettings().getEnable3GSettings());
|
||||
// update 3G screen and 3G performance settings settings
|
||||
updateScreenSettings3G(db, bookmark);
|
||||
updatePerformanceFlags3G(db, bookmark);
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_REDIRECT_SDCARD,
|
||||
bookmark.getAdvancedSettings().getRedirectSDCard());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_REDIRECT_SOUND,
|
||||
bookmark.getAdvancedSettings().getRedirectSound());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_REDIRECT_MICROPHONE,
|
||||
bookmark.getAdvancedSettings().getRedirectMicrophone());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_SECURITY,
|
||||
bookmark.getAdvancedSettings().getSecurity());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_CONSOLE_MODE,
|
||||
bookmark.getAdvancedSettings().getConsoleMode());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_REMOTE_PROGRAM,
|
||||
bookmark.getAdvancedSettings().getRemoteProgram());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_WORK_DIR,
|
||||
bookmark.getAdvancedSettings().getWorkDir());
|
||||
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_ASYNC_CHANNEL,
|
||||
bookmark.getDebugSettings().getAsyncChannel());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_ASYNC_UPDATE,
|
||||
bookmark.getDebugSettings().getAsyncUpdate());
|
||||
values.put(BookmarkDB.DB_KEY_BOOKMARK_DEBUG_LEVEL,
|
||||
bookmark.getDebugSettings().getDebugLevel());
|
||||
|
||||
addBookmarkSpecificColumns(bookmark, values);
|
||||
|
||||
// update bookmark
|
||||
boolean res = (db.update(getBookmarkTableName(), values,
|
||||
BookmarkDB.ID + " = " + bookmark.getId(), null) == 1);
|
||||
|
||||
// commit
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public void delete(long id)
|
||||
{
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.delete(getBookmarkTableName(), BookmarkDB.ID + " = " + id, null);
|
||||
}
|
||||
|
||||
public BookmarkBase findById(long id)
|
||||
{
|
||||
Cursor cursor =
|
||||
queryBookmarks(getBookmarkTableName() + "." + BookmarkDB.ID + " = " + id, null);
|
||||
if (cursor.getCount() == 0)
|
||||
{
|
||||
cursor.close();
|
||||
return null;
|
||||
}
|
||||
|
||||
cursor.moveToFirst();
|
||||
BookmarkBase bookmark = getBookmarkFromCursor(cursor);
|
||||
cursor.close();
|
||||
return bookmark;
|
||||
}
|
||||
|
||||
public BookmarkBase findByLabel(String label)
|
||||
{
|
||||
Cursor cursor = queryBookmarks(BookmarkDB.DB_KEY_BOOKMARK_LABEL + " = '" + label + "'",
|
||||
BookmarkDB.DB_KEY_BOOKMARK_LABEL);
|
||||
if (cursor.getCount() > 1)
|
||||
Log.e(TAG, "More than one bookmark with the same label found!");
|
||||
|
||||
BookmarkBase bookmark = null;
|
||||
if (cursor.moveToFirst() && (cursor.getCount() > 0))
|
||||
bookmark = getBookmarkFromCursor(cursor);
|
||||
|
||||
cursor.close();
|
||||
return bookmark;
|
||||
}
|
||||
|
||||
public ArrayList<BookmarkBase> findByLabelLike(String pattern)
|
||||
{
|
||||
Cursor cursor =
|
||||
queryBookmarks(BookmarkDB.DB_KEY_BOOKMARK_LABEL + " LIKE '%" + pattern + "%'",
|
||||
BookmarkDB.DB_KEY_BOOKMARK_LABEL);
|
||||
ArrayList<BookmarkBase> bookmarks = new ArrayList<>(cursor.getCount());
|
||||
|
||||
if (cursor.moveToFirst() && (cursor.getCount() > 0))
|
||||
{
|
||||
do
|
||||
{
|
||||
bookmarks.add(getBookmarkFromCursor(cursor));
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
|
||||
cursor.close();
|
||||
return bookmarks;
|
||||
}
|
||||
|
||||
public ArrayList<BookmarkBase> findAll()
|
||||
{
|
||||
Cursor cursor = queryBookmarks(null, BookmarkDB.DB_KEY_BOOKMARK_LABEL);
|
||||
final int count = cursor.getCount();
|
||||
ArrayList<BookmarkBase> bookmarks = new ArrayList<>(count);
|
||||
|
||||
if (cursor.moveToFirst() && (count > 0))
|
||||
{
|
||||
do
|
||||
{
|
||||
bookmarks.add(getBookmarkFromCursor(cursor));
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
|
||||
cursor.close();
|
||||
return bookmarks;
|
||||
}
|
||||
|
||||
protected Cursor queryBookmarks(String whereClause, String orderBy)
|
||||
{
|
||||
// create tables string
|
||||
final String ID = BookmarkDB.ID;
|
||||
final String tables =
|
||||
BookmarkDB.DB_TABLE_BOOKMARK + " INNER JOIN " + BookmarkDB.DB_TABLE_SCREEN + " AS " +
|
||||
JOIN_PREFIX + BookmarkDB.DB_KEY_SCREEN_SETTINGS + " ON " + JOIN_PREFIX +
|
||||
BookmarkDB.DB_KEY_SCREEN_SETTINGS + "." + ID + " = " + BookmarkDB.DB_TABLE_BOOKMARK +
|
||||
"." + BookmarkDB.DB_KEY_SCREEN_SETTINGS + " INNER JOIN " +
|
||||
BookmarkDB.DB_TABLE_PERFORMANCE + " AS " + JOIN_PREFIX +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_FLAGS + " ON " + JOIN_PREFIX +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_FLAGS + "." + ID + " = " + BookmarkDB.DB_TABLE_BOOKMARK +
|
||||
"." + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS + " INNER JOIN " +
|
||||
BookmarkDB.DB_TABLE_SCREEN + " AS " + JOIN_PREFIX +
|
||||
BookmarkDB.DB_KEY_SCREEN_SETTINGS_3G + " ON " + JOIN_PREFIX +
|
||||
BookmarkDB.DB_KEY_SCREEN_SETTINGS_3G + "." + ID + " = " + BookmarkDB.DB_TABLE_BOOKMARK +
|
||||
"." + BookmarkDB.DB_KEY_SCREEN_SETTINGS_3G + " INNER JOIN " +
|
||||
BookmarkDB.DB_TABLE_PERFORMANCE + " AS " + JOIN_PREFIX +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_FLAGS_3G + " ON " + JOIN_PREFIX +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_FLAGS_3G + "." + ID + " = " +
|
||||
BookmarkDB.DB_TABLE_BOOKMARK + "." + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS_3G;
|
||||
|
||||
// create columns list
|
||||
ArrayList<String> columns = new ArrayList<>();
|
||||
addBookmarkColumns(columns);
|
||||
addScreenSettingsColumns(columns);
|
||||
addPerformanceFlagsColumns(columns);
|
||||
addScreenSettings3GColumns(columns);
|
||||
addPerformanceFlags3GColumns(columns);
|
||||
|
||||
String[] cols = new String[columns.size()];
|
||||
columns.toArray(cols);
|
||||
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
final String query = SQLiteQueryBuilder.buildQueryString(false, tables, cols, whereClause,
|
||||
null, null, orderBy, null);
|
||||
return db.rawQuery(query, null);
|
||||
}
|
||||
|
||||
private void addBookmarkColumns(ArrayList<String> columns)
|
||||
{
|
||||
columns.add(getBookmarkTableName() + "." + BookmarkDB.ID + " " + KEY_BOOKMARK_ID);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_LABEL);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_USERNAME);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_PASSWORD);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_DOMAIN);
|
||||
|
||||
// advanced settings
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_3G_ENABLE);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_REDIRECT_SDCARD);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_REDIRECT_SOUND);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_REDIRECT_MICROPHONE);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_SECURITY);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_CONSOLE_MODE);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_REMOTE_PROGRAM);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_WORK_DIR);
|
||||
|
||||
// debug settings
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_DEBUG_LEVEL);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_ASYNC_CHANNEL);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_ASYNC_UPDATE);
|
||||
|
||||
addBookmarkSpecificColumns(columns);
|
||||
}
|
||||
|
||||
private void addScreenSettingsColumns(ArrayList<String> columns)
|
||||
{
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_SCREEN_SETTINGS + "." +
|
||||
BookmarkDB.DB_KEY_SCREEN_COLORS + " as " + KEY_SCREEN_COLORS);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_SCREEN_SETTINGS + "." +
|
||||
BookmarkDB.DB_KEY_SCREEN_RESOLUTION + " as " + KEY_SCREEN_RESOLUTION);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_SCREEN_SETTINGS + "." +
|
||||
BookmarkDB.DB_KEY_SCREEN_WIDTH + " as " + KEY_SCREEN_WIDTH);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_SCREEN_SETTINGS + "." +
|
||||
BookmarkDB.DB_KEY_SCREEN_HEIGHT + " as " + KEY_SCREEN_HEIGHT);
|
||||
}
|
||||
|
||||
private void addPerformanceFlagsColumns(ArrayList<String> columns)
|
||||
{
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_RFX + " as " + KEY_PERFORMANCE_RFX);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_GFX + " as " + KEY_PERFORMANCE_GFX);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_H264 + " as " + KEY_PERFORMANCE_H264);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_WALLPAPER + " as " + KEY_PERFORMANCE_WALLPAPER);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_THEME + " as " + KEY_PERFORMANCE_THEME);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_DRAG + " as " + KEY_PERFORMANCE_DRAG);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_MENU_ANIMATIONS + " as " +
|
||||
KEY_PERFORMANCE_MENU_ANIMATIONS);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_FONTS + " as " + KEY_PERFORMANCE_FONTS);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_COMPOSITION + " " + KEY_PERFORMANCE_COMPOSITION);
|
||||
}
|
||||
|
||||
private void addScreenSettings3GColumns(ArrayList<String> columns)
|
||||
{
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_SCREEN_SETTINGS_3G + "." +
|
||||
BookmarkDB.DB_KEY_SCREEN_COLORS + " as " + KEY_SCREEN_COLORS_3G);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_SCREEN_SETTINGS_3G + "." +
|
||||
BookmarkDB.DB_KEY_SCREEN_RESOLUTION + " as " + KEY_SCREEN_RESOLUTION_3G);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_SCREEN_SETTINGS_3G + "." +
|
||||
BookmarkDB.DB_KEY_SCREEN_WIDTH + " as " + KEY_SCREEN_WIDTH_3G);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_SCREEN_SETTINGS_3G + "." +
|
||||
BookmarkDB.DB_KEY_SCREEN_HEIGHT + " as " + KEY_SCREEN_HEIGHT_3G);
|
||||
}
|
||||
|
||||
private void addPerformanceFlags3GColumns(ArrayList<String> columns)
|
||||
{
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS_3G + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_RFX + " as " + KEY_PERFORMANCE_RFX_3G);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS_3G + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_GFX + " as " + KEY_PERFORMANCE_GFX_3G);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS_3G + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_H264 + " as " + KEY_PERFORMANCE_H264_3G);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS_3G + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_WALLPAPER + " as " +
|
||||
KEY_PERFORMANCE_WALLPAPER_3G);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS_3G + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_THEME + " as " + KEY_PERFORMANCE_THEME_3G);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS_3G + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_DRAG + " as " + KEY_PERFORMANCE_DRAG_3G);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS_3G + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_MENU_ANIMATIONS + " as " +
|
||||
KEY_PERFORMANCE_MENU_ANIMATIONS_3G);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS_3G + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_FONTS + " as " + KEY_PERFORMANCE_FONTS_3G);
|
||||
columns.add(JOIN_PREFIX + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS_3G + "." +
|
||||
BookmarkDB.DB_KEY_PERFORMANCE_COMPOSITION + " " +
|
||||
KEY_PERFORMANCE_COMPOSITION_3G);
|
||||
}
|
||||
|
||||
protected BookmarkBase getBookmarkFromCursor(Cursor cursor)
|
||||
{
|
||||
BookmarkBase bookmark = createBookmark();
|
||||
bookmark.setId(cursor.getLong(cursor.getColumnIndex(KEY_BOOKMARK_ID)));
|
||||
bookmark.setLabel(
|
||||
cursor.getString(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_LABEL)));
|
||||
bookmark.setUsername(
|
||||
cursor.getString(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_USERNAME)));
|
||||
bookmark.setPassword(
|
||||
cursor.getString(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_PASSWORD)));
|
||||
bookmark.setDomain(
|
||||
cursor.getString(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_DOMAIN)));
|
||||
readScreenSettings(bookmark, cursor);
|
||||
readPerformanceFlags(bookmark, cursor);
|
||||
|
||||
// advanced settings
|
||||
bookmark.getAdvancedSettings().setEnable3GSettings(
|
||||
cursor.getInt(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_3G_ENABLE)) != 0);
|
||||
readScreenSettings3G(bookmark, cursor);
|
||||
readPerformanceFlags3G(bookmark, cursor);
|
||||
bookmark.getAdvancedSettings().setRedirectSDCard(
|
||||
cursor.getInt(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_REDIRECT_SDCARD)) != 0);
|
||||
bookmark.getAdvancedSettings().setRedirectSound(
|
||||
cursor.getInt(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_REDIRECT_SOUND)));
|
||||
bookmark.getAdvancedSettings().setRedirectMicrophone(
|
||||
cursor.getInt(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_REDIRECT_MICROPHONE)) !=
|
||||
0);
|
||||
bookmark.getAdvancedSettings().setSecurity(
|
||||
cursor.getInt(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_SECURITY)));
|
||||
bookmark.getAdvancedSettings().setConsoleMode(
|
||||
cursor.getInt(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_CONSOLE_MODE)) != 0);
|
||||
bookmark.getAdvancedSettings().setRemoteProgram(
|
||||
cursor.getString(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_REMOTE_PROGRAM)));
|
||||
bookmark.getAdvancedSettings().setWorkDir(
|
||||
cursor.getString(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_WORK_DIR)));
|
||||
|
||||
bookmark.getDebugSettings().setAsyncChannel(
|
||||
cursor.getInt(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_ASYNC_CHANNEL)) == 1);
|
||||
bookmark.getDebugSettings().setAsyncUpdate(
|
||||
cursor.getInt(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_ASYNC_UPDATE)) == 1);
|
||||
bookmark.getDebugSettings().setDebugLevel(
|
||||
cursor.getString(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_DEBUG_LEVEL)));
|
||||
|
||||
readBookmarkSpecificColumns(bookmark, cursor);
|
||||
|
||||
return bookmark;
|
||||
}
|
||||
|
||||
private void readScreenSettings(BookmarkBase bookmark, Cursor cursor)
|
||||
{
|
||||
BookmarkBase.ScreenSettings screenSettings = bookmark.getScreenSettings();
|
||||
screenSettings.setColors(cursor.getInt(cursor.getColumnIndex(KEY_SCREEN_COLORS)));
|
||||
screenSettings.setResolution(cursor.getInt(cursor.getColumnIndex(KEY_SCREEN_RESOLUTION)));
|
||||
screenSettings.setWidth(cursor.getInt(cursor.getColumnIndex(KEY_SCREEN_WIDTH)));
|
||||
screenSettings.setHeight(cursor.getInt(cursor.getColumnIndex(KEY_SCREEN_HEIGHT)));
|
||||
}
|
||||
|
||||
private void readPerformanceFlags(BookmarkBase bookmark, Cursor cursor)
|
||||
{
|
||||
BookmarkBase.PerformanceFlags perfFlags = bookmark.getPerformanceFlags();
|
||||
perfFlags.setRemoteFX(cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_RFX)) != 0);
|
||||
perfFlags.setGfx(cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_GFX)) != 0);
|
||||
perfFlags.setH264(cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_H264)) != 0);
|
||||
perfFlags.setWallpaper(cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_WALLPAPER)) !=
|
||||
0);
|
||||
perfFlags.setTheming(cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_THEME)) != 0);
|
||||
perfFlags.setFullWindowDrag(cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_DRAG)) !=
|
||||
0);
|
||||
perfFlags.setMenuAnimations(
|
||||
cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_MENU_ANIMATIONS)) != 0);
|
||||
perfFlags.setFontSmoothing(cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_FONTS)) !=
|
||||
0);
|
||||
perfFlags.setDesktopComposition(
|
||||
cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_COMPOSITION)) != 0);
|
||||
}
|
||||
|
||||
private void readScreenSettings3G(BookmarkBase bookmark, Cursor cursor)
|
||||
{
|
||||
BookmarkBase.ScreenSettings screenSettings = bookmark.getAdvancedSettings().getScreen3G();
|
||||
screenSettings.setColors(cursor.getInt(cursor.getColumnIndex(KEY_SCREEN_COLORS_3G)));
|
||||
screenSettings.setResolution(
|
||||
cursor.getInt(cursor.getColumnIndex(KEY_SCREEN_RESOLUTION_3G)));
|
||||
screenSettings.setWidth(cursor.getInt(cursor.getColumnIndex(KEY_SCREEN_WIDTH_3G)));
|
||||
screenSettings.setHeight(cursor.getInt(cursor.getColumnIndex(KEY_SCREEN_HEIGHT_3G)));
|
||||
}
|
||||
|
||||
private void readPerformanceFlags3G(BookmarkBase bookmark, Cursor cursor)
|
||||
{
|
||||
BookmarkBase.PerformanceFlags perfFlags = bookmark.getAdvancedSettings().getPerformance3G();
|
||||
perfFlags.setRemoteFX(cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_RFX_3G)) != 0);
|
||||
perfFlags.setGfx(cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_GFX_3G)) != 0);
|
||||
perfFlags.setH264(cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_H264_3G)) != 0);
|
||||
perfFlags.setWallpaper(cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_WALLPAPER_3G)) !=
|
||||
0);
|
||||
perfFlags.setTheming(cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_THEME_3G)) != 0);
|
||||
perfFlags.setFullWindowDrag(cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_DRAG_3G)) !=
|
||||
0);
|
||||
perfFlags.setMenuAnimations(
|
||||
cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_MENU_ANIMATIONS_3G)) != 0);
|
||||
perfFlags.setFontSmoothing(cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_FONTS_3G)) !=
|
||||
0);
|
||||
perfFlags.setDesktopComposition(
|
||||
cursor.getInt(cursor.getColumnIndex(KEY_PERFORMANCE_COMPOSITION_3G)) != 0);
|
||||
}
|
||||
|
||||
private void fillScreenSettingsContentValues(BookmarkBase.ScreenSettings settings,
|
||||
ContentValues values)
|
||||
{
|
||||
values.put(BookmarkDB.DB_KEY_SCREEN_COLORS, settings.getColors());
|
||||
values.put(BookmarkDB.DB_KEY_SCREEN_RESOLUTION, settings.getResolution());
|
||||
values.put(BookmarkDB.DB_KEY_SCREEN_WIDTH, settings.getWidth());
|
||||
values.put(BookmarkDB.DB_KEY_SCREEN_HEIGHT, settings.getHeight());
|
||||
}
|
||||
|
||||
private void fillPerformanceFlagsContentValues(BookmarkBase.PerformanceFlags perfFlags,
|
||||
ContentValues values)
|
||||
{
|
||||
values.put(BookmarkDB.DB_KEY_PERFORMANCE_RFX, perfFlags.getRemoteFX());
|
||||
values.put(BookmarkDB.DB_KEY_PERFORMANCE_GFX, perfFlags.getGfx());
|
||||
values.put(BookmarkDB.DB_KEY_PERFORMANCE_H264, perfFlags.getH264());
|
||||
values.put(BookmarkDB.DB_KEY_PERFORMANCE_WALLPAPER, perfFlags.getWallpaper());
|
||||
values.put(BookmarkDB.DB_KEY_PERFORMANCE_THEME, perfFlags.getTheming());
|
||||
values.put(BookmarkDB.DB_KEY_PERFORMANCE_DRAG, perfFlags.getFullWindowDrag());
|
||||
values.put(BookmarkDB.DB_KEY_PERFORMANCE_MENU_ANIMATIONS, perfFlags.getMenuAnimations());
|
||||
values.put(BookmarkDB.DB_KEY_PERFORMANCE_FONTS, perfFlags.getFontSmoothing());
|
||||
values.put(BookmarkDB.DB_KEY_PERFORMANCE_COMPOSITION, perfFlags.getDesktopComposition());
|
||||
}
|
||||
|
||||
private long insertScreenSettings(SQLiteDatabase db, BookmarkBase.ScreenSettings settings)
|
||||
{
|
||||
ContentValues values = new ContentValues();
|
||||
fillScreenSettingsContentValues(settings, values);
|
||||
return db.insertOrThrow(BookmarkDB.DB_TABLE_SCREEN, null, values);
|
||||
}
|
||||
|
||||
private boolean updateScreenSettings(SQLiteDatabase db, BookmarkBase bookmark)
|
||||
{
|
||||
ContentValues values = new ContentValues();
|
||||
fillScreenSettingsContentValues(bookmark.getScreenSettings(), values);
|
||||
String whereClause = BookmarkDB.ID + " IN "
|
||||
+ "(SELECT " + BookmarkDB.DB_KEY_SCREEN_SETTINGS + " FROM " +
|
||||
getBookmarkTableName() + " WHERE " + BookmarkDB.ID + " = " +
|
||||
bookmark.getId() + ");";
|
||||
return (db.update(BookmarkDB.DB_TABLE_SCREEN, values, whereClause, null) == 1);
|
||||
}
|
||||
|
||||
private boolean updateScreenSettings3G(SQLiteDatabase db, BookmarkBase bookmark)
|
||||
{
|
||||
ContentValues values = new ContentValues();
|
||||
fillScreenSettingsContentValues(bookmark.getAdvancedSettings().getScreen3G(), values);
|
||||
String whereClause = BookmarkDB.ID + " IN "
|
||||
+ "(SELECT " + BookmarkDB.DB_KEY_SCREEN_SETTINGS_3G + " FROM " +
|
||||
getBookmarkTableName() + " WHERE " + BookmarkDB.ID + " = " +
|
||||
bookmark.getId() + ");";
|
||||
return (db.update(BookmarkDB.DB_TABLE_SCREEN, values, whereClause, null) == 1);
|
||||
}
|
||||
|
||||
private long insertPerformanceFlags(SQLiteDatabase db, BookmarkBase.PerformanceFlags perfFlags)
|
||||
{
|
||||
ContentValues values = new ContentValues();
|
||||
fillPerformanceFlagsContentValues(perfFlags, values);
|
||||
return db.insertOrThrow(BookmarkDB.DB_TABLE_PERFORMANCE, null, values);
|
||||
}
|
||||
|
||||
private boolean updatePerformanceFlags(SQLiteDatabase db, BookmarkBase bookmark)
|
||||
{
|
||||
ContentValues values = new ContentValues();
|
||||
fillPerformanceFlagsContentValues(bookmark.getPerformanceFlags(), values);
|
||||
String whereClause = BookmarkDB.ID + " IN "
|
||||
+ "(SELECT " + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS + " FROM " +
|
||||
getBookmarkTableName() + " WHERE " + BookmarkDB.ID + " = " +
|
||||
bookmark.getId() + ");";
|
||||
return (db.update(BookmarkDB.DB_TABLE_PERFORMANCE, values, whereClause, null) == 1);
|
||||
}
|
||||
|
||||
private boolean updatePerformanceFlags3G(SQLiteDatabase db, BookmarkBase bookmark)
|
||||
{
|
||||
ContentValues values = new ContentValues();
|
||||
fillPerformanceFlagsContentValues(bookmark.getAdvancedSettings().getPerformance3G(),
|
||||
values);
|
||||
String whereClause = BookmarkDB.ID + " IN "
|
||||
+ "(SELECT " + BookmarkDB.DB_KEY_PERFORMANCE_FLAGS_3G + " FROM " +
|
||||
getBookmarkTableName() + " WHERE " + BookmarkDB.ID + " = " +
|
||||
bookmark.getId() + ");";
|
||||
return (db.update(BookmarkDB.DB_TABLE_PERFORMANCE, values, whereClause, null) == 1);
|
||||
}
|
||||
|
||||
// safety wrappers
|
||||
// in case of getReadableDatabase it could happen that upgradeDB gets called which is
|
||||
// a problem if the DB is only readable
|
||||
private SQLiteDatabase getWritableDatabase()
|
||||
{
|
||||
return bookmarkDB.getWritableDatabase();
|
||||
}
|
||||
|
||||
private SQLiteDatabase getReadableDatabase()
|
||||
{
|
||||
SQLiteDatabase db;
|
||||
try
|
||||
{
|
||||
db = bookmarkDB.getReadableDatabase();
|
||||
}
|
||||
catch (SQLiteException e)
|
||||
{
|
||||
db = bookmarkDB.getWritableDatabase();
|
||||
}
|
||||
return db;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,412 @@
|
||||
/*
|
||||
Android Bookmark Database
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.services;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.provider.BaseColumns;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class BookmarkDB extends SQLiteOpenHelper
|
||||
{
|
||||
public static final String ID = BaseColumns._ID;
|
||||
private static final int DB_VERSION = 10;
|
||||
private static final String DB_BACKUP_PREFIX = "temp_";
|
||||
private static final String DB_NAME = "bookmarks.db";
|
||||
static final String DB_TABLE_BOOKMARK = "tbl_manual_bookmarks";
|
||||
static final String DB_TABLE_SCREEN = "tbl_screen_settings";
|
||||
static final String DB_TABLE_PERFORMANCE = "tbl_performance_flags";
|
||||
private static final String[] DB_TABLES = { DB_TABLE_BOOKMARK, DB_TABLE_SCREEN,
|
||||
DB_TABLE_PERFORMANCE };
|
||||
|
||||
static final String DB_KEY_SCREEN_COLORS = "colors";
|
||||
static final String DB_KEY_SCREEN_RESOLUTION = "resolution";
|
||||
static final String DB_KEY_SCREEN_WIDTH = "width";
|
||||
static final String DB_KEY_SCREEN_HEIGHT = "height";
|
||||
|
||||
static final String DB_KEY_SCREEN_SETTINGS = "screen_settings";
|
||||
static final String DB_KEY_SCREEN_SETTINGS_3G = "screen_3g";
|
||||
static final String DB_KEY_PERFORMANCE_FLAGS = "performance_flags";
|
||||
static final String DB_KEY_PERFORMANCE_FLAGS_3G = "performance_3g";
|
||||
|
||||
static final String DB_KEY_PERFORMANCE_RFX = "perf_remotefx";
|
||||
static final String DB_KEY_PERFORMANCE_GFX = "perf_gfx";
|
||||
static final String DB_KEY_PERFORMANCE_H264 = "perf_gfx_h264";
|
||||
static final String DB_KEY_PERFORMANCE_WALLPAPER = "perf_wallpaper";
|
||||
static final String DB_KEY_PERFORMANCE_THEME = "perf_theming";
|
||||
static final String DB_KEY_PERFORMANCE_DRAG = "perf_full_window_drag";
|
||||
static final String DB_KEY_PERFORMANCE_MENU_ANIMATIONS = "perf_menu_animations";
|
||||
static final String DB_KEY_PERFORMANCE_FONTS = "perf_font_smoothing";
|
||||
static final String DB_KEY_PERFORMANCE_COMPOSITION = "perf_desktop_composition";
|
||||
|
||||
static final String DB_KEY_BOOKMARK_LABEL = "label";
|
||||
static final String DB_KEY_BOOKMARK_HOSTNAME = "hostname";
|
||||
static final String DB_KEY_BOOKMARK_USERNAME = "username";
|
||||
static final String DB_KEY_BOOKMARK_PASSWORD = "password";
|
||||
static final String DB_KEY_BOOKMARK_DOMAIN = "domain";
|
||||
static final String DB_KEY_BOOKMARK_PORT = "port";
|
||||
|
||||
static final String DB_KEY_BOOKMARK_REDIRECT_SDCARD = "redirect_sdcard";
|
||||
static final String DB_KEY_BOOKMARK_REDIRECT_SOUND = "redirect_sound";
|
||||
static final String DB_KEY_BOOKMARK_REDIRECT_MICROPHONE = "redirect_microphone";
|
||||
static final String DB_KEY_BOOKMARK_SECURITY = "security";
|
||||
static final String DB_KEY_BOOKMARK_REMOTE_PROGRAM = "remote_program";
|
||||
static final String DB_KEY_BOOKMARK_WORK_DIR = "work_dir";
|
||||
static final String DB_KEY_BOOKMARK_ASYNC_CHANNEL = "async_channel";
|
||||
static final String DB_KEY_BOOKMARK_ASYNC_UPDATE = "async_update";
|
||||
static final String DB_KEY_BOOKMARK_CONSOLE_MODE = "console_mode";
|
||||
static final String DB_KEY_BOOKMARK_DEBUG_LEVEL = "debug_level";
|
||||
|
||||
static final String DB_KEY_BOOKMARK_GW_ENABLE = "enable_gateway_settings";
|
||||
static final String DB_KEY_BOOKMARK_GW_HOSTNAME = "gateway_hostname";
|
||||
static final String DB_KEY_BOOKMARK_GW_PORT = "gateway_port";
|
||||
static final String DB_KEY_BOOKMARK_GW_USERNAME = "gateway_username";
|
||||
static final String DB_KEY_BOOKMARK_GW_PASSWORD = "gateway_password";
|
||||
static final String DB_KEY_BOOKMARK_GW_DOMAIN = "gateway_domain";
|
||||
static final String DB_KEY_BOOKMARK_3G_ENABLE = "enable_3g_settings";
|
||||
|
||||
public BookmarkDB(Context context)
|
||||
{
|
||||
super(context, DB_NAME, null, DB_VERSION);
|
||||
}
|
||||
|
||||
private static List<String> GetColumns(SQLiteDatabase db, String tableName)
|
||||
{
|
||||
List<String> ar = null;
|
||||
try (Cursor c = db.rawQuery("SELECT * FROM " + tableName + " LIMIT 1", null))
|
||||
{
|
||||
if (c != null)
|
||||
{
|
||||
ar = new ArrayList<>(Arrays.asList(c.getColumnNames()));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.v(tableName, e.getMessage(), e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
return ar;
|
||||
}
|
||||
|
||||
private static String joinStrings(List<String> list, String delim)
|
||||
{
|
||||
StringBuilder buf = new StringBuilder();
|
||||
int num = list.size();
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
if (i != 0)
|
||||
buf.append(delim);
|
||||
buf.append(list.get(i));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private void backupTables(SQLiteDatabase db)
|
||||
{
|
||||
for (String table : DB_TABLES)
|
||||
{
|
||||
final String tmpTable = DB_BACKUP_PREFIX + table;
|
||||
final String query = "ALTER TABLE '" + table + "' RENAME TO '" + tmpTable + "'";
|
||||
try
|
||||
{
|
||||
db.execSQL(query);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
/* Ignore errors if table does not exist. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dropOldTables(SQLiteDatabase db)
|
||||
{
|
||||
for (String table : DB_TABLES)
|
||||
{
|
||||
final String tmpTable = DB_BACKUP_PREFIX + table;
|
||||
final String query = "DROP TABLE IF EXISTS '" + tmpTable + "'";
|
||||
db.execSQL(query);
|
||||
}
|
||||
}
|
||||
|
||||
private void createDB(SQLiteDatabase db)
|
||||
{
|
||||
final String sqlScreenSettings =
|
||||
"CREATE TABLE IF NOT EXISTS " + DB_TABLE_SCREEN + " (" + ID + " INTEGER PRIMARY KEY, " +
|
||||
DB_KEY_SCREEN_COLORS + " INTEGER DEFAULT 16, " + DB_KEY_SCREEN_RESOLUTION +
|
||||
" INTEGER DEFAULT 0, " + DB_KEY_SCREEN_WIDTH + ", " + DB_KEY_SCREEN_HEIGHT + ");";
|
||||
|
||||
db.execSQL(sqlScreenSettings);
|
||||
|
||||
final String sqlPerformanceFlags =
|
||||
"CREATE TABLE IF NOT EXISTS " + DB_TABLE_PERFORMANCE + " (" + ID +
|
||||
" INTEGER PRIMARY KEY, " + DB_KEY_PERFORMANCE_RFX + " INTEGER, " +
|
||||
DB_KEY_PERFORMANCE_GFX + " INTEGER, " + DB_KEY_PERFORMANCE_H264 + " INTEGER, " +
|
||||
DB_KEY_PERFORMANCE_WALLPAPER + " INTEGER, " + DB_KEY_PERFORMANCE_THEME + " INTEGER, " +
|
||||
DB_KEY_PERFORMANCE_DRAG + " INTEGER, " + DB_KEY_PERFORMANCE_MENU_ANIMATIONS +
|
||||
" INTEGER, " + DB_KEY_PERFORMANCE_FONTS + " INTEGER, " +
|
||||
DB_KEY_PERFORMANCE_COMPOSITION + " INTEGER);";
|
||||
|
||||
db.execSQL(sqlPerformanceFlags);
|
||||
|
||||
final String sqlManualBookmarks = getManualBookmarksCreationString();
|
||||
db.execSQL(sqlManualBookmarks);
|
||||
}
|
||||
|
||||
private void upgradeTables(SQLiteDatabase db)
|
||||
{
|
||||
for (String table : DB_TABLES)
|
||||
{
|
||||
final String tmpTable = DB_BACKUP_PREFIX + table;
|
||||
|
||||
final List<String> newColumns = GetColumns(db, table);
|
||||
List<String> columns = GetColumns(db, tmpTable);
|
||||
|
||||
if (columns != null)
|
||||
{
|
||||
columns.retainAll(newColumns);
|
||||
|
||||
// restore data
|
||||
final String cols = joinStrings(columns, ",");
|
||||
final String query = String.format("INSERT INTO %s (%s) SELECT %s from '%s'", table,
|
||||
cols, cols, tmpTable);
|
||||
db.execSQL(query);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void downgradeTables(SQLiteDatabase db)
|
||||
{
|
||||
for (String table : DB_TABLES)
|
||||
{
|
||||
final String tmpTable = DB_BACKUP_PREFIX + table;
|
||||
|
||||
List<String> oldColumns = GetColumns(db, table);
|
||||
final List<String> columns = GetColumns(db, tmpTable);
|
||||
|
||||
if (oldColumns != null)
|
||||
{
|
||||
oldColumns.retainAll(columns);
|
||||
|
||||
// restore data
|
||||
final String cols = joinStrings(oldColumns, ",");
|
||||
final String query = String.format("INSERT INTO %s (%s) SELECT %s from '%s'", table,
|
||||
cols, cols, tmpTable);
|
||||
db.execSQL(query);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getTableNames(SQLiteDatabase db)
|
||||
{
|
||||
final String query = "SELECT name FROM sqlite_master WHERE type='table'";
|
||||
Cursor cursor = db.rawQuery(query, null);
|
||||
List<String> list = new ArrayList<>();
|
||||
try
|
||||
{
|
||||
if (cursor.moveToFirst() && (cursor.getCount() > 0))
|
||||
{
|
||||
while (!cursor.isAfterLast())
|
||||
{
|
||||
final String name = cursor.getString(cursor.getColumnIndex("name"));
|
||||
list.add(name);
|
||||
cursor.moveToNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private void insertDefault(SQLiteDatabase db)
|
||||
{
|
||||
ContentValues screenValues = new ContentValues();
|
||||
screenValues.put(DB_KEY_SCREEN_COLORS, 32);
|
||||
screenValues.put(DB_KEY_SCREEN_RESOLUTION, 1);
|
||||
screenValues.put(DB_KEY_SCREEN_WIDTH, 1024);
|
||||
screenValues.put(DB_KEY_SCREEN_HEIGHT, 768);
|
||||
|
||||
final long idScreen = db.insert(DB_TABLE_SCREEN, null, screenValues);
|
||||
final long idScreen3g = db.insert(DB_TABLE_SCREEN, null, screenValues);
|
||||
|
||||
ContentValues performanceValues = new ContentValues();
|
||||
performanceValues.put(DB_KEY_PERFORMANCE_RFX, 1);
|
||||
performanceValues.put(DB_KEY_PERFORMANCE_GFX, 1);
|
||||
performanceValues.put(DB_KEY_PERFORMANCE_H264, 0);
|
||||
performanceValues.put(DB_KEY_PERFORMANCE_WALLPAPER, 0);
|
||||
performanceValues.put(DB_KEY_PERFORMANCE_THEME, 0);
|
||||
performanceValues.put(DB_KEY_PERFORMANCE_DRAG, 0);
|
||||
performanceValues.put(DB_KEY_PERFORMANCE_MENU_ANIMATIONS, 0);
|
||||
performanceValues.put(DB_KEY_PERFORMANCE_FONTS, 0);
|
||||
performanceValues.put(DB_KEY_PERFORMANCE_COMPOSITION, 0);
|
||||
|
||||
final long idPerformance = db.insert(DB_TABLE_PERFORMANCE, null, performanceValues);
|
||||
final long idPerformance3g = db.insert(DB_TABLE_PERFORMANCE, null, performanceValues);
|
||||
|
||||
ContentValues bookmarkValues = new ContentValues();
|
||||
bookmarkValues.put(DB_KEY_BOOKMARK_LABEL, "Test Server");
|
||||
bookmarkValues.put(DB_KEY_BOOKMARK_HOSTNAME, "testservice.afreerdp.com");
|
||||
bookmarkValues.put(DB_KEY_BOOKMARK_USERNAME, "");
|
||||
bookmarkValues.put(DB_KEY_BOOKMARK_PASSWORD, "");
|
||||
bookmarkValues.put(DB_KEY_BOOKMARK_DOMAIN, "");
|
||||
bookmarkValues.put(DB_KEY_BOOKMARK_PORT, "3389");
|
||||
|
||||
bookmarkValues.put(DB_KEY_SCREEN_SETTINGS, idScreen);
|
||||
bookmarkValues.put(DB_KEY_SCREEN_SETTINGS_3G, idScreen3g);
|
||||
bookmarkValues.put(DB_KEY_PERFORMANCE_FLAGS, idPerformance);
|
||||
bookmarkValues.put(DB_KEY_PERFORMANCE_FLAGS_3G, idPerformance3g);
|
||||
|
||||
bookmarkValues.put(DB_KEY_BOOKMARK_REDIRECT_SDCARD, 0);
|
||||
bookmarkValues.put(DB_KEY_BOOKMARK_REDIRECT_SOUND, 0);
|
||||
bookmarkValues.put(DB_KEY_BOOKMARK_REDIRECT_MICROPHONE, 0);
|
||||
bookmarkValues.put(DB_KEY_BOOKMARK_SECURITY, 0);
|
||||
bookmarkValues.put(DB_KEY_BOOKMARK_REMOTE_PROGRAM, "");
|
||||
bookmarkValues.put(DB_KEY_BOOKMARK_WORK_DIR, "");
|
||||
bookmarkValues.put(DB_KEY_BOOKMARK_ASYNC_CHANNEL, 1);
|
||||
bookmarkValues.put(DB_KEY_BOOKMARK_ASYNC_UPDATE, 1);
|
||||
bookmarkValues.put(DB_KEY_BOOKMARK_CONSOLE_MODE, 0);
|
||||
bookmarkValues.put(DB_KEY_BOOKMARK_DEBUG_LEVEL, "INFO");
|
||||
|
||||
db.insert(DB_TABLE_BOOKMARK, null, bookmarkValues);
|
||||
}
|
||||
|
||||
@Override public void onCreate(SQLiteDatabase db)
|
||||
{
|
||||
createDB(db);
|
||||
insertDefault(db);
|
||||
}
|
||||
|
||||
private String getManualBookmarksCreationString()
|
||||
{
|
||||
return ("CREATE TABLE IF NOT EXISTS " + DB_TABLE_BOOKMARK + " (" + ID +
|
||||
" INTEGER PRIMARY KEY, " + DB_KEY_BOOKMARK_LABEL + " TEXT NOT NULL, " +
|
||||
DB_KEY_BOOKMARK_HOSTNAME + " TEXT NOT NULL, " + DB_KEY_BOOKMARK_USERNAME +
|
||||
" TEXT NOT NULL, " + DB_KEY_BOOKMARK_PASSWORD + " TEXT, " + DB_KEY_BOOKMARK_DOMAIN +
|
||||
" TEXT, " + DB_KEY_BOOKMARK_PORT + " TEXT, " + DB_KEY_SCREEN_SETTINGS +
|
||||
" INTEGER NOT NULL, " + DB_KEY_PERFORMANCE_FLAGS + " INTEGER NOT NULL, "
|
||||
|
||||
+ DB_KEY_BOOKMARK_GW_ENABLE + " INTEGER DEFAULT 0, " + DB_KEY_BOOKMARK_GW_HOSTNAME +
|
||||
" TEXT, " + DB_KEY_BOOKMARK_GW_PORT + " INTEGER DEFAULT 443, " +
|
||||
DB_KEY_BOOKMARK_GW_USERNAME + " TEXT, " + DB_KEY_BOOKMARK_GW_PASSWORD + " TEXT, " +
|
||||
DB_KEY_BOOKMARK_GW_DOMAIN + " TEXT, "
|
||||
|
||||
+ DB_KEY_BOOKMARK_3G_ENABLE + " INTEGER DEFAULT 0, " + DB_KEY_SCREEN_SETTINGS_3G +
|
||||
" INTEGER NOT NULL, " + DB_KEY_PERFORMANCE_FLAGS_3G + " INTEGER NOT NULL, " +
|
||||
DB_KEY_BOOKMARK_REDIRECT_SDCARD + " INTEGER DEFAULT 0, " +
|
||||
DB_KEY_BOOKMARK_REDIRECT_SOUND + " INTEGER DEFAULT 0, " +
|
||||
DB_KEY_BOOKMARK_REDIRECT_MICROPHONE + " INTEGER DEFAULT 0, " +
|
||||
DB_KEY_BOOKMARK_SECURITY + " INTEGER, " + DB_KEY_BOOKMARK_REMOTE_PROGRAM +
|
||||
" TEXT, " + DB_KEY_BOOKMARK_WORK_DIR + " TEXT, " + DB_KEY_BOOKMARK_ASYNC_CHANNEL +
|
||||
" INTEGER DEFAULT 0, " + DB_KEY_BOOKMARK_ASYNC_UPDATE + " INTEGER DEFAULT 0, " +
|
||||
DB_KEY_BOOKMARK_CONSOLE_MODE + " INTEGER, " + DB_KEY_BOOKMARK_DEBUG_LEVEL +
|
||||
" TEXT DEFAULT 'INFO', "
|
||||
|
||||
+ "FOREIGN KEY(" + DB_KEY_SCREEN_SETTINGS + ") REFERENCES " + DB_TABLE_SCREEN +
|
||||
"(" + ID + "), "
|
||||
+ "FOREIGN KEY(" + DB_KEY_PERFORMANCE_FLAGS + ") REFERENCES " +
|
||||
DB_TABLE_PERFORMANCE + "(" + ID + "), "
|
||||
+ "FOREIGN KEY(" + DB_KEY_SCREEN_SETTINGS_3G + ") REFERENCES " + DB_TABLE_SCREEN +
|
||||
"(" + ID + "), "
|
||||
+ "FOREIGN KEY(" + DB_KEY_PERFORMANCE_FLAGS_3G + ") REFERENCES " +
|
||||
DB_TABLE_PERFORMANCE + "(" + ID + ") "
|
||||
|
||||
+ ");");
|
||||
}
|
||||
|
||||
private void recreateDB(SQLiteDatabase db)
|
||||
{
|
||||
for (String table : DB_TABLES)
|
||||
{
|
||||
final String query = "DROP TABLE IF EXISTS '" + table + "'";
|
||||
db.execSQL(query);
|
||||
}
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
private void upgradeDB(SQLiteDatabase db)
|
||||
{
|
||||
db.beginTransaction();
|
||||
try
|
||||
{
|
||||
/* Back up old tables. */
|
||||
dropOldTables(db);
|
||||
backupTables(db);
|
||||
createDB(db);
|
||||
upgradeTables(db);
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
}
|
||||
finally
|
||||
{
|
||||
db.endTransaction();
|
||||
dropOldTables(db);
|
||||
}
|
||||
}
|
||||
|
||||
private void downgradeDB(SQLiteDatabase db)
|
||||
{
|
||||
db.beginTransaction();
|
||||
try
|
||||
{
|
||||
/* Back up old tables. */
|
||||
dropOldTables(db);
|
||||
backupTables(db);
|
||||
createDB(db);
|
||||
downgradeTables(db);
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
}
|
||||
finally
|
||||
{
|
||||
db.endTransaction();
|
||||
dropOldTables(db);
|
||||
}
|
||||
}
|
||||
|
||||
// from
|
||||
// http://stackoverflow.com/questions/3424156/upgrade-sqlite-database-from-one-version-to-another
|
||||
@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
|
||||
{
|
||||
switch (oldVersion)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
upgradeDB(db);
|
||||
break;
|
||||
default:
|
||||
recreateDB(db);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion)
|
||||
{
|
||||
downgradeDB(db);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
Suggestion Provider for RDP bookmarks
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.services;
|
||||
|
||||
import android.app.SearchManager;
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.net.Uri;
|
||||
|
||||
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 java.util.ArrayList;
|
||||
|
||||
public class FreeRDPSuggestionProvider extends ContentProvider
|
||||
{
|
||||
|
||||
public static final Uri CONTENT_URI =
|
||||
Uri.parse("content://com.freerdp.afreerdp.services.freerdpsuggestionprovider");
|
||||
|
||||
@Override public int delete(Uri uri, String selection, String[] selectionArgs)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override public String getType(Uri uri)
|
||||
{
|
||||
return "vnd.android.cursor.item/vnd.freerdp.remote";
|
||||
}
|
||||
|
||||
@Override public Uri insert(Uri uri, ContentValues values)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override public boolean onCreate()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
||||
String sortOrder)
|
||||
{
|
||||
|
||||
String query = (selectionArgs != null && selectionArgs.length > 0) ? selectionArgs[0] : "";
|
||||
|
||||
// search history
|
||||
ArrayList<BookmarkBase> history =
|
||||
GlobalApp.getQuickConnectHistoryGateway().findHistory(query);
|
||||
|
||||
// search bookmarks
|
||||
ArrayList<BookmarkBase> manualBookmarks;
|
||||
if (query.length() > 0)
|
||||
manualBookmarks = GlobalApp.getManualBookmarkGateway().findByLabelOrHostnameLike(query);
|
||||
else
|
||||
manualBookmarks = GlobalApp.getManualBookmarkGateway().findAll();
|
||||
|
||||
return createResultCursor(history, manualBookmarks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void addBookmarksToCursor(ArrayList<BookmarkBase> bookmarks, MatrixCursor resultCursor)
|
||||
{
|
||||
Object[] row = new Object[5];
|
||||
for (BookmarkBase bookmark : bookmarks)
|
||||
{
|
||||
row[0] = bookmark.getId();
|
||||
row[1] = bookmark.getLabel();
|
||||
row[2] = bookmark.<ManualBookmark>get().getHostname();
|
||||
row[3] = ConnectionReference.getManualBookmarkReference(bookmark.getId());
|
||||
row[4] = "android.resource://" + getContext().getPackageName() + "/" +
|
||||
R.drawable.icon_star_on;
|
||||
resultCursor.addRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
private void addHistoryToCursor(ArrayList<BookmarkBase> history, MatrixCursor resultCursor)
|
||||
{
|
||||
Object[] row = new Object[5];
|
||||
for (BookmarkBase bookmark : history)
|
||||
{
|
||||
row[0] = 1;
|
||||
row[1] = bookmark.getLabel();
|
||||
row[2] = bookmark.getLabel();
|
||||
row[3] = ConnectionReference.getHostnameReference(bookmark.getLabel());
|
||||
row[4] = "android.resource://" + getContext().getPackageName() + "/" +
|
||||
R.drawable.icon_star_off;
|
||||
resultCursor.addRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
private Cursor createResultCursor(ArrayList<BookmarkBase> history,
|
||||
ArrayList<BookmarkBase> manualBookmarks)
|
||||
{
|
||||
|
||||
// create result matrix cursor
|
||||
int totalCount = history.size() + manualBookmarks.size();
|
||||
String[] columns = { android.provider.BaseColumns._ID, SearchManager.SUGGEST_COLUMN_TEXT_1,
|
||||
SearchManager.SUGGEST_COLUMN_TEXT_2,
|
||||
SearchManager.SUGGEST_COLUMN_INTENT_DATA,
|
||||
SearchManager.SUGGEST_COLUMN_ICON_2 };
|
||||
MatrixCursor matrixCursor = new MatrixCursor(columns, totalCount);
|
||||
|
||||
// populate result matrix
|
||||
if (totalCount > 0)
|
||||
{
|
||||
addHistoryToCursor(history, matrixCursor);
|
||||
addBookmarksToCursor(manualBookmarks, matrixCursor);
|
||||
}
|
||||
return matrixCursor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Quick Connect History Database
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.services;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
public class HistoryDB extends SQLiteOpenHelper
|
||||
{
|
||||
|
||||
public static final String QUICK_CONNECT_TABLE_NAME = "quick_connect_history";
|
||||
public static final String QUICK_CONNECT_TABLE_COL_ITEM = "item";
|
||||
public static final String QUICK_CONNECT_TABLE_COL_TIMESTAMP = "timestamp";
|
||||
private static final int DB_VERSION = 1;
|
||||
private static final String DB_NAME = "history.db";
|
||||
|
||||
public HistoryDB(Context context)
|
||||
{
|
||||
super(context, DB_NAME, null, DB_VERSION);
|
||||
}
|
||||
|
||||
@Override public void onCreate(SQLiteDatabase db)
|
||||
{
|
||||
|
||||
String sqlQuickConnectHistory = "CREATE TABLE " + QUICK_CONNECT_TABLE_NAME + " (" +
|
||||
QUICK_CONNECT_TABLE_COL_ITEM + " TEXT PRIMARY KEY, " +
|
||||
QUICK_CONNECT_TABLE_COL_TIMESTAMP + " INTEGER"
|
||||
+ ");";
|
||||
|
||||
db.execSQL(sqlQuickConnectHistory);
|
||||
}
|
||||
|
||||
@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,681 @@
|
||||
/*
|
||||
Android FreeRDP JNI Wrapper
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.services;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.collection.LongSparseArray;
|
||||
|
||||
import com.freerdp.freerdpcore.application.GlobalApp;
|
||||
import com.freerdp.freerdpcore.application.SessionState;
|
||||
import com.freerdp.freerdpcore.domain.BookmarkBase;
|
||||
import com.freerdp.freerdpcore.domain.ManualBookmark;
|
||||
import com.freerdp.freerdpcore.presentation.ApplicationSettingsActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class LibFreeRDP
|
||||
{
|
||||
private static final String TAG = "LibFreeRDP";
|
||||
private static EventListener listener;
|
||||
private static boolean mHasH264 = false;
|
||||
|
||||
private static final LongSparseArray<Boolean> mInstanceState = new LongSparseArray<>();
|
||||
|
||||
public static final long VERIFY_CERT_FLAG_NONE = 0x00;
|
||||
public static final long VERIFY_CERT_FLAG_LEGACY = 0x02;
|
||||
public static final long VERIFY_CERT_FLAG_REDIRECT = 0x10;
|
||||
public static final long VERIFY_CERT_FLAG_GATEWAY = 0x20;
|
||||
public static final long VERIFY_CERT_FLAG_CHANGED = 0x40;
|
||||
public static final long VERIFY_CERT_FLAG_MISMATCH = 0x80;
|
||||
public static final long VERIFY_CERT_FLAG_MATCH_LEGACY_SHA1 = 0x100;
|
||||
public static final long VERIFY_CERT_FLAG_FP_IS_PEM = 0x200;
|
||||
|
||||
private static boolean tryLoad(String[] libraries)
|
||||
{
|
||||
boolean success = false;
|
||||
final String LD_PATH = System.getProperty("java.library.path");
|
||||
for (String lib : libraries)
|
||||
{
|
||||
try
|
||||
{
|
||||
Log.v(TAG, "Trying to load library " + lib + " from LD_PATH: " + LD_PATH);
|
||||
System.loadLibrary(lib);
|
||||
success = true;
|
||||
}
|
||||
catch (UnsatisfiedLinkError e)
|
||||
{
|
||||
Log.e(TAG, "Failed to load library " + lib + ": " + e);
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private static boolean tryLoad(String library)
|
||||
{
|
||||
return tryLoad(new String[] { library });
|
||||
}
|
||||
|
||||
static
|
||||
{
|
||||
try
|
||||
{
|
||||
System.loadLibrary("freerdp-android");
|
||||
|
||||
/* Load dependent libraries too to trigger JNI_OnLoad calls */
|
||||
String version = freerdp_get_jni_version();
|
||||
String[] versions = version.split("[\\.-]");
|
||||
if (versions.length > 0)
|
||||
{
|
||||
System.loadLibrary("freerdp-client" + versions[0]);
|
||||
System.loadLibrary("freerdp" + versions[0]);
|
||||
System.loadLibrary("winpr" + versions[0]);
|
||||
}
|
||||
Pattern pattern = Pattern.compile("^(\\d+)\\.(\\d+)\\.(\\d+).*");
|
||||
Matcher matcher = pattern.matcher(version);
|
||||
if (!matcher.matches() || (matcher.groupCount() < 3))
|
||||
throw new RuntimeException("APK broken: native library version " + version +
|
||||
" does not meet requirements!");
|
||||
int major = Integer.parseInt(Objects.requireNonNull(matcher.group(1)));
|
||||
int minor = Integer.parseInt(Objects.requireNonNull(matcher.group(2)));
|
||||
int patch = Integer.parseInt(Objects.requireNonNull(matcher.group(3)));
|
||||
|
||||
if (major > 2)
|
||||
mHasH264 = freerdp_has_h264();
|
||||
else if (minor > 5)
|
||||
mHasH264 = freerdp_has_h264();
|
||||
else if ((minor == 5) && (patch >= 1))
|
||||
mHasH264 = freerdp_has_h264();
|
||||
else
|
||||
throw new RuntimeException("APK broken: native library version " + version +
|
||||
" does not meet requirements!");
|
||||
Log.i(TAG, "Successfully loaded native library. H264 is " +
|
||||
(mHasH264 ? "supported" : "not available"));
|
||||
}
|
||||
catch (UnsatisfiedLinkError e)
|
||||
{
|
||||
Log.e(TAG, "Failed to load library: " + e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasH264Support()
|
||||
{
|
||||
return mHasH264;
|
||||
}
|
||||
|
||||
private static native boolean freerdp_has_h264();
|
||||
|
||||
private static native String freerdp_get_jni_version();
|
||||
|
||||
private static native String freerdp_get_version();
|
||||
|
||||
private static native String freerdp_get_build_revision();
|
||||
|
||||
private static native String freerdp_get_build_config();
|
||||
|
||||
private static native long freerdp_new(Context context);
|
||||
|
||||
private static native void freerdp_free(long inst);
|
||||
|
||||
private static native boolean freerdp_parse_arguments(long inst, String[] args);
|
||||
|
||||
private static native boolean freerdp_connect(long inst);
|
||||
|
||||
private static native boolean freerdp_disconnect(long inst);
|
||||
|
||||
private static native boolean freerdp_update_graphics(long inst, Bitmap bitmap, int x, int y,
|
||||
int width, int height);
|
||||
|
||||
private static native boolean freerdp_send_cursor_event(long inst, int x, int y, int flags);
|
||||
|
||||
private static native boolean freerdp_send_key_event(long inst, int keycode, boolean down);
|
||||
|
||||
private static native boolean freerdp_send_unicodekey_event(long inst, int keycode,
|
||||
boolean down);
|
||||
|
||||
private static native boolean freerdp_send_clipboard_data(long inst, String data);
|
||||
|
||||
private static native String freerdp_get_last_error_string(long inst);
|
||||
|
||||
public static void setEventListener(EventListener l)
|
||||
{
|
||||
listener = l;
|
||||
}
|
||||
|
||||
public static long newInstance(Context context)
|
||||
{
|
||||
return freerdp_new(context);
|
||||
}
|
||||
|
||||
public static void freeInstance(long inst)
|
||||
{
|
||||
synchronized (mInstanceState)
|
||||
{
|
||||
if (mInstanceState.get(inst, false))
|
||||
{
|
||||
freerdp_disconnect(inst);
|
||||
}
|
||||
while (mInstanceState.get(inst, false))
|
||||
{
|
||||
try
|
||||
{
|
||||
mInstanceState.wait();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
freerdp_free(inst);
|
||||
}
|
||||
|
||||
public static boolean connect(long inst)
|
||||
{
|
||||
synchronized (mInstanceState)
|
||||
{
|
||||
if (mInstanceState.get(inst, false))
|
||||
{
|
||||
throw new RuntimeException("instance already connected");
|
||||
}
|
||||
}
|
||||
return freerdp_connect(inst);
|
||||
}
|
||||
|
||||
public static boolean disconnect(long inst)
|
||||
{
|
||||
synchronized (mInstanceState)
|
||||
{
|
||||
if (mInstanceState.get(inst, false))
|
||||
{
|
||||
return freerdp_disconnect(inst);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean cancelConnection(long inst)
|
||||
{
|
||||
synchronized (mInstanceState)
|
||||
{
|
||||
if (mInstanceState.get(inst, false))
|
||||
{
|
||||
return freerdp_disconnect(inst);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static String addFlag(String name, boolean enabled)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
return "+" + name;
|
||||
}
|
||||
return "-" + name;
|
||||
}
|
||||
|
||||
public static boolean setConnectionInfo(Context context, long inst, BookmarkBase bookmark)
|
||||
{
|
||||
BookmarkBase.ScreenSettings screenSettings = bookmark.getActiveScreenSettings();
|
||||
BookmarkBase.AdvancedSettings advanced = bookmark.getAdvancedSettings();
|
||||
BookmarkBase.DebugSettings debug = bookmark.getDebugSettings();
|
||||
|
||||
String arg;
|
||||
ArrayList<String> args = new ArrayList<>();
|
||||
|
||||
args.add(TAG);
|
||||
args.add("/gdi:sw");
|
||||
|
||||
final String clientName = ApplicationSettingsActivity.getClientName(context);
|
||||
if (!clientName.isEmpty())
|
||||
{
|
||||
args.add("/client-hostname:" + clientName);
|
||||
}
|
||||
String certName = "";
|
||||
if (bookmark.getType() != BookmarkBase.TYPE_MANUAL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int port = bookmark.<ManualBookmark>get().getPort();
|
||||
String hostname = bookmark.<ManualBookmark>get().getHostname();
|
||||
|
||||
args.add("/v:" + hostname);
|
||||
args.add("/port:" + port);
|
||||
|
||||
arg = bookmark.getUsername();
|
||||
if (!arg.isEmpty())
|
||||
{
|
||||
args.add("/u:" + arg);
|
||||
}
|
||||
arg = bookmark.getDomain();
|
||||
if (!arg.isEmpty())
|
||||
{
|
||||
args.add("/d:" + arg);
|
||||
}
|
||||
arg = bookmark.getPassword();
|
||||
if (!arg.isEmpty())
|
||||
{
|
||||
args.add("/p:" + arg);
|
||||
}
|
||||
|
||||
args.add(
|
||||
String.format("/size:%dx%d", screenSettings.getWidth(), screenSettings.getHeight()));
|
||||
args.add("/bpp:" + screenSettings.getColors());
|
||||
|
||||
if (advanced.getConsoleMode())
|
||||
{
|
||||
args.add("/admin");
|
||||
}
|
||||
|
||||
switch (advanced.getSecurity())
|
||||
{
|
||||
case 3: // NLA
|
||||
args.add("/sec:nla");
|
||||
break;
|
||||
case 2: // TLS
|
||||
args.add("/sec:tls");
|
||||
break;
|
||||
case 1: // RDP
|
||||
args.add("/sec:rdp");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!certName.isEmpty())
|
||||
{
|
||||
args.add("/cert-name:" + certName);
|
||||
}
|
||||
|
||||
BookmarkBase.PerformanceFlags flags = bookmark.getActivePerformanceFlags();
|
||||
if (flags.getRemoteFX())
|
||||
{
|
||||
args.add("/rfx");
|
||||
args.add("/network:auto");
|
||||
}
|
||||
|
||||
if (flags.getGfx())
|
||||
{
|
||||
args.add("/gfx");
|
||||
args.add("/network:auto");
|
||||
}
|
||||
|
||||
if (flags.getH264() && mHasH264)
|
||||
{
|
||||
args.add("/gfx:AVC444");
|
||||
args.add("/network:auto");
|
||||
}
|
||||
|
||||
args.add(addFlag("wallpaper", flags.getWallpaper()));
|
||||
args.add(addFlag("window-drag", flags.getFullWindowDrag()));
|
||||
args.add(addFlag("menu-anims", flags.getMenuAnimations()));
|
||||
args.add(addFlag("themes", flags.getTheming()));
|
||||
args.add(addFlag("fonts", flags.getFontSmoothing()));
|
||||
args.add(addFlag("aero", flags.getDesktopComposition()));
|
||||
|
||||
if (!advanced.getRemoteProgram().isEmpty())
|
||||
{
|
||||
args.add("/shell:" + advanced.getRemoteProgram());
|
||||
}
|
||||
|
||||
if (!advanced.getWorkDir().isEmpty())
|
||||
{
|
||||
args.add("/shell-dir:" + advanced.getWorkDir());
|
||||
}
|
||||
|
||||
args.add(addFlag("async-channels", debug.getAsyncChannel()));
|
||||
args.add(addFlag("async-update", debug.getAsyncUpdate()));
|
||||
|
||||
if (advanced.getRedirectSDCard())
|
||||
{
|
||||
String path = android.os.Environment.getExternalStorageDirectory().getPath();
|
||||
args.add("/drive:sdcard," + path);
|
||||
}
|
||||
|
||||
args.add("/clipboard");
|
||||
|
||||
// Gateway enabled?
|
||||
if (bookmark.getType() == BookmarkBase.TYPE_MANUAL &&
|
||||
bookmark.<ManualBookmark>get().getEnableGatewaySettings())
|
||||
{
|
||||
ManualBookmark.GatewaySettings gateway =
|
||||
bookmark.<ManualBookmark>get().getGatewaySettings();
|
||||
|
||||
StringBuilder carg = new StringBuilder();
|
||||
carg.append(
|
||||
String.format("/gateway:g:%s:%d", gateway.getHostname(), gateway.getPort()));
|
||||
|
||||
arg = gateway.getUsername();
|
||||
if (!arg.isEmpty())
|
||||
{
|
||||
carg.append(",u:" + arg);
|
||||
}
|
||||
arg = gateway.getDomain();
|
||||
if (!arg.isEmpty())
|
||||
{
|
||||
carg.append(",d:" + arg);
|
||||
}
|
||||
arg = gateway.getPassword();
|
||||
if (!arg.isEmpty())
|
||||
{
|
||||
carg.append(",p:" + arg);
|
||||
}
|
||||
args.add(carg.toString());
|
||||
}
|
||||
|
||||
/* 0 ... local
|
||||
1 ... remote
|
||||
2 ... disable */
|
||||
args.add("/audio-mode:" + advanced.getRedirectSound());
|
||||
if (advanced.getRedirectSound() == 0)
|
||||
{
|
||||
args.add("/sound");
|
||||
}
|
||||
|
||||
if (advanced.getRedirectMicrophone())
|
||||
{
|
||||
args.add("/microphone");
|
||||
}
|
||||
|
||||
args.add("/kbd:unicode:on");
|
||||
args.add("/cert:ignore");
|
||||
args.add("/log-level:" + debug.getDebugLevel());
|
||||
String[] arrayArgs = args.toArray(new String[0]);
|
||||
return freerdp_parse_arguments(inst, arrayArgs);
|
||||
}
|
||||
|
||||
public static boolean setConnectionInfo(Context context, long inst, Uri openUri)
|
||||
{
|
||||
ArrayList<String> args = new ArrayList<>();
|
||||
|
||||
// Parse URI from query string. Same key overwrite previous one
|
||||
// freerdp://user@ip:port/connect?sound=&rfx=&p=password&clipboard=%2b&themes=-
|
||||
|
||||
// Now we only support Software GDI
|
||||
args.add(TAG);
|
||||
args.add("/gdi:sw");
|
||||
|
||||
final String clientName = ApplicationSettingsActivity.getClientName(context);
|
||||
if (!clientName.isEmpty())
|
||||
{
|
||||
args.add("/client-hostname:" + clientName);
|
||||
}
|
||||
|
||||
// Parse hostname and port. Set to 'v' argument
|
||||
String hostname = openUri.getHost();
|
||||
int port = openUri.getPort();
|
||||
if (hostname != null)
|
||||
{
|
||||
hostname = hostname + ((port == -1) ? "" : (":" + port));
|
||||
args.add("/v:" + hostname);
|
||||
}
|
||||
|
||||
String user = openUri.getUserInfo();
|
||||
if (user != null)
|
||||
{
|
||||
args.add("/u:" + user);
|
||||
}
|
||||
|
||||
for (String key : openUri.getQueryParameterNames())
|
||||
{
|
||||
String value = openUri.getQueryParameter(key);
|
||||
|
||||
if (value.isEmpty())
|
||||
{
|
||||
// Query: key=
|
||||
// To freerdp argument: /key
|
||||
args.add("/" + key);
|
||||
}
|
||||
else if (value.equals("-") || value.equals("+"))
|
||||
{
|
||||
// Query: key=- or key=+
|
||||
// To freerdp argument: -key or +key
|
||||
args.add(value + key);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Query: key=value
|
||||
// To freerdp argument: /key:value
|
||||
if (key.equals("drive") && value.equals("sdcard"))
|
||||
{
|
||||
// Special for sdcard redirect
|
||||
String path = android.os.Environment.getExternalStorageDirectory().getPath();
|
||||
value = "sdcard," + path;
|
||||
}
|
||||
|
||||
args.add("/" + key + ":" + value);
|
||||
}
|
||||
}
|
||||
|
||||
String[] arrayArgs = args.toArray(new String[0]);
|
||||
return freerdp_parse_arguments(inst, arrayArgs);
|
||||
}
|
||||
|
||||
public static boolean updateGraphics(long inst, Bitmap bitmap, int x, int y, int width,
|
||||
int height)
|
||||
{
|
||||
return freerdp_update_graphics(inst, bitmap, x, y, width, height);
|
||||
}
|
||||
|
||||
public static boolean sendCursorEvent(long inst, int x, int y, int flags)
|
||||
{
|
||||
return freerdp_send_cursor_event(inst, x, y, flags);
|
||||
}
|
||||
|
||||
public static boolean sendKeyEvent(long inst, int keycode, boolean down)
|
||||
{
|
||||
return freerdp_send_key_event(inst, keycode, down);
|
||||
}
|
||||
|
||||
public static boolean sendUnicodeKeyEvent(long inst, int keycode, boolean down)
|
||||
{
|
||||
return freerdp_send_unicodekey_event(inst, keycode, down);
|
||||
}
|
||||
|
||||
public static boolean sendClipboardData(long inst, String data)
|
||||
{
|
||||
return freerdp_send_clipboard_data(inst, data);
|
||||
}
|
||||
|
||||
private static void OnConnectionSuccess(long inst)
|
||||
{
|
||||
if (listener != null)
|
||||
listener.OnConnectionSuccess(inst);
|
||||
synchronized (mInstanceState)
|
||||
{
|
||||
mInstanceState.append(inst, true);
|
||||
mInstanceState.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnConnectionFailure(long inst)
|
||||
{
|
||||
if (listener != null)
|
||||
listener.OnConnectionFailure(inst);
|
||||
synchronized (mInstanceState)
|
||||
{
|
||||
mInstanceState.remove(inst);
|
||||
mInstanceState.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnPreConnect(long inst)
|
||||
{
|
||||
if (listener != null)
|
||||
listener.OnPreConnect(inst);
|
||||
}
|
||||
|
||||
private static void OnDisconnecting(long inst)
|
||||
{
|
||||
if (listener != null)
|
||||
listener.OnDisconnecting(inst);
|
||||
}
|
||||
|
||||
private static void OnDisconnected(long inst)
|
||||
{
|
||||
if (listener != null)
|
||||
listener.OnDisconnected(inst);
|
||||
synchronized (mInstanceState)
|
||||
{
|
||||
mInstanceState.remove(inst);
|
||||
mInstanceState.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnSettingsChanged(long inst, int width, int height, int bpp)
|
||||
{
|
||||
SessionState s = GlobalApp.getSession(inst);
|
||||
if (s == null)
|
||||
return;
|
||||
UIEventListener uiEventListener = s.getUIEventListener();
|
||||
if (uiEventListener != null)
|
||||
uiEventListener.OnSettingsChanged(width, height, bpp);
|
||||
}
|
||||
|
||||
private static boolean OnAuthenticate(long inst, StringBuilder username, StringBuilder domain,
|
||||
StringBuilder password)
|
||||
{
|
||||
SessionState s = GlobalApp.getSession(inst);
|
||||
if (s == null)
|
||||
return false;
|
||||
UIEventListener uiEventListener = s.getUIEventListener();
|
||||
if (uiEventListener != null)
|
||||
return uiEventListener.OnAuthenticate(username, domain, password);
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean OnGatewayAuthenticate(long inst, StringBuilder username,
|
||||
StringBuilder domain, StringBuilder password)
|
||||
{
|
||||
SessionState s = GlobalApp.getSession(inst);
|
||||
if (s == null)
|
||||
return false;
|
||||
UIEventListener uiEventListener = s.getUIEventListener();
|
||||
if (uiEventListener != null)
|
||||
return uiEventListener.OnGatewayAuthenticate(username, domain, password);
|
||||
return false;
|
||||
}
|
||||
|
||||
private static int OnVerifyCertificateEx(long inst, String host, long port, String commonName,
|
||||
String subject, String issuer, String fingerprint,
|
||||
long flags)
|
||||
{
|
||||
SessionState s = GlobalApp.getSession(inst);
|
||||
if (s == null)
|
||||
return 0;
|
||||
UIEventListener uiEventListener = s.getUIEventListener();
|
||||
if (uiEventListener != null)
|
||||
return uiEventListener.OnVerifiyCertificateEx(host, port, commonName, subject, issuer,
|
||||
fingerprint, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int OnVerifyChangedCertificateEx(long inst, String host, long port,
|
||||
String commonName, String subject,
|
||||
String issuer, String fingerprint,
|
||||
String oldSubject, String oldIssuer,
|
||||
String oldFingerprint, long flags)
|
||||
{
|
||||
SessionState s = GlobalApp.getSession(inst);
|
||||
if (s == null)
|
||||
return 0;
|
||||
UIEventListener uiEventListener = s.getUIEventListener();
|
||||
if (uiEventListener != null)
|
||||
return uiEventListener.OnVerifyChangedCertificateEx(host, port, commonName, subject,
|
||||
issuer, fingerprint, oldSubject,
|
||||
oldIssuer, oldFingerprint, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void OnGraphicsUpdate(long inst, int x, int y, int width, int height)
|
||||
{
|
||||
SessionState s = GlobalApp.getSession(inst);
|
||||
if (s == null)
|
||||
return;
|
||||
UIEventListener uiEventListener = s.getUIEventListener();
|
||||
if (uiEventListener != null)
|
||||
uiEventListener.OnGraphicsUpdate(x, y, width, height);
|
||||
}
|
||||
|
||||
private static void OnGraphicsResize(long inst, int width, int height, int bpp)
|
||||
{
|
||||
SessionState s = GlobalApp.getSession(inst);
|
||||
if (s == null)
|
||||
return;
|
||||
UIEventListener uiEventListener = s.getUIEventListener();
|
||||
if (uiEventListener != null)
|
||||
uiEventListener.OnGraphicsResize(width, height, bpp);
|
||||
}
|
||||
|
||||
private static void OnRemoteClipboardChanged(long inst, String data)
|
||||
{
|
||||
SessionState s = GlobalApp.getSession(inst);
|
||||
if (s == null)
|
||||
return;
|
||||
UIEventListener uiEventListener = s.getUIEventListener();
|
||||
if (uiEventListener != null)
|
||||
uiEventListener.OnRemoteClipboardChanged(data);
|
||||
}
|
||||
|
||||
public static String getVersion()
|
||||
{
|
||||
return freerdp_get_version();
|
||||
}
|
||||
|
||||
public interface EventListener
|
||||
{
|
||||
void OnPreConnect(long instance);
|
||||
|
||||
void OnConnectionSuccess(long instance);
|
||||
|
||||
void OnConnectionFailure(long instance);
|
||||
|
||||
void OnDisconnecting(long instance);
|
||||
|
||||
void OnDisconnected(long instance);
|
||||
}
|
||||
|
||||
public interface UIEventListener
|
||||
{
|
||||
void OnSettingsChanged(int width, int height, int bpp);
|
||||
|
||||
boolean OnAuthenticate(StringBuilder username, StringBuilder domain,
|
||||
StringBuilder password);
|
||||
|
||||
boolean OnGatewayAuthenticate(StringBuilder username, StringBuilder domain,
|
||||
StringBuilder password);
|
||||
|
||||
int OnVerifiyCertificateEx(String host, long port, String commonName, String subject, String issuer,
|
||||
String fingerprint, long flags);
|
||||
|
||||
int OnVerifyChangedCertificateEx(String host, long port, String commonName, String subject, String issuer,
|
||||
String fingerprint, String oldSubject, String oldIssuer,
|
||||
String oldFingerprint, long flags);
|
||||
|
||||
void OnGraphicsUpdate(int x, int y, int width, int height);
|
||||
|
||||
void OnGraphicsResize(int width, int height, int bpp);
|
||||
|
||||
void OnRemoteClipboardChanged(String data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
Manual bookmarks database gateway
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.services;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import com.freerdp.freerdpcore.domain.BookmarkBase;
|
||||
import com.freerdp.freerdpcore.domain.ManualBookmark;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ManualBookmarkGateway extends BookmarkBaseGateway
|
||||
{
|
||||
|
||||
public ManualBookmarkGateway(SQLiteOpenHelper bookmarkDB)
|
||||
{
|
||||
super(bookmarkDB);
|
||||
}
|
||||
|
||||
@Override protected BookmarkBase createBookmark()
|
||||
{
|
||||
return new ManualBookmark();
|
||||
}
|
||||
|
||||
@Override protected String getBookmarkTableName()
|
||||
{
|
||||
return BookmarkDB.DB_TABLE_BOOKMARK;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addBookmarkSpecificColumns(BookmarkBase bookmark, ContentValues columns)
|
||||
{
|
||||
ManualBookmark bm = (ManualBookmark)bookmark;
|
||||
columns.put(BookmarkDB.DB_KEY_BOOKMARK_HOSTNAME, bm.getHostname());
|
||||
columns.put(BookmarkDB.DB_KEY_BOOKMARK_PORT, bm.getPort());
|
||||
|
||||
// gateway settings
|
||||
columns.put(BookmarkDB.DB_KEY_BOOKMARK_GW_ENABLE, bm.getEnableGatewaySettings());
|
||||
columns.put(BookmarkDB.DB_KEY_BOOKMARK_GW_HOSTNAME, bm.getGatewaySettings().getHostname());
|
||||
columns.put(BookmarkDB.DB_KEY_BOOKMARK_GW_PORT, bm.getGatewaySettings().getPort());
|
||||
columns.put(BookmarkDB.DB_KEY_BOOKMARK_GW_USERNAME, bm.getGatewaySettings().getUsername());
|
||||
columns.put(BookmarkDB.DB_KEY_BOOKMARK_GW_PASSWORD, bm.getGatewaySettings().getPassword());
|
||||
columns.put(BookmarkDB.DB_KEY_BOOKMARK_GW_DOMAIN, bm.getGatewaySettings().getDomain());
|
||||
}
|
||||
|
||||
@Override protected void addBookmarkSpecificColumns(ArrayList<String> columns)
|
||||
{
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_HOSTNAME);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_PORT);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_GW_ENABLE);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_GW_HOSTNAME);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_GW_PORT);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_GW_USERNAME);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_GW_PASSWORD);
|
||||
columns.add(BookmarkDB.DB_KEY_BOOKMARK_GW_DOMAIN);
|
||||
}
|
||||
|
||||
@Override protected void readBookmarkSpecificColumns(BookmarkBase bookmark, Cursor cursor)
|
||||
{
|
||||
ManualBookmark bm = (ManualBookmark)bookmark;
|
||||
bm.setHostname(
|
||||
cursor.getString(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_HOSTNAME)));
|
||||
bm.setPort(cursor.getInt(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_PORT)));
|
||||
|
||||
bm.setEnableGatewaySettings(
|
||||
cursor.getInt(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_GW_ENABLE)) != 0);
|
||||
readGatewaySettings(bm, cursor);
|
||||
}
|
||||
|
||||
public BookmarkBase findByLabelOrHostname(String pattern)
|
||||
{
|
||||
if (pattern.length() == 0)
|
||||
return null;
|
||||
|
||||
Cursor cursor =
|
||||
queryBookmarks(BookmarkDB.DB_KEY_BOOKMARK_LABEL + " = '" + pattern + "' OR " +
|
||||
BookmarkDB.DB_KEY_BOOKMARK_HOSTNAME + " = '" + pattern + "'",
|
||||
BookmarkDB.DB_KEY_BOOKMARK_LABEL);
|
||||
BookmarkBase bookmark = null;
|
||||
if (cursor.moveToFirst() && (cursor.getCount() > 0))
|
||||
bookmark = getBookmarkFromCursor(cursor);
|
||||
|
||||
cursor.close();
|
||||
return bookmark;
|
||||
}
|
||||
|
||||
public ArrayList<BookmarkBase> findByLabelOrHostnameLike(String pattern)
|
||||
{
|
||||
Cursor cursor =
|
||||
queryBookmarks(BookmarkDB.DB_KEY_BOOKMARK_LABEL + " LIKE '%" + pattern + "%' OR " +
|
||||
BookmarkDB.DB_KEY_BOOKMARK_HOSTNAME + " LIKE '%" + pattern + "%'",
|
||||
BookmarkDB.DB_KEY_BOOKMARK_LABEL);
|
||||
ArrayList<BookmarkBase> bookmarks = new ArrayList<>(cursor.getCount());
|
||||
|
||||
if (cursor.moveToFirst() && (cursor.getCount() > 0))
|
||||
{
|
||||
do
|
||||
{
|
||||
bookmarks.add(getBookmarkFromCursor(cursor));
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
|
||||
cursor.close();
|
||||
return bookmarks;
|
||||
}
|
||||
|
||||
private void readGatewaySettings(ManualBookmark bookmark, Cursor cursor)
|
||||
{
|
||||
ManualBookmark.GatewaySettings gatewaySettings = bookmark.getGatewaySettings();
|
||||
gatewaySettings.setHostname(
|
||||
cursor.getString(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_GW_HOSTNAME)));
|
||||
gatewaySettings.setPort(
|
||||
cursor.getInt(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_GW_PORT)));
|
||||
gatewaySettings.setUsername(
|
||||
cursor.getString(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_GW_USERNAME)));
|
||||
gatewaySettings.setPassword(
|
||||
cursor.getString(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_GW_PASSWORD)));
|
||||
gatewaySettings.setDomain(
|
||||
cursor.getString(cursor.getColumnIndex(BookmarkDB.DB_KEY_BOOKMARK_GW_DOMAIN)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
Quick connect history gateway
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.services;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.database.SQLException;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.util.Log;
|
||||
|
||||
import com.freerdp.freerdpcore.domain.BookmarkBase;
|
||||
import com.freerdp.freerdpcore.domain.QuickConnectBookmark;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class QuickConnectHistoryGateway
|
||||
{
|
||||
private final static String TAG = "QuickConnectHistoryGateway";
|
||||
private final SQLiteOpenHelper historyDB;
|
||||
|
||||
public QuickConnectHistoryGateway(SQLiteOpenHelper historyDB)
|
||||
{
|
||||
this.historyDB = historyDB;
|
||||
}
|
||||
|
||||
public ArrayList<BookmarkBase> findHistory(String filter)
|
||||
{
|
||||
String[] column = { HistoryDB.QUICK_CONNECT_TABLE_COL_ITEM };
|
||||
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
String selection =
|
||||
(filter.length() > 0)
|
||||
? (HistoryDB.QUICK_CONNECT_TABLE_COL_ITEM + " LIKE '%" + filter + "%'")
|
||||
: null;
|
||||
Cursor cursor = db.query(HistoryDB.QUICK_CONNECT_TABLE_NAME, column, selection, null, null,
|
||||
null, HistoryDB.QUICK_CONNECT_TABLE_COL_TIMESTAMP);
|
||||
|
||||
ArrayList<BookmarkBase> result = new ArrayList<>(cursor.getCount());
|
||||
if (cursor.moveToFirst())
|
||||
{
|
||||
do
|
||||
{
|
||||
String hostname =
|
||||
cursor.getString(cursor.getColumnIndex(HistoryDB.QUICK_CONNECT_TABLE_COL_ITEM));
|
||||
QuickConnectBookmark bookmark = new QuickConnectBookmark();
|
||||
bookmark.setLabel(hostname);
|
||||
bookmark.setHostname(hostname);
|
||||
result.add(bookmark);
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
cursor.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
public void addHistoryItem(String item)
|
||||
{
|
||||
String insertHistoryItem = "INSERT OR REPLACE INTO " + HistoryDB.QUICK_CONNECT_TABLE_NAME +
|
||||
" (" + HistoryDB.QUICK_CONNECT_TABLE_COL_ITEM + ", " +
|
||||
HistoryDB.QUICK_CONNECT_TABLE_COL_TIMESTAMP + ") VALUES('" +
|
||||
item + "', datetime('now'))";
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
try
|
||||
{
|
||||
db.execSQL(insertHistoryItem);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
Log.v(TAG, e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean historyItemExists(String item)
|
||||
{
|
||||
String[] column = { HistoryDB.QUICK_CONNECT_TABLE_COL_ITEM };
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
Cursor cursor = db.query(HistoryDB.QUICK_CONNECT_TABLE_NAME, column,
|
||||
HistoryDB.QUICK_CONNECT_TABLE_COL_ITEM + " = '" + item + "'", null,
|
||||
null, null, null);
|
||||
boolean exists = (cursor.getCount() == 1);
|
||||
cursor.close();
|
||||
return exists;
|
||||
}
|
||||
|
||||
public void removeHistoryItem(String hostname)
|
||||
{
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.delete(HistoryDB.QUICK_CONNECT_TABLE_NAME,
|
||||
HistoryDB.QUICK_CONNECT_TABLE_COL_ITEM + " = '" + hostname + "'", null);
|
||||
}
|
||||
|
||||
// safety wrappers
|
||||
// in case of getReadableDatabase it could happen that upgradeDB gets called which is
|
||||
// a problem if the DB is only readable
|
||||
private SQLiteDatabase getWritableDatabase()
|
||||
{
|
||||
return historyDB.getWritableDatabase();
|
||||
}
|
||||
|
||||
private SQLiteDatabase getReadableDatabase()
|
||||
{
|
||||
SQLiteDatabase db;
|
||||
try
|
||||
{
|
||||
db = historyDB.getReadableDatabase();
|
||||
}
|
||||
catch (SQLiteException e)
|
||||
{
|
||||
db = historyDB.getWritableDatabase();
|
||||
}
|
||||
return db;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
Activity for handling connection requests
|
||||
|
||||
Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
|
||||
|
||||
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.services;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.SearchManager;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.freerdp.freerdpcore.domain.ConnectionReference;
|
||||
import com.freerdp.freerdpcore.presentation.BookmarkActivity;
|
||||
import com.freerdp.freerdpcore.presentation.SessionActivity;
|
||||
|
||||
public class SessionRequestHandlerActivity extends AppCompatActivity
|
||||
{
|
||||
|
||||
@Override public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
handleIntent(getIntent());
|
||||
}
|
||||
|
||||
@Override protected void onNewIntent(Intent intent)
|
||||
{
|
||||
setIntent(intent);
|
||||
handleIntent(intent);
|
||||
}
|
||||
|
||||
private void startSessionWithConnectionReference(String refStr)
|
||||
{
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(SessionActivity.PARAM_CONNECTION_REFERENCE, refStr);
|
||||
Intent sessionIntent = new Intent(this, SessionActivity.class);
|
||||
sessionIntent.putExtras(bundle);
|
||||
|
||||
startActivityForResult(sessionIntent, 0);
|
||||
}
|
||||
|
||||
private void editBookmarkWithConnectionReference(String refStr)
|
||||
{
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(BookmarkActivity.PARAM_CONNECTION_REFERENCE, refStr);
|
||||
Intent bookmarkIntent = new Intent(this.getApplicationContext(), BookmarkActivity.class);
|
||||
bookmarkIntent.putExtras(bundle);
|
||||
startActivityForResult(bookmarkIntent, 0);
|
||||
}
|
||||
|
||||
private void handleIntent(Intent intent)
|
||||
{
|
||||
|
||||
String action = intent.getAction();
|
||||
if (Intent.ACTION_SEARCH.equals(action))
|
||||
startSessionWithConnectionReference(ConnectionReference.getHostnameReference(
|
||||
intent.getStringExtra(SearchManager.QUERY)));
|
||||
else if (Intent.ACTION_VIEW.equals(action))
|
||||
startSessionWithConnectionReference(intent.getDataString());
|
||||
else if (Intent.ACTION_EDIT.equals(action))
|
||||
editBookmarkWithConnectionReference(intent.getDataString());
|
||||
}
|
||||
|
||||
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
this.setResult(resultCode);
|
||||
this.finish();
|
||||
}
|
||||
}
|
||||