Develop and Download Open Source Software

Browse Subversion Repository

Contents of /hamigaki/trunk/libs/archivers/example/wunzip.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1782 - (show annotations) (download) (as text)
Sun Jun 10 06:01:53 2018 UTC (5 years, 9 months ago) by hamigaki
File MIME type: text/x-c++src
File size: 4140 byte(s)
fix for Zip Slip
1 // wunzip.cpp: a simple ZIP decompressing program (Unicode version)
2
3 // Copyright Takeshi Mouri 2008-2018.
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7
8 // See http://hamigaki.sourceforge.jp/libs/archivers for library home page.
9
10
11 // Security warning:
12 // This program never check the validity of paths in the archive.
13 // See http://www.forest.impress.co.jp/article/2004/07/30/arcsecurity.html .
14 // (The above link is Japanese site)
15
16
17 #include <hamigaki/archivers/zip_file.hpp>
18 #include <hamigaki/filesystem/operations.hpp>
19 #include <boost/filesystem/convenience.hpp>
20 #include <boost/filesystem/fstream.hpp>
21 #include <boost/iostreams/copy.hpp>
22 #include <clocale>
23 #include <exception>
24 #include <iostream>
25
26 namespace ar = hamigaki::archivers;
27 namespace fs_ex = hamigaki::filesystem;
28 namespace io_ex = hamigaki::iostreams;
29 namespace fs = boost::filesystem;
30 namespace io = boost::iostreams;
31
32 template<class Path>
33 inline bool has_parent_path(const Path& ph)
34 {
35 #if BOOST_VERSION < 103600
36 return ph.has_branch_path();
37 #else
38 return ph.has_parent_path();
39 #endif
40 }
41
42 template<class Path>
43 bool is_valid_path(const Path& ph)
44 {
45 #if !defined(HAMIGAKI_ALLOW_DIRECTORY_TRAVERSAL)
46 if (ph.has_root_name() || ph.has_root_directory())
47 return false;
48 for (typename Path::iterator it = ph.begin(); it != ph.end(); ++it)
49 {
50 if (*it == L"..")
51 return false;
52 }
53 #endif
54 return true;
55 }
56
57 inline fs_ex::timestamp make_timestamp(std::time_t t)
58 {
59 return fs_ex::timestamp::from_time_t(t);
60 }
61
62 int main(int argc, char* argv[])
63 {
64 try
65 {
66 if (argc != 2)
67 {
68 std::cerr << "Usage: wunzip (archive)" << std::endl;
69 return 1;
70 }
71
72 std::setlocale(LC_ALL, "");
73
74 ar::wzip_file_source zip(argv[1]);
75
76 while (zip.next_entry())
77 {
78 const ar::zip::wheader& head = zip.header();
79
80 std::wcout << head.path << '\n';
81 if (!is_valid_path(head.path))
82 {
83 std::cerr << "Warning: invalid path" << '\n';
84 continue;
85 }
86
87 if (!head.link_path.empty())
88 {
89 if (::has_parent_path(head.path))
90 fs::create_directories(head.path.branch_path());
91
92 fs_ex::create_symlink(head.link_path, head.path);
93 }
94 else if (head.is_directory())
95 fs::create_directories(head.path);
96 else
97 {
98 if (::has_parent_path(head.path))
99 fs::create_directories(head.path.branch_path());
100
101 fs::ofstream os(head.path, std::ios_base::binary);
102 io::copy(zip, os);
103 }
104
105 // Note:
106 // The POSIX chown() clears S_ISUID/S_ISGID bits.
107 // So, we must call change_symlink_owner()
108 // before calling change_permissions().
109 fs_ex::error_code ec;
110 boost::optional<boost::intmax_t> uid;
111 if (head.uid)
112 uid = head.uid.get();
113 boost::optional<boost::intmax_t> gid;
114 if (head.gid)
115 gid = head.gid.get();
116 fs_ex::change_symlink_owner(head.path, uid, gid, ec);
117
118 fs_ex::change_attributes(head.path, head.attributes, ec);
119 fs_ex::change_permissions(head.path, head.permissions, ec);
120
121 if (head.modified_time)
122 {
123 fs_ex::last_write_time(
124 head.path, make_timestamp(*head.modified_time));
125 }
126 if (head.access_time)
127 {
128 fs_ex::last_access_time(
129 head.path, make_timestamp(*head.access_time));
130 }
131 if (head.creation_time)
132 {
133 fs_ex::creation_time(
134 head.path, make_timestamp(*head.creation_time));
135 }
136 }
137
138 return 0;
139 }
140 catch (const std::exception& e)
141 {
142 std::cerr << "Error: " << e.what() << std::endl;
143 }
144 return 1;
145 }

Properties

Name Value
svn:eol-style native

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26