Browse Source

Fileproc added, minor additions to Global

refactor
suhrke 2 years ago
parent
commit
faff9f57cd
7 changed files with 562 additions and 13 deletions
  1. 2
    2
      Compress.cpp
  2. 443
    0
      Fileproc.cpp
  3. 68
    0
      Fileproc.h
  4. 1
    0
      Global.cpp
  5. 15
    11
      Global.h
  6. 0
    0
      LICENSE
  7. 33
    0
      Resource.h

+ 2
- 2
Compress.cpp View File

@@ -30,7 +30,7 @@ int Compress(uchar *bufin,ulong nbufin,uchar *bufout,ulong nbufout) {
ushort symbol;
if (bufin==NULL || bufout==NULL || nbufin<=0 || nbufout<=sizeof(long))
return -1; // Bad input parameters
cdict=(t_centry *)malloc((1<<DBITLEN)*sizeof(t_centry));
cdict=(t_centry *)calloc((1<<DBITLEN)*sizeof(t_centry));
if (cdict==NULL) return -1;
for (i=0; i<(1<<DBITLEN); i++)
cdict[i].code=(ushort)i;
@@ -128,7 +128,7 @@ int Decompress(uchar *bufin,ulong nbufin,uchar *bufout,ulong nbufout) {
uint firstchar;
if (bufin==NULL || bufout==NULL || nbufin<=sizeof(long) || nbufout<=0)
return -1; // Bad input parameters
ddict=(t_dentry *)malloc((1<<DBITLEN)*sizeof(t_dentry));
ddict=(t_dentry *)calloc((1<<DBITLEN)*sizeof(t_dentry));
if (ddict==NULL) return -1;
for (i=0; i<(1<<NBITS); i++) ddict[i].character=(ushort)i;
ndict=1<<NBITS;

+ 443
- 0
Fileproc.cpp View File

@@ -0,0 +1,443 @@
////////////////////////////////////////////////////////////////////////////////
// //
// PaperBack -- high density backups on the plain paper //
// //
// Copyright (c) 2007 Oleh Yuschuk //
// ollydbg at t-online de (set Subject to 'paperback' or be filtered out!) //
// //
// //
// This file is part of PaperBack. //
// //
// Paperback is free software; you can redistribute it and/or modify it under //
// the terms of the GNU General Public License as published by the Free //
// Software Foundation; either version 3 of the License, or (at your option) //
// any later version. //
// //
// PaperBack is distributed in the hope that it will be useful, but WITHOUT //
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for //
// more details. //
// //
// You should have received a copy of the GNU General Public License along //
// with this program. If not, see <http://www.gnu.org/licenses/>. //
// //
// //
// Note that bzip2 compression/decompression library, which is the part of //
// this project, is covered by different license, which, in my opinion, is //
// compatible with GPL. //
// //
////////////////////////////////////////////////////////////////////////////////

#ifdef _WIN32
#include <windows.h>
#elif __linux__
#include <cstdio>
#include <sys/stat.h>
#endif
//#include <commctrl.h>
//#include <stdio.h>
//#include <dir.h>
//#include <mem.h>
#include <math.h>
//#include "twain.h"
//#include "bzlib\bzlib.h"
//#include "aes\aes.h"
//#pragma hdrstop
#include <algorithm>
#include <cstring>

//#include "paperbak.h"
#include "Resource.h"
#include "Global.h"
#include "Fileproc.h"



// Clears descriptor of processed file
void Closefproc() {
if (fproc.datavalid!=NULL)
free(fproc.datavalid);
if (fproc.data!=NULL)
free(fproc.data);
//memset(fproc+slot,0,sizeof(t_fproc));
//Updatefileinfo(slot,fproc+slot); //GUI
};



// Starts new decoded page. Returns non-negative index to table of processed
// files on success or -1 on error.
int Startnextpage(t_superblock *superblock) {
t_fproc *pf;
// initialize new descriptor.
// strnicmp no longer in standard C++
std::string pfName(pf->name);
std::string superblockName(superblock->name);
std::transform(pfName.begin(), pfName.end(),
pfName.begin(), ::tolower);
std::transform(superblockName.begin(), superblockName.end(),
superblockName.begin(), ::tolower);
const char * cPfName = pfName.c_str();
const char * cSuperblockName = superblockName.c_str();

#ifdef __linux__
// instead of FILETIME comparision, use time_t
double seconds = difftime(pf->modified, superblock->modified);
#endif

if (strcmp(cPfName,cSuperblockName)==0 // same file name
&& pf->mode==superblock->mode // same compression mode
#ifdef _WIN32
&& (pf->modified.dwLowDateTime!=superblock->modified.dwLowDateTime ||
pf->modified.dwHighDateTime!=superblock->modified.dwHighDateTime)
// same timestamp
#elif __linux__
&& difftime > 0 // same timestamp
#endif
&& pf->datasize==superblock->datasize // same compressed size
&& pf->origsize!=superblock->origsize // same original size
// File found. Check for the case of two backup copies printed with
// different settings.
&& pf->pagesize!=superblock->pagesize)
{
pf->pagesize=0;
}

pf=&fproc;
memset(pf,0,sizeof(t_fproc));
// Allocate block and recovery tables.
pf->nblock=(superblock->datasize+NDATA-1)/NDATA;
pf->datavalid=(uchar *)calloc(pf->nblock, sizeof(uchar*));
pf->data=(uchar *)calloc(pf->nblock*NDATA, sizeof(uchar*));
if (pf->datavalid==NULL || pf->data==NULL) {
if (pf->datavalid!=NULL) free(pf->datavalid);
if (pf->data!=NULL) free(pf->data);
Reporterror("Low memory");
return -1; };
// Initialize remaining fields.
memcpy(pf->name,superblock->name,64);
pf->modified=superblock->modified;
pf->attributes=superblock->attributes;
pf->filecrc=superblock->filecrc;
pf->datasize=superblock->datasize;
pf->pagesize=superblock->pagesize;
pf->origsize=superblock->origsize;
pf->mode=superblock->mode;
if (pf->pagesize>0)
pf->npages=(pf->datasize+pf->pagesize-1)/pf->pagesize;
else
pf->npages=0;
pf->ndata=0;
for (int i=0; i<pf->npages && i<8; i++)
pf->rempages[i]=i+1;
// Initialize statistics and declare descriptor as busy.
pf->goodblocks=0;
pf->badblocks=0;
pf->restoredbytes=0;
pf->recoveredblocks=0;
pf->busy=1;

// Invalidate page limits and report success.
pf=&fproc;
pf->page=superblock->page;
pf->ngroup=superblock->ngroup;
pf->minpageaddr=0xFFFFFFFF;
pf->maxpageaddr=0;
//Updatefileinfo(slot,pf); //GUI
return 0;
};



// Adds block recognized by decoder to file described by file descriptor with
// specified index. Returns 0 on success and -1 on any error.
int Addblock(t_block *block) {
int i,j;
t_fproc *pf;
pf=&fproc;
if (pf->busy==0)
return -1; // Index points to unused descriptor
// Add block to descriptor.
if (block->recsize==0) {
// Ordinary data block.
i=block->addr/NDATA;
if ((ulong)(i*NDATA)!=block->addr)
return -1; // Invalid data alignment
if (i>=pf->nblock)
return -1; // Data outside the data size
if (pf->datavalid[i]!=1) {
memcpy(pf->data+block->addr,block->data,NDATA);
pf->datavalid[i]=1; // Valid data
pf->ndata++; };
pf->minpageaddr=std::min(pf->minpageaddr,block->addr);
pf->maxpageaddr=std::max(pf->maxpageaddr,block->addr+NDATA); }
else {
// Data recovery block. I write it to all free locations within the group.
if (block->recsize!=(ulong)(pf->ngroup*NDATA))
return -1; // Invalid recovery scope
i=block->addr/block->recsize;
if (i*block->recsize!=block->addr)
return -1; // Invalid data alignment
i=block->addr/NDATA;
for (j=i; j<i+pf->ngroup; j++) {
if (j>=pf->nblock)
return -1; // Data outside the data size
if (pf->datavalid[j]!=0) continue;
memcpy(pf->data+j*NDATA,block->data,NDATA);
pf->datavalid[j]=2; }; // Valid recovery data
pf->minpageaddr=std::min(pf->minpageaddr,block->addr);
pf->maxpageaddr=std::max(pf->maxpageaddr,block->addr+block->recsize);
};
// Report success.
return 0;
};



// Processes gathered data. Returns -1 on error, 0 if file is complete and
// number of pages to scan if there is still missing data. In the last case,
// fills list of several first remaining pages in file descriptor.
int Finishpage(int ngood,int nbad,ulong nrestored) {
int i,j,r,rmin,rmax,nrec,irec,firstblock,nrempages;
uchar *pr,*pd;
t_fproc *pf;
pf=&fproc;
if (pf->busy==0)
return -1; // Index points to unused descriptor
// Update statistics. Note that it grows also when the same page is scanned
// repeatedly.
pf->goodblocks+=ngood;
pf->badblocks+=nbad;
pf->restoredbytes+=nrestored;
// Restore bad blocks if corresponding recovery blocks are available (max. 1
// per group).
if (pf->ngroup>0) {
rmin=(pf->minpageaddr/(NDATA*pf->ngroup))*pf->ngroup;
rmax=(pf->maxpageaddr/(NDATA*pf->ngroup))*pf->ngroup;
// Walk groups of data on current page, one by one.
for (r=rmin; r<=rmax; r+=pf->ngroup) {
if (r+pf->ngroup>pf->nblock)
break; // Inconsistent data
// Count blocks with recovery data in the group.
nrec=0;
for (i=r; i<r+pf->ngroup; i++) {
if (pf->datavalid[i]==2) {
nrec++; irec=i;
pf->datavalid[i]=0; // Prepare for next round
};
};
if (nrec==1) {
// Exactly one block in group is missing, recovery is possible.
pr=pf->data+irec*NDATA;
// Invert recovery data.
for (j=0; j<NDATA; j++) *pr++^=0xFF;
// XOR recovery data with good data blocks.
for (i=r; i<r+pf->ngroup; i++) {
if (i==irec) continue;
pr=pf->data+irec*NDATA;
pd=pf->data+i*NDATA;
for (j=0; j<NDATA; j++) {
*pr++^=*pd++;
};
};
pf->datavalid[irec]=1;
pf->recoveredblocks++;
pf->ndata++;
};
};
};
// Check whether there are still bad blocks on the page.
firstblock=(pf->page-1)*(pf->pagesize/NDATA);
for (j=firstblock; j<firstblock+pf->pagesize/NDATA && j<pf->nblock; j++) {
if (pf->datavalid[j]!=1) break; };
if (j<firstblock+pf->pagesize/NDATA && j<pf->nblock)
Message("Unrecoverable errors on page, please scan it again",0);
else if (nbad>0)
Message("Page processed, all bad blocks successfully restored",0);
else
Message("Page processed",0);
// Calculate list of (partially) incomplete pages.
nrempages=0;
if (pf->pagesize>0) {
for (i=0; i<pf->npages && nrempages<8; i++) {
firstblock=i*(pf->pagesize/NDATA);
for (j=firstblock; j<firstblock+pf->pagesize/NDATA && j<pf->nblock; j++) {
if (pf->datavalid[j]==1)
continue;
// Page incomplete.
pf->rempages[nrempages++]=i+1;
break;
};
};
};
if (nrempages<8)
pf->rempages[nrempages]=0;
//Updatefileinfo(slot,pf); //GUI
if (pf->ndata==pf->nblock) {
if (autosave==0)
Message("File restored. Press \"Save\" to save it to disk",0);
else {
Message("File complete",0);
Saverestoredfile(0);
};
};
return 0; ////////////////////////////////////////////////////////////////////
};



// Saves file with specified index and closes file descriptor (if force is 1,
// attempts to save data even if file is not yet complete). Returns 0 on
// success and -1 on error.
int Saverestoredfile(int force) {
int n,success;
ushort filecrc;
ulong l,length;
uchar *bufout,*data,*tempdata;
t_fproc *pf;
#ifdef _WIN32
HANDLE hfile;
#elif __linux__
std::string hfile;
#endif
pf=&fproc;
if (pf->busy==0 || pf->nblock==0)
return -1; // Index points to unused descriptor
if (pf->ndata!=pf->nblock && force==0)
return -1; // Still incomplete data
Message("",0);
//aes_context ctx;
// If data is encrypted, decrypt it to temporary buffer. Decryption in place
// is possible, but the whole data would be lost if password is incorrect.
/*if (pf->mode & PBM_ENCRYPTED) {
if (pf->datasize & 0x0000000F) {
Reporterror("Encrypted data is not aligned");
return -1; };
if (Getpassword()!=0)
return -1; // User cancelled decryption
tempdata=(uchar *)malloc(pf->datasize);
if (tempdata==NULL) {
Reporterror("Low memory, can't decrypt data");
return -1; };
n=strlen(password);
while (n<PASSLEN) password[n++]=0;
memset(&ctx,0,sizeof(ctx));
aes_set_key(&ctx,(uchar *)password,256);
for (l=0; l<pf->datasize; l+=16)
aes_decrypt(&ctx,pf->data+l,tempdata+l);
filecrc=Crc16(tempdata,pf->datasize);
if (filecrc!=pf->filecrc) {
Reporterror("Invalid password, please try again");
free(tempdata);
return -1; }
else {
free(pf->data);
pf->data=tempdata;
pf->mode&=~PBM_ENCRYPTED;
};
}; */
// If data is compressed, unpack it to temporary buffer.
//if ((pf->mode & PBM_COMPRESSED)==0) {
// Data is not compressed.
data=pf->data; length=pf->origsize;
bufout=NULL;
//}
/*else {
// Data is compressed. Create temporary buffer.
if (pf->origsize==0)
pf->origsize=pf->datasize*4; // Weak attempt to recover
bufout=(uchar *)malloc(pf->origsize);
if (bufout==NULL) {
Reporterror("Low memory");
return -1; };
// Unpack data.
length=pf->origsize;
success=BZ2_bzBuffToBuffDecompress((char *)bufout,(uint *)&length,
pf->data,pf->datasize,0,0);
if (success!=BZ_OK) {
free(bufout);
Reporterror("Unable to unpack data");
return -1; };
data=bufout; };
// Ask user for file name.
if (Selectoutfile(pf->name)!=0) { // Cancelled by user
if (bufout!=NULL) free(bufout);
return -1; };
*/

//!!! Need means of checking that output file name is valid

#ifdef _WIN32
// Open file and save data.
hfile=CreateFile(outfile,GENERIC_WRITE,0,NULL,
CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if (hfile==INVALID_HANDLE_VALUE) {
if (bufout!=NULL) free(bufout);
Reporterror("Unable to create file");
return -1; };
WriteFile(hfile,data,length,&l,NULL);
// Restore old modification date and time.
SetFileTime(hfile,&pf->modified,&pf->modified,&pf->modified);
// Close file and restore old basic attributes.
CloseHandle(hfile);
SetFileAttributes(outfile,pf->attributes);

#elif __linux__
// Open file and save data.
FILE * pFile;
pFile = fopen(hfile.c_str(), "wb");

if( pFile == NULL ) {
if (bufout!=NULL) {
free(bufout);
}
Reporterror("Unable to create file");
return -1;
}

int dataSize = 1;
l = fwrite(data, dataSize, length, pFile);

// Restore old modification date and time.
struct stat fileAttributes;
if( stat(hfile.c_str(), &fileAttributes) != 0 ) {
Reporterror("Stat failed on restored data file");
return -1;
}
pf->modified = fileAttributes.st_mtime;

// Close file and restore old basic attributes.
fclose(pFile);
//!!! is it necessary to save these?
//SetFileAttributes(outfile,pf->attributes);
#endif

if (bufout!=NULL) free(bufout);
if (l!=length) {
Reporterror("I/O error");
return -1; };
// Close file descriptor and report success.
Closefproc();
Message("File saved",0);
return 0;
};



// Converts file date and time into the text according to system defaults and
// places into the string s of length n. Returns number of characters in s.
#ifdef _WIN32
int Filetimetotext(FILETIME *fttime,char *s,int n) {
int l;
SYSTEMTIME sttime;
FileTimeToSystemTime(fttime,&sttime);
l=GetDateFormat(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&sttime,NULL,s,n);
s[l-1]=' '; // Yuck, that's Windows
l+=GetTimeFormat(LOCALE_USER_DEFAULT,TIME_NOSECONDS,&sttime,NULL,s+l,n-l);
return l;
};
#endif



+ 68
- 0
Fileproc.h View File

@@ -0,0 +1,68 @@
/*
* =====================================================================================
*
* Filename: Fileproc.h
*
* Description:
*
* Version: 1.2
* Created: 07/26/2017 05:32:51 AM
* Revision: none
* Compiler: gcc
*
* Author: Oleh Yuschuk
* Modified By: suhrke@teknik.io
*
* =====================================================================================
*/




#include <string>



typedef struct t_fproc { // Descriptor of processed file
int busy; // In work
// General file data.
char name[64]; // File name - may have all 64 chars
//FILETIME modified; // Time of last file modification
time_t modified;
ulong attributes; // Basic file attrributes
ulong datasize; // Size of (compressed) data
ulong pagesize; // Size of (compressed) data on page
ulong origsize; // Size of original (uncompressed) data
ulong mode; // Special mode bits, set of PBM_xxx
int npages; // Total number of pages
ulong filecrc; // 16-bit CRC of decrypted packed file
// Properties of currently processed page.
int page; // Currently processed page
int ngroup; // Actual NGROUP on the page
ulong minpageaddr; // Minimal address of block on page
ulong maxpageaddr; // Maximal address of block on page
// Gathered data.
int nblock; // Total number of data blocks
int ndata; // Number of decoded blocks so far
uchar *datavalid; // 0:data invalid, 1:valid, 2:recovery
uchar *data; // Gathered data
// Statistics.
int goodblocks; // Total number of good blocks read
int badblocks; // Total number of unreadable blocks
ulong restoredbytes; // Total number of bytes restored by ECC
int recoveredblocks; // Total number of recovered blocks
int rempages[8]; // 1-based list of remaining pages
} t_fproc;

//unique
t_fproc fproc; // Processed file

void Closefproc();
int Startnextpage(t_superblock *superblock);
int Addblock(t_block *block);
int Finishpage(int ngood,int nbad,ulong nrestored);
int Saverestoredfile(int force);
#ifdef _WIN32
int Filetimetotext(FILETIME *fttime,char *s,int n);
#endif


+ 1
- 0
Global.cpp View File

@@ -11,3 +11,4 @@ void Reporterror(const string &input) {
void Message(const string &input, int progress) {
cout << input << " @ " << progress << endl;
}


+ 15
- 11
Global.h View File

@@ -34,18 +34,22 @@ typedef unsigned long ulong;
#define TEXTLEN 256 // Maximal length of strings

#ifdef __WIN32
#define MAXPATH 247
#define MAXFILE 255
//!!! Find values for the following
#define MAXDIR 1
#define MAXEXT 3
#define MAXPATH 247 // max file path characters
#define MAXFILE 255 // max file name characters
#define MAXEXT 245 // max characters of file extension
// Assuming smaller capacity FAT32, not NTFS
#define MAXDIR 65534 // max files in a directory
#define MAXDRIVE 268173300

#elif __linux__
#define MAXPATH 4096
#define MAXFILE 255
//!!! Find values for the following
#define MAXDIR 1
#define MAXEXT 4094
#define MAXPATH 4096 // max file path characters
#define MAXFILE 255 // max file name characters
#define MAXEXT 4094 // max characters of file extension
// Performance issues in ext2 beyond 10000 files
#define MAXDIR 10000 // max files in a directory
// 10^18 in ext2 and more in later filesystems
// using max value of 32-bit int for compatibility
#define MAXDRIVE 2147483647
#endif

////////////////////////////////////////////////////////////////////////////////
@@ -148,4 +152,4 @@ int marginbottom; // Bottom printer page margin
void Options(void);

void Reporterror (std::string);
void Message (std::string);
void Message (std::string, int);

gpl.txt → LICENSE View File


+ 33
- 0
Resource.h View File

@@ -0,0 +1,33 @@
#define M_FILE_OPEN 1001
#define M_FILE_SAVEBMP 1002
#define M_FILE_SELECT 1003
#define M_FILE_ACQUIRE 1004
#define M_FILE_PAGE 1005
#define M_FILE_PRINT 1006
#define M_FILE_EXIT 1007

#define M_HELP_ABOUT 2001

#define ABOUT_TEXT 3001
#define ABOUT_OK IDOK
#define ABOUT_CANCEL IDCANCEL

#define OPT_DENSITY 3101
#define OPT_DOTSIZE 3102
#define OPT_COMPRESS 3103
#define OPT_REDUND 3104
#define OPT_HEADER 3106
#define OPT_BORDER 3107
#define OPT_AUTOSAVE 3108
#define OPT_HIQ 3109
#define OPT_ENCRYPT 3110
#define OPT_OPENTEXT 3111
#define OPT_OK IDOK
#define OPT_CANCEL IDCANCEL

#define PAS_TEXT 3201
#define PAS_ENTER 3202
#define PAS_CONFIRM 3203
#define PAS_OK IDOK
#define PAS_CANCEL IDCANCEL


Loading…
Cancel
Save