comparison bin/db @ 126:d0cd259345f3

Add Dropbox Uploader script See https://github.com/andreafabrizi/Dropbox-Uploader
author zegervdv <zegervdv@me.com>
date Tue, 30 Sep 2014 17:32:18 +0200
parents
children
comparison
equal deleted inserted replaced
125:18db7404aaf2 126:d0cd259345f3
1 #!/usr/bin/env bash
2 #
3 # Dropbox Uploader
4 #
5 # Copyright (C) 2010-2014 Andrea Fabrizi <[email protected]>
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #
21
22 #Default configuration file
23 CONFIG_FILE=~/.dropbox_uploader
24
25 #Default chunk size in Mb for the upload process
26 #It is recommended to increase this value only if you have enough free space on your /tmp partition
27 #Lower values may increase the number of http requests
28 CHUNK_SIZE=4
29
30 #Curl location
31 #If not set, curl will be searched into the $PATH
32 #CURL_BIN="/usr/bin/curl"
33
34 #Default values
35 TMP_DIR="/tmp"
36 DEBUG=0
37 QUIET=0
38 SHOW_PROGRESSBAR=0
39 SKIP_EXISTING_FILES=0
40 ERROR_STATUS=0
41
42 #Don't edit these...
43 API_REQUEST_TOKEN_URL="https://api.dropbox.com/1/oauth/request_token"
44 API_USER_AUTH_URL="https://www2.dropbox.com/1/oauth/authorize"
45 API_ACCESS_TOKEN_URL="https://api.dropbox.com/1/oauth/access_token"
46 API_CHUNKED_UPLOAD_URL="https://api-content.dropbox.com/1/chunked_upload"
47 API_CHUNKED_UPLOAD_COMMIT_URL="https://api-content.dropbox.com/1/commit_chunked_upload"
48 API_UPLOAD_URL="https://api-content.dropbox.com/1/files_put"
49 API_DOWNLOAD_URL="https://api-content.dropbox.com/1/files"
50 API_DELETE_URL="https://api.dropbox.com/1/fileops/delete"
51 API_MOVE_URL="https://api.dropbox.com/1/fileops/move"
52 API_COPY_URL="https://api.dropbox.com/1/fileops/copy"
53 API_METADATA_URL="https://api.dropbox.com/1/metadata"
54 API_INFO_URL="https://api.dropbox.com/1/account/info"
55 API_MKDIR_URL="https://api.dropbox.com/1/fileops/create_folder"
56 API_SHARES_URL="https://api.dropbox.com/1/shares"
57 APP_CREATE_URL="https://www2.dropbox.com/developers/apps"
58 RESPONSE_FILE="$TMP_DIR/du_resp_$RANDOM"
59 CHUNK_FILE="$TMP_DIR/du_chunk_$RANDOM"
60 TEMP_FILE="$TMP_DIR/du_tmp_$RANDOM"
61 BIN_DEPS="sed basename date grep stat dd mkdir"
62 VERSION="0.14"
63
64 umask 077
65
66 #Check the shell
67 if [ -z "$BASH_VERSION" ]; then
68 echo -e "Error: this script requires the BASH shell!"
69 exit 1
70 fi
71
72 shopt -s nullglob #Bash allows filename patterns which match no files to expand to a null string, rather than themselves
73 shopt -s dotglob #Bash includes filenames beginning with a "." in the results of filename expansion
74
75 #Look for optional config file parameter
76 while getopts ":qpskdf:" opt; do
77 case $opt in
78
79 f)
80 CONFIG_FILE=$OPTARG
81 ;;
82
83 d)
84 DEBUG=1
85 ;;
86
87 q)
88 QUIET=1
89 ;;
90
91 p)
92 SHOW_PROGRESSBAR=1
93 ;;
94
95 k)
96 CURL_ACCEPT_CERTIFICATES="-k"
97 ;;
98
99 s)
100 SKIP_EXISTING_FILES=1
101 ;;
102
103 \?)
104 echo "Invalid option: -$OPTARG" >&2
105 exit 1
106 ;;
107
108 :)
109 echo "Option -$OPTARG requires an argument." >&2
110 exit 1
111 ;;
112
113 esac
114 done
115
116 if [[ $DEBUG != 0 ]]; then
117 echo $VERSION
118 set -x
119 RESPONSE_FILE="$TMP_DIR/du_resp_debug"
120 fi
121
122 if [[ $CURL_BIN == "" ]]; then
123 BIN_DEPS="$BIN_DEPS curl"
124 CURL_BIN="curl"
125 fi
126
127 #Dependencies check
128 which $BIN_DEPS > /dev/null
129 if [[ $? != 0 ]]; then
130 for i in $BIN_DEPS; do
131 which $i > /dev/null ||
132 NOT_FOUND="$i $NOT_FOUND"
133 done
134 echo -e "Error: Required program could not be found: $NOT_FOUND"
135 exit 1
136 fi
137
138 #Check if readlink is installed and supports the -m option
139 #It's not necessary, so no problem if it's not installed
140 which readlink > /dev/null
141 if [[ $? == 0 && $(readlink -m "//test" 2> /dev/null) == "/test" ]]; then
142 HAVE_READLINK=1
143 else
144 HAVE_READLINK=0
145 fi
146
147 #Forcing to use the builtin printf, if it's present, because it's better
148 #otherwise the external printf program will be used
149 #Note that the external printf command can cause character encoding issues!
150 builtin printf "" 2> /dev/null
151 if [[ $? == 0 ]]; then
152 PRINTF="builtin printf"
153 PRINTF_OPT="-v o"
154 else
155 PRINTF=$(which printf)
156 if [[ $? != 0 ]]; then
157 echo -e "Error: Required program could not be found: printf"
158 fi
159 PRINTF_OPT=""
160 fi
161
162 #Print the message based on $QUIET variable
163 function print
164 {
165 if [[ $QUIET == 0 ]]; then
166 echo -ne "$1";
167 fi
168 }
169
170 #Returns unix timestamp
171 function utime
172 {
173 echo $(date +%s)
174 }
175
176 #Remove temporary files
177 function remove_temp_files
178 {
179 if [[ $DEBUG == 0 ]]; then
180 rm -fr "$RESPONSE_FILE"
181 rm -fr "$CHUNK_FILE"
182 rm -fr "$TEMP_FILE"
183 fi
184 }
185
186 #Returns the file size in bytes
187 # generic GNU Linux: linux-gnu
188 # windows cygwin: cygwin
189 # raspberry pi: linux-gnueabihf
190 # macosx: darwin10.0
191 # freebsd: FreeBSD
192 # qnap: linux-gnueabi
193 # iOS: darwin9
194 function file_size
195 {
196 #Some embedded linux devices
197 if [[ $OSTYPE == "linux-gnueabi" || $OSTYPE == "linux-gnu" ]]; then
198 stat -c "%s" "$1"
199 return
200
201 #Generic Unix
202 elif [[ ${OSTYPE:0:5} == "linux" || $OSTYPE == "cygwin" || ${OSTYPE:0:7} == "solaris" ]]; then
203 stat --format="%s" "$1"
204 return
205
206 #BSD, OSX and other OSs
207 else
208 stat -f "%z" "$1"
209 return
210 fi
211 }
212
213 #Usage
214 function usage
215 {
216 echo -e "Dropbox Uploader v$VERSION"
217 echo -e "Andrea Fabrizi - [email protected]\n"
218 echo -e "Usage: $0 COMMAND [PARAMETERS]..."
219 echo -e "\nCommands:"
220
221 echo -e "\t upload <LOCAL_FILE/DIR ...> <REMOTE_FILE/DIR>"
222 echo -e "\t download <REMOTE_FILE/DIR> [LOCAL_FILE/DIR]"
223 echo -e "\t delete <REMOTE_FILE/DIR>"
224 echo -e "\t move <REMOTE_FILE/DIR> <REMOTE_FILE/DIR>"
225 echo -e "\t copy <REMOTE_FILE/DIR> <REMOTE_FILE/DIR>"
226 echo -e "\t mkdir <REMOTE_DIR>"
227 echo -e "\t list [REMOTE_DIR]"
228 echo -e "\t share <REMOTE_FILE>"
229 echo -e "\t info"
230 echo -e "\t unlink"
231
232 echo -e "\nOptional parameters:"
233 echo -e "\t-f <FILENAME> Load the configuration file from a specific file"
234 echo -e "\t-s Skip already existing files when download/upload. Default: Overwrite"
235 echo -e "\t-d Enable DEBUG mode"
236 echo -e "\t-q Quiet mode. Don't show messages"
237 echo -e "\t-p Show cURL progress meter"
238 echo -e "\t-k Doesn't check for SSL certificates (insecure)"
239
240 echo -en "\nFor more info and examples, please see the README file.\n\n"
241 remove_temp_files
242 exit 1
243 }
244
245 #Check the curl exit code
246 function check_http_response
247 {
248 CODE=$?
249
250 #Checking curl exit code
251 case $CODE in
252
253 #OK
254 0)
255
256 ;;
257
258 #Proxy error
259 5)
260 print "\nError: Couldn't resolve proxy. The given proxy host could not be resolved.\n"
261
262 remove_temp_files
263 exit 1
264 ;;
265
266 #Missing CA certificates
267 60|58)
268 print "\nError: cURL is not able to performs peer SSL certificate verification.\n"
269 print "Please, install the default ca-certificates bundle.\n"
270 print "To do this in a Debian/Ubuntu based system, try:\n"
271 print " sudo apt-get install ca-certificates\n\n"
272 print "If the problem persists, try to use the -k option (insecure).\n"
273
274 remove_temp_files
275 exit 1
276 ;;
277
278 6)
279 print "\nError: Couldn't resolve host.\n"
280
281 remove_temp_files
282 exit 1
283 ;;
284
285 7)
286 print "\nError: Couldn't connect to host.\n"
287
288 remove_temp_files
289 exit 1
290 ;;
291
292 esac
293
294 #Checking response file for generic errors
295 if grep -q "HTTP/1.1 400" "$RESPONSE_FILE"; then
296 ERROR_MSG=$(sed -n -e 's/{"error": "\([^"]*\)"}/\1/p' "$RESPONSE_FILE")
297
298 case $ERROR_MSG in
299 *access?attempt?failed?because?this?app?is?not?configured?to?have*)
300 echo -e "\nError: The Permission type/Access level configured doesn't match the DropBox App settings!\nPlease run \"$0 unlink\" and try again."
301 exit 1
302 ;;
303 esac
304
305 fi
306
307 }
308
309 #Urlencode
310 function urlencode
311 {
312 local string="${1}"
313 local strlen=${#string}
314 local encoded=""
315
316 for (( pos=0 ; pos<strlen ; pos++ )); do
317 c=${string:$pos:1}
318 case "$c" in
319 [-_.~a-zA-Z0-9] ) o="${c}" ;;
320 * ) $PRINTF $PRINTF_OPT '%%%02x' "'$c"
321 esac
322 encoded+="${o}"
323 done
324
325 echo "$encoded"
326 }
327
328 function normalize_path
329 {
330 path=$(echo -e "$1")
331 if [[ $HAVE_READLINK == 1 ]]; then
332 new_path=$(readlink -m "$path")
333
334 #Adding back the final slash, if present in the source
335 if [[ "${path: -1}" == "/" ]]; then
336 new_path="$new_path/"
337 fi
338
339 echo "$new_path"
340 else
341 echo "$path"
342 fi
343 }
344
345 #Check if it's a file or directory
346 #Returns FILE/DIR/ERR
347 function db_stat
348 {
349 local FILE=$(normalize_path "$1")
350
351 #Checking if it's a file or a directory
352 $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" "$API_METADATA_URL/$ACCESS_LEVEL/$(urlencode "$FILE")?oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" 2> /dev/null
353 check_http_response
354
355 #Even if the file/dir has been deleted from DropBox we receive a 200 OK response
356 #So we must check if the file exists or if it has been deleted
357 if grep -q "\"is_deleted\":" "$RESPONSE_FILE"; then
358 local IS_DELETED=$(sed -n 's/.*"is_deleted":.\([^,]*\).*/\1/p' "$RESPONSE_FILE")
359 else
360 local IS_DELETED="false"
361 fi
362
363 #Exits...
364 grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"
365 if [[ $? == 0 && $IS_DELETED != "true" ]]; then
366
367 local IS_DIR=$(sed -n 's/^\(.*\)\"contents":.\[.*/\1/p' "$RESPONSE_FILE")
368
369 #It's a directory
370 if [[ $IS_DIR != "" ]]; then
371 echo "DIR"
372 #It's a file
373 else
374 echo "FILE"
375 fi
376
377 #Doesn't exists
378 else
379 echo "ERR"
380 fi
381 }
382
383 #Generic upload wrapper around db_upload_file and db_upload_dir functions
384 #$1 = Local source file/dir
385 #$2 = Remote destination file/dir
386 function db_upload
387 {
388 local SRC=$(normalize_path "$1")
389 local DST=$(normalize_path "$2")
390
391 #Checking if the file/dir exists
392 if [[ ! -e $SRC && ! -d $SRC ]]; then
393 print " > No such file or directory: $SRC\n"
394 ERROR_STATUS=1
395 return
396 fi
397
398 #Checking if the file/dir has read permissions
399 if [[ ! -r $SRC ]]; then
400 print " > Error reading file $SRC: permission denied\n"
401 ERROR_STATUS=1
402 return
403 fi
404
405 TYPE=$(db_stat "$DST")
406
407 #If DST it's a file, do nothing, it's the default behaviour
408 if [[ $TYPE == "FILE" ]]; then
409 DST="$DST"
410
411 #if DST doesn't exists and doesn't ends with a /, it will be the destination file name
412 elif [[ $TYPE == "ERR" && "${DST: -1}" != "/" ]]; then
413 DST="$DST"
414
415 #if DST doesn't exists and ends with a /, it will be the destination folder
416 elif [[ $TYPE == "ERR" && "${DST: -1}" == "/" ]]; then
417 local filename=$(basename "$SRC")
418 DST="$DST/$filename"
419
420 #If DST it'a directory, it will be the destination folder
421 elif [[ $TYPE == "DIR" ]]; then
422 local filename=$(basename "$SRC")
423 DST="$DST/$filename"
424 fi
425
426 #It's a directory
427 if [[ -d $SRC ]]; then
428 db_upload_dir "$SRC" "$DST"
429
430 #It's a file
431 elif [[ -e $SRC ]]; then
432 db_upload_file "$SRC" "$DST"
433
434 #Unsupported object...
435 else
436 print " > Skipping not regular file \"$SRC\"\n"
437 fi
438 }
439
440 #Generic upload wrapper around db_chunked_upload_file and db_simple_upload_file
441 #The final upload function will be choosen based on the file size
442 #$1 = Local source file
443 #$2 = Remote destination file
444 function db_upload_file
445 {
446 local FILE_SRC=$(normalize_path "$1")
447 local FILE_DST=$(normalize_path "$2")
448
449 shopt -s nocasematch
450
451 #Checking not allowed file names
452 basefile_dst=$(basename "$FILE_DST")
453 if [[ $basefile_dst == "thumbs.db" || \
454 $basefile_dst == "desktop.ini" || \
455 $basefile_dst == ".ds_store" || \
456 $basefile_dst == "icon\r" || \
457 $basefile_dst == ".dropbox" || \
458 $basefile_dst == ".dropbox.attr" \
459 ]]; then
460 print " > Skipping not allowed file name \"$FILE_DST\"\n"
461 return
462 fi
463
464 shopt -u nocasematch
465
466 #Checking file size
467 FILE_SIZE=$(file_size "$FILE_SRC")
468
469 #Checking if the file already exists
470 TYPE=$(db_stat "$FILE_DST")
471 if [[ $TYPE != "ERR" && $SKIP_EXISTING_FILES == 1 ]]; then
472 print " > Skipping already existing file \"$FILE_DST\"\n"
473 return
474 fi
475
476 if [[ $FILE_SIZE -gt 157286000 ]]; then
477 #If the file is greater than 150Mb, the chunked_upload API will be used
478 db_chunked_upload_file "$FILE_SRC" "$FILE_DST"
479 else
480 db_simple_upload_file "$FILE_SRC" "$FILE_DST"
481 fi
482
483 }
484
485 #Simple file upload
486 #$1 = Local source file
487 #$2 = Remote destination file
488 function db_simple_upload_file
489 {
490 local FILE_SRC=$(normalize_path "$1")
491 local FILE_DST=$(normalize_path "$2")
492
493 if [[ $SHOW_PROGRESSBAR == 1 && $QUIET == 0 ]]; then
494 CURL_PARAMETERS="--progress-bar"
495 LINE_CR="\n"
496 else
497 CURL_PARAMETERS="-s"
498 LINE_CR=""
499 fi
500
501 print " > Uploading \"$FILE_SRC\" to \"$FILE_DST\"... $LINE_CR"
502 $CURL_BIN $CURL_ACCEPT_CERTIFICATES $CURL_PARAMETERS -i --globoff -o "$RESPONSE_FILE" --upload-file "$FILE_SRC" "$API_UPLOAD_URL/$ACCESS_LEVEL/$(urlencode "$FILE_DST")?oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM"
503 check_http_response
504
505 #Check
506 if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then
507 print "DONE\n"
508 else
509 print "FAILED\n"
510 print "An error occurred requesting /upload\n"
511 ERROR_STATUS=1
512 fi
513 }
514
515 #Chunked file upload
516 #$1 = Local source file
517 #$2 = Remote destination file
518 function db_chunked_upload_file
519 {
520 local FILE_SRC=$(normalize_path "$1")
521 local FILE_DST=$(normalize_path "$2")
522
523 print " > Uploading \"$FILE_SRC\" to \"$FILE_DST\""
524
525 local FILE_SIZE=$(file_size "$FILE_SRC")
526 local OFFSET=0
527 local UPLOAD_ID=""
528 local UPLOAD_ERROR=0
529 local CHUNK_PARAMS=""
530
531 #Uploading chunks...
532 while ([[ $OFFSET != $FILE_SIZE ]]); do
533
534 let OFFSET_MB=$OFFSET/1024/1024
535
536 #Create the chunk
537 dd if="$FILE_SRC" of="$CHUNK_FILE" bs=1048576 skip=$OFFSET_MB count=$CHUNK_SIZE 2> /dev/null
538
539 #Only for the first request these parameters are not included
540 if [[ $OFFSET != 0 ]]; then
541 CHUNK_PARAMS="upload_id=$UPLOAD_ID&offset=$OFFSET"
542 fi
543
544 #Uploading the chunk...
545 $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --upload-file "$CHUNK_FILE" "$API_CHUNKED_UPLOAD_URL?$CHUNK_PARAMS&oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" 2> /dev/null
546 check_http_response
547
548 #Check
549 if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then
550 print "."
551 UPLOAD_ERROR=0
552 UPLOAD_ID=$(sed -n 's/.*"upload_id": *"*\([^"]*\)"*.*/\1/p' "$RESPONSE_FILE")
553 OFFSET=$(sed -n 's/.*"offset": *\([^}]*\).*/\1/p' "$RESPONSE_FILE")
554 else
555 print "*"
556 let UPLOAD_ERROR=$UPLOAD_ERROR+1
557
558 #On error, the upload is retried for max 3 times
559 if [[ $UPLOAD_ERROR -gt 2 ]]; then
560 print " FAILED\n"
561 print "An error occurred requesting /chunked_upload\n"
562 ERROR_STATUS=1
563 return
564 fi
565 fi
566
567 done
568
569 UPLOAD_ERROR=0
570
571 #Commit the upload
572 while (true); do
573
574 $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "upload_id=$UPLOAD_ID&oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" "$API_CHUNKED_UPLOAD_COMMIT_URL/$ACCESS_LEVEL/$(urlencode "$FILE_DST")" 2> /dev/null
575 check_http_response
576
577 #Check
578 if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then
579 print "."
580 UPLOAD_ERROR=0
581 break
582 else
583 print "*"
584 let UPLOAD_ERROR=$UPLOAD_ERROR+1
585
586 #On error, the commit is retried for max 3 times
587 if [[ $UPLOAD_ERROR -gt 2 ]]; then
588 print " FAILED\n"
589 print "An error occurred requesting /commit_chunked_upload\n"
590 ERROR_STATUS=1
591 return
592 fi
593 fi
594
595 done
596
597 print " DONE\n"
598 }
599
600 #Directory upload
601 #$1 = Local source dir
602 #$2 = Remote destination dir
603 function db_upload_dir
604 {
605 local DIR_SRC=$(normalize_path "$1")
606 local DIR_DST=$(normalize_path "$2")
607
608 #Creatig remote directory
609 db_mkdir "$DIR_DST"
610
611 for file in "$DIR_SRC/"*; do
612 db_upload "$file" "$DIR_DST"
613 done
614 }
615
616 #Returns the free space on DropBox in bytes
617 function db_free_quota
618 {
619 $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" "$API_INFO_URL" 2> /dev/null
620 check_http_response
621
622 #Check
623 if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then
624
625 quota=$(sed -n 's/.*"quota": \([0-9]*\).*/\1/p' "$RESPONSE_FILE")
626 used=$(sed -n 's/.*"normal": \([0-9]*\).*/\1/p' "$RESPONSE_FILE")
627 let free_quota=$quota-$used
628 echo $free_quota
629
630 else
631 echo 0
632 fi
633 }
634
635 #Generic download wrapper
636 #$1 = Remote source file/dir
637 #$2 = Local destination file/dir
638 function db_download
639 {
640 local SRC=$(normalize_path "$1")
641 local DST=$(normalize_path "$2")
642
643 TYPE=$(db_stat "$SRC")
644
645 #It's a directory
646 if [[ $TYPE == "DIR" ]]; then
647
648 #If the DST folder is not specified, I assume that is the current directory
649 if [[ $DST == "" ]]; then
650 DST="."
651 fi
652
653 #Checking if the destination directory exists
654 if [[ ! -d $DST ]]; then
655 local basedir=""
656 else
657 local basedir=$(basename "$SRC")
658 fi
659
660 local DEST_DIR=$(normalize_path "$DST/$basedir")
661 print " > Downloading \"$SRC\" to \"$DEST_DIR\"... \n"
662 print " > Creating local directory \"$DEST_DIR\"... "
663 mkdir -p "$DEST_DIR"
664
665 #Check
666 if [[ $? == 0 ]]; then
667 print "DONE\n"
668 else
669 print "FAILED\n"
670 ERROR_STATUS=1
671 return
672 fi
673
674 #Extracting directory content [...]
675 #and replacing "}, {" with "}\n{"
676 #I don't like this piece of code... but seems to be the only way to do this with SED, writing a portable code...
677 local DIR_CONTENT=$(sed -n 's/.*: \[{\(.*\)/\1/p' "$RESPONSE_FILE" | sed 's/}, *{/}\
678 {/g')
679
680 #Extracting files and subfolders
681 TMP_DIR_CONTENT_FILE="${RESPONSE_FILE}_$RANDOM"
682 echo "$DIR_CONTENT" | sed -n 's/.*"path": *"\([^"]*\)",.*"is_dir": *\([^"]*\),.*/\1:\2/p' > $TMP_DIR_CONTENT_FILE
683
684 #For each entry...
685 while read -r line; do
686
687 local FILE=${line%:*}
688 local TYPE=${line#*:}
689
690 #Removing unneeded /
691 FILE=${FILE##*/}
692
693 if [[ $TYPE == "false" ]]; then
694 db_download_file "$SRC/$FILE" "$DEST_DIR/$FILE"
695 else
696 db_download "$SRC/$FILE" "$DEST_DIR"
697 fi
698
699 done < $TMP_DIR_CONTENT_FILE
700
701 rm -fr $TMP_DIR_CONTENT_FILE
702
703 #It's a file
704 elif [[ $TYPE == "FILE" ]]; then
705
706 #Checking DST
707 if [[ $DST == "" ]]; then
708 DST=$(basename "$SRC")
709 fi
710
711 #If the destination is a directory, the file will be download into
712 if [[ -d $DST ]]; then
713 DST="$DST/$SRC"
714 fi
715
716 db_download_file "$SRC" "$DST"
717
718 #Doesn't exists
719 else
720 print " > No such file or directory: $SRC\n"
721 ERROR_STATUS=1
722 return
723 fi
724 }
725
726 #Simple file download
727 #$1 = Remote source file
728 #$2 = Local destination file
729 function db_download_file
730 {
731 local FILE_SRC=$(normalize_path "$1")
732 local FILE_DST=$(normalize_path "$2")
733
734 if [[ $SHOW_PROGRESSBAR == 1 && $QUIET == 0 ]]; then
735 CURL_PARAMETERS="--progress-bar"
736 LINE_CR="\n"
737 else
738 CURL_PARAMETERS="-s"
739 LINE_CR=""
740 fi
741
742 #Checking if the file already exists
743 if [[ -e $FILE_DST && $SKIP_EXISTING_FILES == 1 ]]; then
744 print " > Skipping already existing file \"$FILE_DST\"\n"
745 return
746 fi
747
748 #Creating the empty file, that for two reasons:
749 #1) In this way I can check if the destination file is writable or not
750 #2) Curl doesn't automatically creates files with 0 bytes size
751 dd if=/dev/zero of="$FILE_DST" count=0 2> /dev/null
752 if [[ $? != 0 ]]; then
753 print " > Error writing file $FILE_DST: permission denied\n"
754 ERROR_STATUS=1
755 return
756 fi
757
758 print " > Downloading \"$FILE_SRC\" to \"$FILE_DST\"... $LINE_CR"
759 $CURL_BIN $CURL_ACCEPT_CERTIFICATES $CURL_PARAMETERS --globoff -D "$RESPONSE_FILE" -o "$FILE_DST" "$API_DOWNLOAD_URL/$ACCESS_LEVEL/$(urlencode "$FILE_SRC")?oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM"
760 check_http_response
761
762 #Check
763 if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then
764 print "DONE\n"
765 else
766 print "FAILED\n"
767 rm -fr "$FILE_DST"
768 ERROR_STATUS=1
769 return
770 fi
771 }
772
773 #Prints account info
774 function db_account_info
775 {
776 print "Dropbox Uploader v$VERSION\n\n"
777 print " > Getting info... "
778 $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" "$API_INFO_URL" 2> /dev/null
779 check_http_response
780
781 #Check
782 if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then
783
784 name=$(sed -n 's/.*"display_name": "\([^"]*\).*/\1/p' "$RESPONSE_FILE")
785 echo -e "\n\nName:\t$name"
786
787 uid=$(sed -n 's/.*"uid": \([0-9]*\).*/\1/p' "$RESPONSE_FILE")
788 echo -e "UID:\t$uid"
789
790 email=$(sed -n 's/.*"email": "\([^"]*\).*/\1/p' "$RESPONSE_FILE")
791 echo -e "Email:\t$email"
792
793 quota=$(sed -n 's/.*"quota": \([0-9]*\).*/\1/p' "$RESPONSE_FILE")
794 let quota_mb=$quota/1024/1024
795 echo -e "Quota:\t$quota_mb Mb"
796
797 used=$(sed -n 's/.*"normal": \([0-9]*\).*/\1/p' "$RESPONSE_FILE")
798 let used_mb=$used/1024/1024
799 echo -e "Used:\t$used_mb Mb"
800
801 let free_mb=($quota-$used)/1024/1024
802 echo -e "Free:\t$free_mb Mb"
803
804 echo ""
805
806 else
807 print "FAILED\n"
808 ERROR_STATUS=1
809 fi
810 }
811
812 #Account unlink
813 function db_unlink
814 {
815 echo -ne "Are you sure you want unlink this script from your Dropbox account? [y/n]"
816 read answer
817 if [[ $answer == "y" ]]; then
818 rm -fr "$CONFIG_FILE"
819 echo -ne "DONE\n"
820 fi
821 }
822
823 #Delete a remote file
824 #$1 = Remote file to delete
825 function db_delete
826 {
827 local FILE_DST=$(normalize_path "$1")
828
829 print " > Deleting \"$FILE_DST\"... "
830 $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM&root=$ACCESS_LEVEL&path=$(urlencode "$FILE_DST")" "$API_DELETE_URL" 2> /dev/null
831 check_http_response
832
833 #Check
834 if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then
835 print "DONE\n"
836 else
837 print "FAILED\n"
838 ERROR_STATUS=1
839 fi
840 }
841
842 #Move/Rename a remote file
843 #$1 = Remote file to rename or move
844 #$2 = New file name or location
845 function db_move
846 {
847 local FILE_SRC=$(normalize_path "$1")
848 local FILE_DST=$(normalize_path "$2")
849
850 TYPE=$(db_stat "$FILE_DST")
851
852 #If the destination it's a directory, the source will be moved into it
853 if [[ $TYPE == "DIR" ]]; then
854 local filename=$(basename "$FILE_SRC")
855 FILE_DST=$(normalize_path "$FILE_DST/$filename")
856 fi
857
858 print " > Moving \"$FILE_SRC\" to \"$FILE_DST\" ... "
859 $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM&root=$ACCESS_LEVEL&from_path=$(urlencode "$FILE_SRC")&to_path=$(urlencode "$FILE_DST")" "$API_MOVE_URL" 2> /dev/null
860 check_http_response
861
862 #Check
863 if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then
864 print "DONE\n"
865 else
866 print "FAILED\n"
867 ERROR_STATUS=1
868 fi
869 }
870
871 #Copy a remote file to a remote location
872 #$1 = Remote file to rename or move
873 #$2 = New file name or location
874 function db_copy
875 {
876 local FILE_SRC=$(normalize_path "$1")
877 local FILE_DST=$(normalize_path "$2")
878
879 TYPE=$(db_stat "$FILE_DST")
880
881 #If the destination it's a directory, the source will be copied into it
882 if [[ $TYPE == "DIR" ]]; then
883 local filename=$(basename "$FILE_SRC")
884 FILE_DST=$(normalize_path "$FILE_DST/$filename")
885 fi
886
887 print " > Copying \"$FILE_SRC\" to \"$FILE_DST\" ... "
888 $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM&root=$ACCESS_LEVEL&from_path=$(urlencode "$FILE_SRC")&to_path=$(urlencode "$FILE_DST")" "$API_COPY_URL" 2> /dev/null
889 check_http_response
890
891 #Check
892 if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then
893 print "DONE\n"
894 else
895 print "FAILED\n"
896 ERROR_STATUS=1
897 fi
898 }
899
900 #Create a new directory
901 #$1 = Remote directory to create
902 function db_mkdir
903 {
904 local DIR_DST=$(normalize_path "$1")
905
906 print " > Creating Directory \"$DIR_DST\"... "
907 $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM&root=$ACCESS_LEVEL&path=$(urlencode "$DIR_DST")" "$API_MKDIR_URL" 2> /dev/null
908 check_http_response
909
910 #Check
911 if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then
912 print "DONE\n"
913 elif grep -q "^HTTP/1.1 403 Forbidden" "$RESPONSE_FILE"; then
914 print "ALREADY EXISTS\n"
915 else
916 print "FAILED\n"
917 ERROR_STATUS=1
918 fi
919 }
920
921 #List remote directory
922 #$1 = Remote directory
923 function db_list
924 {
925 local DIR_DST=$(normalize_path "$1")
926
927 print " > Listing \"$DIR_DST\"... "
928 $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" "$API_METADATA_URL/$ACCESS_LEVEL/$(urlencode "$DIR_DST")?oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" 2> /dev/null
929 check_http_response
930
931 #Check
932 if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then
933
934 local IS_DIR=$(sed -n 's/^\(.*\)\"contents":.\[.*/\1/p' "$RESPONSE_FILE")
935
936 #It's a directory
937 if [[ $IS_DIR != "" ]]; then
938
939 print "DONE\n"
940
941 #Extracting directory content [...]
942 #and replacing "}, {" with "}\n{"
943 #I don't like this piece of code... but seems to be the only way to do this with SED, writing a portable code...
944 local DIR_CONTENT=$(sed -n 's/.*: \[{\(.*\)/\1/p' "$RESPONSE_FILE" | sed 's/}, *{/}\
945 {/g')
946
947 #Converting escaped quotes to unicode format
948 echo "$DIR_CONTENT" | sed 's/\\"/\\u0022/' > "$TEMP_FILE"
949
950 #Extracting files and subfolders
951 rm -fr "$RESPONSE_FILE"
952 while read -r line; do
953
954 local FILE=$(echo "$line" | sed -n 's/.*"path": *"\([^"]*\)".*/\1/p')
955 local IS_DIR=$(echo "$line" | sed -n 's/.*"is_dir": *\([^,]*\).*/\1/p')
956 local SIZE=$(echo "$line" | sed -n 's/.*"bytes": *\([0-9]*\).*/\1/p')
957
958 echo -e "$FILE:$IS_DIR;$SIZE" >> "$RESPONSE_FILE"
959
960 done < "$TEMP_FILE"
961
962 #Looking for the biggest file size
963 #to calculate the padding to use
964 local padding=0
965 while read -r line; do
966 local FILE=${line%:*}
967 local META=${line##*:}
968 local SIZE=${META#*;}
969
970 if [[ ${#SIZE} -gt $padding ]]; then
971 padding=${#SIZE}
972 fi
973 done < "$RESPONSE_FILE"
974
975 #For each entry, printing directories...
976 while read -r line; do
977
978 local FILE=${line%:*}
979 local META=${line##*:}
980 local TYPE=${META%;*}
981 local SIZE=${META#*;}
982
983 #Removing unneeded /
984 FILE=${FILE##*/}
985
986 if [[ $TYPE == "true" ]]; then
987 FILE=$(echo -e "$FILE")
988 $PRINTF " [D] %-${padding}s %s\n" "$SIZE" "$FILE"
989 fi
990
991 done < "$RESPONSE_FILE"
992
993 #For each entry, printing files...
994 while read -r line; do
995
996 local FILE=${line%:*}
997 local META=${line##*:}
998 local TYPE=${META%;*}
999 local SIZE=${META#*;}
1000
1001 #Removing unneeded /
1002 FILE=${FILE##*/}
1003
1004 if [[ $TYPE == "false" ]]; then
1005 FILE=$(echo -e "$FILE")
1006 $PRINTF " [F] %-${padding}s %s\n" "$SIZE" "$FILE"
1007 fi
1008
1009 done < "$RESPONSE_FILE"
1010
1011 #It's a file
1012 else
1013 print "FAILED: $DIR_DST is not a directory!\n"
1014 ERROR_STATUS=1
1015 fi
1016
1017 else
1018 print "FAILED\n"
1019 ERROR_STATUS=1
1020 fi
1021 }
1022
1023 #Share remote file
1024 #$1 = Remote file
1025 function db_share
1026 {
1027 local FILE_DST=$(normalize_path "$1")
1028
1029 $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" "$API_SHARES_URL/$ACCESS_LEVEL/$(urlencode "$FILE_DST")?oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM&short_url=false" 2> /dev/null
1030 check_http_response
1031
1032 #Check
1033 if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then
1034 print " > Share link: "
1035 SHARE_LINK=$(sed -n 's/.*"url": "\([^"]*\).*/\1/p' "$RESPONSE_FILE")
1036 echo "$SHARE_LINK"
1037 else
1038 print "FAILED\n"
1039 ERROR_STATUS=1
1040 fi
1041 }
1042
1043 ################
1044 #### SETUP ####
1045 ################
1046
1047 #CHECKING FOR AUTH FILE
1048 if [[ -e $CONFIG_FILE ]]; then
1049
1050 #Loading data... and change old format config if necesary.
1051 source "$CONFIG_FILE" 2>/dev/null || {
1052 sed -i'' 's/:/=/' "$CONFIG_FILE" && source "$CONFIG_FILE" 2>/dev/null
1053 }
1054
1055 #Checking the loaded data
1056 if [[ $APPKEY == "" || $APPSECRET == "" || $OAUTH_ACCESS_TOKEN_SECRET == "" || $OAUTH_ACCESS_TOKEN == "" ]]; then
1057 echo -ne "Error loading data from $CONFIG_FILE...\n"
1058 echo -ne "It is recommended to run $0 unlink\n"
1059 remove_temp_files
1060 exit 1
1061 fi
1062
1063 #Back compatibility with previous Dropbox Uploader versions
1064 if [[ $ACCESS_LEVEL == "" ]]; then
1065 ACCESS_LEVEL="dropbox"
1066 fi
1067
1068 #NEW SETUP...
1069 else
1070
1071 echo -ne "\n This is the first time you run this script.\n\n"
1072 echo -ne " 1) Open the following URL in your Browser, and log in using your account: $APP_CREATE_URL\n"
1073 echo -ne " 2) Click on \"Create App\", then select \"Dropbox API app\"\n"
1074 echo -ne " 3) Select \"Files and datastores\"\n"
1075 echo -ne " 4) Now go on with the configuration, choosing the app permissions and access restrictions to your DropBox folder\n"
1076 echo -ne " 5) Enter the \"App Name\" that you prefer (e.g. MyUploader$RANDOM$RANDOM$RANDOM)\n\n"
1077
1078 echo -ne " Now, click on the \"Create App\" button.\n\n"
1079
1080 echo -ne " When your new App is successfully created, please type the\n"
1081 echo -ne " App Key, App Secret and the Permission type shown in the confirmation page:\n\n"
1082
1083 #Getting the app key and secret from the user
1084 while (true); do
1085
1086 echo -n " # App key: "
1087 read APPKEY
1088
1089 echo -n " # App secret: "
1090 read APPSECRET
1091
1092 echo -n " # Permission type, App folder or Full Dropbox [a/f]: "
1093 read ACCESS_LEVEL
1094
1095 if [[ $ACCESS_LEVEL == "a" ]]; then
1096 ACCESS_LEVEL="sandbox"
1097 ACCESS_MSG="App Folder"
1098 else
1099 ACCESS_LEVEL="dropbox"
1100 ACCESS_MSG="Full Dropbox"
1101 fi
1102
1103 echo -ne "\n > App key is $APPKEY, App secret is $APPSECRET and Access level is $ACCESS_MSG. Looks ok? [y/n]: "
1104 read answer
1105 if [[ $answer == "y" ]]; then
1106 break;
1107 fi
1108
1109 done
1110
1111 #TOKEN REQUESTS
1112 echo -ne "\n > Token request... "
1113 $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" "$API_REQUEST_TOKEN_URL" 2> /dev/null
1114 check_http_response
1115 OAUTH_TOKEN_SECRET=$(sed -n 's/oauth_token_secret=\([a-z A-Z 0-9]*\).*/\1/p' "$RESPONSE_FILE")
1116 OAUTH_TOKEN=$(sed -n 's/.*oauth_token=\([a-z A-Z 0-9]*\)/\1/p' "$RESPONSE_FILE")
1117
1118 if [[ $OAUTH_TOKEN != "" && $OAUTH_TOKEN_SECRET != "" ]]; then
1119 echo -ne "OK\n"
1120 else
1121 echo -ne " FAILED\n\n Please, check your App key and secret...\n\n"
1122 remove_temp_files
1123 exit 1
1124 fi
1125
1126 while (true); do
1127
1128 #USER AUTH
1129 echo -ne "\n Please open the following URL in your browser, and allow Dropbox Uploader\n"
1130 echo -ne " to access your DropBox folder:\n\n --> ${API_USER_AUTH_URL}?oauth_token=$OAUTH_TOKEN\n"
1131 echo -ne "\nPress enter when done...\n"
1132 read
1133
1134 #API_ACCESS_TOKEN_URL
1135 echo -ne " > Access Token request... "
1136 $CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" "$API_ACCESS_TOKEN_URL" 2> /dev/null
1137 check_http_response
1138 OAUTH_ACCESS_TOKEN_SECRET=$(sed -n 's/oauth_token_secret=\([a-z A-Z 0-9]*\)&.*/\1/p' "$RESPONSE_FILE")
1139 OAUTH_ACCESS_TOKEN=$(sed -n 's/.*oauth_token=\([a-z A-Z 0-9]*\)&.*/\1/p' "$RESPONSE_FILE")
1140 OAUTH_ACCESS_UID=$(sed -n 's/.*uid=\([0-9]*\)/\1/p' "$RESPONSE_FILE")
1141
1142 if [[ $OAUTH_ACCESS_TOKEN != "" && $OAUTH_ACCESS_TOKEN_SECRET != "" && $OAUTH_ACCESS_UID != "" ]]; then
1143 echo -ne "OK\n"
1144
1145 #Saving data in new format, compatible with source command.
1146 echo "APPKEY=$APPKEY" > "$CONFIG_FILE"
1147 echo "APPSECRET=$APPSECRET" >> "$CONFIG_FILE"
1148 echo "ACCESS_LEVEL=$ACCESS_LEVEL" >> "$CONFIG_FILE"
1149 echo "OAUTH_ACCESS_TOKEN=$OAUTH_ACCESS_TOKEN" >> "$CONFIG_FILE"
1150 echo "OAUTH_ACCESS_TOKEN_SECRET=$OAUTH_ACCESS_TOKEN_SECRET" >> "$CONFIG_FILE"
1151
1152 echo -ne "\n Setup completed!\n"
1153 break
1154 else
1155 print " FAILED\n"
1156 ERROR_STATUS=1
1157 fi
1158
1159 done;
1160
1161 remove_temp_files
1162 exit $ERROR_STATUS
1163 fi
1164
1165 ################
1166 #### START ####
1167 ################
1168
1169 COMMAND=${@:$OPTIND:1}
1170 ARG1=${@:$OPTIND+1:1}
1171 ARG2=${@:$OPTIND+2:1}
1172
1173 let argnum=$#-$OPTIND
1174
1175 #CHECKING PARAMS VALUES
1176 case $COMMAND in
1177
1178 upload)
1179
1180 if [[ $argnum -lt 2 ]]; then
1181 usage
1182 fi
1183
1184 FILE_DST=${@:$#:1}
1185
1186 for (( i=$OPTIND+1; i<$#; i++ )); do
1187 FILE_SRC=${@:$i:1}
1188 db_upload "$FILE_SRC" "/$FILE_DST"
1189 done
1190
1191 ;;
1192
1193 download)
1194
1195 if [[ $argnum -lt 1 ]]; then
1196 usage
1197 fi
1198
1199 FILE_SRC=$ARG1
1200 FILE_DST=$ARG2
1201
1202 db_download "/$FILE_SRC" "$FILE_DST"
1203
1204 ;;
1205
1206 share)
1207
1208 if [[ $argnum -lt 1 ]]; then
1209 usage
1210 fi
1211
1212 FILE_DST=$ARG1
1213
1214 db_share "/$FILE_DST"
1215
1216 ;;
1217
1218 info)
1219
1220 db_account_info
1221
1222 ;;
1223
1224 delete|remove)
1225
1226 if [[ $argnum -lt 1 ]]; then
1227 usage
1228 fi
1229
1230 FILE_DST=$ARG1
1231
1232 db_delete "/$FILE_DST"
1233
1234 ;;
1235
1236 move|rename)
1237
1238 if [[ $argnum -lt 2 ]]; then
1239 usage
1240 fi
1241
1242 FILE_SRC=$ARG1
1243 FILE_DST=$ARG2
1244
1245 db_move "/$FILE_SRC" "/$FILE_DST"
1246
1247 ;;
1248
1249 copy)
1250
1251 if [[ $argnum -lt 2 ]]; then
1252 usage
1253 fi
1254
1255 FILE_SRC=$ARG1
1256 FILE_DST=$ARG2
1257
1258 db_copy "/$FILE_SRC" "/$FILE_DST"
1259
1260 ;;
1261
1262 mkdir)
1263
1264 if [[ $argnum -lt 1 ]]; then
1265 usage
1266 fi
1267
1268 DIR_DST=$ARG1
1269
1270 db_mkdir "/$DIR_DST"
1271
1272 ;;
1273
1274 list)
1275
1276 DIR_DST=$ARG1
1277
1278 #Checking DIR_DST
1279 if [[ $DIR_DST == "" ]]; then
1280 DIR_DST="/"
1281 fi
1282
1283 db_list "/$DIR_DST"
1284
1285 ;;
1286
1287 unlink)
1288
1289 db_unlink
1290
1291 ;;
1292
1293 *)
1294
1295 if [[ $COMMAND != "" ]]; then
1296 print "Error: Unknown command: $COMMAND\n\n"
1297 ERROR_STATUS=1
1298 fi
1299 usage
1300
1301 ;;
1302
1303 esac
1304
1305 remove_temp_files
1306 exit $ERROR_STATUS