~efargaspro/+junk/codeblocks-16.01-release

« back to all changes in this revision

Viewing changes to src/plugins/contrib/devpak_plugin/devpakinstaller.cpp

  • Committer: damienlmoore at gmail
  • Date: 2016-02-02 02:43:22 UTC
  • Revision ID: damienlmoore@gmail.com-20160202024322-yql5qmtbwdyamdwd
Code::BlocksĀ 16.01

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
 
3
 * http://www.gnu.org/licenses/gpl-3.0.html
 
4
 *
 
5
 * $Revision: 7109 $
 
6
 * $Id: devpakinstaller.cpp 7109 2011-04-15 11:53:16Z mortenmacfly $
 
7
 * $HeadURL: http://svn.code.sf.net/p/codeblocks/code/branches/release-16.xx/src/plugins/contrib/devpak_plugin/devpakinstaller.cpp $
 
8
 */
 
9
 
 
10
#include "devpakinstaller.h"
 
11
#include <bzlib.h>
 
12
#include <wx/intl.h>
 
13
#include "mytar.h"
 
14
#include "cbiniparser.h"
 
15
#include <wx/filename.h>
 
16
#include <wx/msgdlg.h>
 
17
 
 
18
DevPakInstaller::DevPakInstaller()
 
19
    : m_pDlg(0)
 
20
{
 
21
        //ctor
 
22
}
 
23
 
 
24
DevPakInstaller::~DevPakInstaller()
 
25
{
 
26
        //dtor
 
27
    EndProgressDialog();
 
28
}
 
29
 
 
30
void DevPakInstaller::CreateProgressDialog(int max)
 
31
{
 
32
    EndProgressDialog();
 
33
    m_pDlg = new wxProgressDialog(_("Progress"), _T(""), max, 0, wxPD_APP_MODAL);
 
34
    m_pDlg->SetSize(480, m_pDlg->GetSize().y);
 
35
    m_pDlg->Centre();
 
36
}
 
37
 
 
38
void DevPakInstaller::EndProgressDialog()
 
39
{
 
40
        if (m_pDlg)
 
41
        m_pDlg->Destroy();
 
42
    m_pDlg = 0;
 
43
}
 
44
 
 
45
void DevPakInstaller::UpdateProgress(int val, const wxString& newtext)
 
46
{
 
47
    if (m_pDlg)
 
48
    {
 
49
        m_pDlg->Update(val, newtext);
 
50
        wxYield();
 
51
    }
 
52
}
 
53
 
 
54
bool DevPakInstaller::Install(const wxString& name, const wxString& filename, const wxString& dir, wxArrayString* files)
 
55
{
 
56
    CreateProgressDialog(4);
 
57
    m_Status.Clear();
 
58
 
 
59
    // Step 1: decompress
 
60
    UpdateProgress(0, _("Decompressing ") + filename);
 
61
    wxYield();
 
62
    wxString m_Status;
 
63
    wxString tmpfile = wxFileName::CreateTempFileName(_T("cb"));
 
64
    if (!Decompress(filename, tmpfile))
 
65
    {
 
66
        m_Status += _(" [Decompression failed]");
 
67
        wxRemoveFile(tmpfile);
 
68
        EndProgressDialog();
 
69
        return false;
 
70
    }
 
71
 
 
72
    // Step 2: un-tar .DevPackage file
 
73
    UpdateProgress(1, _("Unpacking control-file"));
 
74
    wxYield();
 
75
    TAR* t = new TAR(tmpfile.c_str());
 
76
    TAR::Record* r = t->FindFile(_T("*.DevPackage"));
 
77
    wxString controlFile = r->name;
 
78
    wxString status2;
 
79
    if (!r || !t->ExtractFile(r, dir, status2))
 
80
    {
 
81
        m_Status << _(" [Control file unpacking failed] - ");
 
82
        m_Status << status2;
 
83
        delete t;
 
84
        wxRemoveFile(tmpfile);
 
85
        EndProgressDialog();
 
86
        return false;
 
87
    }
 
88
 
 
89
    // Step 3: un-tar
 
90
    UpdateProgress(2, _("Unpacking all files"));
 
91
    wxYield();
 
92
    if (!Untar(controlFile, tmpfile, dir, files))
 
93
    {
 
94
        m_Status += _(" [Unpacking failed]");
 
95
        delete t;
 
96
        wxRemoveFile(tmpfile);
 
97
        RemoveControlFile(dir + _T("/") + controlFile);
 
98
        EndProgressDialog();
 
99
        return false;
 
100
    }
 
101
 
 
102
    UpdateProgress(3, _("Done"));
 
103
    delete t;
 
104
    wxRemoveFile(tmpfile);
 
105
    RemoveControlFile(dir + _T("/") + controlFile);
 
106
    EndProgressDialog();
 
107
    return true;
 
108
}
 
