📄 checksumdlg.cpp
字号:
#include "checksumdlg.h"#include "../krusader.h"#include <klocale.h>#include <qlayout.h>#include <qlabel.h>#include <qcheckbox.h>#include <klineedit.h>#include <klistview.h>#include <qpixmap.h>#include <kcursor.h>#include <kmessagebox.h>#include <qfile.h>#include <qtextstream.h>#include <kfiledialog.h>#include <qframe.h>#include <kiconloader.h>#include <kcombobox.h>#include <qfileinfo.h>#include <kurlrequester.h>#include "../krservices.h"#include <qptrlist.h>#include <qmap.h>#include <ktempfile.h>#include <kstandarddirs.h>class CS_Tool; // forwardtypedef void PREPARE_PROC_FUNC(KProcess& proc, CS_Tool *self, const QStringList& files, const QString checksumFile, bool recursive, const QString& stdoutFileName, const QString& stderrFileName, const QString& type=QString::null);typedef QStringList GET_FAILED_FUNC(const QStringList& stdOut, const QStringList& stdErr);class CS_Tool {public: enum Type { MD5=0, SHA1, SHA256, TIGER, WHIRLPOOL, SFV, CRC, SHA224, SHA384, SHA512, NumOfTypes }; Type type; QString binary; bool recursive; bool standardFormat; PREPARE_PROC_FUNC *create, *verify; GET_FAILED_FUNC *failed;};class CS_ToolByType {public: QPtrList<CS_Tool> tools, r_tools; // normal and recursive tools };// handles md5sum and sha1sumvoid sumCreateFunc(KProcess& proc, CS_Tool *self, const QStringList& files, const QString, bool recursive, const QString& stdoutFileName, const QString& stderrFileName, const QString&) { proc.setUseShell(true, "/bin/bash"); proc << KrServices::fullPathName( self->binary ); Q_ASSERT(!recursive); proc << files << "1>" << stdoutFileName << "2>" << stderrFileName; }void sumVerifyFunc(KProcess& proc, CS_Tool *self, const QStringList& /* files */, const QString checksumFile, bool recursive, const QString& stdoutFileName, const QString& stderrFileName, const QString& /* type */) { proc.setUseShell(true, "/bin/bash"); proc << KrServices::fullPathName( self->binary ); Q_ASSERT(!recursive); proc << "-c" << checksumFile << "1>" << stdoutFileName << "2>" << stderrFileName;}QStringList sumFailedFunc(const QStringList& stdOut, const QStringList& stdErr) { // md5sum and sha1sum print "...: FAILED" for failed files and display // the number of failures to stderr. so if stderr is empty, we'll assume all is ok QStringList result; if (stdErr.size()==0) return result; result += stdErr; // grep for the ":FAILED" substring const QString tmp = QString(": FAILED").local8Bit(); for (uint i=0; i<stdOut.size();++i) { if (stdOut[i].find(tmp) != -1) result += stdOut[i]; } return result;}// handles *deep binariesvoid deepCreateFunc(KProcess& proc, CS_Tool *self, const QStringList& files, const QString, bool recursive, const QString& stdoutFileName, const QString& stderrFileName, const QString&) { proc.setUseShell(true, "/bin/bash"); proc << KrServices::fullPathName( self->binary ); if (recursive) proc << "-r"; proc << "-l" << files << "1>" << stdoutFileName << "2>" << stderrFileName;}void deepVerifyFunc(KProcess& proc, CS_Tool *self, const QStringList& files, const QString checksumFile, bool recursive, const QString& stdoutFileName, const QString& stderrFileName, const QString&) { proc.setUseShell(true, "/bin/bash"); proc << KrServices::fullPathName( self->binary ); if (recursive) proc << "-r"; proc << "-x" << checksumFile << files << "1>" << stdoutFileName << "2>" << stderrFileName;}QStringList deepFailedFunc(const QStringList& stdOut, const QStringList&/* stdErr */) { // *deep dumps (via -x) all failed hashes to stdout return stdOut;}// handles cfv binaryvoid cfvCreateFunc(KProcess& proc, CS_Tool *self, const QStringList& files, const QString, bool recursive, const QString& stdoutFileName, const QString& stderrFileName, const QString& type) { proc.setUseShell(true, "/bin/bash"); proc << KrServices::fullPathName( self->binary ) << "-C" << "-VV"; if (recursive) proc << "-rr"; proc << "-t" << type << "-f-" << "-U" << files << "1>" << stdoutFileName << "2>" << stderrFileName; }void cfvVerifyFunc(KProcess& proc, CS_Tool *self, const QStringList& /* files */, const QString checksumFile, bool recursive, const QString& stdoutFileName, const QString& stderrFileName, const QString&type) { proc.setUseShell(true, "/bin/bash"); proc << KrServices::fullPathName( self->binary ) << "-M"; if (recursive) proc << "-rr"; proc << "-U" << "-VV" << "-t" << type << "-f" << checksumFile << "1>" << stdoutFileName << "2>" << stderrFileName;// << files;}QStringList cfvFailedFunc(const QStringList& /* stdOut */, const QStringList& stdErr) { // cfv dumps all failed hashes to stderr return stdErr;}// important: this table should be ordered like so that all md5 tools should be// one after another, and then all sha1 and so on and so forth. they tools must be grouped,// since the code in getTools() counts on it!CS_Tool cs_tools[] = { // type binary recursive stdFmt create_func verify_func failed_func {CS_Tool::MD5, "md5sum", false, true, sumCreateFunc, sumVerifyFunc, sumFailedFunc}, {CS_Tool::MD5, "md5deep", true, true, deepCreateFunc, deepVerifyFunc, deepFailedFunc}, {CS_Tool::MD5, "cfv", true, true, cfvCreateFunc, cfvVerifyFunc, cfvFailedFunc}, {CS_Tool::SHA1, "sha1sum", false, true, sumCreateFunc, sumVerifyFunc, sumFailedFunc}, {CS_Tool::SHA1, "sha1deep", true, true, deepCreateFunc, deepVerifyFunc, deepFailedFunc}, {CS_Tool::SHA1, "cfv", true, true, cfvCreateFunc, cfvVerifyFunc, cfvFailedFunc}, {CS_Tool::SHA224, "sha224sum", false, true, sumCreateFunc, sumVerifyFunc, sumFailedFunc}, {CS_Tool::SHA256, "sha256sum", false, true, sumCreateFunc, sumVerifyFunc, sumFailedFunc}, {CS_Tool::SHA256, "sha256deep", true, true, deepCreateFunc, deepVerifyFunc, deepFailedFunc}, {CS_Tool::SHA384, "sha384sum", false, true, sumCreateFunc, sumVerifyFunc, sumFailedFunc}, {CS_Tool::SHA512, "sha512sum", false, true, sumCreateFunc, sumVerifyFunc, sumFailedFunc}, {CS_Tool::TIGER, "tigerdeep", true, true, deepCreateFunc, deepVerifyFunc, deepFailedFunc}, {CS_Tool::WHIRLPOOL, "whirlpooldeep", true, true, deepCreateFunc, deepVerifyFunc, deepFailedFunc}, {CS_Tool::SFV, "cfv", true, false, cfvCreateFunc, cfvVerifyFunc, cfvFailedFunc}, {CS_Tool::CRC, "cfv", true, false, cfvCreateFunc, cfvVerifyFunc, cfvFailedFunc},};QMap<QString, CS_Tool::Type> cs_textToType;QMap<CS_Tool::Type, QString> cs_typeToText;void initChecksumModule() { // prepare the dictionaries - pity it has to be manually cs_textToType["md5"]=CS_Tool::MD5; cs_textToType["sha1"]=CS_Tool::SHA1; cs_textToType["sha256"]=CS_Tool::SHA256; cs_textToType["sha224"]=CS_Tool::SHA224; cs_textToType["sha384"]=CS_Tool::SHA384; cs_textToType["sha512"]=CS_Tool::SHA512; cs_textToType["tiger"]=CS_Tool::TIGER; cs_textToType["whirlpool"]=CS_Tool::WHIRLPOOL; cs_textToType["sfv"]=CS_Tool::SFV; cs_textToType["crc"]=CS_Tool::CRC; cs_typeToText[CS_Tool::MD5]="md5"; cs_typeToText[CS_Tool::SHA1]="sha1"; cs_typeToText[CS_Tool::SHA256]="sha256"; cs_typeToText[CS_Tool::SHA224]="sha224"; cs_typeToText[CS_Tool::SHA384]="sha384"; cs_typeToText[CS_Tool::SHA512]="sha512"; cs_typeToText[CS_Tool::TIGER]="tiger"; cs_typeToText[CS_Tool::WHIRLPOOL]="whirlpool"; cs_typeToText[CS_Tool::SFV]="sfv"; cs_typeToText[CS_Tool::CRC]="crc"; // build the checksumFilter (for usage in KRQuery) QMap<QString, CS_Tool::Type>::Iterator it; for (it=cs_textToType.begin(); it!=cs_textToType.end(); ++it) MatchChecksumDlg::checksumTypesFilter += ("*."+it.key()+" ");}// --------------------------------------------------// returns a list of tools which can work with recursive or non-recursive mode and are installed// note: only 1 tool from each type is suggestedstatic QPtrList<CS_Tool> getTools(bool folders) { QPtrList<CS_Tool> result; uint i; for (i=0; i < sizeof(cs_tools)/sizeof(CS_Tool); ++i) { if (result.last() && result.last()->type == cs_tools[i].type) continue; // 1 from each type please if (folders && !cs_tools[i].recursive) continue; if (KrServices::cmdExist(cs_tools[i].binary)) result.append(&cs_tools[i]); } return result;}// ------------- CreateChecksumDlgCreateChecksumDlg::CreateChecksumDlg(const QStringList& files, bool containFolders, const QString& path): KDialogBase(Plain, i18n("Create Checksum"), Ok | Cancel, Ok, krApp) { QPtrList<CS_Tool> tools = getTools(containFolders); if (tools.count() == 0) { // nothing was suggested?! QString error = i18n("<qt>Can't calculate checksum since no supported tool was found. " "Please check the <b>Dependencies</b> page in Krusader's settings.</qt>"); if (containFolders) error += i18n("<qt><b>Note</b>: you've selected directories, and probably have no recursive checksum tool installed." " Krusader currently supports <i>md5deep, sha1deep, sha256deep, tigerdeep and cfv</i></qt>"); KMessageBox::error(0, error); return; } QGridLayout *layout = new QGridLayout( plainPage(), 1, 1, KDialogBase::marginHint(), KDialogBase::spacingHint()); int row=0; // title (icon+text) QHBoxLayout *hlayout = new QHBoxLayout(layout, KDialogBase::spacingHint()); QLabel *p = new QLabel(plainPage()); p->setPixmap(krLoader->loadIcon("binary", KIcon::Desktop, 32)); hlayout->addWidget(p); QLabel *l1 = new QLabel(i18n("About to calculate checksum for the following files") + (containFolders ? i18n(" and folders:") : ":"), plainPage()); hlayout->addWidget(l1); layout->addMultiCellLayout(hlayout, row, row, 0, 1, Qt::AlignLeft); ++row; // file list KListBox *lb = new KListBox(plainPage()); lb->insertStringList(files); layout->addMultiCellWidget(lb, row, row, 0, 1); ++row; // checksum method QHBoxLayout *hlayout2 = new QHBoxLayout(layout, KDialogBase::spacingHint()); QLabel *l2 = new QLabel(i18n("Select the checksum method:"), plainPage()); hlayout2->addWidget(l2); KComboBox *method = new KComboBox(plainPage()); // -- fill the combo with available methods uint i; for ( i=0; i<tools.count(); ++i ) method->insertItem( cs_typeToText[tools.at(i)->type], i); method->setFocus(); hlayout2->addWidget(method); layout->addMultiCellLayout(hlayout2, row, row, 0, 1, Qt::AlignLeft); ++row; if (exec() != Accepted) return; // else implied: run the process tmpOut = new KTempFile(locateLocal("tmp", "krusader"), ".stdout" ); tmpErr = new KTempFile(locateLocal("tmp", "krusader"), ".stderr" ); KProcess proc; CS_Tool *mytool = tools.at(method->currentItem()); mytool->create(proc, mytool, KrServices::quote(files), QString::null, containFolders, tmpOut->name(), tmpErr->name(), method->currentText()); krApp->startWaiting(i18n("Calculating checksums ..."), 0, true); QApplication::setOverrideCursor( KCursor::waitCursor() ); bool r = proc.start(KProcess::NotifyOnExit, KProcess::AllOutput); if (r) while ( proc.isRunning() ) { usleep( 500 ); qApp->processEvents(); if (krApp->wasWaitingCancelled()) { // user cancelled proc.kill(); QApplication::restoreOverrideCursor(); return; } }; krApp->stopWait(); QApplication::restoreOverrideCursor(); if (!r || !proc.normalExit()) { KMessageBox::error(0, i18n("<qt>There was an error while running <b>%1</b>.</qt>").arg(mytool->binary)); return; } // suggest a filename QString suggestedFilename = path + '/'; if (files.count() > 1) suggestedFilename += ("checksum." + cs_typeToText[mytool->type]); else suggestedFilename += (files[0] + '.' + cs_typeToText[mytool->type]); // send both stdout and stderr QStringList stdOut, stdErr; if (!KrServices::fileToStringList(tmpOut->textStream(), stdOut) || !KrServices::fileToStringList(tmpErr->textStream(), stdErr)) { KMessageBox::error(krApp, i18n("Error reading stdout or stderr")); return; } ChecksumResultsDlg dlg( stdOut, stdErr, suggestedFilename, mytool->binary, cs_typeToText[mytool->type], mytool->standardFormat); tmpOut->unlink(); delete tmpOut;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -