itoutline.me

 

“Aplikacja” dla OSX

Słowo aplikacja nie bez powodu jest w cudzysłowiu. Tak naprawdę to bash-owy skrypt umieszczony w odpowiedniej strukturze katalogowej wykorzystujący narzędzie Pashua. W sumie najbardziej mi odpowiada ten sposób ale pomyślałem sobie, że w ramach ćwiczeń spróbuje zrobić jak najprostsze ale w miarę funkcjonalne GUI do xfreerdp. Stąd cała zabawa z Pashua.

Aplikacje w OSX są aplikacjami dzięki rozszerzeniu .app, tak naprawdę to katalog w którym są umieszczone pliki i zasoby niezbędne do działania programu. Moją “aplikację” postanowiłem nazwać “XFreerdp Client”. Jej zawartość wygląda następująco (“Show package content” z menu podręcznego):

  • Info.plist - to plik zawierający informacje o aplikacji. Zdefiniowana jest w nim nazwa pliku, który ma byc uruchomiony, ikony, wersji, architektury itp.

  • rdp_connect - to skrypt, który jest uruchamiany

  • rdp_connect_image.png - obraz który jest wyświetlany w oknie Pashua

  • rdp_connect.icns - ikona aplikacji Xfreerdp Client

Zawartość Info.plist:

(Info.plist) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>en</string>
    <key>CFBundleExecutable</key>
    <string>rdp_connect</string>
    <key>CFBundleIconFile</key>
    <string>rdp_connect.icns</string>
    <key>CFBundleIdentifier</key>
    <string>itoutline.me.Xfreerdp_Client</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleName</key>
    <string>Xfreerdp Client</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>1.0</string>
    <key>CFBundleSignature</key>
    <string>????</string>
    <key>CFBundleVersion</key>
    <string>1</string>
    <key>LSApplicationCategoryType</key>
    <string>public.app-category.utilities</string>
    <key>LSMinimumSystemVersion</key>
    <string>10.5.0</string>
    <key>LSUIElement</key>
    <string>1</string>
    <key>NSHumanReadableCopyright</key>
    <string>© 2013 itoutline.me</string>
    <key>NSMainNibFile</key>
    <string>MainMenu</string>
    <key>NSPrincipalClass</key>
    <string>NSApplication</string>
</dict>
</plist>

Klucz LSUIElement z wartością ustawioną na 1 powoduje, że aplikacja nie pojawia się w Dock-u, co ma sens bo i tak po kliknięciu OK uruchamia się xfreerdp. Modyfikację powyższego klucza można wykorzystać w dowolnym programie, którego nie chcemy widzieć w Dock-u.

Pashua daje całkiem spore możliwości jeżeli chodzi o wprowadzanie danych. Może to być pole tekstowe, pole hasła, check box, lista rozwijana, przycisk.

Tak wygląda sam skrypt rdp_connect:

rdp_connect
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#!/bin/bash -l

xfreerdp=`which xfreerdp`

if [ ! -f $HOME/.serverauth.* ]
    then
        osascript -e 'launch application "Xquartz"'
fi

if [ ! "$DISPLAY" ]
    then
        export DISPLAY=:0
fi

pashua_run() {

    # Write config file
    pashua_configfile=`/usr/bin/mktemp /tmp/pashua_XXXXXXXXX`
    echo "$1" > $pashua_configfile

    bundlepath="Pashua.app/Contents/MacOS/Pashua"
    if [ "$3" = "" ]
    then
        mypath=`dirname "$0"`
        for searchpath in "$mypath/Pashua" "$mypath/$bundlepath" "./$bundlepath" \
                          "/Applications/$bundlepath" "$HOME/Applications/$bundlepath"
        do
            if [ -f "$searchpath" -a -x "$searchpath" ]
            then
                pashuapath=$searchpath
                break
            fi
        done
    else
        # Directory given as argument
        pashuapath="$3/$bundlepath"
    fi

    if [ ! "$pashuapath" ]
    then
        echo "Error: Pashua could not be found"
        exit 1
    fi

    # Manage encoding
    if [ "$2" = "" ]
    then
        encoding=""
    else
        encoding="-e $2"
    fi

    # Get result
    result=`"$pashuapath" $encoding $pashua_configfile | sed 's/ /;;;/g'`

    # Remove config file
    rm $pashua_configfile

    # Parse result
    for line in $result
    do
        key=`echo $line | sed 's/^\([^=]*\)=.*$/\1/'`
        value=`echo $line | sed 's/^[^=]*=\(.*\)$/\1/' | sed 's/;;;/ /g'`
        varname=$key
        varvalue="$value"
        eval $varname='$varvalue'
    done

} # pashua_run()