109
 
 
110
bool DevPakInstaller::Uninstall(const wxString& entry)
 
111
{
 
112
    m_Status.Clear();
 
113
    IniParser* p = new IniParser;
 
114
    p->ParseFile(entry);
 
115
 
 
116
    int idx = p->FindGroupByName(_T("Files"), false);
 
117
    if (idx == -1)
 
118
    {
 
119
        m_Status << _("No [Files] section in ") << entry << _T('\n');
 
120
        return false;
 
121
    }
 
122
    wxArrayString pathlist;
 
123
    CreateProgressDialog(p->GetKeysCount(idx));
 
124
    for (int i = 0; i < p->GetKeysCount(idx); ++i)
 
125
    {
 
126
        wxString file = p->GetKeyName(idx, i);
 
127
        UpdateProgress(i, _("Removing: ") + file);
 
128
        if (!wxRemoveFile(file))
 
129
            m_Status << _("Can't remove ") << file << _T('\n');
 
130
        else
 
131
        {
 
132
            wxString path = wxPathOnly(file);
 
133
            while (path.Last() == _T('/') || path.Last() == _T('\\'))
 
134
                path.RemoveLast();
 
135
            if (pathlist.Index(path) == wxNOT_FOUND)
 
136
                pathlist.Add(path);
 
137
        }
 
138
    }
 
139
    EndProgressDialog();
 
140
    // remove dirs
 
141
    CreateProgressDialog(pathlist.GetCount());
 
142
    for (unsigned int i = 0; i < pathlist.GetCount(); ++i)
 
143
    {
 
144
        wxString path = pathlist[i];
 
145
        int pos = path.Find(_T('/'), true);
 
146
        while (pos != wxNOT_FOUND)
 
147
        {
 
148
            wxRmdir(path);
 
149
            path.Remove(pos, path.Length() - pos);
 
150
            UpdateProgress(i, _("Removing directory: ") + path);
 
151
            pos = path.Find(_T('/'), true);
 
152
        }
 
153
    }
 
154
    EndProgressDialog();
 
155
    delete p;
 
156
    if (!wxRemoveFile(entry))
 
157
        m_Status << _("Can't remove ") << entry << _T('\n');
 
158
 
 
159
    return true; //m_Status.IsEmpty();
 
160
}
 
161
 
 
162
void DevPakInstaller::RemoveControlFile(const wxString& filename)
 
163
{
 
164
    if (filename.IsEmpty())
 
165
        return;
 
166
    wxRemoveFile(filename);
 
167
    wxRmdir(wxFileName(filename).GetPath()); // deletes it if non-empty
 
168
}
 
169
 
 
170
bool DevPakInstaller::Decompress(const wxString& filename, const wxString& tmpfile)
 
