Table of Contents
Plowshare
plowshare is a command-line (CLI) download/upload tool for popular file sharing websites (aka file hosting provider or One-Click hoster). With plowshare, you will be able to download or upload files and manage remote folders and link deletion. It runs on Linux/BSD/Unix operating system.
download and install
git clone https://code.google.com/p/plowshare/ make
plowshare examples
plowdown examples
- Download a file from RapidShare:
plowdown http://www.rapidshare.com/files/86545320/Tux-Trainer_25-01-2008.rar
- Download a file from HotFile using an account (free or premium):
plowdown -a myuser:mypassword http://hotfile.com/dl/68261330/2f2926f/
Note: Don't forget to simple quote if your credentials have got characters that bash can interpret. For example: 'matt:foo$bar' or 'matt:foo+ -bar'.
- Download a file from Oron with Antigate.com service (feature added since 2012.02.01):
plowdown --antigate=key http://oron.com/dw726z0ohky5
- Download a file from Oron with Death by Captcha service (feature added since 2012.05.04):
plowdown --deathbycaptcha='user:pass' http://oron.com/dw726z0ohky5
- Download a file from RapidShare with a proxy. curl supports http_proxy and https_proxy environment variables (notice that 3128 is the default port).
export http_proxy=http://xxx.xxx.xxx.xxx:80 plowdown http://www.rapidshare.com/files/86545320/Tux-Trainer_25-01-2008.rar
- Download a list of links (one link per line):
cat file_with_links.txt # This is a comment http://depositfiles.com/files/abcdefghi http://www.rapidshare.com/files/86545320/Tux-Trainer_25-01-2008.rar plowdown file_with_links.txt
- Download a list of links (one link per line) commenting out (with #) those successfully downloaded:
plowdown -m file_with_links.txt
- Limit the download rate (in bytes per second). Accepted prefixes are k, K, Ki, M, m, Mi:
plowdown --max-rate 900K http://www.rapidshare.com/files/86545320/Tux-Trainer_25-01-2008.rar
- Download a password-protected link from Mediafire:
plowdown -p somepassword http://www.mediafire.com/?mt0egmhietj60iy
- Avoid never-ending downloads: limit the number of tries (for captchas) and wait delays for each link:
plowdown --max-retries=20 --timeout=3600 ...
plowup examples
Upload
- Upload a file to your RapidShare account:
plowup --auth=myuser:mypassword rapidshare /path/myfile.txt
- Upload a file to RapidShare anonymously changing uploaded file name:
plowup rapidshare /path/myfile.txt:anothername.txt
- Upload a file to TurboBit with an account (premium or free):
plowup -a myuser:mypassword turbobit /path/xxx
- Upload a bunch of files (anonymously to 2Shared):
plowup 2shared /path/myphotos/* Notice that only files will be sent, subdirectories will be ignored.
- Upload a file to megashares (anonymously) + set description
plowup -d 'Important document' megashares /path/myfile.tex
- Upload a file to Zshare anonymously with a proxy.
export http_proxy=http://xxx.xxx.xxx.xxx:80 export https_proxy=http://xxx.xxx.xxx.xxx:80 plowup zshare /path/myfile.txt
- Abort slow upload (if rate is below limit during 30 seconds)
plowup --min-rate 100k mediafire /path/bigfile.zip
- Modify remote filenames (example: foobar.rar gives foobar-PLOW.rar)
plowup --name='%g-PLOW.%x' mirrorcreator *.rar
plowlist examples
- List links contained in a shared folder link and download them all:
plowlist http://www.mediafire.com/?qouncpzfe74s9 > links.txt plowdown -m links.txt
Some hosters are handling tree folders, you must specify -R/–recursive command-line switch to plowlist for enabing recursive lisiting.
- List some sendspace.com web folder. Render results for vBulletin “BB” syntax.
plowlist --printf '[url=%u]%f[/url]%n' http://www.sendspace.com/folder/5njdw7
- List links contained in a dummy web page. Render results as HTML list:
plowlist --fallback --printf '<li><a href="%u">%u</a></li>%n' http://en.wikipedia.org/wiki/SI_prefix
real examples for mediafire
prepare config for mediafire
plowshare commands
- plownlist
plowlist http://www.mediafire.com/folder/cirj9u226cn3d/softs Retrieving list (mediafire): http://www.mediafire.com/folder/cirj9u226cn3d/softs # AOE2.zip http://www.mediafire.com/?cm8jl9p668vomba # avast_free_antivirus_setup.exe http://www.mediafire.com/?4nrlt3bpf8i69yz # Beyond Compare 3.1.3 Build 10374 + Serial Key.rar http://www.mediafire.com/?vcifnqbyg0t5dn2 # dropbox-2-4-6.zip http://www.mediafire.com/?e6133i8i3j5i8w8 # FshareSetup_4.7.0.exe http://www.mediafire.com/?emtdd7lei7dqbhh # Linux System Administration.pdf http://www.mediafire.com/?n1i6zi2r74czy58 # MediaFireDesktop-0.10.50.9468-windows-PRODUCTION.exe http://www.mediafire.com/?p9qqqkx1ikh66c1 # navicat8_mysql_en.zip http://www.mediafire.com/?cntytp9ja9y642d # OneDriveSetup.exe http://www.mediafire.com/?os9abu5gh9qhjte # Sparx Enterprise Architect v9.0.0.908.rar http://www.mediafire.com/?59gu9hygmrx2pjz
- plowndown
- plownup
Basic knowlege
Using basic commands(non script) from plowshare source
debug plowlist
debug below command:
bash -x /usr/local/bin/plowlist http://www.mediafire.com/folder/cirj9u226cn3d/softs
⇒ Check curl and php call
- command 1:
curl --insecure --compressed --speed-time 600 --connect-timeout 240 --user-agent 'Mozilla/5.0 (X11; Linux x86_64; rv:6.0) Gecko/20100101 Firefox/6.0' --silent -d folder_key=cirj9u226cn3d http://www.mediafire.com/api/folder/get_info.php
<?xml version="1.0" encoding="UTF-8"?> <response> <action>folder/get_info</action> <folder_info> <folderkey>cirj9u226cn3d</folderkey> <name>softs</name> <description/> <tags/> <created>2014-05-27 20:55:54</created> <privacy>public</privacy> <file_count>10</file_count> <folder_count>2</folder_count> <revision>294</revision> <owner_name>Anh Vo</owner_name> <avatar> http://www.mediafire.com/images/icons/myfiles/default.png </avatar> <flag>0</flag> </folder_info> <result>Success</result> <current_api_version>2.14</current_api_version> </response>
- command 2:
curl --insecure --compressed --speed-time 600 --connect-timeout 240 --user-agent 'Mozilla/5.0 (X11; Linux x86_64; rv:6.0) Gecko/20100101 Firefox/6.0' --silent -d folder_key=cirj9u226cn3d -d content_type=files -d chunk=1 http://www.mediafire.com/api/folder/get_content.php
<?xml version="1.0" encoding="UTF-8"?> <response> <action>folder/get_content</action> <folder_content> <chunk_size>100</chunk_size> <content_type>files</content_type> <chunk_number>1</chunk_number> <files> <file> <quickkey>cm8jl9p668vomba</quickkey> <hash> 4d737c99c02ac5f3b81b95ec32c2d81f099c1b91f7c505f9cebad2a01f0a7598 </hash> <filename>AOE2.zip</filename> <description/> <size>382775345</size> <privacy>public</privacy> <created>2014-05-29 02:35:59</created> <password_protected>no</password_protected> <mimetype>application/zip</mimetype> <filetype>archive</filetype> <view>0</view> <edit>0</edit> <revision>275</revision> <flag>0</flag> <links> <normal_download> http://www.mediafire.com/download/cm8jl9p668vomba/AOE2.zip </normal_download> </links> </file> .................... </files> </folder_content> <result>Success</result> <current_api_version>2.14</current_api_version> </response>
debug plowdown
debug below command:
bash -x /usr/local/bin/plowdown http://www.mediafire.com/?os9abu5gh9qhjte
⇒ Check curl and php call
- command 1:
curl --insecure --compressed --speed-time 600 --connect-timeout 240 --user-agent 'Mozilla/5.0 (X11; Linux x86_64; rv:6.0) Gecko/20100101 Firefox/6.0' --silent --head 'http://www.mediafire.com/?os9abu5gh9qhjte'
HTTP/1.1 301 Date: Fri, 30 May 2014 04:20:28 GMT Content-Type: text/html; charset=utf-8 Connection: close Cache-control: no-cache Expires: 0 Location: /download/os9abu5gh9qhjte/OneDriveSetup.exe Pragma: no-cache Set-Cookie: ukey=ue25ueitucwb8fbolgu8dpn869nur89o; expires=Fri, 29-Apr-2016 04:20:28 GMT; path=/; domain=.mediafire.com; httponly Server: MediaFire Access-Control-Allow-Origin: *
- command 2:
curl --insecure --compressed --speed-time 600 --connect-timeout 240 --user-agent 'Mozilla/5.0 (X11; Linux x86_64; rv:6.0) Gecko/20100101 Firefox/6.0' --silent -b /tmp/plowdown.23305.18589 -c /tmp/plowdown.23305.18589 http://www.mediafire.com/download/os9abu5gh9qhjte/OneDriveSetup.exe
Using basic commands base on mediafire API
Get Login Token
curl -k "https://www.mediafire.com/api/user/[email protected]&password=8941362&application_id=41323&signature=8d71ce0791d93d9192800b20b1b5aceb486534c2&version=2"
<login_token>7pbzcy6sm6hnzbfgdxxtt5nn610a1k8k4j2i9t5f11f6a99rikcpt19zpaq14ta6</login_token>
Get Session Token
curl -k "https://www.mediafire.com/api/user/[email protected]&password=xxxxxxx&application_id=41323&signature=8d71ce0791d93d9192800b20b1b5aceb486534c2&version=2"
<response> <action>user/get_session_token</action> <session_token> b781767140c809f2c7fea45275161504ac29a545ee4d451d4e25f075de67c45f93b22945df3eaf005fa92436ca80a496eab36332f5d401a84a6e31e2448c02606da9c23fce60a5bb </session_token> <pkey>5c83209e7f</pkey> <result>Success</result> <current_api_version>2.14</current_api_version> </response>
Get mediafire setting
curl "http://www.mediafire.com/api/user/get_settings.php?session_token=b781767140c809f2c7fea45275161504ac29a545ee4d451d4e25f075de67c45f93b22945df3eaf005fa92436ca80a496eab36332f5d401a84a6e31e2448c02606da9c23fce60a5bb"
<?xml version="1.0" encoding="UTF-8"?> <response> <action>user/get_settings</action> <settings> <max_upload_size>21474836580</max_upload_size> <max_instant_upload_size>21474836580</max_instant_upload_size> <validated>yes</validated> <instant_uploads_enabled>yes</instant_uploads_enabled> <show_download_page> <me_from_me>no</me_from_me> <me_from_others>yes</me_from_others> <others_from_me>no</others_from_me> </show_download_page> <used_storage_size>3192776282</used_storage_size> <storage_limit>12886999040</storage_limit> <storage_limit_exceeded>no</storage_limit_exceeded> <previous_file_versions>10</previous_file_versions> <default_share_link_status>inherit</default_share_link_status> </settings> <result>Success</result> <current_api_version>2.14</current_api_version> </response
Get folder information
curl "http://www.mediafire.com/api/folder/get_content.php?folder_key=cirj9u226cn3d&session_token=b781767140c809f2c7fea45275161504ac29a545ee4d451d4e25f075de67c45f93b22945df3eaf005fa92436ca80a496eab36332f5d401a84a6e31e2448c02606da9c23fce60a5bb&content_type=folders"
<?xml version="1.0" encoding="UTF-8"?> <response> <action>folder/get_content</action> <folder_content> <chunk_size>100</chunk_size> <content_type>folders</content_type> <chunk_number>1</chunk_number> <folders> <folder> <folderkey>obj7d1qatoaop</folderkey> <name>designer</name> <description/> <tags/> <privacy>public</privacy> <created>2014-05-28 18:41:34</created> <revision>266</revision> <flag>2</flag> <file_count>15</file_count> <folder_count>0</folder_count> <dropbox_enabled>no</dropbox_enabled> </folder> </folders> </folder_content> <result>Success</result> <current_api_version>2.14</current_api_version> </response>
Get list files in folder
curl "http://www.mediafire.com/api/folder/get_content.php?folder_key=cirj9u226cn3d&session_token=b781767140c809f2c7fea45275161504ac29a545ee4d451d4e25f075de67c45f93b22945df3eaf005fa92436ca80a496eab36332f5d401a84a6e31e2448c02606da9c23fce60a5bb&content_type=files"
<?xml version=“1.0” encoding=“UTF-8”?> <response>
<action>folder/get_content</action> <folder_content> <chunk_size>100</chunk_size> <content_type>files</content_type> <chunk_number>1</chunk_number> <files> <file> <quickkey>4nrlt3bpf8i69yz</quickkey> <hash> ed34cb6a33372502ef61aa949fc58fe643a1d8cf830e2a455ab4bcb49759ceda </hash> <filename>avast_free_antivirus_setup.exe</filename> <description/> <size>94714880</size> <privacy>public</privacy> <created>2014-05-27 20:53:58</created> <password_protected>no</password_protected> <mimetype>application/x-dosexec</mimetype> <filetype>application</filetype> <view>0</view> <edit>0</edit> <revision>271</revision> <flag>2</flag> <downloads>0</downloads> <views>0</views> <links> <normal_download> http://www.mediafire.com/download/4nrlt3bpf8i69yz/avast_free_antivirus_setup.exe </normal_download> </links> </file> <file> <quickkey>vcifnqbyg0t5dn2</quickkey> <hash> 0b7c1953ef9aa4e396dfef944b392d7ae094ffb781c121b89d0e19ee01c6eb8b </hash> <filename>Beyond Compare 3.1.3 Build 10374 + Serial Key.rar</filename> <description/> <size>5680787</size> <privacy>public</privacy> <created>2012-05-20 21:05:56</created> <password_protected>no</password_protected> <mimetype>application/x-rar</mimetype> <filetype>archive</filetype> <view>0</view> <edit>0</edit> <revision>289</revision> <flag>2</flag> <downloads>1</downloads> <views>0</views> <links> <normal_download> http://www.mediafire.com/download/vcifnqbyg0t5dn2/Beyond_Compare_3.1.3_Build_10374_+_Serial_Key.rar </normal_download> </links> </file> ................. </files> </folder_content> <result>Success</result> <current_api_version>2.14</current_api_version>
</response>
Get direct download link base on quickey
curl "http://www.mediafire.com/api/file/get_links.php?link_type=direct_download&session_token=b781767140c809f2c7fea45275161504ac29a545ee4d451d4e25f075de67c45f93b22945df3eaf005fa92436ca80a496eab36332f5d401a84a6e31e2448c02606da9c23fce60a5bb&quick_key=59gu9hygmrx2pjz&response_format=xml"
<?xml version="1.0" encoding="UTF-8"?> <response> <action>file/get_links</action> <links> <link> <quickkey>59gu9hygmrx2pjz</quickkey> <direct_download> http://download646.mediafire.com/8fhslcdsebjg/59gu9hygmrx2pjz/Sparx+Enterprise+Architect+v9.0.0.908.rar </direct_download> </link> </links> <direct_download_free_bandwidth>46</direct_download_free_bandwidth> <result>Success</result> <current_api_version>2.14</current_api_version> </response>
add web upload
curl "http://www.mediafire.com/api/upload/add_web_upload.php?session_token=b781767140c809f2c7fea45275161504ac29a545ee4d451d4e25f075de67c45f93b22945df3eaf005fa92436ca80a496eab36332f5d401a84a6e31e2448c02606da9c23fce60a5bb&url=http%3A%2F%2Fvn.easyvn.biz%2Ffiles%2Fsoftware%2F2013%2F08%2Facdsee-pro-6-3-build-221.zip&filename=acdsee-pro-6-3-build-221.zip"
<?xml version="1.0" encoding="UTF-8"?> <response> <action>upload/add_web_upload</action> <upload_key>sxs36umq1d</upload_key> <result>Success</result> <current_api_version>2.14</current_api_version> </response>
make file for install
plowshare core
post_login
post_login() { local -r AUTH=$1 local -r COOKIE=$2 local -r POSTDATA=$3 local -r LOGIN_URL=$4 shift 4 local -a CURL_ARGS=("$@") local USER PASSWORD DATA RESULT if [ -z "$AUTH" ]; then log_error "$FUNCNAME: authentication string is empty" return $ERR_LOGIN_FAILED fi if [ -z "$COOKIE" ]; then log_error "$FUNCNAME: cookie file expected" return $ERR_LOGIN_FAILED fi # Seem faster than # IFS=":" read -r USER PASSWORD <<< "$AUTH" USER=$(echo "${AUTH%%:*}" | uri_encode_strict) PASSWORD=$(echo "${AUTH#*:}" | uri_encode_strict) if [ -z "$PASSWORD" -o "$AUTH" = "${AUTH#*:}" ]; then PASSWORD=$(prompt_for_password) || true fi log_notice "Starting login process: $USER/${PASSWORD//?/*}" DATA=$(eval echo "${POSTDATA//&/\\&}") RESULT=$(curl --cookie-jar "$COOKIE" --data "$DATA" "${CURL_ARGS[@]}" \ "$LOGIN_URL") || return # "$RESULT" can be empty, this is not necessarily an error if [ ! -s "$COOKIE" ]; then log_debug "$FUNCNAME: no entry was set (empty cookie file)" return $ERR_LOGIN_FAILED fi log_report '=== COOKIE BEGIN ===' logcat_report "$COOKIE" log_report '=== COOKIE END ===' if ! find_in_array CURL_ARGS[@] '-o' '--output'; then echo "$RESULT" fi }
parse
# Get lines that match filter+parse regular expressions and extract string from it. # # $1: regexp to filter (take lines matching $1 pattern; "." or "" disable filtering). # $2: regexp to parse (must contain parentheses to capture text). Example: "url:'\(http.*\)'" # $3: (optional) how many lines to skip (default is 0: filter and match regexp on same line). # Note: $3 may only be used if line filtering is active ($1 != ".") # Example ($3=1): get lines matching filter regexp, then apply parse regexp on the line after. # Example ($3=-1): get lines matching filter regexp, then apply parse regexp on the line before. # stdin: text data # stdout: result parse_all() { local PARSE=$2 local -i N=${3:-0} local -r D=$'\001' # Change sed separator to allow '/' characters in regexp local STRING FILTER if [ -n "$1" -a "$1" != '.' ]; then FILTER="\\${D}$1${D}" # /$1/ else [ $N -eq 0 ] || return $ERR_FATAL fi [ '^' = "${PARSE:0:1}" ] || PARSE="^.*$PARSE" [ '$' = "${PARSE:(-1):1}" ] || PARSE+='.*$' PARSE="s${D}$PARSE${D}\1${D}p" # s/$PARSE/\1/p if [ $N -eq 0 ]; then # STRING=$(sed -ne "/$1/ s/$2/\1/p") STRING=$(sed -ne "$FILTER $PARSE") elif [ $N -eq 1 ]; then # Note: Loop (with label) is required for consecutive matches # STRING=$(sed -ne ":a /$1/ {n;h; s/$2/\1/p; g;ba;}") STRING=$(sed -ne ":a $FILTER {n;h; $PARSE; g;ba;}") elif [ $N -eq -1 ]; then # STRING=$(sed -ne "/$1/ {x; s/$2/\1/p; b;}" -e 'h') STRING=$(sed -ne "$FILTER {x; $PARSE; b;}" -e 'h') else local -r FIRST_LINE='^\([^\n]*\).*$' local -r LAST_LINE='^.*\n\(.*\)$' local N_ABS=$(( N < 0 ? -N : N )) local I=$(( N_ABS - 2 )) # Note: N_ABS >= 2 due to "elif" above local LINES='.*' local INIT='N' local FILTER_LINE PARSE_LINE [ $N_ABS -gt 10 ] && log_notice "$FUNCNAME: are you sure you want to skip $N lines?" while (( I-- )); do INIT+=';N' done while (( N_ABS-- )); do LINES+='\n.*' done if [ $N -gt 0 ]; then FILTER_LINE=$FIRST_LINE PARSE_LINE=$LAST_LINE else FILTER_LINE=$LAST_LINE PARSE_LINE=$FIRST_LINE fi STRING=$(sed -ne "1 {$INIT;h;n}" \ -e "H;g;s/^.*\\n\\($LINES\)$/\\1/;h" \ -e "s/$FILTER_LINE/\1/" \ -e "$FILTER {g;s/$PARSE_LINE/\1/;$PARSE }") # Explanation: [1], [2] let hold space always contain the current line # as well as the previous N lines # [3] let pattern space contain only the line we test filter regex # on (i.e. first buffered line on skip > 0, last line on skip < 0) # [4] if filter regex matches, let pattern space contain the line to # be parsed and apply parse command fi if [ -z "$STRING" ]; then log_error "$FUNCNAME failed (sed): \"/$1/ ${PARSE//$D//}\" (skip $N)" log_notice_stack return $ERR_FATAL fi echo "$STRING" } # Like parse_all, but get only first match parse() { local PARSE=$2 local -i N=${3:-0} local -r D=$'\001' # Change sed separator to allow '/' characters in regexp local STRING FILTER if [ -n "$1" -a "$1" != '.' ]; then FILTER="\\${D}$1${D}" # /$1/ else [ $N -eq 0 ] || return $ERR_FATAL fi [ '^' = "${PARSE:0:1}" ] || PARSE="^.*$PARSE" [ '$' = "${PARSE:(-1):1}" ] || PARSE+='.*$' PARSE="s${D}$PARSE${D}\1${D}p" # s/$PARSE/\1/p if [ $N -eq 0 ]; then # Note: This requires GNU sed (which is assumed by Plowshare4) #STRING=$(sed -ne "$FILTER {$PARSE;ta;b;:a;q;}") STRING=$(sed -ne "$FILTER {$PARSE;T;q;}") elif [ $N -eq 1 ]; then #STRING=$(sed -ne ":a $FILTER {n;h;$PARSE;tb;ba;:b;q;}") STRING=$(sed -ne ":a $FILTER {n;$PARSE;Ta;q;}") elif [ $N -eq -1 ]; then #STRING=$(sed -ne "$FILTER {g;$PARSE;ta;b;:a;q;}" -e 'h') STRING=$(sed -ne "$FILTER {g;$PARSE;T;q;}" -e 'h') else local -r FIRST_LINE='^\([^\n]*\).*$' local -r LAST_LINE='^.*\n\(.*\)$' local N_ABS=$(( N < 0 ? -N : N )) local I=$(( N_ABS - 2 )) local LINES='.*' local INIT='N' local FILTER_LINE PARSE_LINE [ $N_ABS -gt 10 ] && log_notice "$FUNCNAME: are you sure you want to skip $N lines?" while (( I-- )); do INIT+=';N' done while (( N_ABS-- )); do LINES+='\n.*' done if [ $N -gt 0 ]; then FILTER_LINE=$FIRST_LINE PARSE_LINE=$LAST_LINE else FILTER_LINE=$LAST_LINE PARSE_LINE=$FIRST_LINE fi # Note: Need to "clean" conditionnal flag after s/$PARSE_LINE/\1/ STRING=$(sed -ne "1 {$INIT;h;n}" \ -e "H;g;s/^.*\\n\\($LINES\)$/\\1/;h" \ -e "s/$FILTER_LINE/\1/" \ -e "$FILTER {g;s/$PARSE_LINE/\1/;ta;:a;$PARSE;T;q;}") fi if [ -z "$STRING" ]; then log_error "$FUNCNAME failed (sed): \"/$1/ ${PARSE//$D//}\" (skip $N)" log_notice_stack return $ERR_FATAL fi echo "$STRING" }
parse_json
# Simple and limited JSON parsing # # Notes: # - Single line parsing oriented (user should strip newlines first): no tree model # - Array and Object types: basic poor support (depth 1 without complex types) # - String type: no support for escaped unicode characters (\uXXXX) # - No non standard C/C++ comments handling (like in JSONP) # - If several entries exist on same line: last occurrence is taken, but: # consider precedence (order of priority): number, boolean/empty, string. # - If several entries exist on different lines: all are returned (it's a parse_all_json) # # $1: variable name (string) # $2: (optional) preprocess option. Accepted values are: # - "join": make a single line of input stream. # - "split": split input buffer on comma character (,). # stdin: JSON data # stdout: result parse_json() { local -r NAME="\"$1\"[[:space:]]*:[[:space:]]*" local STRING PRE local -r END='\([,}[:space:]].*\)\?$' if [ "$2" = 'join' ]; then PRE="tr -d '\n\r'" elif [ "$2" = 'split' ]; then PRE=sed\ -e\ 's/,[[:space:]]*\(["{]\)/\n\1/g' else PRE='cat' fi # Note: "ta;:a" is a trick for cleaning conditionnal flag STRING=$($PRE | sed \ -ne "/$NAME\[/{s/^.*$NAME\(\[[^]]*\]\).*$/\1/;ta;:a;s/^\[.*\[//;t;p;q;}" \ -ne "/$NAME{/{s/^.*$NAME\({[^}]*}\).*$/\1/;ta;:a;s/^{.*{//;t;p;q;}" \ -ne "s/^.*$NAME\(-\?\(0\|[1-9][[:digit:]]*\)\(\.[[:digit:]]\+\)\?\([eE][-+]\?[[:digit:]]\+\)\?\)$END/\1/p" \ -ne "s/^.*$NAME\(true\|false\|null\)$END/\1/p" \ -ne "s/\\\\\"/\\\\q/g;s/^.*$NAME\"\([^\"]*\)\"$END/\1/p") if [ -z "$STRING" ]; then log_error "$FUNCNAME failed (json): \"$1\"" log_notice_stack return $ERR_FATAL fi # Translate two-character sequence escape representations STRING=${STRING//\\\//\/} STRING=${STRING//\\\\/\\} STRING=${STRING//\\q/\"} STRING=${STRING//\\b/$'\b'} STRING=${STRING//\\f/$'\f'} STRING=${STRING//\\n/$'\n'} STRING=${STRING//\\r/$'\r'} STRING=${STRING//\\t/ } echo "$STRING" }
plowshare for mediafire
mediafire login
mediafire web
login form
<div id="loginStep1"> <div class="popup-title">How do you want to log in?</div> <div id="emailLogin" class="left"> <div class="errorBox">Invalid email or password.</div> <form id="form_login1" id="form_login1" method="post" action="/dynamic/client_login/mediafire.php" target="widgetwork"> <label class="ieLabel">Email address</label> <input type="email" pattern="^(.)+@[A-Za-z0-9]([A-Za-z0-9\.-]*[A-Za-z0-9])?\.[A-Za-z]{2,13}$" name="login_email" id="widget_login_email" placeholder="Email address"/> <label class="ieLabel">Password</label> <input type="password" name="login_pass" id="widget_login_pass" placeholder="Password" maxlength="30"/> <div id="login_remember_wrap"> <input type="checkbox" name="login_remember" id="login_remember" checked="checked"/> <label for="login_remember">Keep me logged in</label> </div> <a class="forgotPassword" href="/lost_password.php" target="_blank">Forgot password?</a> <button type="submit" class="gbtnTertiary" onclick="">Log in</button> </form> </div>
⇒ post url: /dynamic/client_login/mediafire.php
debug post login send
- Header
(Request-Line) POST /dynamic/client_login/mediafire.php HTTP/1.1 Host www.mediafire.com
- Post data
login_email [email protected] login_pass xxxxxxx login_remember on
debug reponse code for login
mediafire login code
mediafire_download() { local -r COOKIE_FILE=$1 local -r BASE_URL='http://www.mediafire.com' local FILE_ID URL PAGE JSON JS_VAR if [ -n "$AUTH_FREE" ]; then mediafire_login "$AUTH_FREE" "$COOKIE_FILE" "$BASE_URL" || return fi ................. } # Static function. Proceed with login # $1: authentication # $2: cookie file # $3: base URL mediafire_login() { local -r AUTH_FREE=$1 local -r COOKIE_FILE=$2 local -r BASE_URL=$3 local -r ENC_BASE_URL=$(uri_encode_strict <<< "$BASE_URL/") local LOGIN_DATA PAGE CODE NAME # Make sure we have "ukey" cookie (mandatory) curl -c "$COOKIE_FILE" -o /dev/null "$BASE_URL" # Notes: - "login_remember=on" not required # - force SSLv3 to avoid problems with curl using OpenSSL/1.0.1 LOGIN_DATA='login_email=$USER&login_pass=$PASSWORD&submit_login=Login+to+MediaFire' PAGE=$(post_login "$AUTH_FREE" "$COOKIE_FILE" "$LOGIN_DATA" \ "${BASE_URL/#http/https}/dynamic/login.php?popup=1" \ -b "$COOKIE_FILE" --sslv3 --referer "$BASE_URL") || return # Note: Cookies "user" and "session" get set on successful login, "skey" is changed" CODE=$(echo "$PAGE" | parse 'var et' 'var et= \(-\?[[:digit:]]\+\);') || return NAME=$(echo "$PAGE" | parse 'var fp' "var fp='\([^']\+\)';") || return # Check for errors # Note: All error codes are explained in page returned by server. if [ $CODE -ne 15 ]; then log_debug "Remote error: $ERR" return $ERR_LOGIN_FAILED fi log_debug "Successfully logged in as member '$NAME'" }
mediafire download
- download.sh
local FUNCTION=${MODULE}_download $FUNCTION "$COOKIE_FILE" "$URL_ENCODED" >"$DRESULT" || DRETVAL=$?
- mediafire.sh
# Output a mediafire file download URL # $1: cookie file # $2: mediafire.com url # stdout: real file download link mediafire_download() { local -r COOKIE_FILE=$1 local -r BASE_URL='http://www.mediafire.com' local FILE_ID URL PAGE JSON JS_VAR if [ -n "$AUTH_FREE" ]; then mediafire_login "$AUTH_FREE" "$COOKIE_FILE" "$BASE_URL" || return fi FILE_ID=$(mediafire_extract_id "$2") || return if ! mediafire_is_file_id "$FILE_ID"; then log_error 'This is a folder link. Please use plowlist!' return $ERR_FATAL fi # Only get site headers first to capture direct download links URL=$(curl --head "$BASE_URL/?$FILE_ID" | grep_http_header_location_quiet) || return case "$URL" in # no redirect, normal download '') URL="$BASE_URL/?$FILE_ID" ;; /download/*) URL="$BASE_URL$URL" ;; http://*) log_debug 'Direct download' echo "$URL" return 0 ;; *errno=999) return $ERR_LINK_NEED_PERMISSIONS ;; *errno=320|*errno=378) return $ERR_LINK_DEAD ;; *errno=*) log_error "Unexpected remote error: ${URL#*errno=}" return $ERR_FATAL esac PAGE=$(curl -b "$COOKIE_FILE" -c "$COOKIE_FILE" "$URL" | break_html_lines) || return # <h3 class="error_msg_title">Invalid or Deleted File.</h3> match 'Invalid or Deleted File' "$PAGE" && return $ERR_LINK_DEAD # handle captcha (reCaptcha or SolveMedia) if there is one if match '<form[^>]*form_captcha' "$PAGE"; then local FORM_CAPTCHA PUBKEY CHALLENGE ID RESP CAPTCHA_DATA FORM_CAPTCHA=$(grep_form_by_name "$PAGE" 'form_captcha') || return if match 'recaptcha/api' "$FORM_CAPTCHA"; then log_debug 'reCaptcha found' local WORD PUBKEY='6LextQUAAAAAALlQv0DSHOYxqF3DftRZxA5yebEe' RESP=$(recaptcha_process $PUBKEY) || return { read WORD; read CHALLENGE; read ID; } <<< "$RESP" CAPTCHA_DATA="-d recaptcha_challenge_field=$CHALLENGE -d recaptcha_response_field=$WORD" elif match 'api\.solvemedia' "$FORM_CAPTCHA"; then log_debug 'Solve Media CAPTCHA found' PUBKEY='Z94dMnWequbvKmy-HchLrZJ3-.qB6AJ1' RESP=$(solvemedia_captcha_process $PUBKEY) || return { read CHALLENGE; read ID; } <<< "$RESP" CAPTCHA_DATA="--data-urlencode adcopy_challenge=$CHALLENGE -d adcopy_response=manual_challenge" else log_error 'Unexpected content/captcha type. Site updated?' return $ERR_FATAL fi log_debug "Captcha data: $CAPTCHA_DATA" PAGE=$(curl --location -b "$COOKIE_FILE" --referer "$URL" \ $CAPTCHA_DATA "$BASE_URL/?$FILE_ID") || return # Your entry was incorrect, please try again! if match 'Your entry was incorrect' "$PAGE"; then captcha_nack $ID log_error 'Wrong captcha' return $ERR_CAPTCHA fi captcha_ack $ID log_debug 'Correct captcha' fi # Check for password protected link if match 'name="downloadp"' "$PAGE"; then log_debug 'File is password protected' if [ -z "$LINK_PASSWORD" ]; then LINK_PASSWORD=$(prompt_for_password) || return fi PAGE=$(curl -L --post301 -b "$COOKIE_FILE" \ -d "downloadp=$LINK_PASSWORD" "$URL" | break_html_lines) || return match 'name="downloadp"' "$PAGE" && return $ERR_LINK_PASSWORD_REQUIRED fi JS_VAR=$(echo "$PAGE" | parse 'function[[:space:]]*_' '"\([^"]\+\)";' 1) || return # extract + output download link + file name mediafire_get_ofuscated_link "$JS_VAR" | parse_attr href || return if ! parse_attr 'og:title' 'content' <<< "$PAGE"; then parse_tag 'title' <<< "$PAGE" || return fi }
mediafire upload
upload code
- [upload.sh]
FUNCTION=${MODULE}_upload $FUNCTION "$UCOOKIE" "$LOCALFILE" \ "$DESTFILE" >"$URESULT" || URETVAL=$?
- [mediafire.sh]
# Upload a file to mediafire using official API. # https://www.mediafire.com/developers/upload.php # $1: cookie file (unused here) # $2: input file (with full path) # $3: remote filename # stdout: mediafire.com download link mediafire_upload() { local -r COOKIE_FILE=$1 local -r FILE=$2 local -r DEST_FILE=$3 local -r BASE_URL='https://www.mediafire.com' local SESSION_TOKEN JSON RES KEY_ID UPLOAD_KEY QUICK_KEY FOLDER_KEY # Sanity checks [ -n "$AUTH_FREE" ] || return $ERR_LINK_NEED_PERMISSIONS if [ -n "$ASYNC" ] && ! match_remote_url "$FILE"; then log_error 'Cannot upload local files asynchronously.' return $ERR_BAD_COMMAND_LINE fi if [ -n "$ASYNC" -a \( -n "$DESCRIPTION" -o -n "$LINK_PASSWORD" -o \ -n "$PRIVATE_FILE" \) ] ; then log_error 'Advanced options not available for asynchronously uploaded files.' return $ERR_BAD_COMMAND_LINE fi # FIXME if [ -z "$ASYNC" ] && match_remote_url "$FILE"; then log_error 'Synchronous remote upload not implemented.' return $ERR_BAD_COMMAND_LINE fi SESSION_TOKEN=$(mediafire_api_get_session_token "$AUTH_FREE" "$BASE_URL") || return log_debug "Session Token: '$SESSION_TOKEN'" # API bug if [ "${#DEST_FILE}" -lt 3 ]; then log_error 'Filenames less than 3 characters cannot be uploaded. Mediafire API bug? This is not a plowshare bug!' fi if [ -n "$FOLDER" ]; then FOLDER_KEY=$(mediafire_check_folder "$SESSION_TOKEN" "$BASE_URL" "$FOLDER") || return fi # Check for duplicate name JSON=$(curl --get -d "session_token=$SESSION_TOKEN" -d "filename=$DEST_FILE" \ -d 'response_format=json' \ -d 'action_on_duplicate=keep' \ ${FOLDER:+-d "upload_folder_key=$FOLDER_KEY"} \ "$BASE_URL/api/upload/pre_upload.php") || return RES=$(parse_json result <<<"$JSON") || return if [ "$RES" != 'Success' ]; then local NUM MSG NUM=$(parse_json_quiet error <<<"$JSON") MSG=$(parse_json_quiet message <<<"$JSON") log_error "Unexpected remote error (pre_upload): $NUM, '$MSG'" return $ERR_FATAL fi # "duplicate_name":"yes","duplicate_quickkey":"2xrys3f97a9t9ce" # Note: "duplicate_name" is not always returned ??? QUICK_KEY=$(parse_json_quiet 'duplicate_quickkey' <<<"$JSON") || return if [ -n "$QUICK_KEY" ]; then if [ -n "$UNIQUE_FILE" ]; then log_error 'Duplicated filename. Return original quickkey.' echo "$BASE_URL/?$QUICK_KEY" return 0 else log_debug 'a file with the same filename already exists. File will be renamed.' fi fi # "used_storage_size":"10438024","storage_limit":"53687091200","storage_limit_exceeded":"no" RES=$(parse_json storage_limit_exceeded <<<"$JSON") || return if [ "$RES" = 'yes' ]; then log_error 'Storage limit exceeded. Abort.' return $ERR_SIZE_LIMIT_EXCEEDED fi # Start upload if match_remote_url "$FILE"; then JSON=$(curl -d "session_token=$SESSION_TOKEN" \ -d "filename=$DESTFILE" \ -d 'response_format=json' \ --data-urlencode "url=$FILE" \ ${FOLDER:+"-d folder_key=$FOLDER_KEY"} \ "$BASE_URL/api/upload/add_web_upload.php") || return KEY_ID='upload_key' else local FILE_SIZE FILE_SIZE=$(get_filesize "$FILE") || return JSON=$(curl_with_log -F "Filedata=@$FILE;filename=$DESTFILE" \ --header "x-filename: $DEST_FILE" \ --header "x-size: $FILE_SIZE" \ "$BASE_URL/api/upload/upload.php?session_token=$SESSION_TOKEN&action_on_duplicate=keep&response_format=json${FOLDER:+"&uploadkey=$FOLDER_KEY"}") || return KEY_ID='key' fi # Check for errors RES=$(parse_json result <<<"$JSON") || return if [ "$RES" != 'Success' ]; then local NUM MSG NUM=$(parse_json_quiet error <<<"$JSON") MSG=$(parse_json_quiet message <<<"$JSON") log_error "Unexpected remote error (upload): $NUM, '$MSG'" return $ERR_FATAL fi UPLOAD_KEY=$(parse_json "$KEY_ID" <<< "$JSON") || return log_debug "polling for status update (with key $UPLOAD_KEY)" QUICK_KEY='' # Wait for upload to finish if match_remote_url "$FILE"; then [ -n "$ASYNC" ] && return $ERR_ASYNC_REQUEST else for N in 3 3 2 2 2; do wait $N seconds || return JSON=$(curl --get -d "session_token=$SESSION_TOKEN" \ -d 'response_format=json' -d "key=$UPLOAD_KEY" \ "$BASE_URL/api/upload/poll_upload.php") || return RES=$(parse_json result <<<"$JSON") || return if [ "$RES" != 'Success' ]; then log_error "FIXME '$JSON'" return $ERR_FATAL fi # No more requests for this key RES=$(parse_json status <<<"$JSON") || return if [ "$RES" = '99' ]; then QUICK_KEY=$(parse_json quickkey <<<"$JSON") || return break fi done fi if [ -z "$QUICK_KEY" ]; then local MSG ERR MSG=$(parse_json_quiet description <<<"$JSON") ERR=$(parse_json_quiet fileerror <<<"$JSON") log_error "Bad status $RES: '$MSG'" log_debug "fileerror: '$ERR'" return $ERR_FATAL fi if [ -n "$DESCRIPTION" -o -n "$PRIVATE_FILE" ]; then JSON=$(curl -d "session_token=$SESSION_TOKEN" \ -d "quick_key=$QUICK_KEY" -d 'response_format=json' \ ${DESCRIPTION:+-d "description=$DESCRIPTION"} \ ${PRIVATE_FILE:+-d 'privacy=private'} \ "$BASE_URL/api/file/update.php") || return RES=$(parse_json result <<<"$JSON") if [ "$RES" != 'Success' ]; then log_error 'Could not set description/hide file.' fi fi # Note: Making a file private removes its password... if [ -n "$LINK_PASSWORD" ]; then JSON=$(curl -d "session_token=$SESSION_TOKEN" \ -d "quick_key=$QUICK_KEY" -d 'response_format=json' \ -d "password=$LINK_PASSWORD" \ "$BASE_URL/api/file/update_password.php") || return RES=$(parse_json result <<<"$JSON") if [ "$RES" != 'Success' ]; then log_error 'Could not set password.' fi fi echo "$BASE_URL/?$QUICK_KEY" }
Analyser code
- Step1: Get session token using $BASE_URL/api/user/get_session_token.php
SESSION_TOKEN=$(mediafire_api_get_session_token "$AUTH_FREE" "$BASE_URL") || return
- Step2: Check for duplicate name using $BASE_URL/api/upload/pre_upload.php
JSON=$(curl --get -d "session_token=$SESSION_TOKEN" -d "filename=$DEST_FILE" \ -d 'response_format=json' \ -d 'action_on_duplicate=keep' \ ${FOLDER:+-d "upload_folder_key=$FOLDER_KEY"} \ "$BASE_URL/api/upload/pre_upload.php") || return
- Step3: Start upload
- using remote upload $BASE_URL/api/upload/add_web_upload.php
if match_remote_url "$FILE"; then JSON=$(curl -d "session_token=$SESSION_TOKEN" \ -d "filename=$DESTFILE" \ -d 'response_format=json' \ --data-urlencode "url=$FILE" \ ${FOLDER:+"-d folder_key=$FOLDER_KEY"} \ "$BASE_URL/api/upload/add_web_upload.php") || return
- Or using upload file with $BASE_URL/api/upload/upload.php
else local FILE_SIZE FILE_SIZE=$(get_filesize "$FILE") || return JSON=$(curl_with_log -F "Filedata=@$FILE;filename=$DESTFILE" \ --header "x-filename: $DEST_FILE" \ --header "x-size: $FILE_SIZE" \ "$BASE_URL/api/upload/upload.php?session_token=$SESSION_TOKEN&action_on_duplicate=keep&response_format=json${FOLDER:+"&uploadkey=$FOLDER_KEY"}") || return KEY_ID='key' fi