Browse Source

2008-07-12 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

	Added the ability to retrieve signature from Metalink file.
	A retrieved signature is stored in Signature class and it is 
held by
	DownloadContext class. Note that aria2 doesn't verify signature.
	* src/DownloadContext.cc
	* src/DownloadContext.h
	* src/Makefile.am
	* src/Makefile.in
	* src/Metalink2RequestGroup.cc
	* src/MetalinkEntry.cc
	* src/MetalinkEntry.h
	* src/MetalinkParserController.cc
	* src/MetalinkParserController.h
	* src/MetalinkParserStateMachine.cc
	* src/MetalinkParserStateMachine.h
	* src/Signature.cc
	* src/Signature.h
	* src/SignatureMetalinkParserState.cc
	* src/SignatureMetalinkParserState.h
	* src/VerificationMetalinkParserState.cc
	* src/VerificationMetalinkParserState.h
	* test/Metalink2RequestGroupTest.cc
	* test/MetalinkParserControllerTest.cc
	* test/MetalinkProcessorTest.cc
	* test/test.xml
Tatsuhiro Tsujikawa 17 years ago
parent
commit
5472c8033e

+ 27 - 0
ChangeLog

@@ -1,3 +1,30 @@
+2008-07-12  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	Added the ability to retrieve signature from Metalink file.
+	A retrieved signature is stored in Signature class and it is held by
+	DownloadContext class. Note that aria2 doesn't verify signature.
+	* src/DownloadContext.cc
+	* src/DownloadContext.h
+	* src/Makefile.am
+	* src/Makefile.in
+	* src/Metalink2RequestGroup.cc
+	* src/MetalinkEntry.cc
+	* src/MetalinkEntry.h
+	* src/MetalinkParserController.cc
+	* src/MetalinkParserController.h
+	* src/MetalinkParserStateMachine.cc
+	* src/MetalinkParserStateMachine.h
+	* src/Signature.cc
+	* src/Signature.h
+	* src/SignatureMetalinkParserState.cc
+	* src/SignatureMetalinkParserState.h
+	* src/VerificationMetalinkParserState.cc
+	* src/VerificationMetalinkParserState.h
+	* test/Metalink2RequestGroupTest.cc
+	* test/MetalinkParserControllerTest.cc
+	* test/MetalinkProcessorTest.cc
+	* test/test.xml
+	
 2008-07-12  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 	Close DiskAdaptor after renaming file.

+ 63 - 0
src/DownloadContext.cc

@@ -0,0 +1,63 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 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 "DownloadContext.h"
+
+namespace aria2 {
+
+DownloadContext::DownloadContext():_dir(".") {}
+
+DownloadContext::~DownloadContext() {}
+
+const std::string& DownloadContext::getDir() const
+{
+  return _dir;
+}
+
+void DownloadContext::setDir(const std::string& dir)
+{
+  _dir = dir;
+}
+
+SharedHandle<Signature> DownloadContext::getSignature() const
+{
+  return _signature;
+}
+
+void DownloadContext::setSignature(const SharedHandle<Signature>& signature)
+{
+  _signature = signature;
+}
+
+} // namespace aria2

+ 11 - 11
src/DownloadContext.h

@@ -37,6 +37,7 @@
 
 #include "common.h"
 #include "SharedHandle.h"
+#include "Signature.h"
 #include <string>
 #include <deque>
 
@@ -49,11 +50,13 @@ class DownloadContext
 protected:
   std::string _dir;
 
-public:
-  DownloadContext():_dir(".") {}
+private:
+  SharedHandle<Signature> _signature;
 
-  virtual ~DownloadContext() {}
+public:
+  DownloadContext();
 
+  virtual ~DownloadContext();
 
   enum FILE_MODE {
     SINGLE,
@@ -88,16 +91,13 @@ public:
    */
   virtual std::string getActualBasePath() const = 0;
 
-  const std::string& getDir() const
-  {
-    return _dir;
-  }
+  const std::string& getDir() const;
+
+  void setDir(const std::string& dir);
 
-  void setDir(const std::string& dir)
-  {
-    _dir = dir;
-  }
+  SharedHandle<Signature> getSignature() const;
 
+  void setSignature(const SharedHandle<Signature>& signature);
 };
 
 typedef SharedHandle<DownloadContext> DownloadContextHandle;

+ 4 - 2
src/Makefile.am

@@ -158,7 +158,7 @@ SRCS =  Socket.h\
 	TaggedItem.cc TaggedItem.h\
 	TagContainer.cc TagContainer.h\
 	HelpItemFactory.cc HelpItemFactory.h\
-	DownloadContext.h\
+	DownloadContext.cc DownloadContext.h\
 	SingleFileDownloadContext.cc SingleFileDownloadContext.h\
 	TimedHaltCommand.cc TimedHaltCommand.h\
 	CUIDCounter.h\
@@ -188,7 +188,8 @@ SRCS =  Socket.h\
 	A2STR.cc A2STR.h\
 	RarestPieceSelector.cc RarestPieceSelector.h\
 	Decoder.h\
-	ChunkedDecoder.cc ChunkedDecoder.h
+	ChunkedDecoder.cc ChunkedDecoder.h\
+	Signature.cc Signature.h
 
 if HAVE_LIBZ
 SRCS += GZipDecoder.cc GZipDecoder.h
@@ -409,6 +410,7 @@ SRCS += Metalinker.cc Metalinker.h\
 	HashMetalinkParserState.cc HashMetalinkParserState.h\
 	PiecesMetalinkParserState.cc PiecesMetalinkParserState.h\
 	PieceHashMetalinkParserState.cc PieceHashMetalinkParserState.h\
+	SignatureMetalinkParserState.cc SignatureMetalinkParserState.h\
 	ResourcesMetalinkParserState.cc ResourcesMetalinkParserState.h\
 	URLMetalinkParserState.cc URLMetalinkParserState.h\
 	FinMetalinkParserState.cc FinMetalinkParserState.h\

+ 39 - 30
src/Makefile.in

@@ -243,6 +243,7 @@ bin_PROGRAMS = aria2c$(EXEEXT)
 @ENABLE_METALINK_TRUE@	HashMetalinkParserState.cc HashMetalinkParserState.h\
 @ENABLE_METALINK_TRUE@	PiecesMetalinkParserState.cc PiecesMetalinkParserState.h\
 @ENABLE_METALINK_TRUE@	PieceHashMetalinkParserState.cc PieceHashMetalinkParserState.h\
+@ENABLE_METALINK_TRUE@	SignatureMetalinkParserState.cc SignatureMetalinkParserState.h\
 @ENABLE_METALINK_TRUE@	ResourcesMetalinkParserState.cc ResourcesMetalinkParserState.h\
 @ENABLE_METALINK_TRUE@	URLMetalinkParserState.cc URLMetalinkParserState.h\
 @ENABLE_METALINK_TRUE@	FinMetalinkParserState.cc FinMetalinkParserState.h\
@@ -393,11 +394,12 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
 	ByteArrayDiskWriterFactory.cc ByteArrayDiskWriterFactory.h \
 	ServerHost.cc ServerHost.h HelpItem.cc HelpItem.h \
 	TaggedItem.cc TaggedItem.h TagContainer.cc TagContainer.h \
-	HelpItemFactory.cc HelpItemFactory.h DownloadContext.h \
-	SingleFileDownloadContext.cc SingleFileDownloadContext.h \
-	TimedHaltCommand.cc TimedHaltCommand.h CUIDCounter.h \
-	DNSCache.h DownloadResult.h Sequence.h IntSequence.h \
-	PostDownloadHandler.h PreDownloadHandler.h SingletonHolder.h \
+	HelpItemFactory.cc HelpItemFactory.h DownloadContext.cc \
+	DownloadContext.h SingleFileDownloadContext.cc \
+	SingleFileDownloadContext.h TimedHaltCommand.cc \
+	TimedHaltCommand.h CUIDCounter.h DNSCache.h DownloadResult.h \
+	Sequence.h IntSequence.h PostDownloadHandler.h \
+	PreDownloadHandler.h SingletonHolder.h \
 	TrueRequestGroupCriteria.h a2algo.h a2functional.h a2io.h \
 	a2netcompat.h a2time.h array_fun.h help_tags.h prefs.cc \
 	prefs.h usage_text.h ProtocolDetector.cc ProtocolDetector.h \
@@ -406,9 +408,9 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
 	InitiateConnectionCommand.cc InitiateConnectionCommand.h \
 	FtpFinishDownloadCommand.cc FtpFinishDownloadCommand.h \
 	A2STR.cc A2STR.h RarestPieceSelector.cc RarestPieceSelector.h \
-	Decoder.h ChunkedDecoder.cc ChunkedDecoder.h GZipDecoder.cc \
-	GZipDecoder.h AsyncNameResolver.cc AsyncNameResolver.h \
-	IteratableChunkChecksumValidator.cc \
+	Decoder.h ChunkedDecoder.cc ChunkedDecoder.h Signature.cc \
+	Signature.h GZipDecoder.cc GZipDecoder.h AsyncNameResolver.cc \
+	AsyncNameResolver.h IteratableChunkChecksumValidator.cc \
 	IteratableChunkChecksumValidator.h \
 	IteratableChecksumValidator.cc IteratableChecksumValidator.h \
 	CheckIntegrityCommand.cc CheckIntegrityCommand.h \
@@ -550,7 +552,8 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
 	VerificationMetalinkParserState.h HashMetalinkParserState.cc \
 	HashMetalinkParserState.h PiecesMetalinkParserState.cc \
 	PiecesMetalinkParserState.h PieceHashMetalinkParserState.cc \
