浏览代码

2010-09-19 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Added keys parameter to aria2.tellStatus, aria2.tellActive,
	aria2.tellWaiting and aria2.tellStopped XML-RPC method.  'keys' is
	array of string. If it is specified, the response contains only
	keys in 'keys' array. If 'keys' is empty or not specified, the
	response contains all keys.  This is useful when you just want
	specific keys and avoid unnecessary transfers. For example,
	*aria2.tellStatus*("1", ["gid", "status"]) returns 'gid' and
	'status' key. Made get*Param() functions XmlRpcRequest's
	methods and changed portions of the code that were affected by
	this change.
	* doc/aria2c.1.txt
	* src/Makefile.am
	* src/XmlRpcMethodImpl.cc
	* src/XmlRpcMethodImpl.h
	* src/XmlRpcRequest.cc
	* src/XmlRpcRequest.h
	* test/XmlRpcMethodTest.cc
Tatsuhiro Tsujikawa 15 年之前
父节点
当前提交
c56a9bc669
共有 11 个文件被更改,包括 456 次插入244 次删除
  1. 20 0
      ChangeLog
  2. 10 10
      doc/aria2c.1
  3. 16 8
      doc/aria2c.1.html
  4. 14 6
      doc/aria2c.1.txt
  5. 1 1
      src/Makefile.am
  6. 8 5
      src/Makefile.in
  7. 249 203
      src/XmlRpcMethodImpl.cc
  8. 32 9
      src/XmlRpcMethodImpl.h
  9. 79 0
      src/XmlRpcRequest.cc
  10. 8 0
      src/XmlRpcRequest.h
  11. 19 2
      test/XmlRpcMethodTest.cc

+ 20 - 0
ChangeLog

@@ -1,3 +1,23 @@
+2010-09-19  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Added keys parameter to aria2.tellStatus, aria2.tellActive,
+	aria2.tellWaiting and aria2.tellStopped XML-RPC method.  'keys' is
+	array of string. If it is specified, the response contains only
+	keys in 'keys' array. If 'keys' is empty or not specified, the
+	response contains all keys.  This is useful when you just want
+	specific keys and avoid unnecessary transfers. For example,
+	*aria2.tellStatus*("1", ["gid", "status"]) returns 'gid' and
+	'status' key. Made get*Param() functions XmlRpcRequest's
+	methods and changed portions of the code that were affected by
+	this change.
+	* doc/aria2c.1.txt
+	* src/Makefile.am
+	* src/XmlRpcMethodImpl.cc
+	* src/XmlRpcMethodImpl.h
+	* src/XmlRpcRequest.cc
+	* src/XmlRpcRequest.h
+	* test/XmlRpcMethodTest.cc
+
 2010-09-15  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 2010-09-15  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 
 	Release 1.10.3
 	Release 1.10.3

+ 10 - 10
doc/aria2c.1

@@ -2,12 +2,12 @@
 .\"     Title: aria2c
 .\"     Title: aria2c
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: 09/15/2010
+.\"      Date: 09/19/2010
 .\"    Manual: Aria2 Manual
 .\"    Manual: Aria2 Manual
 .\"    Source: Aria2 1.10.3
 .\"    Source: Aria2 1.10.3
 .\"  Language: English
 .\"  Language: English
 .\"
 .\"
-.TH "ARIA2C" "1" "09/15/2010" "Aria2 1\&.10\&.3" "Aria2 Manual"
+.TH "ARIA2C" "1" "09/19/2010" "Aria2 1\&.10\&.3" "Aria2 Manual"
 .\" -----------------------------------------------------------------
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
 .\" -----------------------------------------------------------------
@@ -2858,9 +2858,9 @@ This method changes the status of the download denoted by \fIgid\fR from "paused
 .sp
 .sp
 This method is equal to calling \fBaria2\&.unpause\fR for every active/waiting download\&. This methods returns "OK" for success\&.
 This method is equal to calling \fBaria2\&.unpause\fR for every active/waiting download\&. This methods returns "OK" for success\&.
 .sp
 .sp
-\fBaria2\&.tellStatus\fR \fIgid\fR
+\fBaria2\&.tellStatus\fR \fIgid[, keys]\fR
 .sp
 .sp
-This method returns download progress of the download denoted by \fIgid\fR\&. \fIgid\fR is of type string\&. The response is of type struct and it contains following keys\&. The value type is string\&.
+This method returns download progress of the download denoted by \fIgid\fR\&. \fIgid\fR is of type string\&. \fIkeys\fR is array of string\&. If it is specified, the response contains only keys in \fIkeys\fR array\&. If \fIkeys\fR is empty or not specified, the response contains all keys\&. This is useful when you just want specific keys and avoid unnecessary transfers\&. For example, \fBaria2\&.tellStatus\fR("1", ["gid", "status"]) returns \fIgid\fR and \fIstatus\fR key\&. The response is of type struct and it contains following keys\&. The value type is string\&.
 .PP
 .PP
 gid
 gid
 .RS 4
 .RS 4
@@ -3125,13 +3125,13 @@ Download speed (byte/sec)
 .RE
 .RE
 .RE
 .RE
 .sp
 .sp
-\fBaria2\&.tellActive\fR
+\fBaria2\&.tellActive\fR \fI[keys]\fR
 .sp
 .sp
-This method returns the list of active downloads\&. The response is of type array and its element is the same struct returned by \fBaria2\&.tellStatus\fR method\&.
+This method returns the list of active downloads\&. The response is of type array and its element is the same struct returned by \fBaria2\&.tellStatus\fR method\&. For \fIkeys\fR parameter, please refer to \fBaria2\&.tellStatus\fR method\&.
 .sp
 .sp
-\fBaria2\&.tellWaiting\fR \fIoffset, num\fR
+\fBaria2\&.tellWaiting\fR \fIoffset, num, [keys]\fR
 .sp
 .sp
-This method returns the list of waiting download, including paused downloads\&. \fIoffset\fR is of type integer and specifies the offset from the download waiting at the front\&. \fInum\fR is of type integer and specifies the number of downloads to be returned\&.
+This method returns the list of waiting download, including paused downloads\&. \fIoffset\fR is of type integer and specifies the offset from the download waiting at the front\&. \fInum\fR is of type integer and specifies the number of downloads to be returned\&. For \fIkeys\fR parameter, please refer to \fBaria2\&.tellStatus\fR method\&.
 .sp
 .sp
 If offset is a positive integer, this method returns downloads in the range of [\fIoffset\fR, \fIoffset\fR+\fInum\fR)\&.
 If offset is a positive integer, this method returns downloads in the range of [\fIoffset\fR, \fIoffset\fR+\fInum\fR)\&.
 .sp
 .sp
@@ -3141,9 +3141,9 @@ For example, imagine that three downloads "A","B" and "C" are waiting in this or
 .sp
 .sp
 The response is of type array and its element is the same struct returned by \fBaria2\&.tellStatus\fR method\&.
 The response is of type array and its element is the same struct returned by \fBaria2\&.tellStatus\fR method\&.
 .sp
 .sp
-\fBaria2\&.tellStopped\fR \fIoffset, num\fR
+\fBaria2\&.tellStopped\fR \fIoffset, num, [keys]\fR
 .sp
 .sp
-This method returns the list of stopped download\&. \fIoffset\fR is of type integer and specifies the offset from the oldest download\&. \fInum\fR is of type integer and specifies the number of downloads to be returned\&.
+This method returns the list of stopped download\&. \fIoffset\fR is of type integer and specifies the offset from the oldest download\&. \fInum\fR is of type integer and specifies the number of downloads to be returned\&. For \fIkeys\fR parameter, please refer to \fBaria2\&.tellStatus\fR method\&.
 .sp
 .sp
 \fIoffset\fR and \fInum\fR have the same semantics as \fBaria2\&.tellWaiting\fR method\&.
 \fIoffset\fR and \fInum\fR have the same semantics as \fBaria2\&.tellWaiting\fR method\&.
 .sp
 .sp

+ 16 - 8
doc/aria2c.1.html

@@ -3338,9 +3338,14 @@ download.</p></div>
 <div class="paragraph"><p><strong>aria2.unpauseAll</strong></p></div>
 <div class="paragraph"><p><strong>aria2.unpauseAll</strong></p></div>
 <div class="paragraph"><p>This method is equal to calling <strong>aria2.unpause</strong> for every active/waiting
 <div class="paragraph"><p>This method is equal to calling <strong>aria2.unpause</strong> for every active/waiting
 download. This methods returns "OK" for success.</p></div>
 download. This methods returns "OK" for success.</p></div>
-<div class="paragraph"><p><strong>aria2.tellStatus</strong> <em>gid</em></p></div>
+<div class="paragraph"><p><strong>aria2.tellStatus</strong> <em>gid[, keys]</em></p></div>
 <div class="paragraph"><p>This method returns download progress of the download denoted by
 <div class="paragraph"><p>This method returns download progress of the download denoted by
-<em>gid</em>. <em>gid</em> is of type string. The response is of type struct and it
+<em>gid</em>. <em>gid</em> is of type string. <em>keys</em> is array of string. If it is
+specified, the response contains only keys in <em>keys</em> array. If <em>keys</em>
+is empty or not specified, the response contains all keys.  This is
+useful when you just want specific keys and avoid unnecessary
+transfers. For example, <strong>aria2.tellStatus</strong>("1", ["gid", "status"])
+returns <em>gid</em> and <em>status</em> key.  The response is of type struct and it
 contains following keys. The value type is string.</p></div>
 contains following keys. The value type is string.</p></div>
 <div class="dlist"><dl>
 <div class="dlist"><dl>
 <dt class="hdlist1">
 <dt class="hdlist1">
@@ -3779,15 +3784,17 @@ downloadSpeed
 </dl></div>
 </dl></div>
 </dd>
 </dd>
 </dl></div>
 </dl></div>
