~ubuntu-branches/debian/experimental/nzbget/experimental

« back to all changes in this revision

Viewing changes to .pc/fix_fsf_address.patch/ParChecker.cpp

  • Committer: Package Import Robot
  • Author(s): Andreas Moog
  • Date: 2013-07-18 14:50:28 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20130718145028-qhxse81w1sj5w424
Tags: 11.0+dfsg-1
* New upstream release (Closes: #701896)
* Repackage original tarball to remove copies of jquery and twitter-
  bootstrap
* debian/watch: Update for new versioning scheme
* debian/patches: Remove all old patches, add one patch:
  - dont-embed-libraries.patch: Don't install embedded jquery and bootstrap 
    libraries
* debian/combat: Upgrade to debhelper combat 9
* debian/control:
  - Fix Vcs-Git field
  - Adjust debhelper version for combat level 9
  - Add jquery and bootstrap to depends for integrated webserver
  - Add python to recommends for post-processing scripts
  - Bump build-depends on libpar2-dev to support the cancel function
* debian/links:
  - Use the system jquery and bootstrap libraries
* debian/rules:
  - Add get-orig-source target to build modified upstream tarball
* Adjust sample nzbget.conf:
  - Only listen to 127.0.0.1 instead of 0.0.0.0
  - Use nzbget.conf as template for webui configuration
* Adjust sample nzbgetd init file:
  - Point to correct location of nzbget binary

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  This file is part of nzbget
3
 
 *
4
 
 *  Copyright (C) 2007-2009 Andrei Prygounkov <hugbug@users.sourceforge.net>
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; either version 2 of the License, or
9
 
 *  (at your option) any later version.
10
 
 *
11
 
 *  This program is distributed in the hope that it will be useful,
12
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 *  GNU General Public License for more details.
15
 
 *
16
 
 *  You should have received a copy of the GNU General Public License
17
 
 *  along with this program; if not, write to the Free Software
18
 
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 
 *
20
 
 * $Revision: 323 $
21
 
 * $Date: 2009-05-27 23:09:08 +0200 (Wed, 27 May 2009) $
22
 
 *
23
 
 */
24
 
 
25
 
 
26
 
#ifdef HAVE_CONFIG_H
27
 
#include <config.h>
28
 
#endif
29
 
 
30
 
#ifdef WIN32
31
 
#include "win32.h"
32
 
#endif
33
 
 
34
 
#ifndef DISABLE_PARCHECK
35
 
 
36
 
#include <stdlib.h>
37
 
#include <string.h>
38
 
#include <ctype.h>
39
 
#include <fstream>
40
 
#ifdef WIN32
41
 
#include <par2cmdline.h>
42
 
#include <par2repairer.h>
43
 
#else
44
 
#include <libpar2/par2cmdline.h>
45
 
#include <libpar2/par2repairer.h>
46
 
#endif
47
 
 
48
 
#include "nzbget.h"
49
 
#include "ParChecker.h"
50
 
#include "Log.h"
51
 
#include "Options.h"
52
 
#include "Util.h"
53
 
 
54
 
extern Options* g_pOptions;
55
 
 
56
 
const char* Par2CmdLineErrStr[] = { "OK",
57
 
        "data files are damaged and there is enough recovery data available to repair them",
58
 
        "data files are damaged and there is insufficient recovery data available to be able to repair them",
59
 
        "there was something wrong with the command line arguments",
60
 
        "the PAR2 files did not contain sufficient information about the data files to be able to verify them",
61
 
        "repair completed but the data files still appear to be damaged",
62
 
        "an error occured when accessing files",
63
 
        "internal error occurred",
64
 
        "out of memory" };
65
 
 
66
 
 
67
 
class Repairer : public Par2Repairer
68
 
{
69
 
        friend class ParChecker;
70
 
};
71
 
 
72
 
 
73
 
ParChecker::ParChecker()
74
 
{
75
 
    debug("Creating ParChecker");
76
 
 
77
 
        m_eStatus = psUndefined;
78
 
        m_szParFilename = NULL;
79
 
        m_szInfoName = NULL;
80
 
        m_szErrMsg = NULL;
81
 
        m_szProgressLabel = (char*)malloc(1024);
82
 
        m_iFileProgress = 0;
83
 
        m_iStageProgress = 0;
84
 
        m_iExtraFiles = 0;
85
 
        m_bVerifyingExtraFiles = false;
86
 
        m_bCancelled = false;
87
 
        m_eStage = ptLoadingPars;
88
 
        m_QueuedParFiles.clear();
89
 
}
90
 
 
91
 
ParChecker::~ParChecker()
92
 
{
93
 
    debug("Destroying ParChecker");
94
 
 
95
 
        if (m_szParFilename)
96
 
        {
97
 
                free(m_szParFilename);
98
 
        }
99
 
        if (m_szInfoName)
100
 
        {
101
 
                free(m_szInfoName);
102
 
        }
103
 
        if (m_szErrMsg)
104
 
        {
105
 
                free(m_szErrMsg);
106
 
        }
107
 
        free(m_szProgressLabel);
108
 
 
109
 
        for (QueuedParFiles::iterator it = m_QueuedParFiles.begin(); it != m_QueuedParFiles.end() ;it++)
110
 
        {
111
 
                free(*it);
112
 
        }
113
 
        m_QueuedParFiles.clear();
114
 
}
115
 
 
116
 
void ParChecker::SetParFilename(const char * szParFilename)
117
 
{
118
 
        if (m_szParFilename)
119
 
        {
120
 
                free(m_szParFilename);
121
 
        }
122
 
        m_szParFilename = strdup(szParFilename);
123
 
}
124
 
 
125
 
void ParChecker::SetInfoName(const char * szInfoName)
126
 
{
127
 
        if (m_szInfoName)
128
 
        {
129
 
                free(m_szInfoName);
130
 
        }
131
 
        m_szInfoName = strdup(szInfoName);
132
 
}
133
 
 
134
 
void ParChecker::SetStatus(EStatus eStatus)
135
 
{
136
 
        m_eStatus = eStatus;
137
 
        Notify(NULL);
138
 
}
139
 
 
140
 
void ParChecker::Run()
141
 
{
142
 
        m_bRepairNotNeeded = false;
143
 
        m_eStage = ptLoadingPars;
144
 
        m_iProcessedFiles = 0;
145
 
        m_iExtraFiles = 0;
146
 
        m_bVerifyingExtraFiles = false;
147
 
        m_bCancelled = false;
148
 
 
149
 
        info("Verifying %s", m_szInfoName);
150
 
        SetStatus(psWorking);
151
 
 
152
 
    debug("par: %s", m_szParFilename);
153
 
    CommandLine commandLine;
154
 
    const char* argv[] = { "par2", "r", "-v", "-v", m_szParFilename };
155
 
    if (!commandLine.Parse(5, (char**)argv))
156
 
    {
157
 
        error("Could not start par-check for %s. Par-file: %s", m_szInfoName, m_szParFilename);
158
 
                SetStatus(psFailed);
159
 
        return;
160
 
    }
161
 
 
162
 
    Result res;
163
 
 
164
 
        Repairer* pRepairer = new Repairer();
165
 
        m_pRepairer = pRepairer;
166
 
 
167
 
        pRepairer->sig_filename.connect(sigc::mem_fun(*this, &ParChecker::signal_filename));
168
 
        pRepairer->sig_progress.connect(sigc::mem_fun(*this, &ParChecker::signal_progress));
169
 
        pRepairer->sig_done.connect(sigc::mem_fun(*this, &ParChecker::signal_done));
170
 
 
171
 
        snprintf(m_szProgressLabel, 1024, "Verifying %s", m_szInfoName);
172
 
        m_szProgressLabel[1024-1] = '\0';
173
 
        m_iFileProgress = 0;
174
 
        m_iStageProgress = 0;
175
 
        UpdateProgress();
176
 
 
177
 
    res = pRepairer->PreProcess(commandLine);
178
 
    debug("ParChecker: PreProcess-result=%i", res);
179
 
 
180
 
        if (res != eSuccess || IsStopped())
181
 
        {
182
 
        error("Could not verify %s: %s", m_szInfoName, IsStopped() ? "due stopping" : "par2-file could not be processed");
183
 
                m_szErrMsg = strdup("par2-file could not be processed");
184
 
                SetStatus(psFailed);
185
 
                delete pRepairer;
186
 
                return;
187
 
        }
188
 
 
189
 
        char BufReason[1024];
190
 
        BufReason[0] = '\0';
191
 
        if (m_szErrMsg)
192
 
        {
193
 
                free(m_szErrMsg);
194
 
        }
195
 
        m_szErrMsg = NULL;
196
 
        
197
 
        m_eStage = ptVerifyingSources;
198
 
    res = pRepairer->Process(commandLine, false);
199
 
    debug("ParChecker: Process-result=%i", res);
200
 
 
201
 
        if (!IsStopped() && res == eRepairNotPossible && CheckSplittedFragments())
202
 
        {
203
 
                pRepairer->UpdateVerificationResults();
204
 
                res = pRepairer->Process(commandLine, false);
205
 
                debug("ParChecker: Process-result=%i", res);
206
 
        }
207
 
 
208
 
        bool bMoreFilesLoaded = true;
209
 
        while (!IsStopped() && res == eRepairNotPossible)
210
 
        {
211
 
                int missingblockcount = pRepairer->missingblockcount - pRepairer->recoverypacketmap.size();
212
 
                if (bMoreFilesLoaded)
213
 
                {
214
 
                        info("Need more %i par-block(s) for %s", missingblockcount, m_szInfoName);
215
 
                }
216
 
                
217
 
                m_mutexQueuedParFiles.Lock();
218
 
        bool hasMorePars = !m_QueuedParFiles.empty();
219
 
                m_mutexQueuedParFiles.Unlock();
220
 
                
221
 
                if (!hasMorePars)
222
 
                {
223
 
                        int iBlockFound = 0;
224
 
                        bool requested = RequestMorePars(missingblockcount, &iBlockFound);
225
 
                        if (requested)
226
 
                        {
227
 
                                strncpy(m_szProgressLabel, "Awaiting additional par-files", 1024);
228
 
                                m_szProgressLabel[1024-1] = '\0';
229
 
                                m_iFileProgress = 0;
230
 
                                UpdateProgress();
231
 
                        }
232
 
                        
233
 
                        m_mutexQueuedParFiles.Lock();
234
 
                        hasMorePars = !m_QueuedParFiles.empty();
235
 
                        m_bQueuedParFilesChanged = false;
236
 
                        m_mutexQueuedParFiles.Unlock();
237
 
                        
238
 
                        if (!requested && !hasMorePars)
239
 
                        {
240
 
                                snprintf(BufReason, 1024, "not enough par-blocks, %i block(s) needed, but %i block(s) available", missingblockcount, iBlockFound);
241
 
                BufReason[1024-1] = '\0';
242
 
                                m_szErrMsg = strdup(BufReason);
243
 
                                break;
244
 
                        }
245
 
                        
246
 
                        if (!hasMorePars)
247
 
                        {
248
 
                                // wait until new files are added by "AddParFile" or a change is signaled by "QueueChanged"
249
 
                                bool bQueuedParFilesChanged = false;
250
 
                                while (!bQueuedParFilesChanged && !IsStopped())
251
 
                                {
252
 
                                        m_mutexQueuedParFiles.Lock();
253
 
                                        bQueuedParFilesChanged = m_bQueuedParFilesChanged;
254
 
                                        m_mutexQueuedParFiles.Unlock();
255
 
                                        usleep(100 * 1000);
256
 
                                }
257
 
                        }
258
 
                }
259
 
 
260
 
                if (IsStopped())
261
 
                {
262
 
                        break;
263
 
                }
264
 
 
265
 
                bMoreFilesLoaded = LoadMorePars();
266
 
                if (bMoreFilesLoaded)
267
 
                {
268
 
                        pRepairer->UpdateVerificationResults();
269
 
                        res = pRepairer->Process(commandLine, false);
270
 
                        debug("ParChecker: Process-result=%i", res);
271
 
                }
272
 
        }
273
 
 
274
 
        if (IsStopped())
275
 
        {
276
 
                SetStatus(psFailed);
277
 
                delete pRepairer;
278
 
                return;
279
 
        }
280
 
        
281
 
        if (res == eSuccess)
282
 
        {
283
 
        info("Repair not needed for %s", m_szInfoName);
284
 
                m_bRepairNotNeeded = true;
285
 
        }
286
 
        else if (res == eRepairPossible)
287
 
        {
288
 
                if (g_pOptions->GetParRepair())
289
 
                {
290
 
                info("Repairing %s", m_szInfoName);
291
 
 
292
 
                        snprintf(m_szProgressLabel, 1024, "Repairing %s", m_szInfoName);
293
 
                        m_szProgressLabel[1024-1] = '\0';
294
 
                        m_iFileProgress = 0;
295
 
                        m_iStageProgress = 0;
296
 
                        m_iProcessedFiles = 0;
297
 
                        m_eStage = ptRepairing;
298
 
                        m_iFilesToRepair = pRepairer->damagedfilecount + pRepairer->missingfilecount;
299
 
                        UpdateProgress();
300
 
 
301
 
                        res = pRepairer->Process(commandLine, true);
302
 
                debug("ParChecker: Process-result=%i", res);
303
 
                        if (res == eSuccess)
304
 
                        {
305
 
                        info("Successfully repaired %s", m_szInfoName);
306
 
                        }
307
 
                }
308
 
                else
309
 
                {
310
 
                info("Repair possible for %s", m_szInfoName);
311
 
                        res = eSuccess;
312
 
                }
313
 
        }
314
 
        
315
 
        if (m_bCancelled)
316
 
        {
317
 
                warn("Repair cancelled for %s", m_szInfoName);
318
 
                m_szErrMsg = strdup("repair cancelled");
319
 
                SetStatus(psFailed);
320
 
        }
321
 
        else if (res == eSuccess)
322
 
        {
323
 
                SetStatus(psFinished);
324
 
        }
325
 
        else
326
 
        {
327
 
                if (!m_szErrMsg && (int)res >= 0 && (int)res <= 8)
328
 
                {
329
 
                        m_szErrMsg = strdup(Par2CmdLineErrStr[res]);
330
 
                }
331
 
                error("Repair failed for %s: %s", m_szInfoName, m_szErrMsg ? m_szErrMsg : "");
332
 
                SetStatus(psFailed);
333
 
        }
334
 
        
335
 
        delete pRepairer;
336
 
}
337
 
 
338
 
bool ParChecker::LoadMorePars()
339
 
{
340
 
        m_mutexQueuedParFiles.Lock();
341
 
        QueuedParFiles moreFiles;
342
 
        moreFiles.assign(m_QueuedParFiles.begin(), m_QueuedParFiles.end());
343
 
        m_QueuedParFiles.clear();
344
 
        m_mutexQueuedParFiles.Unlock();
345
 
        
346
 
        for (QueuedParFiles::iterator it = moreFiles.begin(); it != moreFiles.end() ;it++)
347
 
        {
348
 
                char* szParFilename = *it;
349
 
                bool loadedOK = ((Repairer*)m_pRepairer)->LoadPacketsFromFile(szParFilename);
350
 
                if (loadedOK)
351
 
                {
352
 
                        info("File %s successfully loaded for par-check", Util::BaseFileName(szParFilename), m_szInfoName);
353
 
                }
354
 
                else
355
 
                {
356
 
                        info("Could not load file %s for par-check", Util::BaseFileName(szParFilename), m_szInfoName);
357
 
                }
358
 
                free(szParFilename);
359
 
        }
360
 
 
361
 
        return !moreFiles.empty();
362
 
}
363
 
 
364
 
void ParChecker::AddParFile(const char * szParFilename)
365
 
{
366
 
        m_mutexQueuedParFiles.Lock();
367
 
        m_QueuedParFiles.push_back(strdup(szParFilename));
368
 
        m_bQueuedParFilesChanged = true;
369
 
        m_mutexQueuedParFiles.Unlock();
370
 
}
371
 
 
372
 
void ParChecker::QueueChanged()
373
 
{
374
 
        m_mutexQueuedParFiles.Lock();
375
 
        m_bQueuedParFilesChanged = true;
376
 
        m_mutexQueuedParFiles.Unlock();
377
 
}
378
 
 
379
 
bool ParChecker::CheckSplittedFragments()
380
 
{
381
 
        bool bFragmentsAdded = false;
382
 
 
383
 
        for (vector<Par2RepairerSourceFile*>::iterator it = ((Repairer*)m_pRepairer)->sourcefiles.begin();
384
 
                it != ((Repairer*)m_pRepairer)->sourcefiles.end(); it++)
385
 
        {
386
 
                Par2RepairerSourceFile *sourcefile = *it;
387
 
                if (!sourcefile->GetTargetExists() && AddSplittedFragments(sourcefile->TargetFileName().c_str()))
388
 
                {
389
 
                        bFragmentsAdded = true;
390
 
                }
391
 
        }
392
 
 
393
 
        return bFragmentsAdded;
394
 
}
395
 
 
396
 
bool ParChecker::AddSplittedFragments(const char* szFilename)
397
 
{
398
 
        char szDirectory[1024];
399
 
        strncpy(szDirectory, szFilename, 1024);
400
 
        szDirectory[1024-1] = '\0';
401
 
 
402
 
        char* szBasename = Util::BaseFileName(szDirectory);
403
 
        if (szBasename == szDirectory)
404
 
        {
405
 
                return false;
406
 
        }
407
 
        szBasename[-1] = '\0';
408
 
        int iBaseLen = strlen(szBasename);
409
 
 
410
 
        list<CommandLine::ExtraFile> extrafiles;
411
 
 
412
 
        DirBrowser dir(szDirectory);
413
 
        while (const char* filename = dir.Next())
414
 
        {
415
 
                if (!strncasecmp(filename, szBasename, iBaseLen))
416
 
                {
417
 
                        const char* p = filename + iBaseLen;
418
 
                        if (*p == '.')
419
 
                        {
420
 
                                for (p++; *p && strchr("0123456789", *p); p++) ;
421
 
                                if (!*p)
422
 
                                {
423
 
                                        debug("Found splitted fragment %s", filename);
424
 
 
425
 
                                        char fullfilename[1024];
426
 
                                        snprintf(fullfilename, 1024, "%s%c%s", szDirectory, PATH_SEPARATOR, filename);
427
 
                                        fullfilename[1024-1] = '\0';
428
 
 
429
 
                                        CommandLine::ExtraFile extrafile(fullfilename, Util::FileSize(fullfilename));
430
 
                                        extrafiles.push_back(extrafile);
431
 
                                }
432
 
                        }
433
 
                }
434
 
        }
435
 
 
436
 
        bool bFragmentsAdded = false;
437
 
 
438
 
        if (!extrafiles.empty())
439
 
        {
440
 
                m_iExtraFiles = extrafiles.size();
441
 
                m_bVerifyingExtraFiles = true;
442
 
                bFragmentsAdded = ((Repairer*)m_pRepairer)->VerifyExtraFiles(extrafiles);
443
 
                m_bVerifyingExtraFiles = false;
444
 
        }
445
 
 
446
 
        return bFragmentsAdded;
447
 
}
448
 
 
449
 
void ParChecker::signal_filename(std::string str)
450
 
{
451
 
    const char* szStageMessage[] = { "Loading file", "Verifying file", "Repairing file", "Verifying repaired file" };
452
 
 
453
 
        if (m_eStage == ptRepairing)
454
 
        {
455
 
                m_eStage = ptVerifyingRepaired;
456
 
        }
457
 
 
458
 
        info("%s %s", szStageMessage[m_eStage], str.c_str());
459
 
 
460
 
        snprintf(m_szProgressLabel, 1024, "%s %s", szStageMessage[m_eStage], str.c_str());
461
 
        m_szProgressLabel[1024-1] = '\0';
462
 
        m_iFileProgress = 0;
463
 
        UpdateProgress();
464
 
}
465
 
 
466
 
void ParChecker::signal_progress(double progress)
467
 
{
468
 
        m_iFileProgress = (int)progress;
469
 
 
470
 
        if (m_eStage == ptRepairing)
471
 
        {
472
 
                // calculating repair-data for all files
473
 
                m_iStageProgress = m_iFileProgress;
474
 
        }
475
 
        else
476
 
        {
477
 
                // processing individual files
478
 
 
479
 
                int iTotalFiles = 0;
480
 
                if (m_eStage == ptVerifyingRepaired)
481
 
                {
482
 
                        // repairing individual files
483
 
                        iTotalFiles = m_iFilesToRepair;
484
 
                }
485
 
                else
486
 
                {
487
 
                        // verifying individual files
488
 
                        iTotalFiles = ((Repairer*)m_pRepairer)->sourcefiles.size() + m_iExtraFiles;
489
 
                }
490
 
 
491
 
                if (iTotalFiles > 0)
492
 
                {
493
 
                        if (m_iFileProgress < 1000)
494
 
                        {
495
 
                                m_iStageProgress = (m_iProcessedFiles * 1000 + m_iFileProgress) / iTotalFiles;
496
 
                        }
497
 
                        else
498
 
                        {
499
 
                                m_iStageProgress = m_iProcessedFiles * 1000 / iTotalFiles;
500
 
                        }
501
 
                }
502
 
                else
503
 
                {
504
 
                        m_iStageProgress = 0;
505
 
                }
506
 
        }
507
 
 
508
 
        debug("Current-progres: %i, Total-progress: %i", m_iFileProgress, m_iStageProgress);
509
 
 
510
 
        UpdateProgress();
511
 
}
512
 
 
513
 
void ParChecker::signal_done(std::string str, int available, int total)
514
 
{
515
 
        m_iProcessedFiles++;
516
 
 
517
 
        if (m_eStage == ptVerifyingSources)
518
 
        {
519
 
                if (available < total && !m_bVerifyingExtraFiles)
520
 
                {
521
 
                        bool bFileExists = true;
522
 
 
523
 
                        for (vector<Par2RepairerSourceFile*>::iterator it = ((Repairer*)m_pRepairer)->sourcefiles.begin();
524
 
                                it != ((Repairer*)m_pRepairer)->sourcefiles.end(); it++)
525
 
                        {
526
 
                                Par2RepairerSourceFile *sourcefile = *it;
527
 
                                if (sourcefile && !strcmp(str.c_str(), Util::BaseFileName(sourcefile->TargetFileName().c_str())) &&
528
 
                                        !sourcefile->GetTargetExists())
529
 
                                {
530
 
                                        bFileExists = false;
531
 
                                        break;
532
 
                                }
533
 
                        }
534
 
 
535
 
                        if (bFileExists)
536
 
                        {
537
 
                                warn("File %s has %i bad block(s) of total %i block(s)", str.c_str(), total - available, total);
538
 
                        }
539
 
                        else
540
 
                        {
541
 
                                warn("File %s with %i block(s) is missing", str.c_str(), total);
542
 
                        }
543
 
                }
544
 
        }
545
 
}
546
 
 
547
 
void ParChecker::Cancel()
548
 
{
549
 
#ifdef HAVE_PAR2_CANCEL
550
 
        ((Repairer*)m_pRepairer)->cancelled = true;
551
 
        m_bCancelled = true;
552
 
#else
553
 
        error("Could not cancel par-repair. The used version of libpar2 does not support the cancelling of par-repair. Libpar2 needs to be patched for that feature to work.");
554
 
#endif
555
 
}
556
 
 
557
 
#endif