-	PieceHashMetalinkParserState.h ResourcesMetalinkParserState.cc \
+	PieceHashMetalinkParserState.h SignatureMetalinkParserState.cc \
+	SignatureMetalinkParserState.h ResourcesMetalinkParserState.cc \
 	ResourcesMetalinkParserState.h URLMetalinkParserState.cc \
 	URLMetalinkParserState.h FinMetalinkParserState.cc \
 	FinMetalinkParserState.h SkipTagMetalinkParserState.cc \
@@ -703,6 +706,7 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
 @ENABLE_METALINK_TRUE@	HashMetalinkParserState.$(OBJEXT) \
 @ENABLE_METALINK_TRUE@	PiecesMetalinkParserState.$(OBJEXT) \
 @ENABLE_METALINK_TRUE@	PieceHashMetalinkParserState.$(OBJEXT) \
+@ENABLE_METALINK_TRUE@	SignatureMetalinkParserState.$(OBJEXT) \
 @ENABLE_METALINK_TRUE@	ResourcesMetalinkParserState.$(OBJEXT) \
 @ENABLE_METALINK_TRUE@	URLMetalinkParserState.$(OBJEXT) \
 @ENABLE_METALINK_TRUE@	FinMetalinkParserState.$(OBJEXT) \
@@ -787,19 +791,19 @@ am__objects_17 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
 	PeerConnection.$(OBJEXT) ByteArrayDiskWriter.$(OBJEXT) \
 	ByteArrayDiskWriterFactory.$(OBJEXT) ServerHost.$(OBJEXT) \
 	HelpItem.$(OBJEXT) TaggedItem.$(OBJEXT) TagContainer.$(OBJEXT) \
-	HelpItemFactory.$(OBJEXT) SingleFileDownloadContext.$(OBJEXT) \
-	TimedHaltCommand.$(OBJEXT) prefs.$(OBJEXT) \
-	ProtocolDetector.$(OBJEXT) StringFormat.$(OBJEXT) \
-	HttpSkipResponseCommand.$(OBJEXT) \
+	HelpItemFactory.$(OBJEXT) DownloadContext.$(OBJEXT) \
+	SingleFileDownloadContext.$(OBJEXT) TimedHaltCommand.$(OBJEXT) \
+	prefs.$(OBJEXT) ProtocolDetector.$(OBJEXT) \
+	StringFormat.$(OBJEXT) HttpSkipResponseCommand.$(OBJEXT) \
 	InitiateConnectionCommand.$(OBJEXT) \
 	FtpFinishDownloadCommand.$(OBJEXT) A2STR.$(OBJEXT) \
 	RarestPieceSelector.$(OBJEXT) ChunkedDecoder.$(OBJEXT) \
-	$(am__objects_1) $(am__objects_2) $(am__objects_3) \
-	$(am__objects_4) $(am__objects_5) $(am__objects_6) \
-	$(am__objects_7) $(am__objects_8) $(am__objects_9) \
-	$(am__objects_10) $(am__objects_11) $(am__objects_12) \
-	$(am__objects_13) $(am__objects_14) $(am__objects_15) \
-	$(am__objects_16)
+	Signature.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
+	$(am__objects_3) $(am__objects_4) $(am__objects_5) \
+	$(am__objects_6) $(am__objects_7) $(am__objects_8) \
+	$(am__objects_9) $(am__objects_10) $(am__objects_11) \
+	$(am__objects_12) $(am__objects_13) $(am__objects_14) \
+	$(am__objects_15) $(am__objects_16)
 am_libaria2c_a_OBJECTS = $(am__objects_17)
 libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
 am__installdirs = "$(DESTDIR)$(bindir)"
@@ -1103,11 +1107,12 @@ SRCS = Socket.h SocketCore.cc SocketCore.h BinaryStream.h Command.cc \
 	ByteArrayDiskWriterFactory.cc ByteArrayDiskWriterFactory.h \
 	ServerHost.cc ServerHost.h HelpItem.cc HelpItem.h \
 	TaggedItem.cc TaggedItem.h TagContainer.cc TagContainer.h \
-	HelpItemFactory.cc HelpItemFactory.h DownloadContext.h \
-	SingleFileDownloadContext.cc SingleFileDownloadContext.h \
-	TimedHaltCommand.cc TimedHaltCommand.h CUIDCounter.h \
-	DNSCache.h DownloadResult.h Sequence.h IntSequence.h \
-	PostDownloadHandler.h PreDownloadHandler.h SingletonHolder.h \
+	HelpItemFactory.cc HelpItemFactory.h DownloadContext.cc \
+	DownloadContext.h SingleFileDownloadContext.cc \
+	SingleFileDownloadContext.h TimedHaltCommand.cc \
+	TimedHaltCommand.h CUIDCounter.h DNSCache.h DownloadResult.h \
+	Sequence.h IntSequence.h PostDownloadHandler.h \
+	PreDownloadHandler.h SingletonHolder.h \
 	TrueRequestGroupCriteria.h a2algo.h a2functional.h a2io.h \
 	a2netcompat.h a2time.h array_fun.h help_tags.h prefs.cc \
 	prefs.h usage_text.h ProtocolDetector.cc ProtocolDetector.h \