-<div class="paragraph"><p><strong>aria2.tellActive</strong></p></div>
+<div class="paragraph"><p><strong>aria2.tellActive</strong> <em>[keys]</em></p></div>
 <div class="paragraph"><p>This method returns the list of active downloads.  The response is of
 <div class="paragraph"><p>This method returns the list of active downloads.  The response is of
 type array and its element is the same struct returned by
 type array and its element is the same struct returned by
+<strong>aria2.tellStatus</strong> method. For <em>keys</em> parameter, please refer to
 <strong>aria2.tellStatus</strong> method.</p></div>
 <strong>aria2.tellStatus</strong> method.</p></div>
-<div class="paragraph"><p><strong>aria2.tellWaiting</strong> <em>offset, num</em></p></div>
+<div class="paragraph"><p><strong>aria2.tellWaiting</strong> <em>offset, num, [keys]</em></p></div>
 <div class="paragraph"><p>This method returns the list of waiting download, including paused
 <div class="paragraph"><p>This method returns the list of waiting download, including paused
 downloads. <em>offset</em> is of type integer and specifies the offset from
 downloads. <em>offset</em> is of type integer and specifies the offset from
 the download waiting at the front. <em>num</em> is of type integer and
 the download waiting at the front. <em>num</em> is of type integer and
-specifies the number of downloads to be returned.</p></div>
+specifies the number of downloads to be returned.  For <em>keys</em>
+parameter, please refer to <strong>aria2.tellStatus</strong> method.</p></div>
 <div class="paragraph"><p>If offset is a positive integer, this method returns downloads in the
 <div class="paragraph"><p>If offset is a positive integer, this method returns downloads in the
 range of [<em>offset</em>, <em>offset</em>+<em>num</em>).</p></div>
 range of [<em>offset</em>, <em>offset</em>+<em>num</em>).</p></div>
 <div class="paragraph"><p><em>offset</em> can be a negative integer. <em>offset</em> == -1 points last
 <div class="paragraph"><p><em>offset</em> can be a negative integer. <em>offset</em> == -1 points last
@@ -3800,10 +3807,11 @@ in this order. aria2.tellWaiting(0, 1) returns
 aria2.tellWaiting(-1, 2) returns ["C", "B"].</p></div>
 aria2.tellWaiting(-1, 2) returns ["C", "B"].</p></div>
 <div class="paragraph"><p>The response is of type array and its element is the same struct
 <div class="paragraph"><p>The response is of type array and its element is the same struct
 returned by <strong>aria2.tellStatus</strong> method.</p></div>
 returned by <strong>aria2.tellStatus</strong> method.</p></div>
-<div class="paragraph"><p><strong>aria2.tellStopped</strong> <em>offset, num</em></p></div>
+<div class="paragraph"><p><strong>aria2.tellStopped</strong> <em>offset, num, [keys]</em></p></div>
 <div class="paragraph"><p>This method returns the list of stopped download.  <em>offset</em> is of type
 <div class="paragraph"><p>This method returns the list of stopped download.  <em>offset</em> is of type
 integer and specifies the offset from the oldest download. <em>num</em> is of
 integer and specifies the offset from the oldest download. <em>num</em> is of
-type integer and specifies the number of downloads to be returned.</p></div>
+type integer and specifies the number of downloads to be returned.
+For <em>keys</em> parameter, please refer to <strong>aria2.tellStatus</strong> method.</p></div>
 <div class="paragraph"><p><em>offset</em> and <em>num</em> have the same semantics as <strong>aria2.tellWaiting</strong>
 <div class="paragraph"><p><em>offset</em> and <em>num</em> have the same semantics as <strong>aria2.tellWaiting</strong>
 method.</p></div>
 method.</p></div>
 <div class="paragraph"><p>The response is of type array and its element is the same struct
 <div class="paragraph"><p>The response is of type array and its element is the same struct
@@ -4404,7 +4412,7 @@ files in the program, then also delete it here.</p></div>
 <div id="footnotes"><hr /></div>
 <div id="footnotes"><hr /></div>
 <div id="footer">
 <div id="footer">
 <div id="footer-text">
 <div id="footer-text">
-Last updated 2010-09-15 21:37:52 JST
+Last updated 2010-09-19 18:43:46 JST
 </div>
 </div>
 </div>
 </div>
 </body>
 </body>

+ 14 - 6
doc/aria2c.1.txt

@@ -1549,10 +1549,15 @@ download.
 This method is equal to calling *aria2.unpause* for every active/waiting
 This method is equal to calling *aria2.unpause* for every active/waiting
 download. This methods returns "OK" for success.
 download. This methods returns "OK" for success.
 
 
-*aria2.tellStatus* 'gid'
+*aria2.tellStatus* 'gid[, keys]'
 
 
 This method returns download progress of the download denoted by
 This method returns download progress of the download denoted by
-'gid'. 'gid' is of type string. The response is of type struct and it
+'gid'. 'gid' is of type string. 'keys' is array of string. If it is
+specified, the response contains only keys in 'keys' array. If 'keys'
+is empty or not specified, the response contains all keys.  This is
+useful when you just want specific keys and avoid unnecessary
+transfers. For example, *aria2.tellStatus*("1", ["gid", "status"])
+returns 'gid' and 'status' key.  The response is of type struct and it
 contains following keys. The value type is string.
 contains following keys. The value type is string.
 
 
 gid::
 gid::
@@ -1801,18 +1806,20 @@ servers::
 
 
     Download speed (byte/sec)
     Download speed (byte/sec)
 
 
-*aria2.tellActive*
+*aria2.tellActive* '[keys]'
 
 
 This method returns the list of active downloads.  The response is of
 This method returns the list of active downloads.  The response is of
 type array and its element is the same struct returned by
 type array and its element is the same struct returned by
+*aria2.tellStatus* method. For 'keys' parameter, please refer to
 *aria2.tellStatus* method.
 *aria2.tellStatus* method.
 
 
-*aria2.tellWaiting* 'offset, num'
+*aria2.tellWaiting* 'offset, num, [keys]'
 
 
 This method returns the list of waiting download, including paused
 This method returns the list of waiting download, including paused
 downloads. 'offset' is of type integer and specifies the offset from
 downloads. 'offset' is of type integer and specifies the offset from
 the download waiting at the front. 'num' is of type integer and
 the download waiting at the front. 'num' is of type integer and
-specifies the number of downloads to be returned.
+specifies the number of downloads to be returned.  For 'keys'
+parameter, please refer to *aria2.tellStatus* method.
 
 
 If offset is a positive integer, this method returns downloads in the
 If offset is a positive integer, this method returns downloads in the
 range of ['offset', 'offset'+'num').
 range of ['offset', 'offset'+'num').
@@ -1830,11 +1837,12 @@ aria2.tellWaiting(-1, 2) returns ["C", "B"].
 The response is of type array and its element is the same struct
 The response is of type array and its element is the same struct
 returned by *aria2.tellStatus* method.
 returned by *aria2.tellStatus* method.
 
 
-*aria2.tellStopped* 'offset, num'
+*aria2.tellStopped* 'offset, num, [keys]'
 
 
 This method returns the list of stopped download.  'offset' is of type
 This method returns the list of stopped download.  'offset' is of type
 integer and specifies the offset from the oldest download. 'num' is of
 integer and specifies the offset from the oldest download. 'num' is of
 type integer and specifies the number of downloads to be returned.
 type integer and specifies the number of downloads to be returned.
+For 'keys' parameter, please refer to *aria2.tellStatus* method.
 
 
 'offset' and 'num' have the same semantics as *aria2.tellWaiting*
 'offset' and 'num' have the same semantics as *aria2.tellWaiting*
 method.
 method.

+ 1 - 1
src/Makefile.am

@@ -218,7 +218,7 @@ SRCS += XmlRpcRequestParserController.cc XmlRpcRequestParserController.h\
 	XmlRpcRequestParserState.h\
 	XmlRpcRequestParserState.h\
 	XmlRpcRequestParserStateImpl.cc XmlRpcRequestParserStateImpl.h\
 	XmlRpcRequestParserStateImpl.cc XmlRpcRequestParserStateImpl.h\
 	XmlRpcElements.cc XmlRpcElements.h\
 	XmlRpcElements.cc XmlRpcElements.h\
-	XmlRpcRequest.h\
+	XmlRpcRequest.cc XmlRpcRequest.h\
 	XmlRpcRequestProcessor.h\
 	XmlRpcRequestProcessor.h\
 	HttpServerBodyCommand.cc HttpServerBodyCommand.h\
 	HttpServerBodyCommand.cc HttpServerBodyCommand.h\
 	XmlRpcMethod.cc XmlRpcMethod.h\
 	XmlRpcMethod.cc XmlRpcMethod.h\

+ 8 - 5
src/Makefile.in

@@ -42,7 +42,7 @@ bin_PROGRAMS = aria2c$(EXEEXT)
 @ENABLE_XML_RPC_TRUE@	XmlRpcRequestParserState.h\
 @ENABLE_XML_RPC_TRUE@	XmlRpcRequestParserState.h\
 @ENABLE_XML_RPC_TRUE@	XmlRpcRequestParserStateImpl.cc XmlRpcRequestParserStateImpl.h\
 @ENABLE_XML_RPC_TRUE@	XmlRpcRequestParserStateImpl.cc XmlRpcRequestParserStateImpl.h\
 @ENABLE_XML_RPC_TRUE@	XmlRpcElements.cc XmlRpcElements.h\
 @ENABLE_XML_RPC_TRUE@	XmlRpcElements.cc XmlRpcElements.h\
