1#!/usr/bin/env ruby 2# The MIT License 3# 4# Copyright (c) 2009 Tatsuhiro Tsujikawa 5# 6# Permission is hereby granted, free of charge, to any person obtaining a copy 7# of this software and associated documentation files (the "Software"), to deal 8# in the Software without restriction, including without limitation the rights 9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10# copies of the Software, and to permit persons to whom the Software is 11# furnished to do so, subject to the following conditions: 12# 13# The above copyright notice and this permission notice shall be included in 14# all copies or substantial portions of the Software. 15# 16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22# THE SOFTWARE. 23require 'xmlrpc/client' 24require 'pp' 25require 'optparse' 26 27program_name=File.basename($0) 28options={} 29args=nil 30OptionParser.new do |opt| 31 opt.on("-d","--dir DIR"){|val| options["dir"]=val} 32 opt.on("-V","--check-integrity [BOOL]", ["true","false"]){|val| 33 options["check-integrity"]= val||"true" 34 } 35 opt.on("-c","--continue [BOOL]",["true","false"]){|val| 36 options["continue"]=val||"true" 37 } 38 opt.on("--all-proxy PROXY"){|val| options["all-proxy"]=val} 39 opt.on("--all-proxy-user USER"){|val| options["all-proxy-user"]=val} 40 opt.on("--all-proxy-passwd PASSWD"){|val| options["all-proxy-passwd"]=val} 41 opt.on("--connect-timeout SEC"){|val| options["connect-timeout"]=val} 42 opt.on("--dry-run [BOOL]",["true","false"]){|val| 43 options["dry-run"]=val||"true" 44 } 45 opt.on("--lowest-speed-limit SPEED"){|val| options["lowest-speed-limit"]=val} 46 opt.on("--max-file-not-found NUM"){|val| options["max-file-not-found"]=val} 47 opt.on("-m","--max-tries N"){|val| options["max-tries"]=val} 48 opt.on("--no-proxy DOMAINS"){|val| options["no-proxy"]=val} 49 opt.on("-o","--out FILE"){|val| options["out"]=val} 50 opt.on("--proxy-method METHOD"){|val| options["proxy-method"]=val} 51 opt.on("-R","--remote-time [BOOL]",["true","false"]){|val| 52 options["remote-time"]=val||"true" 53 } 54 opt.on("-s","--split N"){|val| options["split"]=val} 55 opt.on("-t","--timeout SEC"){|val| options["timeout"]=val} 56 opt.on("--http-auth-challenge [BOOL]",["true","false"]){|val| 57 options["http-auth-challenge"]=val||"true" 58 } 59 opt.on("--http-no-cache [BOOL]",["true","false"]){|val| 60 options["http-no-cache"]=val||"true" 61 } 62 opt.on("--http-user USER"){|val| options["http-user"]=val} 63 opt.on("--http-passwd PASSWD"){|val| options["http-passwd"]=val} 64 opt.on("--http-proxy PROXY"){|val| options["http-proxy"]=val} 65 opt.on("--http-proxy-user USER"){|val| options["http-proxy-user"]=val} 66 opt.on("--http-proxy-passwd PASSWD"){|val| options["http-proxy-passwd"]=val} 67 opt.on("--https-proxy PROXY"){|val| options["https-proxy"]=val} 68 opt.on("--https-proxy-user USER"){|val| options["https-proxy-user"]=val} 69 opt.on("--https-proxy-passwd PASSWD"){|val| options["https-proxy-passwd"]=val} 70 opt.on("--referer REFERER"){|val| options["referer"]=val} 71 opt.on("--enable-http-keep-alive [BOOL]",["true","false"]){|val| 72 options["enable-http-keep-alive"]=val||"true" 73 } 74 opt.on("--enable-http-pipelining [BOOL]",["true","false"]){|val| 75 options["enable-http-pipelining"]=val||"true" 76 } 77 opt.on("--header HEADER"){|val| 78 options["header"] = [] if options["header"] == nil 79 options["header"] << val 80 } 81 opt.on("--use-head [BOOL]",["true","false"]){|val| 82 options["use-head"]=val||"true" 83 } 84 opt.on("-U","--user-agent USERAGENT"){|val| options["user-agent"]=val} 85 opt.on("--ftp-user USER"){|val| options["ftp-user"]=val} 86 opt.on("--ftp-passwd PASSWD"){|val| options["ftp-passwd"]=val} 87 opt.on("-p","--ftp-pasv [BOOL]",["true","false"]){|val| 88 options["ftp-pasv"]=val||"true" 89 } 90 opt.on("--ftp-proxy PROXY"){|val| options["ftp-proxy"]=val} 91 opt.on("--ftp-proxy-user USER"){|val| options["ftp-proxy-user"]=val} 92 opt.on("--ftp-proxy-passwd PASSWD"){|val| options["ftp-proxy-passwd"]=val} 93 opt.on("--ftp-type TYPE"){|val| options["ftp-type"]=val} 94 opt.on("--ftp-reuse-connection [BOOL]",["true","false"]){|val| 95 options["ftp-reuse-connection"]=val||"true" 96 } 97 opt.on("-n","--no-netrc [BOOL]",["true","false"]){|val| 98 options["no-netrc"]=val||"true" 99 } 100 opt.on("--reuse-uri [BOOL]",["true","false"]){|val| 101 options["reuse-uri"]=val||"true" 102 } 103 opt.on("--select-file INDEXES"){|val| options["select-file"]=val} 104 opt.on("--bt-enable-lpd [BOOL]",["true","false"]){|val| 105 options["bt-enable-lpd"]=val||"true" 106 } 107 opt.on("--bt-external-ip IPADDRESS"){|val| options["bt-external-ip"]=val} 108 opt.on("--bt-hash-check-seed [BOOL]",["true","false"]){|val| 109 options["bt-hash-check-seed"]=val||"true" 110 } 111 opt.on("--bt-max-open-files NUM"){|val| options["bt-max-open-files"]=val} 112 opt.on("--bt-max-peers NUM"){|val| options["bt-max-peers"]=val} 113 opt.on("--bt-metadata-only [BOOL]",["true","false"]){|val| 114 options["bt-metadata-only"]=val||"true" 115 } 116 opt.on("--bt-min-crypto-level LEVEL",["plain","arc4"]){|val| 117 options["bt-min-crypto-level"]=val 118 } 119 opt.on("--bt-prioritize-piece RANGE") {|val| 120 options["bt-prioritize-piece"]=val 121 } 122 opt.on("--bt-require-crypto [BOOL]",["true","false"]){|val| 123 options["bt-require-crypto"]=val||"true" 124 } 125 opt.on("--bt-request-peer-speed-limit SPEED"){|val| 126 options["bt-request-peer-speed-limit"]=val 127 } 128 opt.on("--bt-save-metadata [BOOL]",["true","false"]){|val| 129 options["bt-save-metadata"]=val||"true" 130 } 131 opt.on("--bt-seed-unverified [BOOL]",["true","false"]){|val| 132 options["bt-seed-unverified"]=val||"true" 133 } 134 opt.on("--bt-stop-timeout SEC"){|val| options["bt-stop-timeout"]=val} 135 opt.on("--bt-tracker-interval SEC"){|val| options["bt-tracker-interval"]=val} 136 opt.on("--bt-tracker-timeout SEC"){|val| options["bt-tracker-timeout"]=val} 137 opt.on("--bt-tracker-connect-timeout SEC"){|val| 138 options["bt-tracker-connect-timeout"]=val 139 } 140 opt.on("--enable-peer-exchange [BOOL]",["true","false"]){|val| 141 options["enable-peer-exchange"]=val||"true" 142 } 143 opt.on("--follow-torrent VALUE", ["true","false","mem"]){|val| 144 options["follow-torrent"]=val 145 } 146 opt.on("-O","--index-out INDEXPATH"){|val| 147 options["index-out"]=[] if options["index-out"] == nil 148 options["index-out"] << val 149 } 150 opt.on("-u","--max-upload-limit SPEED"){|val| options["max-upload-limit"]=val} 151 opt.on("--seed-ratio RATIO"){|val| options["seed-ratio"]=val} 152 opt.on("--seed-time MINUTES"){|val| options["seed-time"]=val} 153 opt.on("--follow-metalink VALUE", ["true","false","mem"]){|val| 154 options["follow-metalink"]=val 155 } 156 opt.on("-C","--metalink-servers NUM"){|val| options["metalink-servers"]=val} 157 opt.on("--metalink-language LANG"){|val| options["metalink-language"]=val} 158 opt.on("--metalink-location LOCS"){|val| options["metalink-location"]=val} 159 opt.on("--metalink-os OS"){|val| options["metalink-os"]=val} 160 opt.on("--metalink-version VERSION"){|val| options["metalink-version"]=val} 161 opt.on("--metalink-preferred-protocol PROTO"){|val| 162 options["metalink-preferred-protocol"]=val 163 } 164 opt.on("--metalink-enable-unique-protocol [BOOL]",["true","false"]){|val| 165 options["metalink-enable-unique-protocol"]=val||"true" 166 } 167 opt.on("--allow-overwrite [BOOL]",["true","false"]){|val| 168 options["allow-overwrite"]=val||"true" 169 } 170 opt.on("--allow-piece-length-change [BOOL]",["true","false"]){|val| 171 options["allow-piece-length-change"]=val||"true" 172 } 173 opt.on("--async-dns [BOOL]",["true","false"]){|val| 174 options["async-dns"]=val||"true" 175 } 176 opt.on("--auto-file-renaming [BOOL]",["true","false"]){|val| 177 options["auto-file-renaming"]=val||"true" 178 } 179 opt.on("--file-allocation METHOD",["none","prealloc","falloc"]){|val| 180 options["file-allocation"]=val 181 } 182 opt.on("--max-download-limit LIMIT"){|val| options["max-download-limit"]=val} 183 opt.on("--no-file-allocation-limit SIZE"){|val| 184 options["no-file-allocation-limit"]=val 185 } 186 opt.on("-P","--parameterized-uri [BOOL]",["true","false"]){|val| 187 options["parameterized-uri"]=val||"true" 188 } 189 opt.on("--realtime-chunk-checksum [BOOL]",["true","false"]){|val| 190 options["realtime-chunk-checksum"]=val||"true" 191 } 192 opt.on("--remove-control-file [BOOL]",["true","false"]){|val| 193 options["remove-control-file"]=val||"true" 194 } 195 opt.on("--always-resume [BOOL]",["true","false"]){|val| 196 options["always-resume"]=val||"true" 197 } 198 opt.on("--max-resume-failure-tries N"){|val| 199 options["max-resume-failure-tries"]=val 200 } 201 opt.on("--http-accept-gzip [BOOL]",["true","false"]){|val| 202 options["http-accept-gzip"]=val||"true" 203 } 204 opt.on("-x","--max-connection-per-server NUM"){|val| options["max-connection-per-server"]=val} 205 opt.on("-k","--min-split-size SIZE"){|val| options["min-split-size"]=val} 206 opt.on("--conditional-get [BOOL]",["true","false"]){|val| 207 options["conditional-get"]=val||"true" 208 } 209 opt.on("--enable-async-dns6 [BOOL]",["true","false"]){|val| 210 options["enable-async-dns6"]=val||"true" 211 } 212 opt.on("--bt-tracker URIS"){|val| options["bt-tracker"]=val} 213 opt.on("--bt-exclude-tracker URIS"){|val| options["bt-exclude-tracker"]=val} 214 opt.on("--retry-wait SEC"){|val| options["retry-wait"]=val} 215 opt.on("--metalink-base-uri URI"){|val| options["metalink-base-uri"]=val} 216 opt.on("--pause [BOOL]",["true","false"]){|val| options["pause"]=val||"true"} 217 opt.on("--stream-piece-selector SELECTOR"){|val| options["stream-piece-selector"]=val} 218 opt.on("--hash-check-only [BOOL]",["true","false"]){|val| 219 options["hash-check-only"]=val||"true" 220 } 221 opt.on("--checksum TYPE_DIGEST"){|val| options["checksum"]=val} 222 opt.on("--piece-length LENGTH"){|val| options["piece-length"]=val} 223 opt.on("--uri-selector SELECTOR"){|val| options["uri-selector"]=val} 224 225 opt.on("--max-overall-download-limit LIMIT"){|val| options["max-overall-download-limit"]=val} 226 opt.on("--max-overall-upload-limit LIMIT"){|val| options["max-overall-upload-limit"]=val} 227 opt.on("-j","--max-concurrent-downloads N"){|val| options["max-concurrent-downloads"]=val} 228 opt.on("-l","--log FILE"){|val| options["log"]=val} 229 opt.on("--max-download-result NUM"){|val| options["max-download-result"]=val} 230 opt.on("--download-result OPT"){|val| options["download-result"]=val} 231 opt.on("--keep-unfinished-download-result [BOOL]",["true","false"]){|val| 232 options["keep-unfinished-download-result"]=val||"true" 233 } 234 opt.on("--save-session FILE"){|val| options["save-session"]=val} 235 opt.on("--server-stat-of FILE"){|val| options["server-stat-of"]=val} 236 opt.on("--save-cookies FILE"){|val| options["save-cookies"]=val} 237 opt.on("--gid GID"){|val| options["gid"]=val} 238 opt.on("--pause-metadata [BOOL]",["true","false"]){|val| options["pause-metadata"]=val||"true"} 239 240 opt.on("--server SERVER", "hostname of XML-RPC server. Default: localhost"){|val| options["server"]=val } 241 opt.on("--port PORT", "port of XML-RPC server. Default: 6800"){|val| options["port"]=val } 242 243 opt.on("--user USERNAME", "XML-RPC username"){|val| options["user"]=val } 244 opt.on("--passwd PASSWORD", "XML-RPC password"){|val| options["passwd"]=val } 245 opt.on("--secure [BOOL]",["true","false"]){|val| options["secure"]=val||"true" } 246 opt.on("--check-rpc-cert [BOOL]",["true","false"]){|val| options["check-rpc-cert"]=val||"true" } 247 248 opt.on("--secret SECRET", "XML-RPC secret authorization token"){|val| options["secret"]=val } 249 250 opt.banner=<<EOS 251Usage: #{program_name} addUri URI... [options] 252 #{program_name} addTorrent /path/to/torrent_file URI... [options] 253 #{program_name} addMetalink /path/to/metalink_file [options] 254 #{program_name} remove GID [options] 255 #{program_name} forceRemove GID [options] 256 #{program_name} pause GID [options] 257 #{program_name} pauseAll [options] 258 #{program_name} forcePause GID [options] 259 #{program_name} forcePauseAll [options] 260 #{program_name} unpause GID [options] 261 #{program_name} unpauseAll [options] 262 #{program_name} changePosition GID pos how [options] 263 #{program_name} tellStatus GID [keys] [options] 264 #{program_name} tellActive [keys] [options] 265 #{program_name} tellWaiting offset num [keys] [options] 266 #{program_name} tellStopped offset num [keys] [options] 267 #{program_name} getOption GID [options] 268 #{program_name} getGlobalOption [options] 269 #{program_name} getFiles GID [options] 270 #{program_name} getUris GID [options] 271 #{program_name} getPeers GID [options] 272 #{program_name} getServers GID [options] 273 #{program_name} purgeDownloadResult [options] 274 #{program_name} removeDownloadResult GID [options] 275 #{program_name} changeOption GID [options] 276 #{program_name} changeGlobalOption [options] 277 #{program_name} getVersion [options] 278 #{program_name} getSessionInfo [options] 279 #{program_name} shutdown [options] 280 #{program_name} forceShutdown [options] 281 #{program_name} getGlobalStat [options] 282 #{program_name} saveSession [options] 283 #{program_name} appendUri GID fileIndex URI... [options] 284 This command calls aria2.changeUri(GID, fileIndex, [], [URI,...]) 285 internally. 286Options: 287EOS 288 289 290 args=opt.parse(ARGV) 291 292end 293 294if !args or args.size == 0 then 295 puts "No command specified" 296 exit 1 297end 298 299command=args[0] 300resources=args[1..-1] 301 302auth="" 303if options.has_key?("user") then 304 auth=options["user"]+":"+options["passwd"]+"@" 305end 306if not options.has_key?("server") then 307 options["server"]="localhost" 308end 309if not options.has_key?("port") then 310 options["port"]="6800" 311end 312if not options.has_key?("secure") then 313 options["secure"]="false" 314end 315if not options.has_key?("check-rpc-cert") then 316 options["check-rpc-cert"]="true" 317end 318secret = if options.has_key?("secret") then "token:"+options["secret"] else nil end 319 320client=XMLRPC::Client.new3({:host => options["server"], 321 :port => options["port"], 322 :path => "/rpc", 323 :user => options["user"], 324 :password => options["passwd"], 325 :use_ssl => options["secure"] == "true"}) 326 327if options["check-rpc-cert"] == "false" then 328 client.instance_variable_get(:@http).instance_variable_set(:@verify_mode, OpenSSL::SSL::VERIFY_NONE) 329end 330 331options.delete("server") 332options.delete("port") 333options.delete("user") 334options.delete("passwd") 335options.delete("secret") 336options.delete("secure") 337options.delete("check-rpc-cert") 338 339def client_call client, secret, method, *params 340 if secret.nil? 341 client.call(method, *params) 342 else 343 client.call(method, secret, *params) 344 end 345end 346 347if command == "addUri" then 348 result=client_call(client, secret, "aria2."+command, resources, options) 349elsif command == "addTorrent" then 350 torrentData=IO.read(resources[0]) 351 result=client_call(client, secret, "aria2."+command, 352 XMLRPC::Base64.new(torrentData), resources[1..-1], options) 353elsif command == "addMetalink" then 354 metalinkData=IO.read(resources[0]) 355 result=client_call(client, secret, "aria2."+command, 356 XMLRPC::Base64.new(metalinkData), options) 357elsif command == "tellStatus" then 358 result=client_call(client, secret, "aria2."+command, 359 resources[0], resources[1..-1]) 360elsif command == "tellActive" then 361 result=client_call(client, secret, "aria2."+command, resources[0..-1]) 362elsif command == "tellWaiting" then 363 result=client_call(client, secret, "aria2."+command, resources[0].to_i(), 364 resources[1].to_i(), resources[2..-1]) 365elsif command == "tellStopped" then 366 result=client_call(client, secret, "aria2."+command, resources[0].to_i(), 367 resources[1].to_i(), resources[2..-1]) 368elsif command == "getOption" then 369 result=client_call(client, secret, "aria2."+command, resources[0]) 370elsif command == "getGlobalOption" then 371 result=client_call(client, secret, "aria2."+command) 372elsif command == "pause" then 373 result=client_call(client, secret, "aria2."+command, resources[0]) 374elsif command == "pauseAll" then 375 result=client_call(client, secret, "aria2."+command) 376elsif command == "forcePause" then 377 result=client_call(client, secret, "aria2."+command, resources[0]) 378elsif command == "forcePauseAll" then 379 result=client_call(client, secret, "aria2."+command) 380elsif command == "unpause" then 381 result=client_call(client, secret, "aria2."+command, resources[0]) 382elsif command == "unpauseAll" then 383 result=client_call(client, secret, "aria2."+command) 384elsif command == "remove" then 385 result=client_call(client, secret, "aria2."+command, resources[0]) 386elsif command == "forceRemove" then 387 result=client_call(client, secret, "aria2."+command, resources[0]) 388elsif command == "changePosition" then 389 result=client_call(client, secret, "aria2."+command, resources[0], 390 resources[1].to_i(), resources[2]) 391elsif command == "getFiles" then 392 result=client_call(client, secret, "aria2."+command, resources[0]) 393elsif command == "getUris" then 394 result=client_call(client, secret, "aria2."+command, resources[0]) 395elsif command == "getPeers" then 396 result=client_call(client, secret, "aria2."+command, resources[0]) 397elsif command == "getServers" then 398 result=client_call(client, secret, "aria2."+command, resources[0]) 399elsif command == "purgeDownloadResult" then 400 result=client_call(client, secret, "aria2."+command) 401elsif command == "removeDownloadResult" then 402 result=client_call(client, secret, "aria2."+command, resources[0]) 403elsif command == "changeOption" then 404 result=client_call(client, secret, "aria2."+command, resources[0], options) 405elsif command == "changeGlobalOption" then 406 result=client_call(client, secret, "aria2."+command, options) 407elsif command == "getVersion" then 408 result=client_call(client, secret, "aria2."+command) 409elsif command == "getSessionInfo" then 410 result=client_call(client, secret, "aria2."+command) 411elsif command == "shutdown" then 412 result=client_call(client, secret, "aria2."+command) 413elsif command == "forceShutdown" then 414 result=client_call(client, secret, "aria2."+command) 415elsif command == "getGlobalStat" then 416 result=client_call(client, secret, "aria2."+command) 417elsif command == "saveSession" then 418 result=client_call(client, secret, "aria2."+command) 419elsif command == "appendUri" then 420 result=client_call(client, secret, "aria2.changeUri", resources[0], 421 resources[1].to_i(), [], resources[2..-1]) 422else 423 puts "Command not recognized" 424 exit 1 425end 426 427pp result 428