@@ -1116,12 +1121,13 @@ SRCS = Socket.h SocketCore.cc SocketCore.h BinaryStream.h Command.cc \
 	InitiateConnectionCommand.cc InitiateConnectionCommand.h \
 	FtpFinishDownloadCommand.cc FtpFinishDownloadCommand.h \
 	A2STR.cc A2STR.h RarestPieceSelector.cc RarestPieceSelector.h \
-	Decoder.h ChunkedDecoder.cc ChunkedDecoder.h $(am__append_1) \
-	$(am__append_2) $(am__append_3) $(am__append_4) \
-	$(am__append_5) $(am__append_6) $(am__append_7) \
-	$(am__append_8) $(am__append_9) $(am__append_10) \
-	$(am__append_11) $(am__append_12) $(am__append_13) \
-	$(am__append_14) $(am__append_15) $(am__append_16)
+	Decoder.h ChunkedDecoder.cc ChunkedDecoder.h Signature.cc \
+	Signature.h $(am__append_1) $(am__append_2) $(am__append_3) \
+	$(am__append_4) $(am__append_5) $(am__append_6) \
+	$(am__append_7) $(am__append_8) $(am__append_9) \
+	$(am__append_10) $(am__append_11) $(am__append_12) \
+	$(am__append_13) $(am__append_14) $(am__append_15) \
+	$(am__append_16)
 noinst_LIBRARIES = libaria2c.a
 libaria2c_a_SOURCES = $(SRCS)
 aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
@@ -1344,6 +1350,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DirectDiskAdaptor.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DiskAdaptor.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadCommand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadContext.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadEngine.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadEngineFactory.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadHandler.Po@am__quote@
@@ -1454,6 +1461,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SeedCheckCommand.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SegmentMan.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ServerHost.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Signature.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SignatureMetalinkParserState.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleBtMessage.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleLogger.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleRandomizer.Po@am__quote@

+ 1 - 0
src/Metalink2RequestGroup.cc

@@ -220,6 +220,7 @@ Metalink2RequestGroup::createRequestGroup
       dctx->setPieceHashAlgo(entry->chunkChecksum->getAlgo());
     }
 #endif // ENABLE_MESSAGE_DIGEST
+    dctx->setSignature(entry->getSignature());
     rg->setDownloadContext(dctx);
     rg->setNumConcurrentCommand(entry->maxConnections < 0 ?
 				_option->getAsInt(PREF_METALINK_SERVERS) :

+ 12 - 0
src/MetalinkEntry.cc

@@ -41,6 +41,7 @@
 # include "Checksum.h"
 # include "ChunkChecksum.h"
 #endif // ENABLE_MESSAGE_DIGEST
+#include "Signature.h"
 #include <algorithm>
 
 namespace aria2 {
@@ -83,6 +84,7 @@ MetalinkEntry& MetalinkEntry::operator=(const MetalinkEntry& metalinkEntry)
     this->checksum = metalinkEntry.checksum;
     this->chunkChecksum = metalinkEntry.chunkChecksum;
 #endif // ENABLE_MESSAGE_DIGEST
+    this->_signature = metalinkEntry._signature;
   }
   return *this;
 }
@@ -180,4 +182,14 @@ SharedHandle<FileEntry> MetalinkEntry::getFile() const
   return file;
 }
 
+void MetalinkEntry::setSignature(const SharedHandle<Signature>& signature)
+{
+  _signature = signature;
+}
+
+SharedHandle<Signature> MetalinkEntry::getSignature() const
+{
+  return _signature;
+}
+
 } // namespace aria2

+ 7 - 0
src/MetalinkEntry.h

@@ -48,6 +48,7 @@ class FileEntry;
 class Checksum;
 class ChunkChecksum;
 #endif // ENABLE_MESSAGE_DIGEST
+class Signature;
 
 class MetalinkEntry {
 public:
@@ -61,6 +62,8 @@ public:
   SharedHandle<Checksum> checksum;
   SharedHandle<ChunkChecksum> chunkChecksum;
 #endif // ENABLE_MESSAGE_DIGEST
+private:
+  SharedHandle<Signature> _signature;
 public:
   MetalinkEntry();
 
@@ -84,6 +87,10 @@ public:
   static void toFileEntry
   (std::deque<SharedHandle<FileEntry> >& fileEntries,
    const std::deque<SharedHandle<MetalinkEntry> >& metalinkEntries);
+
+  void setSignature(const SharedHandle<Signature>& signature);
+
+  SharedHandle<Signature> getSignature() const;
 };
 
 } // namespace aria2

+ 49 - 0
src/MetalinkParserController.cc

@@ -44,6 +44,7 @@
 # include "ChunkChecksum.h"
 # include "messageDigest.h"
 #endif // ENABLE_MESSAGE_DIGEST
