1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
/*
* UpdateActivity.cpp
*
* Created on: Jun 20, 2012
* Author: Simon
*/
#include <bzlib.h>
#include <sstream>
#include "dialogues/ConfirmPrompt.h"
#include "interface/Engine.h"
#include "UpdateActivity.h"
#include "tasks/Task.h"
#include "client/HTTP.h"
#include "client/Client.h"
#include "Update.h"
#include "Misc.h"
class UpdateDownloadTask : public Task
{
public:
UpdateDownloadTask(std::string updateName, UpdateActivity * a) : updateName(updateName), a(a) {};
private:
UpdateActivity * a;
std::string updateName;
virtual void notifyDoneMain(){
a->NotifyDone(this);
}
virtual void notifyErrorMain()
{
a->NotifyError(this);
}
virtual bool doWork()
{
std::stringstream errorStream;
void * request = http_async_req_start(NULL, (char*)updateName.c_str(), NULL, 0, 0);
notifyStatus("Downloading update");
notifyProgress(-1);
while(!http_async_req_status(request))
{
int total, done;
http_async_get_length(request, &total, &done);
notifyProgress((float(done)/float(total))*100.0f);
}
char * data;
int dataLength, status;
data = http_async_req_stop(request, &status, &dataLength);
if (status!=200)
{
if (data)
free(data);
errorStream << "Server responded with Status " << status;
notifyError("Could not download update");
return false;
}
if (!data)
{
errorStream << "Server responded with nothing";
notifyError("Server did not return any data");
return false;
}
notifyStatus("Unpacking update");
notifyProgress(-1);
int uncompressedLength;
if(dataLength<16)
{
errorStream << "Unsufficient data, got " << dataLength << " bytes";
goto corrupt;
}
if (data[0]!=0x42 || data[1]!=0x75 || data[2]!=0x54 || data[3]!=0x54)
{
errorStream << "Invalid update format";
goto corrupt;
}
uncompressedLength = (unsigned char)data[4];
uncompressedLength |= ((unsigned char)data[5])<<8;
uncompressedLength |= ((unsigned char)data[6])<<16;
uncompressedLength |= ((unsigned char)data[7])<<24;
char * res;
res = (char *)malloc(uncompressedLength);
if (!res)
{
errorStream << "Unable to allocate " << uncompressedLength << " bytes of memory for decompression";
goto corrupt;
}
int dstate;
dstate = BZ2_bzBuffToBuffDecompress((char *)res, (unsigned *)&uncompressedLength, (char *)(data+8), dataLength-8, 0, 0);
if (dstate)
{
errorStream << "Unable to decompress update: " << dstate;
free(res);
goto corrupt;
}
free(data);
notifyStatus("Applying update");
notifyProgress(-1);
if (update_start(res, uncompressedLength))
{
update_cleanup();
notifyError("Update failed - try downloading a new version.");
}
Client::Ref().SetPref("version.update", true);
return true;
corrupt:
notifyError("Downloaded update is corrupted\n" + errorStream.str());
free(data);
return false;
}
};
UpdateActivity::UpdateActivity() {
std::stringstream file;
file << "http://" << SERVER << Client::Ref().GetUpdateInfo().File;
updateDownloadTask = new UpdateDownloadTask(file.str(), this);
updateWindow = new TaskWindow("Downloading update...", updateDownloadTask, true);
}
void UpdateActivity::NotifyDone(Task * sender)
{
if(sender->GetSuccess())
{
Exit();
}
}
void UpdateActivity::Exit()
{
updateWindow->Exit();
ui::Engine::Ref().Exit();
delete this;
}
void UpdateActivity::NotifyError(Task * sender)
{
class ErrorMessageCallback: public ConfirmDialogueCallback
{
UpdateActivity * a;
public:
ErrorMessageCallback(UpdateActivity * a_) { a = a_; }
virtual void ConfirmCallback(ConfirmPrompt::DialogueResult result) {
if (result == ConfirmPrompt::ResultOkay)
{
OpenURI("http://powdertoy.co.uk/Download.html");
}
a->Exit();
}
virtual ~ErrorMessageCallback() { }
};
new ConfirmPrompt("Autoupdate failed", "Please visit the website to download a newer version.\nError: " + sender->GetError(), new ErrorMessageCallback(this));
}
UpdateActivity::~UpdateActivity() {
// TODO Auto-generated destructor stub
}
|