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

plowup examples

Upload

plowlist examples

real examples for mediafire

prepare config for mediafire

plowshare commands

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

debug plowdown

debug below command:

 bash -x  /usr/local/bin/plowdown  http://www.mediafire.com/?os9abu5gh9qhjte

⇒ Check curl and php call

Using basic commands base on mediafire API

refer: http://www.mediafire.com/developers/

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>

 
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
debug reponse code for login

compare reponse OK and response fail

var et= 15

⇒ Login OK

var fp='[email protected]';

⇒ username

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

mediafire upload

Refer: https://www.mediafire.com/developers/upload.php

upload code

Analyser code