+#include "Signature.h"
 #include <algorithm>
 
 namespace aria2 {
@@ -135,6 +136,7 @@ void MetalinkParserController::commitEntryTransaction()
   commitResourceTransaction();
   commitChecksumTransaction();
   commitChunkChecksumTransaction();
+  commitSignatureTransaction();
   _metalinker->entries.push_back(_tEntry);
   _tEntry.reset();
 }
@@ -144,6 +146,7 @@ void MetalinkParserController::cancelEntryTransaction()
   cancelResourceTransaction();
   cancelChecksumTransaction();
   cancelChunkChecksumTransaction();
+  cancelSignatureTransaction();
   _tEntry.reset();
 }
 
@@ -379,4 +382,50 @@ void MetalinkParserController::cancelChunkChecksumTransaction()
 #endif // ENABLE_MESSAGE_DIGEST
 }
 
+void MetalinkParserController::newSignatureTransaction()
+{
+  if(_tEntry.isNull()) {
+    return;
+  }
+  _tSignature.reset(new Signature());
+}
+
+void MetalinkParserController::setTypeOfSignature(const std::string& type)
+{
+  if(_tSignature.isNull()) {
+    return;
+  }
+  _tSignature->setType(type);
+}
+
+void MetalinkParserController::setFileOfSignature(const std::string& file)
+{
+  if(_tSignature.isNull()) {
+    return;
+  }
+  _tSignature->setFile(file);
+}
+
+void MetalinkParserController::setBodyOfSignature(const std::string& body)
+{
+  if(_tSignature.isNull()) {
+    return;
+  }
+  _tSignature->setBody(body);
+}
+
+void MetalinkParserController::commitSignatureTransaction()
+{
+  if(_tSignature.isNull()) {
+    return;
+  }
+  _tEntry->setSignature(_tSignature);
+  _tSignature.reset();
+}
+
+void MetalinkParserController::cancelSignatureTransaction()
+{
+  _tSignature.reset();
+}
+
 } // namespace aria2

+ 15 - 0
src/MetalinkParserController.h

@@ -46,6 +46,7 @@ namespace aria2 {
 class Metalinker;
 class MetalinkEntry;
 class MetalinkResource;
+class Signature;
 
 #ifdef ENABLE_MESSAGE_DIGEST
 class Checksum;
@@ -70,6 +71,8 @@ private:
   std::pair<size_t, std::string> _tempHashPair;
 #endif // ENABLE_MESSAGE_DIGEST
 
+  SharedHandle<Signature> _tSignature;
+
   static const std::string SHA1;
 public:
   MetalinkParserController();
@@ -139,6 +142,18 @@ public:
   void commitChunkChecksumTransaction();
 
   void cancelChunkChecksumTransaction();
+
+  void newSignatureTransaction();
+
+  void setTypeOfSignature(const std::string& type);
+
+  void setFileOfSignature(const std::string& file);
+
+  void setBodyOfSignature(const std::string& body);
+
+  void commitSignatureTransaction();
+
+  void cancelSignatureTransaction();
 };
 
 } // namespace aria2

+ 38 - 0
src/MetalinkParserStateMachine.cc

@@ -46,6 +46,7 @@
 #include "HashMetalinkParserState.h"
 #include "PiecesMetalinkParserState.h"
 #include "PieceHashMetalinkParserState.h"
+#include "SignatureMetalinkParserState.h"
 #include "ResourcesMetalinkParserState.h"
 #include "URLMetalinkParserState.h"
 #include "FinMetalinkParserState.h"
@@ -67,6 +68,8 @@ MetalinkParserState* MetalinkParserStateMachine::_verificationState = new Verifi
 MetalinkParserState* MetalinkParserStateMachine::_hashState = new HashMetalinkParserState();
 MetalinkParserState* MetalinkParserStateMachine::_piecesState = new PiecesMetalinkParserState();
 MetalinkParserState* MetalinkParserStateMachine::_pieceHashState = new PieceHashMetalinkParserState();
+MetalinkParserState* MetalinkParserStateMachine::_signatureState =
+  new SignatureMetalinkParserState();
 MetalinkParserState* MetalinkParserStateMachine::_resourcesState = new ResourcesMetalinkParserState();
 MetalinkParserState* MetalinkParserStateMachine::_urlState = new URLMetalinkParserState();
 MetalinkParserState* MetalinkParserStateMachine::_finState = new FinMetalinkParserState();
@@ -136,6 +139,11 @@ void MetalinkParserStateMachine::setPieceHashState()
   _state = _pieceHashState;
 }
 
+void MetalinkParserStateMachine::setSignatureState()
+{
+  _state = _signatureState;
+}
+
 void MetalinkParserStateMachine::setResourcesState()
 {
   _state = _resourcesState;
@@ -313,6 +321,36 @@ void MetalinkParserStateMachine::cancelChunkChecksumTransaction()
   _ctrl->cancelChunkChecksumTransaction();
 }
 
