1 /* <!-- copyright */
2 /*
3  * aria2 - The high speed download utility
4  *
5  * Copyright (C) 2010 Tatsuhiro Tsujikawa
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  *
21  * In addition, as a special exception, the copyright holders give
22  * permission to link the code of portions of this program with the
23  * OpenSSL library under certain conditions as described in each
24  * individual source file, and distribute linked combinations
25  * including the two.
26  * You must obey the GNU General Public License in all respects
27  * for all of the code used other than OpenSSL.  If you modify
28  * file(s) with this exception, you may extend this exception to your
29  * version of the file(s), but you are not obligated to do so.  If you
30  * do not wish to do so, delete this exception statement from your
31  * version.  If you delete this exception statement from all source
32  * files in the program, then also delete it here.
33  */
34 /* copyright --> */
35 #include "bencode2.h"
36 
37 #include <sstream>
38 
39 #include "fmt.h"
40 #include "DlAbortEx.h"
41 #include "error_code.h"
42 #include "BufferedFile.h"
43 #include "util.h"
44 #include "ValueBaseBencodeParser.h"
45 
46 namespace aria2 {
47 
48 namespace bencode2 {
49 
decode(const unsigned char * data,size_t len)50 std::unique_ptr<ValueBase> decode(const unsigned char* data, size_t len)
51 {
52   size_t end;
53   return decode(data, len, end);
54 }
55 
decode(const std::string & data)56 std::unique_ptr<ValueBase> decode(const std::string& data)
57 {
58   size_t end;
59   return decode(reinterpret_cast<const unsigned char*>(data.c_str()),
60                 data.size(), end);
61 }
62 
decode(const unsigned char * data,size_t len,size_t & end)63 std::unique_ptr<ValueBase> decode(const unsigned char* data, size_t len,
64                                   size_t& end)
65 {
66   ssize_t error;
67   bittorrent::ValueBaseBencodeParser parser;
68   auto res = parser.parseFinal(reinterpret_cast<const char*>(data), len, error);
69   if (error < 0) {
70     throw DL_ABORT_EX2(
71         fmt("Bencode decoding failed: error=%d", static_cast<int>(error)),
72         error_code::BENCODE_PARSE_ERROR);
73   }
74   end = error;
75   return res;
76 }
77 
encode(const ValueBase * vlb)78 std::string encode(const ValueBase* vlb)
79 {
80   class BencodeValueBaseVisitor : public ValueBaseVisitor {
81   private:
82     std::ostringstream out_;
83 
84   public:
85     virtual void visit(const String& string) CXX11_OVERRIDE
86     {
87       const std::string& s = string.s();
88       out_ << s.size() << ":";
89       out_.write(s.data(), s.size());
90     }
91 
92     virtual void visit(const Integer& integer) CXX11_OVERRIDE
93     {
94       out_ << "i" << integer.i() << "e";
95     }
96 
97     virtual void visit(const Bool& v) CXX11_OVERRIDE {}
98     virtual void visit(const Null& v) CXX11_OVERRIDE {}
99 
100     virtual void visit(const List& list) CXX11_OVERRIDE
101     {
102       out_ << "l";
103       for (const auto& e : list) {
104         e->accept(*this);
105       }
106       out_ << "e";
107     }
108 
109     virtual void visit(const Dict& dict) CXX11_OVERRIDE
110     {
111       out_ << "d";
112       for (const auto& e : dict) {
113         auto& key = e.first;
114         out_ << key.size() << ":";
115         out_.write(key.data(), key.size());
116         e.second->accept(*this);
117       }
118       out_ << "e";
119     }
120 
121     std::string getResult() const { return out_.str(); }
122   };
123   BencodeValueBaseVisitor visitor;
124   vlb->accept(visitor);
125   return visitor.getResult();
126 }
127 
128 } // namespace bencode2
129 
130 } // namespace aria2
131