171
{
 
172
    // open file
 
173
    FILE* f = fopen(filename.mb_str(), "rb");
 
174
    if (!f)
 
175
    {
 
176
        m_Status = _("Error opening input file!");
 
177
        return false;
 
178
    }
 
179
 
 
180
    // open BZIP2 stream
 
181
    int bzerror;
 
182
    BZFILE* bz = BZ2_bzReadOpen(&bzerror, f, 0, 0, 0L, 0);
 
183
    if (!bz || bzerror != BZ_OK)
 
184
    {
 
185
        m_Status = _("Can't read compressed stream!");
 
186
        fclose(f);
 
187
        return false;
 
188
    }
 
189
 
 
190
    // open output file
 
191
    FILE* fo = fopen(tmpfile.mb_str(), "wb");
 
192
    if (!fo)
 
193
    {
 
194
        m_Status = _("Error opening output file!");
 
195
        fclose(f);
 
196
        return false;
 
197
    }
 
198
 
 
199
    // read stream writing to uncompressed file
 
200
    char buffer[2048];
 
201
    while (bzerror != BZ_STREAM_END)
 
202
    {
 
203
        int read_bytes = BZ2_bzRead(&bzerror, bz, buffer, 2048);
 
204
        if (bzerror != BZ_OK && bzerror != BZ_STREAM_END)
 
205
        {
 
206
            m_Status = _("Error reading from stream!");
 
207
            BZ2_bzReadClose(&bzerror, bz);
 
208
            fclose(fo);
 
209
            fclose(f);
 
210
            return false;
 
211
        }
 
212
        fwrite(buffer, read_bytes, 1, fo);
 
213
    }
 
214
 
 
215
    BZ2_bzReadClose(&bzerror, bz);
 
216
 
 
217
 
 
218
    fclose(fo);
 
219
    fclose(f);
 
220
    return true;
 
221
}
 
222
 
 
223
bool DevPakInstaller::Untar(const wxString& controlFile, const wxString& filename, const wxString& dirname, wxArrayString* files)
 
224
{
 
225
    TAR t(filename.c_str());
 
226
    wxString tmpControlFile;
 
227
 
 
228
    if (!controlFile.IsEmpty())
 
229
    {
 
230
        IniParser ini;
 
231
        ini.ParseFile(dirname + _T("/") + controlFile);
 
232
        int grp = ini.FindGroupByName(_T("Files"));
 
233
        for (int i = 0; grp != -1 && i < ini.GetKeysCount(grp); ++i)
 
234
        {
 
235
            t.AddReplacer(ini.GetKeyName(grp, i), ini.GetKeyValue(grp, i));
 
236
        }
 
237
 
 
238
        // add replacers for all paths above controlFile
 
239
        // i.e. in Allegro.DevPak:
 
240
        // Test/Allegro.DevPackage (everything is below Test/),
 
241
        // add replacer for Test/
 
242
        int pos = controlFile.Last('/');
 
243
        if (pos != wxNOT_FOUND)
 
244
        {
 
245
            wxString replacer = controlFile.SubString(0, pos);
 
246
            tmpControlFile = controlFile;
 
247
            tmpControlFile.Replace(replacer, _T(""));
 
248
            t.AddReplacer(replacer, _T(""));
 
249
        }
 
250
 
 
251
        // add replacers (with user's permission) for DLLs
 
252
        #ifdef __WXMSW__
 
253
        TAR::Record* r = t.FindFile(_T("*.dll"));
 
254
        if (!r)
 
255
            r = t.FindFile(_T("*.DLL"));
 
256
        if (r)
 
257
        {
 
258
            if (wxMessageBox(_("This package contains some DLLs.\nDo you want to install them system-wide (YES recommended)?"), _("Confirmation"), wxICON_QUESTION | wxYES_NO) == wxYES)
 
259
            {
 
260
                wxFileName fname(wxGetOSDirectory() + _T("/system32/"));
 
261
                fname.MakeRelativeTo(dirname);
 
262
                t.AddReplacer(_T("dll/"), fname.GetFullPath());
 
263
            }
 
264
            wxYield();
 
265
        }
 
266
        #endif
 
267
    }
 
268
 
 
269
    bool ret = t.ExtractAll(dirname.c_str(), m_Status, files);
 
270
    if (!tmpControlFile.IsEmpty())
 
271
        RemoveControlFile(dirname + _T("/") + tmpControlFile);
 
272
    return ret;
 
273
}