+void MetalinkParserStateMachine::newSignatureTransaction()
+{
+  _ctrl->newSignatureTransaction();
+}
+
+void MetalinkParserStateMachine::setTypeOfSignature(const std::string& type)
+{
+  _ctrl->setTypeOfSignature(type);
+}
+
+void MetalinkParserStateMachine::setFileOfSignature(const std::string& file)
+{
+  _ctrl->setFileOfSignature(file);
+}
+
+void MetalinkParserStateMachine::setBodyOfSignature(const std::string& body)
+{
+  _ctrl->setBodyOfSignature(body);
+}
+
+void MetalinkParserStateMachine::commitSignatureTransaction()
+{
+  _ctrl->commitSignatureTransaction();
+}
+
+void MetalinkParserStateMachine::cancelSignatureTransaction()
+{
+  _ctrl->cancelSignatureTransaction();
+}
+
 void MetalinkParserStateMachine::beginElement(const std::string& name,
 					      const std::map<std::string, std::string>& attrs)
 {

+ 17 - 1
src/MetalinkParserStateMachine.h

@@ -65,6 +65,7 @@ private:
   static MetalinkParserState* _hashState;
   static MetalinkParserState* _piecesState;
   static MetalinkParserState* _pieceHashState;
+  static MetalinkParserState* _signatureState;
   static MetalinkParserState* _resourcesState;
   static MetalinkParserState* _urlState;
   static MetalinkParserState* _finState;
@@ -97,6 +98,8 @@ public:
 
   void setPieceHashState();
 
+  void setSignatureState();
+
   void setResourcesState();
 
   void setURLState();
@@ -111,7 +114,8 @@ public:
 
   bool error() const;
 
-  void beginElement(const std::string& name, const std::map<std::string, std::string>& attrs);
+  void beginElement(const std::string& name, const std::map<std::string,
+		    std::string>& attrs);
   
   void endElement(const std::string& name, const std::string& characters);
 
@@ -173,6 +177,18 @@ public:
 
   void cancelChunkChecksumTransaction();
 
+  void newSignatureTransaction();
+
+  void setTypeOfSignature(const std::string& type);
+
+  void setFileOfSignature(const std::string& file);
+
+  void setBodyOfSignature(const std::string& body);
+
+  void commitSignatureTransaction();
+
+  void cancelSignatureTransaction();
+
   bool needsCharactersBuffering() const;
 
   SharedHandle<Metalinker> getResult() const;

+ 79 - 0
src/Signature.cc

@@ -0,0 +1,79 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 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 "Signature.h"
+
+namespace aria2 {
+
+Signature::Signature() {}
+
+Signature::~Signature() {}
+
+void Signature::setType(const std::string& type)
+{
+  _type = type;
+}
+
+const std::string& Signature::getType() const
+{
+  return _type;
+}
+
+void Signature::setFile(const std::string& file)
+{
+  _file = file;
+}
+
+const std::string& Signature::getFile() const
+{
+  return _file;
+}
+
+void Signature::setBody(const std::string& body)
+{
+  _body = body;
+}
+
+const std::string& Signature::getBody() const
+{
+  return _body;
+}
+
+bool Signature::save(const std::string& filepath) const
+{
+  // TODO not yet implemented
+  return false;
+}
+
+} // namespace aria2

+ 73 - 0
src/Signature.h

@@ -0,0 +1,73 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 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 --> */
+#ifndef _D_SIGNATURE_H_
+#define _D_SIGNATURE_H_
+
+#include "common.h"
+#include "SharedHandle.h"
+#include <string>
+
+namespace aria2 {
+
+class Signature {
+private:
+  std::string _type;
+
+  std::string _file;
+
+  std::string _body;
+public:
+  Signature();
+
+  ~Signature();
+
+  void setType(const std::string& type);
+
+  const std::string& getType() const;
+
+  void setFile(const std::string& file);
+
+  const std::string& getFile() const;
+
+  void setBody(const std::string& body);
+
+  const std::string& getBody() const;
+
+  bool save(const std::string& filepath) const;
+};
+
+} // namespace aria2
+
+#endif // _D_SIGNATURE_H_

+ 58 - 0
src/SignatureMetalinkParserState.cc

@@ -0,0 +1,58 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 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 "SignatureMetalinkParserState.h"
+#include "MetalinkParserStateMachine.h"
+
+namespace aria2 {
+
+void SignatureMetalinkParserState::beginElement
+(MetalinkParserStateMachine* stm,
+ const std::string& name,
+ const std::map<std::string, std::string>& attrs)
+{
+  stm->setSkipTagState(this);
+}
+
+void SignatureMetalinkParserState::endElement
+(MetalinkParserStateMachine* stm,
+ const std::string& name,
+ const std::string& characters)
+{
+  stm->setBodyOfSignature(characters);
+  stm->commitSignatureTransaction();
+  stm->setVerificationState();
+}
+
+} //  namespace aria2

+ 60 - 0
src/SignatureMetalinkParserState.h

@@ -0,0 +1,60 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 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 --> */
+#ifndef _D_SIGNATURE_METALINK_PARSER_STATE_H_
+#define _D_SIGNATURE_METALINK_PARSER_STATE_H_
+
+#include "MetalinkParserState.h"
+
+namespace aria2 {
+
+class SignatureMetalinkParserState:public MetalinkParserState
+{
+public:
+  void beginElement(MetalinkParserStateMachine* stm,
+		    const std::string& name, const std::map<std::string,
+		    std::string>& attrs);
+
+  void endElement(MetalinkParserStateMachine* stm,
+		  const std::string& name, const std::string& characters);
+
+  virtual bool needsCharactersBuffering() const
+  {
+    return true;
+  }
+};
+
+} // namespace aria2
+
+#endif // _D_SIGNATURE_METALINK_PARSER_STATE_H_

+ 28 - 6
src/VerificationMetalinkParserState.cc

@@ -47,9 +47,14 @@ const std::string VerificationMetalinkParserState::PIECES("pieces");
 
 const std::string VerificationMetalinkParserState::LENGTH("length");
 
-void VerificationMetalinkParserState::beginElement(MetalinkParserStateMachine* stm,
-						   const std::string& name,
-						   const std::map<std::string, std::string>& attrs)
+const std::string VerificationMetalinkParserState::SIGNATURE("signature");
+
+const std::string VerificationMetalinkParserState::FILE("file");
+
+void VerificationMetalinkParserState::beginElement
+(MetalinkParserStateMachine* stm,
+ const std::string& name,
+ const std::map<std::string, std::string>& attrs)
 {
   if(name == VerificationMetalinkParserState::HASH) {
     stm->setHashState();
@@ -91,14 +96,31 @@ void VerificationMetalinkParserState::beginElement(MetalinkParserStateMachine* s
     } catch(RecoverableException& e) {
       stm->cancelChunkChecksumTransaction();
     }
+  } else if(name == VerificationMetalinkParserState::SIGNATURE) {
+    stm->setSignatureState();
+    std::map<std::string, std::string>::const_iterator itr =
+      attrs.find(VerificationMetalinkParserState::TYPE);
+    if(itr == attrs.end()) {
+      return;
+    } else {
+      stm->newSignatureTransaction();
+      stm->setTypeOfSignature((*itr).second);
+
+      std::map<std::string, std::string>::const_iterator itr =
+	attrs.find(VerificationMetalinkParserState::FILE);
+      if(itr != attrs.end()) {
+	stm->setFileOfSignature((*itr).second);
+      }
+    }
   } else {
     stm->setSkipTagState(this);
   }
 }
 
-void VerificationMetalinkParserState::endElement(MetalinkParserStateMachine* stm,
-						 const std::string& name,
-						 const std::string& characters)
+void VerificationMetalinkParserState::endElement
+(MetalinkParserStateMachine* stm,
+ const std::string& name,
+ const std::string& characters)
 {
   stm->setFileState();
 }

+ 4 - 0
src/VerificationMetalinkParserState.h

@@ -49,6 +49,10 @@ private:
   static const std::string PIECES;
 
   static const std::string LENGTH;
+
+  static const std::string SIGNATURE;
+  
+  static const std::string FILE;
 public:
   void beginElement(MetalinkParserStateMachine* stm,
 		    const std::string& name, const std::map<std::string, std::string>& attrs);

+ 3 - 0
test/Metalink2RequestGroupTest.cc

@@ -52,6 +52,8 @@ void Metalink2RequestGroupTest::testGenerate()
     CPPUNIT_ASSERT_EQUAL(std::string("a96cf3f0266b91d87d5124cf94326422800b627d"),
 			 dctx->getChecksum());
 #endif // ENABLE_MESSAGE_DIGEST
+    CPPUNIT_ASSERT(!dctx->getSignature().isNull());
+    CPPUNIT_ASSERT_EQUAL(std::string("pgp"), dctx->getSignature()->getType());
   }
   // second file
   {
@@ -69,6 +71,7 @@ void Metalink2RequestGroupTest::testGenerate()
     CPPUNIT_ASSERT_EQUAL(std::string(""), dctx->getChecksumHashAlgo());
     CPPUNIT_ASSERT_EQUAL(std::string(""), dctx->getChecksum());
 #endif // ENABLE_MESSAGE_DIGEST
+    CPPUNIT_ASSERT(dctx->getSignature().isNull());
   }
 
 #ifdef ENABLE_BITTORRENT