-@ENABLE_XML_RPC_TRUE@	XmlRpcRequest.h\
+@ENABLE_XML_RPC_TRUE@	XmlRpcRequest.cc XmlRpcRequest.h\
 @ENABLE_XML_RPC_TRUE@	XmlRpcRequestProcessor.h\
 @ENABLE_XML_RPC_TRUE@	XmlRpcRequestProcessor.h\
 @ENABLE_XML_RPC_TRUE@	HttpServerBodyCommand.cc HttpServerBodyCommand.h\
 @ENABLE_XML_RPC_TRUE@	HttpServerBodyCommand.cc HttpServerBodyCommand.h\
 @ENABLE_XML_RPC_TRUE@	XmlRpcMethod.cc XmlRpcMethod.h\
 @ENABLE_XML_RPC_TRUE@	XmlRpcMethod.cc XmlRpcMethod.h\
@@ -452,10 +452,11 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
 	XmlRpcRequestParserStateMachine.cc \
 	XmlRpcRequestParserStateMachine.cc \
 	XmlRpcRequestParserStateMachine.h XmlRpcRequestParserState.h \
 	XmlRpcRequestParserStateMachine.h XmlRpcRequestParserState.h \
 	XmlRpcRequestParserStateImpl.cc XmlRpcRequestParserStateImpl.h \
 	XmlRpcRequestParserStateImpl.cc XmlRpcRequestParserStateImpl.h \
-	XmlRpcElements.cc XmlRpcElements.h XmlRpcRequest.h \
-	XmlRpcRequestProcessor.h HttpServerBodyCommand.cc \
-	HttpServerBodyCommand.h XmlRpcMethod.cc XmlRpcMethod.h \
-	XmlRpcMethodImpl.cc XmlRpcMethodImpl.h XmlRpcMethodFactory.cc \
+	XmlRpcElements.cc XmlRpcElements.h XmlRpcRequest.cc \
+	XmlRpcRequest.h XmlRpcRequestProcessor.h \
+	HttpServerBodyCommand.cc HttpServerBodyCommand.h \
+	XmlRpcMethod.cc XmlRpcMethod.h XmlRpcMethodImpl.cc \
+	XmlRpcMethodImpl.h XmlRpcMethodFactory.cc \
 	XmlRpcMethodFactory.h XmlRpcResponse.cc XmlRpcResponse.h \
 	XmlRpcMethodFactory.h XmlRpcResponse.cc XmlRpcResponse.h \
 	HttpListenCommand.cc HttpListenCommand.h HttpServerCommand.cc \
 	HttpListenCommand.cc HttpListenCommand.h HttpServerCommand.cc \
 	HttpServerCommand.h HttpServerResponseCommand.cc \
 	HttpServerCommand.h HttpServerResponseCommand.cc \
@@ -628,6 +629,7 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
 @ENABLE_XML_RPC_TRUE@	XmlRpcRequestParserStateMachine.$(OBJEXT) \
 @ENABLE_XML_RPC_TRUE@	XmlRpcRequestParserStateMachine.$(OBJEXT) \
 @ENABLE_XML_RPC_TRUE@	XmlRpcRequestParserStateImpl.$(OBJEXT) \
 @ENABLE_XML_RPC_TRUE@	XmlRpcRequestParserStateImpl.$(OBJEXT) \
 @ENABLE_XML_RPC_TRUE@	XmlRpcElements.$(OBJEXT) \
 @ENABLE_XML_RPC_TRUE@	XmlRpcElements.$(OBJEXT) \
+@ENABLE_XML_RPC_TRUE@	XmlRpcRequest.$(OBJEXT) \
 @ENABLE_XML_RPC_TRUE@	HttpServerBodyCommand.$(OBJEXT) \
 @ENABLE_XML_RPC_TRUE@	HttpServerBodyCommand.$(OBJEXT) \
 @ENABLE_XML_RPC_TRUE@	XmlRpcMethod.$(OBJEXT) \
 @ENABLE_XML_RPC_TRUE@	XmlRpcMethod.$(OBJEXT) \
 @ENABLE_XML_RPC_TRUE@	XmlRpcMethodImpl.$(OBJEXT) \
 @ENABLE_XML_RPC_TRUE@	XmlRpcMethodImpl.$(OBJEXT) \
@@ -1655,6 +1657,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcMethod.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcMethod.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcMethodFactory.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcMethodFactory.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcMethodImpl.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcMethodImpl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcRequest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcRequestParserController.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcRequestParserController.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcRequestParserStateImpl.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcRequestParserStateImpl.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcRequestParserStateMachine.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XmlRpcRequestParserStateMachine.Po@am__quote@

+ 249 - 203
src/XmlRpcMethodImpl.cc

@@ -168,66 +168,26 @@ findRequestGroup(const SharedHandle<RequestGroupMan>& rgman, gid_t gid)
   return group;
   return group;
 }
 }
 
 
-static const String* getStringParam
-(const SharedHandle<List>& params, size_t index)
-{
-  const String* stringParam = 0;
-  if(params->size() > index) {
-    stringParam = asString(params->get(index));
-  }
-  return stringParam;
-}
-
-static const Integer* getIntegerParam
-(const SharedHandle<List>& params, size_t index)
-{
-  const Integer* integerParam = 0;
-  if(params->size() > index) {
-    integerParam = asInteger(params->get(index));
-  }
-  return integerParam;
-}
-
-static const List* getListParam(const SharedHandle<List>& params, size_t index)
-{
-  const List* listParam = 0;
-  if(params->size() > index) {
-    listParam = asList(params->get(index));
-  }
-  return listParam;
-}
-
-static const Dict* getDictParam(const SharedHandle<List>& params, size_t index)
-{
-  const Dict* dictParam = 0;
-  if(params->size() > index) {
-    dictParam = asDict(params->get(index));
-  }
-  return dictParam;
-}
-
-static void getPosParam(const SharedHandle<List>& params, size_t posParamIndex,
+static void getPosParam(const XmlRpcRequest& req, size_t posParamIndex,
                         bool& posGiven, size_t& pos)
                         bool& posGiven, size_t& pos)
 {
 {
-  if(params->size() > posParamIndex) {
-    const Integer* p = asInteger(params->get(posParamIndex));
-    if(p) {
-      if(p->i() >= 0) {
-        pos = p->i();
-        posGiven = true;
-        return;
-      } else {
-        throw DL_ABORT_EX("Position must be greater than or equal to 0.");
-      }
+  const Integer* p = req.getIntegerParam(posParamIndex);
+  if(p) {
+    if(p->i() >= 0) {
+      pos = p->i();
+      posGiven = true;
+      return;
+    } else {
+      throw DL_ABORT_EX("Position must be greater than or equal to 0.");
     }
     }
   }
   }
   posGiven = false;
   posGiven = false;
 } 
 } 
 
 
 static gid_t getRequiredGidParam
 static gid_t getRequiredGidParam
