Kaynağa Gözat

privatebin app

Bob Mottram 7 yıl önce
ebeveyn
işleme
ace52490ab
1 değiştirilmiş dosya ile 454 ekleme ve 0 silme
  1. 454
    0
      src/freedombone-app-privatebin

+ 454
- 0
src/freedombone-app-privatebin Dosyayı Görüntüle

@@ -0,0 +1,454 @@
1
+#!/bin/bash
2
+#
3
+# .---.                  .              .
4
+# |                      |              |
5
+# |--- .--. .-.  .-.  .-.|  .-. .--.--. |.-.  .-. .--.  .-.
6
+# |    |   (.-' (.-' (   | (   )|  |  | |   )(   )|  | (.-'
7
+# '    '     --'  --'  -' -  -' '  '   -' -'   -' '   -  --'
8
+#
9
+#                    Freedom in the Cloud
10
+#
11
+# privatebin application
12
+#
13
+# License
14
+# =======
15
+#
16
+# Copyright (C) 2018 Bob Mottram <bob@freedombone.net>
17
+#
18
+# This program is free software: you can redistribute it and/or modify
19
+# it under the terms of the GNU Affero General Public License as published by
20
+# the Free Software Foundation, either version 3 of the License, or
21
+# (at your option) any later version.
22
+#
23
+# This program is distributed in the hope that it will be useful,
24
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
25
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
+# GNU Affero General Public License for more details.
27
+#
28
+# You should have received a copy of the GNU Affero General Public License
29
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
30
+
31
+VARIANTS='full full-vim writer'
32
+
33
+IN_DEFAULT_INSTALL=0
34
+SHOW_ON_ABOUT=1
35
+
36
+PRIVATEBIN_DOMAIN_NAME=
37
+PRIVATEBIN_CODE=
38
+PRIVATEBIN_ONION_PORT=8150
39
+PRIVATEBIN_REPO="https://github.com/PrivateBin/PrivateBin"
40
+PRIVATEBIN_COMMIT='9c132cd839fd5e91da18e4a1e8ebef64fce605fb'
41
+PRIVATEBIN_ADMIN_PASSWORD=
42
+
43
+privatebin_variables=(ONION_ONLY
44
+                      PRIVATEBIN_DOMAIN_NAME
45
+                      PRIVATEBIN_CODE
46
+                      DDNS_PROVIDER
47
+                      MY_USERNAME)
48
+
49
+function secure_privatebin {
50
+    pbpath="/var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs"
51
+    pbdata="/var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs/data"
52
+    htgroup='www-data'
53
+    rootuser='root'
54
+
55
+    find "${pbpath}/" -type f -print0 | xargs -0 chmod 0640
56
+    find "${pbpath}/" -type d -print0 | xargs -0 chmod 0550
57
+    find "${pbdata}/" -type f -print0 | xargs -0 chmod 0640
58
+    find "${pbdata}/" -type d -print0 | xargs -0 chmod 0750
59
+
60
+    chown -R ${rootuser}:${htgroup} "${pbpath}/"
61
+}
62
+
63
+function logging_on_privatebin {
64
+    echo -n ''
65
+}
66
+
67
+function logging_off_privatebin {
68
+    echo -n ''
69
+}
70
+
71
+function remove_user_privatebin {
72
+    remove_username="$1"
73
+}
74
+
75
+function add_user_privatebin {
76
+    new_username="$1"
77
+    new_user_password="$2"
78
+
79
+    echo '0'
80
+}
81
+
82
+function install_interactive_privatebin {
83
+    if [ ! $ONION_ONLY ]; then
84
+        ONION_ONLY='no'
85
+    fi
86
+
87
+    if [[ $ONION_ONLY != "no" ]]; then
88
+        PRIVATEBIN_DOMAIN_NAME='privatebin.local'
89
+    else
90
+        PRIVATEBIN_DETAILS_COMPLETE=
91
+        while [ ! $PRIVATEBIN_DETAILS_COMPLETE ]
92
+        do
93
+            data=$(tempfile 2>/dev/null)
94
+            trap "rm -f $data" 0 1 2 5 15
95
+            if [[ $DDNS_PROVIDER == "default@freedns.afraid.org" ]]; then
96
+                dialog --backtitle $"Freedombone Configuration" \
97
+                       --title $"PrivateBin Configuration" \
98
+                       --form $"\nPlease enter your privatebin details. The background image URL can be left blank.\n\nIMPORTANT: This should be a domain name which is supported by Let's Encrypt:" 16 65 4 \
99
+                       $"Domain:" 1 1 "$(grep 'PRIVATEBIN_DOMAIN_NAME' temp.cfg | awk -F '=' '{print $2}')" 1 25 33 40 \
100
+                       $"Code:" 2 1 "$(grep 'PRIVATEBIN_CODE' temp.cfg | awk -F '=' '{print $2}')" 4 25 33 255 \
101
+                       2> $data
102
+            else
103
+                dialog --backtitle $"Freedombone Configuration" \
104
+                       --title $"PrivateBin Configuration" \
105
+                       --form $"\nPlease enter your privatebin details. The background image URL can be left blank.\n\nIMPORTANT: This should be a domain name which is supported by Let's Encrypt:" 16 65 4 \
106
+                       $"Domain:" 1 1 "$(grep 'PRIVATEBIN_DOMAIN_NAME' temp.cfg | awk -F '=' '{print $2}')" 1 25 33 40 \
107
+                       2> $data
108
+            fi
109
+            sel=$?
110
+            case $sel in
111
+                1) exit 1;;
112
+                255) exit 1;;
113
+            esac
114
+            PRIVATEBIN_DOMAIN_NAME=$(cat $data | sed -n 1p)
115
+            if [ $PRIVATEBIN_DOMAIN_NAME ]; then
116
+                if [[ $PRIVATEBIN_DOMAIN_NAME == "$HUBZILLA_DOMAIN_NAME" ]]; then
117
+                    PRIVATEBIN_DOMAIN_NAME=""
118
+                fi
119
+                TEST_DOMAIN_NAME=$PRIVATEBIN_DOMAIN_NAME
120
+                validate_domain_name
121
+                if [[ $TEST_DOMAIN_NAME != $PRIVATEBIN_DOMAIN_NAME ]]; then
122
+                    PRIVATEBIN_DOMAIN_NAME=
123
+                    dialog --title $"Domain name validation" --msgbox "$TEST_DOMAIN_NAME" 15 50
124
+                else
125
+                    if [[ $DDNS_PROVIDER == "default@freedns.afraid.org" ]]; then
126
+                        PRIVATEBIN_CODE=$(cat $data | sed -n 2p)
127
+                        validate_freedns_code "$PRIVATEBIN_CODE"
128
+                        if [ ! $VALID_CODE ]; then
129
+                            PRIVATEBIN_DOMAIN_NAME=
130
+                        fi
131
+                    fi
132
+                fi
133
+            fi
134
+            if [ $PRIVATEBIN_DOMAIN_NAME ]; then
135
+                PRIVATEBIN_DETAILS_COMPLETE="yes"
136
+            fi
137
+        done
138
+
139
+        write_config_param "PRIVATEBIN_CODE" "$PRIVATEBIN_CODE"
140
+    fi
141
+    write_config_param "PRIVATEBIN_DOMAIN_NAME" "$PRIVATEBIN_DOMAIN_NAME"
142
+    APP_INSTALLED=1
143
+}
144
+
145
+function change_password_privatebin {
146
+    curr_username="$1"
147
+    new_user_password="$2"
148
+}
149
+
150
+function reconfigure_privatebin {
151
+    echo -n ''
152
+}
153
+
154
+function upgrade_privatebin {
155
+    CURR_PRIVATEBIN_COMMIT=$(get_completion_param "privatebin commit")
156
+    if [[ "$CURR_PRIVATEBIN_COMMIT" == "$PRIVATEBIN_COMMIT" ]]; then
157
+        return
158
+    fi
159
+
160
+    if grep -q "privatebin domain" $COMPLETION_FILE; then
161
+        PRIVATEBIN_DOMAIN_NAME=$(get_completion_param "privatebin domain")
162
+    fi
163
+
164
+    # update to the next commit
165
+    function_check set_repo_commit
166
+    set_repo_commit /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs "privatebin commit" "$PRIVATEBIN_COMMIT" $PRIVATEBIN_REPO
167
+
168
+    secure_privatebin
169
+}
170
+
171
+
172
+function backup_local_privatebin {
173
+    PRIVATEBIN_DOMAIN_NAME='privatebin'
174
+    if grep -q "privatebin domain" $COMPLETION_FILE; then
175
+        PRIVATEBIN_DOMAIN_NAME=$(get_completion_param "privatebin domain")
176
+    fi
177
+
178
+    source_directory=/var/www/${PRIVATEBIN_DOMAIN_NAME}/htdocs/data
179
+
180
+    function_check suspend_site
181
+    suspend_site ${PRIVATEBIN_DOMAIN_NAME}
182
+
183
+    function_check backup_directory_to_usb
184
+    dest_directory=privatebin
185
+    backup_directory_to_usb $source_directory $dest_directory
186
+
187
+    function_check restart_site
188
+    restart_site
189
+}
190
+
191
+function restore_local_privatebin {
192
+    if ! grep -q "privatebin domain" $COMPLETION_FILE; then
193
+        return
194
+    fi
195
+    PRIVATEBIN_DOMAIN_NAME=$(get_completion_param "privatebin domain")
196
+    if [ $PRIVATEBIN_DOMAIN_NAME ]; then
197
+        echo $"Restoring privatebin"
198
+        temp_restore_dir=/root/tempprivatebin
199
+        privatebin_dir=/var/www/${PRIVATEBIN_DOMAIN_NAME}/htdocs/data
200
+
201
+        function_check restore_directory_from_usb
202
+        restore_directory_from_usb $temp_restore_dir privatebin
203
+        if [ -d $temp_restore_dir ]; then
204
+            if [ -d cp $temp_restore_dir$privatebin_dir ]; then
205
+                cp -rp $temp_restore_dir$privatebin_dir/* $privatebin_dir/
206
+            else
207
+                cp -rp $temp_restore_dir/* $privatebin_dir/
208
+            fi
209
+            secure_privatebin
210
+            rm -rf $temp_restore_dir
211
+        fi
212
+
213
+        echo $"Restore of privatebin complete"
214
+    fi
215
+}
216
+
217
+function backup_remote_privatebin {
218
+    PRIVATEBIN_DOMAIN_NAME='privatebin'
219
+    if grep -q "privatebin domain" $COMPLETION_FILE; then
220
+        PRIVATEBIN_DOMAIN_NAME=$(get_completion_param "privatebin domain")
221
+    fi
222
+
223
+    source_directory=/var/www/${PRIVATEBIN_DOMAIN_NAME}/htdocs/data
224
+
225
+    function_check suspend_site
226
+    suspend_site ${PRIVATEBIN_DOMAIN_NAME}
227
+
228
+    function_check backup_directory_to_friend
229
+    dest_directory=privatebin
230
+    backup_directory_to_friend $source_directory $dest_directory
231
+
232
+    function_check restart_site
233
+    restart_site
234
+}
235
+
236
+function restore_remote_privatebin {
237
+    if ! grep -q "privatebin domain" $COMPLETION_FILE; then
238
+        return
239
+    fi
240
+    PRIVATEBIN_DOMAIN_NAME=$(get_completion_param "privatebin domain")
241
+    if [ $PRIVATEBIN_DOMAIN_NAME ]; then
242
+        temp_restore_dir=/root/tempprivatebin
243
+        privatebin_dir=/var/www/${PRIVATEBIN_DOMAIN_NAME}/htdocs/data
244
+
245
+        function_check restore_directory_from_friend
246
+        restore_directory_from_friend $temp_restore_dir privatebin
247
+        if [ -d $temp_restore_dir ]; then
248
+            if [ -d cp $temp_restore_dir$privatebin_dir ]; then
249
+                cp -rp $temp_restore_dir$privatebin_dir/* $privatebin_dir/
250
+            else
251
+                cp -rp $temp_restore_dir/* $privatebin_dir/
252
+            fi
253
+            secure_privatebin
254
+            rm -rf $temp_restore_dir
255
+        fi
256
+    fi
257
+}
258
+
259
+function remove_privatebin {
260
+    if [ ${#PRIVATEBIN_DOMAIN_NAME} -eq 0 ]; then
261
+        return
262
+    fi
263
+    read_config_param "PRIVATEBIN_DOMAIN_NAME"
264
+    read_config_param "MY_USERNAME"
265
+    echo "Removing $PRIVATEBIN_DOMAIN_NAME"
266
+    nginx_dissite $PRIVATEBIN_DOMAIN_NAME
267
+    remove_certs $PRIVATEBIN_DOMAIN_NAME
268
+
269
+    if [ -d /var/www/$PRIVATEBIN_DOMAIN_NAME ]; then
270
+        rm -rf /var/www/$PRIVATEBIN_DOMAIN_NAME
271
+    fi
272
+    if [ -f /etc/nginx/sites-available/$PRIVATEBIN_DOMAIN_NAME ]; then
273
+        rm /etc/nginx/sites-available/$PRIVATEBIN_DOMAIN_NAME
274
+    fi
275
+    function_check remove_onion_service
276
+    remove_onion_service privatebin ${PRIVATEBIN_ONION_PORT}
277
+    if grep -q "privatebin" /etc/crontab; then
278
+        sed -i "/privatebin/d" /etc/crontab
279
+    fi
280
+    remove_app privatebin
281
+    remove_completion_param install_privatebin
282
+    sed -i '/privatebin/d' $COMPLETION_FILE
283
+
284
+    function_check remove_ddns_domain
285
+    remove_ddns_domain $PRIVATEBIN_DOMAIN_NAME
286
+}
287
+
288
+function install_privatebin {
289
+    if [ ! $ONION_ONLY ]; then
290
+        ONION_ONLY='no'
291
+    fi
292
+
293
+    if [ ! $PRIVATEBIN_DOMAIN_NAME ]; then
294
+        echo $'No domain name was given for privatebin'
295
+        exit 7359
296
+    fi
297
+
298
+    apt-get -yq install php-gettext php-curl php-gd php-mysql git curl
299
+    apt-get -yq install memcached php-memcached php-intl exiftool libfcgi0ldbl
300
+
301
+    if [ ! -d /var/www/$PRIVATEBIN_DOMAIN_NAME ]; then
302
+        mkdir /var/www/$PRIVATEBIN_DOMAIN_NAME
303
+    fi
304
+    if [ ! -d /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs ]; then
305
+
306
+        if [ -d /repos/privatebin ]; then
307
+            mkdir /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs
308
+            cp -r -p /repos/privatebin/. /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs
309
+            cd /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs
310
+            git pull
311
+        else
312
+            function_check git_clone
313
+            git_clone $PRIVATEBIN_REPO /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs
314
+        fi
315
+
316
+        if [ ! -d /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs ]; then
317
+            echo $'Unable to clone privatebin repo'
318
+            exit 63763873
319
+        fi
320
+    fi
321
+
322
+    cd /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs
323
+    git checkout $PRIVATEBIN_COMMIT -b $PRIVATEBIN_COMMIT
324
+    set_completion_param "privatebin commit" "$PRIVATEBIN_COMMIT"
325
+
326
+    chmod g+w /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs
327
+    chown -R www-data:www-data /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs
328
+
329
+    function_check add_ddns_domain
330
+    add_ddns_domain $PRIVATEBIN_DOMAIN_NAME
331
+
332
+    PRIVATEBIN_ONION_HOSTNAME=$(add_onion_service privatebin 80 ${PRIVATEBIN_ONION_PORT})
333
+
334
+    privatebin_nginx_site=/etc/nginx/sites-available/$PRIVATEBIN_DOMAIN_NAME
335
+    if [[ $ONION_ONLY == "no" ]]; then
336
+        function_check nginx_http_redirect
337
+        nginx_http_redirect $PRIVATEBIN_DOMAIN_NAME "index index.php"
338
+        echo 'server {' >> $privatebin_nginx_site
339
+        echo '  listen 443 ssl;' >> $privatebin_nginx_site
340
+        echo '  listen [::]:443 ssl;' >> $privatebin_nginx_site
341
+        echo "  server_name $PRIVATEBIN_DOMAIN_NAME;" >> $privatebin_nginx_site
342
+        echo '' >> $privatebin_nginx_site
343
+        function_check nginx_compress
344
+        nginx_compress $PRIVATEBIN_DOMAIN_NAME
345
+        echo '' >> $privatebin_nginx_site
346
+        echo '  # Security' >> $privatebin_nginx_site
347
+        function_check nginx_ssl
348
+        nginx_ssl $PRIVATEBIN_DOMAIN_NAME
349
+
350
+        function_check nginx_disable_sniffing
351
+        nginx_disable_sniffing $PRIVATEBIN_DOMAIN_NAME
352
+
353
+        echo '  add_header Strict-Transport-Security max-age=15768000;' >> $privatebin_nginx_site
354
+        echo '' >> $privatebin_nginx_site
355
+        echo '  # Logs' >> $privatebin_nginx_site
356
+        echo '  access_log /dev/null;' >> $privatebin_nginx_site
357
+        echo '  error_log /dev/null;' >> $privatebin_nginx_site
358
+        echo '' >> $privatebin_nginx_site
359
+        echo "  root /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs;" >> $privatebin_nginx_site
360
+        echo '' >> $privatebin_nginx_site
361
+        echo '  index index.php;' >> $privatebin_nginx_site
362
+        echo '' >> $privatebin_nginx_site
363
+        echo '  location ~ \.php {' >> $privatebin_nginx_site
364
+        echo '    include snippets/fastcgi-php.conf;' >> $privatebin_nginx_site
365
+        echo '    fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;' >> $privatebin_nginx_site
366
+        echo '    fastcgi_read_timeout 30;' >> $privatebin_nginx_site
367
+        echo '  }' >> $privatebin_nginx_site
368
+        echo '' >> $privatebin_nginx_site
369
+        echo '  # Location' >> $privatebin_nginx_site
370
+        echo '  location / {' >> $privatebin_nginx_site
371
+        function_check nginx_limits
372
+        nginx_limits $PRIVATEBIN_DOMAIN_NAME '15m'
373
+        echo '    try_files $uri $uri/ @privatebin;' >> $privatebin_nginx_site
374
+        echo '  }' >> $privatebin_nginx_site
375
+        echo '' >> $privatebin_nginx_site
376
+        echo '  # Restrict access that is unnecessary anyway' >> $privatebin_nginx_site
377
+        echo '  location ~ /\.(ht|git) {' >> $privatebin_nginx_site
378
+        echo '    deny all;' >> $privatebin_nginx_site
379
+        echo '  }' >> $privatebin_nginx_site
380
+        echo '}' >> $privatebin_nginx_site
381
+        echo '' >> $privatebin_nginx_site
382
+    else
383
+        echo -n '' > $privatebin_nginx_site
384
+    fi
385
+    echo 'server {' >> $privatebin_nginx_site
386
+    echo "    listen 127.0.0.1:$PRIVATEBIN_ONION_PORT default_server;" >> $privatebin_nginx_site
387
+    echo "    server_name $PRIVATEBIN_ONION_HOSTNAME;" >> $privatebin_nginx_site
388
+    echo '' >> $privatebin_nginx_site
389
+    function_check nginx_compress
390
+    nginx_compress $PRIVATEBIN_DOMAIN_NAME
391
+    echo '' >> $privatebin_nginx_site
392
+    function_check nginx_disable_sniffing
393
+    nginx_disable_sniffing $PRIVATEBIN_DOMAIN_NAME
394
+    echo '' >> $privatebin_nginx_site
395
+    echo '  # Logs' >> $privatebin_nginx_site
396
+    echo '  access_log /dev/null;' >> $privatebin_nginx_site
397
+    echo '  error_log /dev/null;' >> $privatebin_nginx_site
398
+    echo '' >> $privatebin_nginx_site
399
+    echo "  root /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs;" >> $privatebin_nginx_site
400
+    echo '' >> $privatebin_nginx_site
401
+    echo '  index index.php;' >> $privatebin_nginx_site
402
+    echo '' >> $privatebin_nginx_site
403
+    echo '  location ~ \.php {' >> $privatebin_nginx_site
404
+    echo '    include snippets/fastcgi-php.conf;' >> $privatebin_nginx_site
405
+    echo '    fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;' >> $privatebin_nginx_site
406
+    echo '    fastcgi_read_timeout 30;' >> $privatebin_nginx_site
407
+    echo '  }' >> $privatebin_nginx_site
408
+    echo '' >> $privatebin_nginx_site
409
+    echo '  # Location' >> $privatebin_nginx_site
410
+    echo '  location / {' >> $privatebin_nginx_site
411
+    function_check nginx_limits
412
+    nginx_limits $PRIVATEBIN_DOMAIN_NAME '15m'
413
+    echo '    try_files $uri $uri/ @privatebin;' >> $privatebin_nginx_site
414
+    echo '  }' >> $privatebin_nginx_site
415
+    echo '' >> $privatebin_nginx_site
416
+    echo '  # Restrict access that is unnecessary anyway' >> $privatebin_nginx_site
417
+    echo '  location ~ /\.(ht|git) {' >> $privatebin_nginx_site
418
+    echo '    deny all;' >> $privatebin_nginx_site
419
+    echo '  }' >> $privatebin_nginx_site
420
+    echo '}' >> $privatebin_nginx_site
421
+
422
+    function_check configure_php
423
+    configure_php
424
+
425
+    function_check create_site_certificate
426
+    create_site_certificate $PRIVATEBIN_DOMAIN_NAME 'yes'
427
+
428
+    function_check nginx_ensite
429
+    nginx_ensite $PRIVATEBIN_DOMAIN_NAME
430
+
431
+    cp /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs/cfg/conf.sample.php /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs/cfg/conf.php
432
+
433
+    # Change some defaults
434
+    sed -i 's|; qrcode|qrcode|g' /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs/cfg/conf.php
435
+    sed -i 's|default =.*|default = "1day"|g' /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs/cfg/conf.php
436
+    sed -i 's|1week =|; 1week =|g' /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs/cfg/conf.php
437
+    sed -i 's|1month =|; 1month =|g' /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs/cfg/conf.php
438
+    sed -i 's|1year =|; 1year =|g' /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs/cfg/conf.php
439
+    sed -i 's|never =|; never =|g' /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs/cfg/conf.php
440
+    sed -i 's|limit =.*|limit = 30|g' /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs/cfg/conf.php
441
+    sed -i 's|sizelimit =.*|sizelimit = 32768|g' /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs/cfg/conf.php
442
+    sed -i 's|defaultformatter =.*|defaultformatter = "Markdown"|g' /var/www/$PRIVATEBIN_DOMAIN_NAME/htdocs/cfg/conf.php
443
+
444
+    secure_privatebin
445
+
446
+    systemctl restart php7.0-fpm
447
+    systemctl restart nginx
448
+
449
+    set_completion_param "privatebin domain" "$PRIVATEBIN_DOMAIN_NAME"
450
+
451
+    APP_INSTALLED=1
452
+}
453
+
454
+# NOTE: deliberately there is no "exit 0"