+ 39 - 0
test/MetalinkParserControllerTest.cc

@@ -7,6 +7,7 @@
 # include "Checksum.h"
 # include "ChunkChecksum.h"
 #endif // ENABLE_MESSAGE_DIGEST
+#include "Signature.h"
 #include <cppunit/extensions/HelperMacros.h>
 
 namespace aria2 {
@@ -20,6 +21,7 @@ class MetalinkParserControllerTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testChecksumTransaction);
   CPPUNIT_TEST(testChunkChecksumTransaction);
 #endif // ENABLE_MESSAGE_DIGEST
+  CPPUNIT_TEST(testSignatureTransaction);
 
   CPPUNIT_TEST_SUITE_END();
 private:
@@ -35,6 +37,7 @@ public:
   void testChecksumTransaction();
   void testChunkChecksumTransaction();
 #endif // ENABLE_MESSAGE_DIGEST
+  void testSignatureTransaction();
 };
 
 
@@ -150,4 +153,40 @@ void MetalinkParserControllerTest::testChunkChecksumTransaction()
 }
 #endif // ENABLE_MESSAGE_DIGEST
 
+void MetalinkParserControllerTest::testSignatureTransaction()
+{
+  static std::string pgpSignature =
+    "-----BEGIN PGP SIGNATURE-----\n"
+    "Version: GnuPG v1.4.9 (GNU/Linux)\n"
+    "\n"
+    "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
+    "ffffffffffffffffffffffff\n"
+    "fffff\n"
+    "-----END PGP SIGNATURE-----\n";
+
+  MetalinkParserController ctrl;
+  ctrl.newEntryTransaction();
+
+  ctrl.newSignatureTransaction();
+  ctrl.setTypeOfSignature("pgp");
+  ctrl.setFileOfSignature("aria2.sig");
+  ctrl.setBodyOfSignature(pgpSignature);
+  // commitEntryTransaction also commits signature transaction.
+  ctrl.commitEntryTransaction();
+
+  SharedHandle<Metalinker> m = ctrl.getResult();
+  CPPUNIT_ASSERT_EQUAL((size_t)1, m->entries.size());
+  SharedHandle<Signature> sig = m->entries.front()->getSignature();
+  CPPUNIT_ASSERT_EQUAL(std::string("pgp"), sig->getType());
+  CPPUNIT_ASSERT_EQUAL(std::string("aria2.sig"), sig->getFile());
+  CPPUNIT_ASSERT_EQUAL(pgpSignature, sig->getBody());
+
+  // See when signature transaction is canceled:
+  ctrl.newEntryTransaction();
+  ctrl.newSignatureTransaction();
+  ctrl.cancelSignatureTransaction();
+  ctrl.commitEntryTransaction();
+  CPPUNIT_ASSERT(ctrl.getResult()->entries[1]->getSignature().isNull());
+}
+
 } // namespace aria2

