1 #include "core/filedownload.hpp"
2 #include "core/moviedata.hpp"
3 #include "core/rom.hpp"
4 #include "interface/romtype.hpp"
5 #include "library/string.hpp"
6 #include "library/zip.hpp"
12 void file_download_thread_trampoline(file_download
* d
, loaded_rom
* rom
)
17 class file_download_handler
: public http_request::output_handler
20 file_download_handler(const std::string
& filename
)
22 fp
.open(filename
, std::ios::binary
);
25 ~file_download_handler()
28 void header(const std::string
& name
, const std::string
& content
)
32 void write(const char* source
, size_t srcsize
)
34 fp
.write(source
, srcsize
);
43 file_download::file_download()
49 file_download::~file_download()
51 if(req
.ohandler
) delete req
.ohandler
;
54 void file_download::cancel()
57 errormsg
= "Canceled";
61 void file_download::do_async(loaded_rom
& rom
)
63 tempname
= get_temp_file();
65 req
.ohandler
= new file_download_handler(tempname
);
70 (new threads::thread(file_download_thread_trampoline
, this, &rom
))->detach();
71 } catch(std::exception
& e
) {
80 std::string
file_download::statusmsg()
82 int64_t dn
, dt
, un
, ut
;
84 return (stringfmt() << "Downloading finished").str();
85 req
.get_xfer_status(dn
, dt
, un
, ut
);
87 return "Connecting...";
89 return (stringfmt() << "Downloading (" << dn
<< "/<unknown>)").str();
91 return (stringfmt() << "Downloading (" << (100 * dn
/ dt
) << "%)").str();
93 return (stringfmt() << "Downloading finished").str();
96 void file_download::_do_async(loaded_rom
& rom
)
98 while(!req
.finished
) {
99 threads::alock
h(req
.m
);
100 req
.finished_cond
.wait(h
);
103 if(req
.errormsg
!= "") {
104 remove(tempname
.c_str());
106 errormsg
= req
.errormsg
;
114 if(req
.http_code
> 299) {
116 errormsg
= (stringfmt() << "Got HTTP error " << req
.http_code
).str();
120 //Okay, we got the file.
121 std::istream
* s
= NULL
;
123 zip::reader
r(tempname
);
129 std::istream
& s
= r
[*r
.begin()];
130 std::ofstream
out(tempname2
= get_temp_file(), std::ios::binary
);
133 s
.read(buf
, sizeof(buf
));
134 out
.write(buf
, s
.gcount());
138 tempname2
= tempname
;
142 tempname2
= tempname
;
144 if(tempname
!= tempname2
) remove(tempname
.c_str());
146 core_type
* gametype
= NULL
;
148 gametype
= &rom
.get_internal_rom_type();
150 moviefile::brief_info
info(tempname2
);
151 auto sysregs
= core_sysregion::find_matching(info
.sysregion
);
152 for(auto i
: sysregs
)
153 if(i
->get_type().get_core_identifier() == info
.corename
)
154 gametype
= &i
->get_type();
156 for(auto i
: sysregs
)
157 gametype
= &i
->get_type();
159 auto mv
= moviefile::memref(target_slot
);
160 moviefile::memref(target_slot
) = new moviefile(tempname2
, *gametype
);
162 remove(tempname2
.c_str());
163 } catch(std::exception
& e
) {
164 remove(tempname2
.c_str());
177 urirewrite::rewriter lsnes_uri_rewrite
;