Mercurial > dotfiles.old
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 |