+ 19 - 0
test/MetalinkProcessorTest.cc

@@ -11,6 +11,7 @@
 # include "ChunkChecksum.h"
 # include "Checksum.h"
 #endif // ENABLE_MESSAGE_DIGEST
+#include "Signature.h"
 #include <iostream>
 #include <cppunit/extensions/HelperMacros.h>
 
@@ -82,6 +83,22 @@ void MetalinkProcessorTest::testParseFile()
 			 entry1->checksum->getMessageDigest());
     CPPUNIT_ASSERT_EQUAL(std::string("sha1"), entry1->checksum->getAlgo());
 #endif // ENABLE_MESSAGE_DIGEST
+    CPPUNIT_ASSERT(!entry1->getSignature().isNull());
+    CPPUNIT_ASSERT_EQUAL(std::string("pgp"), entry1->getSignature()->getType());
+    CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.5.2.tar.bz2.sig"),
+			 entry1->getSignature()->getFile());
+    // Note that last '\n' character is trimmed.
+    CPPUNIT_ASSERT_EQUAL
+      (std::string
+       ("-----BEGIN PGP SIGNATURE-----\n"
+	"Version: GnuPG v1.4.9 (GNU/Linux)\n"
+	"\n"
+	"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n"
+	"ffffffffffffffffffffffff\n"
+	"fffff\n"
+	"-----END PGP SIGNATURE-----"),
+       entry1->getSignature()->getBody());
+
     std::deque<SharedHandle<MetalinkResource> >::iterator resourceItr1 = entry1->resources.begin();
     SharedHandle<MetalinkResource> resource1 = *resourceItr1;
     CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_FTP, resource1->type);
@@ -120,6 +137,8 @@ void MetalinkProcessorTest::testParseFile()
 			 entry2->chunkChecksum->getChecksum(1));
     CPPUNIT_ASSERT_EQUAL(std::string("sha1"), entry2->checksum->getAlgo());
 #endif // ENABLE_MESSAGE_DIGEST
+    // See that signature is null
+    CPPUNIT_ASSERT(entry2->getSignature().isNull());
 
     entryItr++;
 

+ 9 - 0
test/test.xml

@@ -13,6 +13,15 @@
       <verification>
         <hash type="sha1">a96cf3f0266b91d87d5124cf94326422800b627d</hash>
         <hash type="md5">fc4d834e89c18c99b2615d902750948c</hash>
+	<signature type="pgp" file="aria2-0.5.2.tar.bz2.sig">
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.9 (GNU/Linux)
+
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffff
+fffff
+-----END PGP SIGNATURE-----
+	</signature>
       </verification>
       <resources maxconnections="1">
         <url type="ftp" location="jp" preference="100" maxconnections="1">ftp://ftphost/aria2-0.5.2.tar.bz2</url>