conf="
# Set transparency: 0 is transparent, 1 is opaque
*.transparency=1

# Set window title
*.title = Xfreerdp Client

# Host
txh.type = textfield
txh.label = Host:Port
txh.default = 192.168.1.1:8403
txh.width = 150

# User name
txu.type = textfield
txu.label = User
txu.default = itoutline.me
txu.width = 120

# Password
pw.type = password
pw.label = Password
pw.default = Secret!
pw.width = 120

# Resolution - radiobuttons
res.type = radiobutton
res.label = Resolution
res.option = 1024x768
res.option = 1280x800
res.option = 1440x900
res.option = 1920x1080
res.option = fullscreen
res.default = 1280x800

# Connection Speed - popup menu
popspeed.type = popup
popspeed.label = Connection Speed
popspeed.width = 100
popspeed.option = lan
popspeed.option = broadband
popspeed.option = modem
popspeed.default = lan

# Console session
cons.type = checkbox
cons.label = Connect to console session
cons.rely = -18
cons.default = 0

# Compression
compres.type = checkbox
compres.label = Enable compression
compres.rely = -18
compres.default = 1

# desktop composition
compos.type = checkbox
compos.label = Enable desktop composition
compos.rely = -18
compos.default = 0

# kill x after dissconection
killx.type = checkbox
killx.label = Exit Xquartz after disconnection
killx.rely = -18
killx.default = 0

# Add a cancel button with default label
cb.type=cancelbutton
"

# Set the images' paths relative to this file's path /
# skip images if they can not be found in this file's path
bgimg=$(dirname "$0")'/rdp_connect_image.png'

if [ -e "$bgimg" ]
then
    # Display background image
    conf="$conf
          bg.type = image
          bg.x = 70
          bg.y = 40
          bg.path = $bgimg"
fi

pashua_run "$conf"

if [[ $cons == 1 ]]; then
    cons="-0"
else
    cons=""
fi

if [[ $res == fullscreen ]]; then
    res="-f"
else
    res="-g $res"
fi

if [[ $compres == 1 ]]; then
    compres="-z"
else
    compres=""
fi

if [[ $compos == 1 ]]; then
    compos="--composition"
else
    compos=""
fi

if [[ $cb != 1 ]]; then
    $xfreerdp -u $txu -p $pw $res $cons $compres --no-rdp -x $popspeed $compos --plugin cliprdr --plugin rdpdr --data disk:HDD:$HOME -- $txh
    if [[ $killx == 1 ]]; then
        osascript -e 'tell application "Xquartz" to quit'
    fi
fi

W powyższym skrypcie wart wspomnienia jest sposób w jaki uruchamiany jest serwer X. Wykorzystałem do tego osascript i przyznam, że nie znalazłem jakiegoś lepszego rozwiązania.

Uruchomienie serwera X:

osascript -e 'launch application "Xquartz"'

Zatrzymanie:

osascript -e 'tell application "Xquartz" to quit'

W poleceniu xfreerdp automatycznie ładowane są pluginy opowiedzialne za funkcjonalność schowka i dostępu do lokalnych dysków (--plugin rdpdr --data disk:HDD:$HOME), na Windowsie montowany jest katalog domowy.

Konieczne jest również zainstalowanie aplikacji Pashua. Można tego nie robić i umieść tylko binarkę (Pashua) w katalogu XFreerdp Client.app/Contents/MacOS. Ma to sens kiedy chcemy wykorzystać tylko do jednej “aplikacji” narzędzie Pashua ale jeśli chcemy przygotować więcej tego typu rozwiązań to nie najlepszym pomysłem jest umieszczanie w każdej paczce wspomnianej binarki.

Po skopiowaniu Xfreerdp Ciient.app do katalogu /Applications w Launchpadzie wygląda bardzo dobrze:

Okno generowane przez Pashua, w przypadku kiedy nie działa serwer X trzeba chwilę na nie poczekać. Pojawi się dopiero po zainicjowaniu serwera:

Nawiązana sesja:

Jeśli ktoś nie przepada za shellem albo musi pomóc komuś kto tak ma, może w całkiem prosty sposób zrobić sobie nakładkę graficzną na dowolny program, który po uruchomieniu wymaga jakichś parametrów. Rozwiązanie jest bardzo proste i oczywiście ma w związku z tym swoje ograniczenia (np. kiepska obsługa błędów a w zasadzie jej brak).

Comments