-(const SharedHandle<List>& params, size_t posParamIndex)
+(const XmlRpcRequest& req, size_t posParamIndex)
 {
 {
-  const String* gidParam = getStringParam(params, posParamIndex);
+  const String* gidParam = req.getStringParam(posParamIndex);
   if(gidParam) {
   if(gidParam) {
     return util::parseLLInt(gidParam->s());
     return util::parseLLInt(gidParam->s());
   } else {
   } else {
@@ -252,19 +212,18 @@ static void extractUris(OutputIterator out, const List* src)
 SharedHandle<ValueBase> AddUriXmlRpcMethod::process
 SharedHandle<ValueBase> AddUriXmlRpcMethod::process
 (const XmlRpcRequest& req, DownloadEngine* e)
 (const XmlRpcRequest& req, DownloadEngine* e)
 {
 {
-  const SharedHandle<List>& params = req.params;
   std::vector<std::string> uris;
   std::vector<std::string> uris;
-  extractUris(std::back_inserter(uris), getListParam(params, 0));
+  extractUris(std::back_inserter(uris), req.getListParam(0));
   if(uris.empty()) {
   if(uris.empty()) {
     throw DL_ABORT_EX("URI is not provided.");
     throw DL_ABORT_EX("URI is not provided.");
   }
   }
 
 
   SharedHandle<Option> requestOption(new Option(*e->getOption()));
   SharedHandle<Option> requestOption(new Option(*e->getOption()));
-  gatherRequestOption(requestOption, getDictParam(params, 1));
+  gatherRequestOption(requestOption, req.getDictParam(1));
 
 
   size_t pos = 0;
   size_t pos = 0;
   bool posGiven = false;
   bool posGiven = false;
-  getPosParam(params, 2, posGiven, pos);
+  getPosParam(req, 2, posGiven, pos);
 
 
   std::vector<SharedHandle<RequestGroup> > result;
   std::vector<SharedHandle<RequestGroup> > result;
   createRequestGroupForUri(result, requestOption, uris,
   createRequestGroupForUri(result, requestOption, uris,
@@ -282,21 +241,20 @@ SharedHandle<ValueBase> AddUriXmlRpcMethod::process
 SharedHandle<ValueBase> AddTorrentXmlRpcMethod::process
 SharedHandle<ValueBase> AddTorrentXmlRpcMethod::process
 (const XmlRpcRequest& req, DownloadEngine* e)
 (const XmlRpcRequest& req, DownloadEngine* e)
 {
 {
-  const SharedHandle<List>& params = req.params;
-  const String* torrentParam = getStringParam(params, 0);
+  const String* torrentParam = req.getStringParam(0);
   if(!torrentParam) {
   if(!torrentParam) {
     throw DL_ABORT_EX("Torrent data is not provided.");
     throw DL_ABORT_EX("Torrent data is not provided.");
   }
   }
   
   
   std::vector<std::string> uris;
   std::vector<std::string> uris;
-  extractUris(std::back_inserter(uris), getListParam(params, 1));
+  extractUris(std::back_inserter(uris), req.getListParam(1));
 
 
   SharedHandle<Option> requestOption(new Option(*e->getOption()));
   SharedHandle<Option> requestOption(new Option(*e->getOption()));
-  gatherRequestOption(requestOption, getDictParam(params, 2));
+  gatherRequestOption(requestOption, req.getDictParam(2));
 
 
   size_t pos = 0;
   size_t pos = 0;
   bool posGiven = false;
   bool posGiven = false;
-  getPosParam(params, 3, posGiven, pos);
+  getPosParam(req, 3, posGiven, pos);
 
 
   std::vector<SharedHandle<RequestGroup> > result;
   std::vector<SharedHandle<RequestGroup> > result;
   createRequestGroupForBitTorrent(result, requestOption,
   createRequestGroupForBitTorrent(result, requestOption,
@@ -314,18 +272,17 @@ SharedHandle<ValueBase> AddTorrentXmlRpcMethod::process
 SharedHandle<ValueBase> AddMetalinkXmlRpcMethod::process
 SharedHandle<ValueBase> AddMetalinkXmlRpcMethod::process
 (const XmlRpcRequest& req, DownloadEngine* e)
 (const XmlRpcRequest& req, DownloadEngine* e)
 {
 {
-  const SharedHandle<List>& params = req.params;
-  const String* metalinkParam = getStringParam(params, 0);
+  const String* metalinkParam = req.getStringParam(0);
   if(!metalinkParam) {
   if(!metalinkParam) {
     throw DL_ABORT_EX("Metalink data is not provided.");
     throw DL_ABORT_EX("Metalink data is not provided.");
   }
   }
   
   
   SharedHandle<Option> requestOption(new Option(*e->getOption()));
   SharedHandle<Option> requestOption(new Option(*e->getOption()));
-  gatherRequestOption(requestOption, getDictParam(params, 1));
+  gatherRequestOption(requestOption, req.getDictParam(1));
 
 
   size_t pos = 0;
   size_t pos = 0;
   bool posGiven = false;
   bool posGiven = false;
-  getPosParam(params, 2, posGiven, pos);
+  getPosParam(req, 2, posGiven, pos);
 
 
   std::vector<SharedHandle<RequestGroup> > result;
   std::vector<SharedHandle<RequestGroup> > result;
   createRequestGroupForMetalink(result, requestOption, metalinkParam->s());
   createRequestGroupForMetalink(result, requestOption, metalinkParam->s());
@@ -348,8 +305,7 @@ SharedHandle<ValueBase> AddMetalinkXmlRpcMethod::process
 static SharedHandle<ValueBase> removeDownload
 static SharedHandle<ValueBase> removeDownload
 (const XmlRpcRequest& req, DownloadEngine* e, bool forceRemove)
 (const XmlRpcRequest& req, DownloadEngine* e, bool forceRemove)
 {
 {
-  const SharedHandle<List>& params = req.params;
-  gid_t gid = getRequiredGidParam(params, 0);
+  gid_t gid = getRequiredGidParam(req, 0);
 
 
   SharedHandle<RequestGroup> group =
   SharedHandle<RequestGroup> group =
     e->getRequestGroupMan()->findRequestGroup(gid);
     e->getRequestGroupMan()->findRequestGroup(gid);
@@ -416,8 +372,7 @@ static bool pauseRequestGroup
 static SharedHandle<ValueBase> pauseDownload
 static SharedHandle<ValueBase> pauseDownload
 (const XmlRpcRequest& req, DownloadEngine* e, bool forcePause)
 (const XmlRpcRequest& req, DownloadEngine* e, bool forcePause)
 {
 {
-  const SharedHandle<List>& params = req.params;
-  gid_t gid = getRequiredGidParam(params, 0);
+  gid_t gid = getRequiredGidParam(req, 0);
 
 
   bool reserved = false;
   bool reserved = false;
   SharedHandle<RequestGroup> group =
   SharedHandle<RequestGroup> group =
@@ -484,8 +439,7 @@ SharedHandle<ValueBase> ForcePauseAllXmlRpcMethod::process
 SharedHandle<ValueBase> UnpauseXmlRpcMethod::process
 SharedHandle<ValueBase> UnpauseXmlRpcMethod::process
 (const XmlRpcRequest& req, DownloadEngine* e)
 (const XmlRpcRequest& req, DownloadEngine* e)
 {
 {
-  const SharedHandle<List>& params = req.params;
-  gid_t gid = getRequiredGidParam(params, 0);
+  gid_t gid = getRequiredGidParam(req, 0);
   SharedHandle<RequestGroup> group =
   SharedHandle<RequestGroup> group =
     e->getRequestGroupMan()->findReservedGroup(gid);
     e->getRequestGroupMan()->findReservedGroup(gid);
   if(group.isNull() || !group->isPauseRequested()) {
   if(group.isNull() || !group->isPauseRequested()) {
@@ -557,46 +511,84 @@ static void createFileEntry
   }
   }
 }
 }
 
 
+static bool requested_key
+(const std::vector<std::string>& keys, const std::string& k)
+{
+  return keys.empty() || std::find(keys.begin(), keys.end(), k) != keys.end();
+}
+
 void gatherProgressCommon
 void gatherProgressCommon
-(const SharedHandle<Dict>& entryDict, const SharedHandle<RequestGroup>& group)
+(const SharedHandle<Dict>& entryDict,
+ const SharedHandle<RequestGroup>& group,
+ const std::vector<std::string>& keys)
 {
 {
-  entryDict->put(KEY_GID, util::itos(group->getGID()));
-  // This is "filtered" total length if --select-file is used.
-  entryDict->put(KEY_TOTAL_LENGTH, util::uitos(group->getTotalLength()));
-  // This is "filtered" total length if --select-file is used.
-  entryDict->put(KEY_COMPLETED_LENGTH,util::uitos(group->getCompletedLength()));
+  if(requested_key(keys, KEY_GID)) {
+    entryDict->put(KEY_GID, util::itos(group->getGID()));
+  }
+  if(requested_key(keys, KEY_TOTAL_LENGTH)) {
+    // This is "filtered" total length if --select-file is used.
+    entryDict->put(KEY_TOTAL_LENGTH, util::uitos(group->getTotalLength()));
+  }
+  if(requested_key(keys, KEY_COMPLETED_LENGTH)) {
+    // This is "filtered" total length if --select-file is used.
+    entryDict->put
+      (KEY_COMPLETED_LENGTH,util::uitos(group->getCompletedLength()));
+  }
   TransferStat stat = group->calculateStat();
   TransferStat stat = group->calculateStat();
-  entryDict->put(KEY_DOWNLOAD_SPEED, util::uitos(stat.getDownloadSpeed()));
-  entryDict->put(KEY_UPLOAD_SPEED, util::uitos(stat.getUploadSpeed()));
-  entryDict->put(KEY_UPLOAD_LENGTH, util::uitos(stat.getAllTimeUploadLength()));
-  entryDict->put(KEY_CONNECTIONS, util::uitos(group->getNumConnection()));
-  SharedHandle<PieceStorage> ps = group->getPieceStorage();
-  if(!ps.isNull()) {
-    if(ps->getBitfieldLength() > 0) {
-      entryDict->put(KEY_BITFIELD,
-                     util::toHex(ps->getBitfield(), ps->getBitfieldLength()));
+  if(requested_key(keys, KEY_DOWNLOAD_SPEED)) {
+    entryDict->put(KEY_DOWNLOAD_SPEED, util::uitos(stat.getDownloadSpeed()));
+  }
+  if(requested_key(keys, KEY_UPLOAD_SPEED)) {
+    entryDict->put(KEY_UPLOAD_SPEED, util::uitos(stat.getUploadSpeed()));
+  }
+  if(requested_key(keys, KEY_UPLOAD_LENGTH)) {
+    entryDict->put
+      (KEY_UPLOAD_LENGTH, util::uitos(stat.getAllTimeUploadLength()));
+  }
+  if(requested_key(keys, KEY_CONNECTIONS)) {
+    entryDict->put(KEY_CONNECTIONS, util::uitos(group->getNumConnection()));
+  }
+  if(requested_key(keys, KEY_BITFIELD)) {
+    SharedHandle<PieceStorage> ps = group->getPieceStorage();
+    if(!ps.isNull()) {
+      if(ps->getBitfieldLength() > 0) {
+        entryDict->put(KEY_BITFIELD,
+                       util::toHex(ps->getBitfield(), ps->getBitfieldLength()));
+      }
     }
     }
   }
   }
   const SharedHandle<DownloadContext>& dctx = group->getDownloadContext();
   const SharedHandle<DownloadContext>& dctx = group->getDownloadContext();
-  entryDict->put(KEY_PIECE_LENGTH, util::uitos(dctx->getPieceLength()));
-  entryDict->put(KEY_NUM_PIECES, util::uitos(dctx->getNumPieces()));
-  if(!group->followedBy().empty()) {
-    SharedHandle<List> list = List::g();
-    // The element is GID.
-    for(std::vector<gid_t>::const_iterator i = group->followedBy().begin(),
-          eoi = group->followedBy().end(); i != eoi; ++i) {
-      list->append(util::itos(*i));
+  if(requested_key(keys, KEY_PIECE_LENGTH)) {
+    entryDict->put(KEY_PIECE_LENGTH, util::uitos(dctx->getPieceLength()));
+  }
+  if(requested_key(keys, KEY_NUM_PIECES)) {
+    entryDict->put(KEY_NUM_PIECES, util::uitos(dctx->getNumPieces()));
+  }
+  if(requested_key(keys, KEY_FOLLOWED_BY)) {
+    if(!group->followedBy().empty()) {
+      SharedHandle<List> list = List::g();
+      // The element is GID.
+      for(std::vector<gid_t>::const_iterator i = group->followedBy().begin(),
+            eoi = group->followedBy().end(); i != eoi; ++i) {
+        list->append(util::itos(*i));
+      }
+      entryDict->put(KEY_FOLLOWED_BY, list);
     }
     }
-    entryDict->put(KEY_FOLLOWED_BY, list);
   }
   }
-  if(group->belongsTo()) {
-    entryDict->put(KEY_BELONGS_TO, util::itos(group->belongsTo()));
+  if(requested_key(keys, KEY_BELONGS_TO)) {
+    if(group->belongsTo()) {
+      entryDict->put(KEY_BELONGS_TO, util::itos(group->belongsTo()));
+    }
+  }
+  if(requested_key(keys, KEY_FILES)) {
+    SharedHandle<List> files = List::g();
+    createFileEntry
+      (files, dctx->getFileEntries().begin(), dctx->getFileEntries().end());
+    entryDict->put(KEY_FILES, files);
+  }
+  if(requested_key(keys, KEY_DIR)) {
+    entryDict->put(KEY_DIR, dctx->getDir());
   }
   }
-  SharedHandle<List> files = List::g();
-  createFileEntry
-    (files, dctx->getFileEntries().begin(), dctx->getFileEntries().end());
-  entryDict->put(KEY_FILES, files);
-  entryDict->put(KEY_DIR, dctx->getDir());
 }
 }
 
 
 #ifdef ENABLE_BITTORRENT
 #ifdef ENABLE_BITTORRENT
@@ -635,21 +627,28 @@ void gatherBitTorrentMetadata
 static void gatherProgressBitTorrent
 static void gatherProgressBitTorrent
 (const SharedHandle<Dict>& entryDict,
 (const SharedHandle<Dict>& entryDict,
  const SharedHandle<TorrentAttribute>& torrentAttrs,
  const SharedHandle<TorrentAttribute>& torrentAttrs,
- const BtObject& btObject)
+ const BtObject& btObject,
+ const std::vector<std::string>& keys)
 {
 {
-  entryDict->put(KEY_INFO_HASH, util::toHex(torrentAttrs->infoHash));
-  SharedHandle<Dict> btDict = Dict::g();
-  gatherBitTorrentMetadata(btDict, torrentAttrs);
-  entryDict->put(KEY_BITTORRENT, btDict);
-  if(btObject.isNull()) {
-    entryDict->put(KEY_NUM_SEEDERS, VLB_ZERO);
-  } else {
-    SharedHandle<PeerStorage> peerStorage = btObject.peerStorage_;
-    assert(!peerStorage.isNull());
-    std::vector<SharedHandle<Peer> > peers;
-    peerStorage->getActivePeers(peers);
-    entryDict->put(KEY_NUM_SEEDERS,
-                   util::uitos(countSeeder(peers.begin(), peers.end())));
+  if(requested_key(keys, KEY_INFO_HASH)) {
+    entryDict->put(KEY_INFO_HASH, util::toHex(torrentAttrs->infoHash));
+  }
+  if(requested_key(keys, KEY_BITTORRENT)) {
+    SharedHandle<Dict> btDict = Dict::g();
+    gatherBitTorrentMetadata(btDict, torrentAttrs);
+    entryDict->put(KEY_BITTORRENT, btDict);
+  }
+  if(requested_key(keys, KEY_NUM_SEEDERS)) {
+    if(btObject.isNull()) {
+      entryDict->put(KEY_NUM_SEEDERS, VLB_ZERO);
+    } else {
+      SharedHandle<PeerStorage> peerStorage = btObject.peerStorage_;
+      assert(!peerStorage.isNull());
+      std::vector<SharedHandle<Peer> > peers;
+      peerStorage->getActivePeers(peers);
+      entryDict->put(KEY_NUM_SEEDERS,
+                     util::uitos(countSeeder(peers.begin(), peers.end())));
+    }
   }
   }
 }
 }
 
 
@@ -684,69 +683,107 @@ static void gatherPeer
 
 
 static void gatherProgress
 static void gatherProgress
 (const SharedHandle<Dict>& entryDict,
 (const SharedHandle<Dict>& entryDict,
- const SharedHandle<RequestGroup>& group, DownloadEngine* e)
+ const SharedHandle<RequestGroup>& group,
+ DownloadEngine* e,
+ const std::vector<std::string>& keys)
 {
 {
-  gatherProgressCommon(entryDict, group);
+  gatherProgressCommon(entryDict, group, keys);
 #ifdef ENABLE_BITTORRENT
 #ifdef ENABLE_BITTORRENT
   if(group->getDownloadContext()->hasAttribute(bittorrent::BITTORRENT)) {
   if(group->getDownloadContext()->hasAttribute(bittorrent::BITTORRENT)) {
     SharedHandle<TorrentAttribute> torrentAttrs =
     SharedHandle<TorrentAttribute> torrentAttrs =
       bittorrent::getTorrentAttrs(group->getDownloadContext());
       bittorrent::getTorrentAttrs(group->getDownloadContext());
     BtObject btObject = e->getBtRegistry()->get(group->getGID());
     BtObject btObject = e->getBtRegistry()->get(group->getGID());
-    gatherProgressBitTorrent(entryDict, torrentAttrs, btObject);
+    gatherProgressBitTorrent(entryDict, torrentAttrs, btObject, keys);
   }
   }
 #endif // ENABLE_BITTORRENT
 #endif // ENABLE_BITTORRENT
 }
 }
 
 
 void gatherStoppedDownload
 void gatherStoppedDownload
-(const SharedHandle<Dict>& entryDict, const SharedHandle<DownloadResult>& ds)
+(const SharedHandle<Dict>& entryDict, const SharedHandle<DownloadResult>& ds,
+ const std::vector<std::string>& keys)
 {
 {
-  entryDict->put(KEY_GID, util::itos(ds->gid));
-  entryDict->put(KEY_ERROR_CODE, util::itos(static_cast<int>(ds->result)));
-  if(ds->result == downloadresultcode::IN_PROGRESS) {
-    entryDict->put(KEY_STATUS, VLB_REMOVED);
-  } else if(ds->result == downloadresultcode::FINISHED) {
-    entryDict->put(KEY_STATUS, VLB_COMPLETE);
-  } else {
-    entryDict->put(KEY_STATUS, VLB_ERROR);
-  }
-  if(!ds->followedBy.empty()) {
-    SharedHandle<List> list = List::g();
-    // The element is GID.
-    for(std::vector<gid_t>::const_iterator i = ds->followedBy.begin(),
-          eoi = ds->followedBy.end(); i != eoi; ++i) {
-      list->append(util::itos(*i));
+  if(requested_key(keys, KEY_GID)) {
+    entryDict->put(KEY_GID, util::itos(ds->gid));
+  }
+  if(requested_key(keys, KEY_ERROR_CODE)) {
+    entryDict->put(KEY_ERROR_CODE, util::itos(static_cast<int>(ds->result)));
+  }
+  if(requested_key(keys, KEY_STATUS)) {
+    if(ds->result == downloadresultcode::IN_PROGRESS) {
+      entryDict->put(KEY_STATUS, VLB_REMOVED);
+    } else if(ds->result == downloadresultcode::FINISHED) {
+      entryDict->put(KEY_STATUS, VLB_COMPLETE);
+    } else {
+      entryDict->put(KEY_STATUS, VLB_ERROR);
+    }
+  }
+  if(requested_key(keys, KEY_FOLLOWED_BY)) {
+    if(!ds->followedBy.empty()) {
+      SharedHandle<List> list = List::g();
+      // The element is GID.
+      for(std::vector<gid_t>::const_iterator i = ds->followedBy.begin(),
+            eoi = ds->followedBy.end(); i != eoi; ++i) {
+        list->append(util::itos(*i));
+      }
+      entryDict->put(KEY_FOLLOWED_BY, list);
     }
     }
-    entryDict->put(KEY_FOLLOWED_BY, list);
   }
   }
-  if(ds->belongsTo) {
-    entryDict->put(KEY_BELONGS_TO, util::itos(ds->belongsTo));
+  if(requested_key(keys, KEY_BELONGS_TO)) {
+    if(ds->belongsTo) {
+      entryDict->put(KEY_BELONGS_TO, util::itos(ds->belongsTo));
+    }
+  }
+  if(requested_key(keys, KEY_FILES)) {
+    SharedHandle<List> files = List::g();
+    createFileEntry(files, ds->fileEntries.begin(), ds->fileEntries.end());
+    entryDict->put(KEY_FILES, files);
+  }
+  if(requested_key(keys, KEY_TOTAL_LENGTH)) {
+    entryDict->put(KEY_TOTAL_LENGTH, util::uitos(ds->totalLength));
+  }
+  if(requested_key(keys, KEY_COMPLETED_LENGTH)) {
+    entryDict->put(KEY_COMPLETED_LENGTH, util::uitos(ds->completedLength));
+  }
+  if(requested_key(keys, KEY_UPLOAD_LENGTH)) {
+    entryDict->put(KEY_UPLOAD_LENGTH, util::uitos(ds->uploadLength));
+  }
+  if(requested_key(keys, KEY_BITFIELD)) {
+    if(!ds->bitfieldStr.empty()) {
+      entryDict->put(KEY_BITFIELD, ds->bitfieldStr);
+    }
+  }
+  if(requested_key(keys, KEY_DOWNLOAD_SPEED)) {
+    entryDict->put(KEY_DOWNLOAD_SPEED, VLB_ZERO);
+  }
+  if(requested_key(keys, KEY_UPLOAD_SPEED)) {
+    entryDict->put(KEY_UPLOAD_SPEED, VLB_ZERO);
   }
   }
-  SharedHandle<List> files = List::g();
-  createFileEntry(files, ds->fileEntries.begin(), ds->fileEntries.end());
-  entryDict->put(KEY_FILES, files);
-  entryDict->put(KEY_TOTAL_LENGTH, util::uitos(ds->totalLength));
-  entryDict->put(KEY_COMPLETED_LENGTH, util::uitos(ds->completedLength));
-  entryDict->put(KEY_UPLOAD_LENGTH, util::uitos(ds->uploadLength));
-  if(!ds->bitfieldStr.empty()) {
-    entryDict->put(KEY_BITFIELD, ds->bitfieldStr);
-  }
-  entryDict->put(KEY_DOWNLOAD_SPEED, VLB_ZERO);
-  entryDict->put(KEY_UPLOAD_SPEED, VLB_ZERO);
   if(!ds->infoHashStr.empty()) {
   if(!ds->infoHashStr.empty()) {
-    entryDict->put(KEY_INFO_HASH, ds->infoHashStr);
-    entryDict->put(KEY_NUM_SEEDERS, VLB_ZERO);
+    if(requested_key(keys, KEY_INFO_HASH)) {
+      entryDict->put(KEY_INFO_HASH, ds->infoHashStr);
+    }
+    if(requested_key(keys, KEY_NUM_SEEDERS)) {
+      entryDict->put(KEY_NUM_SEEDERS, VLB_ZERO);
+    }
+  }
+  if(requested_key(keys, KEY_PIECE_LENGTH)) {
+    entryDict->put(KEY_PIECE_LENGTH, util::uitos(ds->pieceLength));
+  }
+  if(requested_key(keys, KEY_NUM_PIECES)) {
+    entryDict->put(KEY_NUM_PIECES, util::uitos(ds->numPieces));
+  }
+  if(requested_key(keys, KEY_CONNECTIONS)) {
+    entryDict->put(KEY_CONNECTIONS, VLB_ZERO);
+  }
+  if(requested_key(keys, KEY_DIR)) {
+    entryDict->put(KEY_DIR, ds->dir);
   }
   }
-  entryDict->put(KEY_PIECE_LENGTH, util::uitos(ds->pieceLength));
-  entryDict->put(KEY_NUM_PIECES, util::uitos(ds->numPieces));
-  entryDict->put(KEY_CONNECTIONS, VLB_ZERO);
-  entryDict->put(KEY_DIR, ds->dir);
 }
 }
 
 
 SharedHandle<ValueBase> GetFilesXmlRpcMethod::process
 SharedHandle<ValueBase> GetFilesXmlRpcMethod::process
 (const XmlRpcRequest& req, DownloadEngine* e)
 (const XmlRpcRequest& req, DownloadEngine* e)
 {
 {
-  const SharedHandle<List>& params = req.params;
-  gid_t gid = getRequiredGidParam(params, 0);
+  gid_t gid = getRequiredGidParam(req, 0);
   SharedHandle<List> files = List::g();
   SharedHandle<List> files = List::g();
   SharedHandle<RequestGroup> group =
   SharedHandle<RequestGroup> group =
     findRequestGroup(e->getRequestGroupMan(), gid);
     findRequestGroup(e->getRequestGroupMan(), gid);
@@ -771,8 +808,7 @@ SharedHandle<ValueBase> GetFilesXmlRpcMethod::process
 SharedHandle<ValueBase> GetUrisXmlRpcMethod::process
 SharedHandle<ValueBase> GetUrisXmlRpcMethod::process
 (const XmlRpcRequest& req, DownloadEngine* e)
 (const XmlRpcRequest& req, DownloadEngine* e)
 {
 {
-  const SharedHandle<List>& params = req.params;
-  gid_t gid = getRequiredGidParam(params, 0);
+  gid_t gid = getRequiredGidParam(req, 0);
   SharedHandle<RequestGroup> group =
   SharedHandle<RequestGroup> group =
     findRequestGroup(e->getRequestGroupMan(), gid);
     findRequestGroup(e->getRequestGroupMan(), gid);
   if(group.isNull()) {
   if(group.isNull()) {
@@ -792,8 +828,7 @@ SharedHandle<ValueBase> GetUrisXmlRpcMethod::process
 SharedHandle<ValueBase> GetPeersXmlRpcMethod::process
 SharedHandle<ValueBase> GetPeersXmlRpcMethod::process
 (const XmlRpcRequest& req, DownloadEngine* e)
 (const XmlRpcRequest& req, DownloadEngine* e)
 {
 {
-  const SharedHandle<List>& params = req.params;
-  gid_t gid = getRequiredGidParam(params, 0);
+  gid_t gid = getRequiredGidParam(req, 0);
 
 
   SharedHandle<RequestGroup> group =
   SharedHandle<RequestGroup> group =
     findRequestGroup(e->getRequestGroupMan(), gid);
     findRequestGroup(e->getRequestGroupMan(), gid);
@@ -815,8 +850,11 @@ SharedHandle<ValueBase> GetPeersXmlRpcMethod::process
 SharedHandle<ValueBase> TellStatusXmlRpcMethod::process
 SharedHandle<ValueBase> TellStatusXmlRpcMethod::process
 (const XmlRpcRequest& req, DownloadEngine* e)
 (const XmlRpcRequest& req, DownloadEngine* e)
 {
 {
-  const SharedHandle<List>& params = req.params;
-  gid_t gid = getRequiredGidParam(params, 0);
+  gid_t gid = getRequiredGidParam(req, 0);
+  
+  const List* keysParam = req.getListParam(1);
+  std::vector<std::string> keys;
+  toStringList(std::back_inserter(keys), keysParam);
 
 
   SharedHandle<RequestGroup> group =
   SharedHandle<RequestGroup> group =
     e->getRequestGroupMan()->findRequestGroup(gid);
     e->getRequestGroupMan()->findRequestGroup(gid);
@@ -832,18 +870,22 @@ SharedHandle<ValueBase> TellStatusXmlRpcMethod::process
           (StringFormat("No such download for GID#%s",
           (StringFormat("No such download for GID#%s",
                         util::itos(gid).c_str()).str());
                         util::itos(gid).c_str()).str());
       }
       }
-      gatherStoppedDownload(entryDict, ds);
+      gatherStoppedDownload(entryDict, ds, keys);
     } else {
     } else {
-      if(group->isPauseRequested()) {
-        entryDict->put(KEY_STATUS, VLB_PAUSED);
-      } else {
-        entryDict->put(KEY_STATUS, VLB_WAITING);
+      if(requested_key(keys, KEY_STATUS)) {
+        if(group->isPauseRequested()) {
+          entryDict->put(KEY_STATUS, VLB_PAUSED);
+        } else {
+          entryDict->put(KEY_STATUS, VLB_WAITING);
+        }
       }
       }
-      gatherProgress(entryDict, group, e);
+      gatherProgress(entryDict, group, e, keys);
     }
     }
   } else {
   } else {
-    entryDict->put(KEY_STATUS, VLB_ACTIVE);
-    gatherProgress(entryDict, group, e);
+    if(requested_key(keys, KEY_STATUS)) {
+      entryDict->put(KEY_STATUS, VLB_ACTIVE);
+    }
+    gatherProgress(entryDict, group, e, keys);
   }
   }
   return entryDict;
   return entryDict;
 }
 }
@@ -851,14 +893,19 @@ SharedHandle<ValueBase> TellStatusXmlRpcMethod::process
 SharedHandle<ValueBase> TellActiveXmlRpcMethod::process
 SharedHandle<ValueBase> TellActiveXmlRpcMethod::process
 (const XmlRpcRequest& req, DownloadEngine* e)
 (const XmlRpcRequest& req, DownloadEngine* e)
 {
 {
+  const List* keysParam = req.getListParam(0);
+  std::vector<std::string> keys;
+  toStringList(std::back_inserter(keys), keysParam);
   SharedHandle<List> list = List::g();
   SharedHandle<List> list = List::g();
   const std::deque<SharedHandle<RequestGroup> >& groups =
   const std::deque<SharedHandle<RequestGroup> >& groups =
     e->getRequestGroupMan()->getRequestGroups();
     e->getRequestGroupMan()->getRequestGroups();
   for(std::deque<SharedHandle<RequestGroup> >::const_iterator i =
   for(std::deque<SharedHandle<RequestGroup> >::const_iterator i =
         groups.begin(), eoi = groups.end(); i != eoi; ++i) {
         groups.begin(), eoi = groups.end(); i != eoi; ++i) {
     SharedHandle<Dict> entryDict = Dict::g();
     SharedHandle<Dict> entryDict = Dict::g();
-    entryDict->put(KEY_STATUS, VLB_ACTIVE);
-    gatherProgress(entryDict, *i, e);
+    if(requested_key(keys, KEY_STATUS)) {
+      entryDict->put(KEY_STATUS, VLB_ACTIVE);
+    }
+    gatherProgress(entryDict, *i, e, keys);
     list->append(entryDict);
     list->append(entryDict);
   }
   }
   return list;
   return list;
@@ -871,15 +918,19 @@ TellWaitingXmlRpcMethod::getItems(DownloadEngine* e) const
 }
 }
 
 
 void TellWaitingXmlRpcMethod::createEntry
 void TellWaitingXmlRpcMethod::createEntry
-(const SharedHandle<Dict>& entryDict, const SharedHandle<RequestGroup>& item,
- DownloadEngine* e) const
+(const SharedHandle<Dict>& entryDict,
+ const SharedHandle<RequestGroup>& item,
+ DownloadEngine* e,
+ const std::vector<std::string>& keys) const
 {
 {
-  if(item->isPauseRequested()) {
-    entryDict->put(KEY_STATUS, VLB_PAUSED);
-  } else {
-    entryDict->put(KEY_STATUS, VLB_WAITING);
+  if(requested_key(keys, KEY_STATUS)) {
+    if(item->isPauseRequested()) {
+      entryDict->put(KEY_STATUS, VLB_PAUSED);
+    } else {
+      entryDict->put(KEY_STATUS, VLB_WAITING);
+    }
   }
   }
-  gatherProgress(entryDict, item, e);
+  gatherProgress(entryDict, item, e, keys);
 }
 }
 
 
 const std::deque<SharedHandle<DownloadResult> >&
 const std::deque<SharedHandle<DownloadResult> >&
@@ -889,10 +940,12 @@ TellStoppedXmlRpcMethod::getItems(DownloadEngine* e) const
 }
 }
 
 
 void TellStoppedXmlRpcMethod::createEntry
 void TellStoppedXmlRpcMethod::createEntry
-(const SharedHandle<Dict>& entryDict, const SharedHandle<DownloadResult>& item,
- DownloadEngine* e) const
+(const SharedHandle<Dict>& entryDict,
+ const SharedHandle<DownloadResult>& item,
+ DownloadEngine* e,
+ const std::vector<std::string>& keys) const
 {
 {
-  gatherStoppedDownload(entryDict, item);
+  gatherStoppedDownload(entryDict, item, keys);
 }
 }
 
 
 SharedHandle<ValueBase> PurgeDownloadResultXmlRpcMethod::process
 SharedHandle<ValueBase> PurgeDownloadResultXmlRpcMethod::process
@@ -905,8 +958,7 @@ SharedHandle<ValueBase> PurgeDownloadResultXmlRpcMethod::process
 SharedHandle<ValueBase> ChangeOptionXmlRpcMethod::process
 SharedHandle<ValueBase> ChangeOptionXmlRpcMethod::process
 (const XmlRpcRequest& req, DownloadEngine* e)
 (const XmlRpcRequest& req, DownloadEngine* e)
 {
 {
-  const SharedHandle<List>& params = req.params;
-  gid_t gid = getRequiredGidParam(params, 0);
+  gid_t gid = getRequiredGidParam(req, 0);
 
 
   SharedHandle<RequestGroup> group =
   SharedHandle<RequestGroup> group =
     findRequestGroup(e->getRequestGroupMan(), gid);
     findRequestGroup(e->getRequestGroupMan(), gid);
@@ -916,7 +968,7 @@ SharedHandle<ValueBase> ChangeOptionXmlRpcMethod::process
                     util::itos(gid).c_str()).str());
                     util::itos(gid).c_str()).str());
   }
   }
   SharedHandle<Option> option(new Option());
   SharedHandle<Option> option(new Option());
-  const Dict* optionsParam = getDictParam(params, 1);
+  const Dict* optionsParam = req.getDictParam(1);
   if(optionsParam) {
   if(optionsParam) {
     gatherChangeableOption(option, optionsParam);
     gatherChangeableOption(option, optionsParam);
     applyChangeableOption(group->getOption().get(), option.get());
     applyChangeableOption(group->getOption().get(), option.get());
@@ -942,8 +994,7 @@ SharedHandle<ValueBase> ChangeOptionXmlRpcMethod::process
 SharedHandle<ValueBase> ChangeGlobalOptionXmlRpcMethod::process
 SharedHandle<ValueBase> ChangeGlobalOptionXmlRpcMethod::process
 (const XmlRpcRequest& req, DownloadEngine* e)
 (const XmlRpcRequest& req, DownloadEngine* e)
 {
 {
-  const SharedHandle<List>& params = req.params;
-  const Dict* optionsParam = getDictParam(params, 0);
+  const Dict* optionsParam = req.getDictParam(0);
   if(!optionsParam) {
   if(!optionsParam) {
     return VLB_OK;
     return VLB_OK;
   }
   }
@@ -1012,8 +1063,7 @@ static void pushRequestOption
 SharedHandle<ValueBase> GetOptionXmlRpcMethod::process
 SharedHandle<ValueBase> GetOptionXmlRpcMethod::process
 (const XmlRpcRequest& req, DownloadEngine* e)
 (const XmlRpcRequest& req, DownloadEngine* e)
 {
 {
-  const SharedHandle<List>& params = req.params;
-  gid_t gid = getRequiredGidParam(params, 0);
+  gid_t gid = getRequiredGidParam(req, 0);
 
 
   SharedHandle<RequestGroup> group =
   SharedHandle<RequestGroup> group =
     findRequestGroup(e->getRequestGroupMan(), gid);
     findRequestGroup(e->getRequestGroupMan(), gid);
@@ -1045,10 +1095,9 @@ SharedHandle<ValueBase> GetGlobalOptionXmlRpcMethod::process
 SharedHandle<ValueBase> ChangePositionXmlRpcMethod::process
 SharedHandle<ValueBase> ChangePositionXmlRpcMethod::process
 (const XmlRpcRequest& req, DownloadEngine* e)
 (const XmlRpcRequest& req, DownloadEngine* e)
 {
 {
-  const SharedHandle<List>& params = req.params;
-  gid_t gid = getRequiredGidParam(params, 0);
-  const Integer* posParam = getIntegerParam(params, 1);
-  const String* howParam = getStringParam(params, 2);
+  gid_t gid = getRequiredGidParam(req, 0);
+  const Integer* posParam = req.getIntegerParam(1);
+  const String* howParam = req.getStringParam(2);
 
 
   if(!posParam || !howParam) {
   if(!posParam || !howParam) {
     throw DL_ABORT_EX("Illegal argument.");
     throw DL_ABORT_EX("Illegal argument.");
@@ -1082,8 +1131,7 @@ SharedHandle<ValueBase> GetSessionInfoXmlRpcMethod::process
 SharedHandle<ValueBase> GetServersXmlRpcMethod::process
 SharedHandle<ValueBase> GetServersXmlRpcMethod::process
 (const XmlRpcRequest& req, DownloadEngine* e)
 (const XmlRpcRequest& req, DownloadEngine* e)
 {
 {
-  const SharedHandle<List>& params = req.params;
-  gid_t gid = getRequiredGidParam(params, 0);
+  gid_t gid = getRequiredGidParam(req, 0);
   SharedHandle<RequestGroup> group =
   SharedHandle<RequestGroup> group =
     e->getRequestGroupMan()->findRequestGroup(gid);
     e->getRequestGroupMan()->findRequestGroup(gid);
   if(group.isNull()) {
   if(group.isNull()) {
@@ -1122,17 +1170,16 @@ SharedHandle<ValueBase> GetServersXmlRpcMethod::process
 SharedHandle<ValueBase> ChangeUriXmlRpcMethod::process
 SharedHandle<ValueBase> ChangeUriXmlRpcMethod::process
 (const XmlRpcRequest& req, DownloadEngine* e)
 (const XmlRpcRequest& req, DownloadEngine* e)
 {
 {
-  const SharedHandle<List>& params = req.params;
-  gid_t gid = getRequiredGidParam(params, 0);
-  const Integer* indexParam = getIntegerParam(params, 1);
-  const List* delUrisParam = getListParam(params, 2);
-  const List* addUrisParam = getListParam(params, 3);
+  gid_t gid = getRequiredGidParam(req, 0);
+  const Integer* indexParam = req.getIntegerParam(1);
+  const List* delUrisParam = req.getListParam(2);
+  const List* addUrisParam = req.getListParam(3);
   if(!indexParam || !delUrisParam || ! addUrisParam) {
   if(!indexParam || !delUrisParam || ! addUrisParam) {
     throw DL_ABORT_EX("Bad request");
     throw DL_ABORT_EX("Bad request");
   }
   }
   size_t pos = 0;
   size_t pos = 0;
   bool posGiven = false;
   bool posGiven = false;
-  getPosParam(params, 4, posGiven, pos);
+  getPosParam(req, 4, posGiven, pos);
 
 
   size_t index = indexParam->i()-1;
   size_t index = indexParam->i()-1;
   SharedHandle<RequestGroup> group =
   SharedHandle<RequestGroup> group =
@@ -1212,8 +1259,7 @@ SharedHandle<ValueBase> ForceShutdownXmlRpcMethod::process
 SharedHandle<ValueBase> SystemMulticallXmlRpcMethod::process
 SharedHandle<ValueBase> SystemMulticallXmlRpcMethod::process
 (const XmlRpcRequest& req, DownloadEngine* e)
 (const XmlRpcRequest& req, DownloadEngine* e)
 {
 {
-  const SharedHandle<List>& params = req.params;
-  const List* methodSpecs = getListParam(params, 0);
+  const List* methodSpecs = req.getListParam(0);
   if(!methodSpecs) {
   if(!methodSpecs) {
     throw DL_ABORT_EX("Illegal argument. One item list is expected.");
     throw DL_ABORT_EX("Illegal argument. One item list is expected.");
   }
   }

+ 32 - 9
src/XmlRpcMethodImpl.h

@@ -53,6 +53,21 @@ class RequestGroup;
 
 
 namespace xmlrpc {
 namespace xmlrpc {
 
 
+template<typename OutputIterator>
+void toStringList(OutputIterator out, const List* src)
+{
+  if(!src) {
+    return;
+  }
+  for(List::ValueType::const_iterator i = src->begin(), eoi = src->end();
+      i != eoi; ++i) {
+    const String* s = asString(*i);
+    if(s) {
+      *out++ = s->s();
+    }
+  }
+}
+
 class AddUriXmlRpcMethod:public XmlRpcMethod {
 class AddUriXmlRpcMethod:public XmlRpcMethod {
 protected:
 protected:
   virtual SharedHandle<ValueBase> process
   virtual SharedHandle<ValueBase> process
@@ -311,7 +326,7 @@ private:
 
 
   void checkPaginationParams(const SharedHandle<List>& params) const
   void checkPaginationParams(const SharedHandle<List>& params) const
   {
   {
-    if(params->size() != 2) {
+    if(params->size() < 2) {
       throw DL_ABORT_EX("Invalid argument. Specify offset and num in integer.");
       throw DL_ABORT_EX("Invalid argument. Specify offset and num in integer.");
     }
     }
     const Integer* p1 = asInteger(params->get(0));
     const Integer* p1 = asInteger(params->get(0));
@@ -326,8 +341,11 @@ protected:
   {
   {
     const SharedHandle<List>& params = req.params;
     const SharedHandle<List>& params = req.params;
     checkPaginationParams(params);
     checkPaginationParams(params);
-    ssize_t offset = asInteger(params->get(0))->i();
-    size_t num = asInteger(params->get(1))->i();
+    ssize_t offset = req.getIntegerParam(0)->i();
+    size_t num = req.getIntegerParam(1)->i();
+    const List* keysParam = req.getListParam(2);
+    std::vector<std::string> keys;
+    toStringList(std::back_inserter(keys), keysParam);
     const std::deque<SharedHandle<T> >& items = getItems(e);
     const std::deque<SharedHandle<T> >& items = getItems(e);
     std::pair<typename std::deque<SharedHandle<T> >::const_iterator,
     std::pair<typename std::deque<SharedHandle<T> >::const_iterator,
       typename std::deque<SharedHandle<T> >::const_iterator> range =
       typename std::deque<SharedHandle<T> >::const_iterator> range =
@@ -335,7 +353,7 @@ protected:
     SharedHandle<List> list = List::g();
     SharedHandle<List> list = List::g();
     for(; range.first != range.second; ++range.first) {
     for(; range.first != range.second; ++range.first) {
       SharedHandle<Dict> entryDict = Dict::g();
       SharedHandle<Dict> entryDict = Dict::g();
-      createEntry(entryDict, *range.first, e);
+      createEntry(entryDict, *range.first, e, keys);
       list->append(entryDict);
       list->append(entryDict);
     }
     }
     if(offset < 0) {
     if(offset < 0) {
@@ -350,7 +368,8 @@ protected:
   virtual void createEntry
   virtual void createEntry
   (const SharedHandle<Dict>& entryDict,
   (const SharedHandle<Dict>& entryDict,
    const SharedHandle<T>& item,
    const SharedHandle<T>& item,
-   DownloadEngine* e) const = 0;
+   DownloadEngine* e,
+   const std::vector<std::string>& keys) const = 0;
 };
 };
 
 
 class TellWaitingXmlRpcMethod:
 class TellWaitingXmlRpcMethod:
@@ -362,7 +381,8 @@ protected:
   virtual void createEntry
   virtual void createEntry
   (const SharedHandle<Dict>& entryDict,
   (const SharedHandle<Dict>& entryDict,
    const SharedHandle<RequestGroup>& item,
    const SharedHandle<RequestGroup>& item,
-   DownloadEngine* e) const;
+   DownloadEngine* e,
+   const std::vector<std::string>& keys) const;
 public:
 public:
   static const std::string& getMethodName()
   static const std::string& getMethodName()
   {
   {
@@ -380,7 +400,8 @@ protected:
   virtual void createEntry
   virtual void createEntry
   (const SharedHandle<Dict>& entryDict,
   (const SharedHandle<Dict>& entryDict,
    const SharedHandle<DownloadResult>& item,
    const SharedHandle<DownloadResult>& item,
-   DownloadEngine* e) const;
+   DownloadEngine* e,
+   const std::vector<std::string>& keys) const;
 public:
 public:
   static const std::string& getMethodName()
   static const std::string& getMethodName()
   {
   {
@@ -530,12 +551,14 @@ protected:
 // Helper function to store data to entryDict from ds. This function
 // Helper function to store data to entryDict from ds. This function
 // is used by tellStatus method.
 // is used by tellStatus method.
 void gatherStoppedDownload
 void gatherStoppedDownload
-(const SharedHandle<Dict>& entryDict, const SharedHandle<DownloadResult>& ds);
+(const SharedHandle<Dict>& entryDict, const SharedHandle<DownloadResult>& ds,
+ const std::vector<std::string>& keys);
 
 
 // Helper function to store data to entryDict from group. This
 // Helper function to store data to entryDict from group. This
 // function is used by tellStatus/tellActive/tellWaiting method
 // function is used by tellStatus/tellActive/tellWaiting method
 void gatherProgressCommon
 void gatherProgressCommon
-(const SharedHandle<Dict>& entryDict, const SharedHandle<RequestGroup>& group);
+(const SharedHandle<Dict>& entryDict, const SharedHandle<RequestGroup>& group,
+ const std::vector<std::string>& keys);
 
 
 #ifdef ENABLE_BITTORRENT
 #ifdef ENABLE_BITTORRENT
 // Helper function to store BitTorrent metadata from torrentAttrs.
 // Helper function to store BitTorrent metadata from torrentAttrs.

+ 79 - 0
src/XmlRpcRequest.cc

@@ -0,0 +1,79 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2010 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "XmlRpcRequest.h"
+
+namespace aria2 {
+
+namespace xmlrpc {
+
+const String* XmlRpcRequest::getStringParam(size_t index) const
+{
+  const String* stringParam = 0;
+  if(params->size() > index) {
+    stringParam = asString(params->get(index));
+  }
+  return stringParam;
+}
+
+const Integer* XmlRpcRequest::getIntegerParam(size_t index) const
+{
+  const Integer* integerParam = 0;
+  if(params->size() > index) {
+    integerParam = asInteger(params->get(index));
+  }
+  return integerParam;
+}
+
+const List* XmlRpcRequest::getListParam(size_t index) const
+{
+  const List* listParam = 0;
+  if(params->size() > index) {
+    listParam = asList(params->get(index));
+  }
+  return listParam;
+}
+
+const Dict* XmlRpcRequest::getDictParam(size_t index) const
+{
+  const Dict* dictParam = 0;
+  if(params->size() > index) {
+    dictParam = asDict(params->get(index));
+  }
+  return dictParam;
+}
+
+} // namespace xmlrpc
+
+} // namespace aria2

+ 8 - 0
src/XmlRpcRequest.h

@@ -52,6 +52,14 @@ struct XmlRpcRequest {
   XmlRpcRequest(const std::string& methodName,
   XmlRpcRequest(const std::string& methodName,
                 const SharedHandle<List>& params):
                 const SharedHandle<List>& params):
     methodName(methodName), params(params) {}
     methodName(methodName), params(params) {}
+
+  const String* getStringParam(size_t index) const;
+
+  const Integer* getIntegerParam(size_t index) const;
+
+  const List* getListParam(size_t index) const;
+  
+  const Dict* getDictParam(size_t index) const;
 };
 };
 
 
 } // namespace xmlrpc
 } // namespace xmlrpc

+ 19 - 2
test/XmlRpcMethodTest.cc

@@ -728,13 +728,21 @@ void XmlRpcMethodTest::testGatherStoppedDownload()
   d->followedBy = followedBy;
   d->followedBy = followedBy;
   d->belongsTo = 2;
   d->belongsTo = 2;
   SharedHandle<Dict> entry = Dict::g();
   SharedHandle<Dict> entry = Dict::g();
-  gatherStoppedDownload(entry, d);
+  std::vector<std::string> keys;
+  gatherStoppedDownload(entry, d, keys);
 
 
   const List* followedByRes = asList(entry->get("followedBy"));
   const List* followedByRes = asList(entry->get("followedBy"));
   CPPUNIT_ASSERT_EQUAL(std::string("3"), asString(followedByRes->get(0))->s());
   CPPUNIT_ASSERT_EQUAL(std::string("3"), asString(followedByRes->get(0))->s());
   CPPUNIT_ASSERT_EQUAL(std::string("4"), asString(followedByRes->get(1))->s());
   CPPUNIT_ASSERT_EQUAL(std::string("4"), asString(followedByRes->get(1))->s());
   CPPUNIT_ASSERT_EQUAL(std::string("2"),
   CPPUNIT_ASSERT_EQUAL(std::string("2"),
                        asString(entry->get("belongsTo"))->s());
                        asString(entry->get("belongsTo"))->s());
+
+  keys.push_back("gid");
+
+  entry = Dict::g();
+  gatherStoppedDownload(entry, d, keys);
+  CPPUNIT_ASSERT_EQUAL((size_t)1, entry->size());
+  CPPUNIT_ASSERT(entry->containsKey("gid"));
 }
 }
 
 
 void XmlRpcMethodTest::testGatherProgressCommon()
 void XmlRpcMethodTest::testGatherProgressCommon()
@@ -754,7 +762,8 @@ void XmlRpcMethodTest::testGatherProgressCommon()
   group->belongsTo(2);
   group->belongsTo(2);
 
 
   SharedHandle<Dict> entry = Dict::g();
   SharedHandle<Dict> entry = Dict::g();
-  gatherProgressCommon(entry, group);
+  std::vector<std::string> keys;
+  gatherProgressCommon(entry, group, keys);
   
   
   const List* followedByRes = asList(entry->get("followedBy"));
   const List* followedByRes = asList(entry->get("followedBy"));
   CPPUNIT_ASSERT_EQUAL(util::itos(followedBy[0]->getGID()),
   CPPUNIT_ASSERT_EQUAL(util::itos(followedBy[0]->getGID()),
@@ -775,6 +784,14 @@ void XmlRpcMethodTest::testGatherProgressCommon()
                         ->get("uri"))
                         ->get("uri"))
                        ->s());
                        ->s());
   CPPUNIT_ASSERT_EQUAL(std::string("/tmp"), asString(entry->get("dir"))->s());
   CPPUNIT_ASSERT_EQUAL(std::string("/tmp"), asString(entry->get("dir"))->s());
+
+  keys.push_back("gid");
+  entry = Dict::g();
+  gatherProgressCommon(entry, group, keys);
+
+  CPPUNIT_ASSERT_EQUAL((size_t)1, entry->size());
+  CPPUNIT_ASSERT(entry->containsKey("gid"));
+  
 }
 }
 
 
 #ifdef ENABLE_BITTORRENT
 #ifdef ENABLE_BITTORRENT