@@ -13,9 +13,10 @@ | |||
# executables | |||
paperback-cli | |||
*.out | |||
runtests | |||
# files from tools | |||
tags | |||
.swp | |||
.swo | |||
@@ -1,6 +1,3 @@ | |||
[submodule "source/cxxopts"] | |||
path = src/cxxopts | |||
url = https://github.com/jarro2783/cxxopts.git | |||
[submodule "src/PortLibCpp"] | |||
path = src/PortLibCpp | |||
url = https://git.teknik.io/suhrke/PortLibCpp.git | |||
[submodule "lib/PortLibC"] | |||
path = lib/PortLibC | |||
url = https://git.teknik.io/suhrke/PortLibC.git |
@@ -1,18 +1,17 @@ | |||
EX=paperback-cli | |||
SDIR=./src | |||
SDIR=src | |||
BZDIR=lib/BZLIB | |||
AESDIR=lib/AES | |||
CC=g++ | |||
PORTDIR=$(SDIR)/PortLibCpp/src | |||
CFLAGS=-std=c++11 -I"$(SDIR)" -I"$(PORTDIR)" -I"$(SDIR)/cxxopts/include" -I"$(SDIR)/AES" -I"$(SDIR)/BZLIB" | |||
PORTDIR=lib/PortLibC/src | |||
CFLAGS=-std=c++11 -I"include" -I"$(PORTDIR)" -I"lib/cxxopts/include" -I"lib/AES" -I"lib/BZLIB" | |||
all: main | |||
main: $(SDIR)/main.cpp $(SDIR)/Printer.cpp $(SDIR)/Scanner.cpp $(SDIR)/Fileproc.cpp $(SDIR)/Decoder.cpp $(SDIR)/Fileproc.cpp $(SDIR)/Crc16.cpp $(SDIR)/Ecc.cpp $(SDIR)/BZLIB/bz_lib.cpp $(SDIR)/BZLIB/bz_blocksort.cpp $(SDIR)/BZLIB/bz_compress.cpp $(SDIR)/BZLIB/bz_crctable.cpp $(SDIR)/BZLIB/bz_decompress.cpp $(SDIR)/BZLIB/bz_huffman.cpp $(SDIR)/BZLIB/bz_randtable.cpp $(SDIR)/AES/ae_aes.cpp $(PORTDIR)/FileAttributes.cpp #$(SDIR)/Decoder.cpp | |||
main: $(SDIR)/main.cpp $(SDIR)/Printer.cpp $(SDIR)/Scanner.cpp $(SDIR)/Fileproc.cpp $(SDIR)/Decoder.cpp $(SDIR)/Fileproc.cpp $(SDIR)/Crc16.cpp $(SDIR)/Ecc.cpp $(BZDIR)/bz_lib.cpp $(BZDIR)/bz_blocksort.cpp $(BZDIR)/bz_compress.cpp $(BZDIR)/bz_crctable.cpp $(BZDIR)/bz_decompress.cpp $(BZDIR)/bz_huffman.cpp $(BZDIR)/bz_randtable.cpp $(AESDIR)/ae_aes.cpp $(PORTDIR)/FileAttributes.c | |||
$(CC) $^ $(CFLAGS) -o $(EX) | |||
msys: $(SDIR)/main.cpp $(SDIR)/Printer.cpp $(SDIR)/Fileproc.cpp $(SDIR)/Decoder.cpp | |||
$(CC) $^ $(CFLAGS) -o $(EX) -mwin32 | |||
clean: | |||
rm $(EX) #*.o *.log | |||
rm $(EX) *.o *.log | |||
@@ -23,7 +23,7 @@ | |||
#endif | |||
#include "bzlib.h" | |||
#include "Bitmap.h" | |||
#include "FileAttributes.hpp" | |||
#include "FileAttributes.h" | |||
@@ -0,0 +1 @@ | |||
Subproject commit 8196bd4c38a255020ad53f1cca305fafe49dc1d6 |
@@ -38,7 +38,6 @@ | |||
#include <stdint.h> | |||
#include "bzlib.h" | |||
#include "aes.h" | |||
#include "FileAttributes.hpp" | |||
#include "paperbak.h" | |||
#include "Resource.h" |
@@ -1 +0,0 @@ | |||
Subproject commit 5ec94e2bfeaa1cf4c2f7e807697c923e3d8aeb14 |
@@ -38,7 +38,7 @@ | |||
#include "bzlib.h" | |||
#include "aes.h" | |||
#include "Bitmap.h" | |||
#include "FileAttributes.hpp" | |||
#include "FileAttributes.h" | |||
#include "paperbak.h" | |||
#include "Resource.h" | |||
@@ -221,9 +221,9 @@ static void Preparefiletoprint(t_printdata *print) | |||
return; | |||
} | |||
uint32_t mode = (uint32_t)fileInfo.st_mode; | |||
print->attributes = FileAttributes::convertToWindowsAttributes(mode); | |||
print->attributes = convertToWindowsAttributes(mode); | |||
// Get time of last file modification. | |||
print->modified = FileAttributes::convertToFileTime(fileInfo.st_mtime); | |||
print->modified = convertToFileTime(fileInfo.st_mtime); | |||
// Get original (uncompressed) file size. | |||
print->origsize = fileInfo.st_size; | |||
if (print->origsize==0 || print->origsize>MAXSIZE) { |
@@ -1 +0,0 @@ | |||
Subproject commit 5e9f8225982e9711b548c886fe6b477cdefd0fd4 |
@@ -240,6 +240,7 @@ int arguments(int ac, char **av) { | |||
is_ok = false; | |||
} else { | |||
strcpy (::pb_outfile, optarg); | |||
strcpy (::pb_outbmp, optarg); | |||
} | |||
break; | |||
case 'd': |
@@ -1,88 +0,0 @@ | |||
/* | |||
* ===================================================================================== | |||
* | |||
* Filename: Bitmap.h | |||
* | |||
* Description: Bitmap structs and defines | |||
* | |||
* Version: 1.0 | |||
* Created: 07/26/2017 09:38:18 PM | |||
* Revision: none | |||
* Compiler: gcc | |||
* | |||
* Author: suhrke@teknik.io | |||
* | |||
* ===================================================================================== | |||
*/ | |||
#ifndef BITMAP_H | |||
#define BITMAP_H | |||
#include <cstdint> | |||
#define BI_RGB 0 //bitmap value for uncompressed color data | |||
#define CHAR_BM 19778 | |||
//Padding specific to compiler - must account for padded bfType | |||
// and little-endian order when overlaying struct on buffer | |||
typedef struct OverlayBitmapFileHeader { | |||
uint16_t bfType = CHAR_BM; //filetype, must be 'BM' | |||
uint8_t bfSize0; | |||
uint8_t bfSize1; | |||
uint8_t bfSize2; | |||
uint8_t bfSize3; | |||
uint16_t bfReserved1 = 0; | |||
uint16_t bfReserved2 = 0; | |||
uint8_t bfOffBits0; | |||
uint8_t bfOffBits1; | |||
uint8_t bfOffBits2; | |||
uint8_t bfOffBits3; | |||
} OverlayBitmapFileHeader; | |||
typedef struct BITMAPFILEHEADER { | |||
uint16_t bfType = CHAR_BM;//filetype, must be 'BM' | |||
uint32_t bfSize; //size in bytes of bitmap file | |||
uint16_t bfReserved1 = 0; //unused, except to keep alignment | |||
uint16_t bfReserved2 = 0; //unused, except to keep alignment | |||
uint32_t bfOffBits; //offset in bytes from beginning of | |||
// BITMAPFILEHEADER to the bitmap bits | |||
} BITMAPFILEHEADER; | |||
typedef struct BITMAPINFOHEADER { | |||
uint32_t biSize; //# of bytes in struct | |||
int32_t biWidth; //width of bitmap in pixels | |||
int32_t biHeight; //height of bitmap in pixels | |||
uint16_t biPlanes = 1; //# of planes for target device | |||
uint16_t biBitCount; //bitmap, bits per pixel | |||
uint32_t biCompression; //bitmap, type of compression | |||
uint32_t biSizeImage; //size of image, in bytes | |||
// 0 if BI_RGB | |||
int32_t biXPelsPerMeter; //horizontal resolution of target device | |||
int32_t biYPelsPerMeter; //vertical resolution of target device | |||
uint32_t biClrUsed; //# of color indices in color table | |||
// if 0, bitmap uses max # of colors that | |||
// correspond to biBitCount | |||
uint32_t biClrImportant; //# of color indices required for displaying bitmap | |||
} BITMAPINFOHEADER; | |||
typedef struct RGBQUAD { | |||
unsigned char rgbBlue; | |||
unsigned char rgbGreen; | |||
unsigned char rgbRed; | |||
unsigned char rgbReserved = 0; | |||
} RGBQUAD; | |||
typedef struct BITMAPINFO { | |||
BITMAPINFOHEADER bmiHeader; | |||
RGBQUAD bmiColors[1]; | |||
} BITMAPINFO; | |||
#endif //BITMAP_H | |||
@@ -1,76 +0,0 @@ | |||
/* | |||
* ===================================================================================== | |||
* | |||
* Filename: Crc16.h | |||
* | |||
* Description: Cyclic redundancy checks for file integrity | |||
* | |||
* Version: 1.2 | |||
* Created: 07/26/2017 08:42:11 PM | |||
* Revision: none | |||
* Compiler: gcc | |||
* | |||
* Author: Oleh Yuschuk | |||
* Modified By: scuti@teknik.io | |||
* | |||
* ===================================================================================== | |||
*/ | |||
#ifndef CRC16_H | |||
#define CRC16_H | |||
//////////////////////////////////////////////////////////////////////////////// | |||
// // | |||
// Fast 16-bit CRC (CCITT version). // | |||
// // | |||
//////////////////////////////////////////////////////////////////////////////// | |||
const unsigned int crctab[256] = { | |||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, | |||
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, | |||
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, | |||
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, | |||
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, | |||
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, | |||
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, | |||
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, | |||
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, | |||
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, | |||
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, | |||
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, | |||
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, | |||
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, | |||
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, | |||
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, | |||
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, | |||
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, | |||
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, | |||
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, | |||
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, | |||
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, | |||
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, | |||
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, | |||
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, | |||
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, | |||
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, | |||
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, | |||
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, | |||
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, | |||
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, | |||
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 | |||
}; | |||
inline unsigned short Crc16(unsigned char *data,int length) { | |||
unsigned int crc; | |||
for (crc=0; length>0; length--) | |||
crc=((crc<<8)^crctab[((crc>>8)^(*data++))]) & 0xFFFF; | |||
return (unsigned short)crc; | |||
}; | |||
#endif //CRC16_H | |||
@@ -1,167 +0,0 @@ | |||
/* | |||
* ===================================================================================== | |||
* | |||
* Filename: Decoder.h | |||
* | |||
* Description: Decode paperbak data obtained from bitmap file | |||
* | |||
* Version: 1.2 | |||
* Created: 07/26/2017 05:43:57 AM | |||
* Revision: none | |||
* Compiler: gcc | |||
* | |||
* Author: Oleh Yuschuk | |||
* Modified By: suhrke@teknik.io | |||
* | |||
* ===================================================================================== | |||
*/ | |||
#ifndef DECODER_H | |||
#define DECODER_H | |||
#include <string> | |||
#include "Global.h" | |||
#define M_BEST 0x00000001 // Search for best possible quality | |||
typedef struct t_procdata { // Descriptor of processed data | |||
int step; // Next data processing step (0 - idle) | |||
int mode; // Set of M_xxx | |||
uchar *data; // Pointer to bitmap | |||
int sizex; // X bitmap size, pixels | |||
int sizey; // Y bitmap size, pixels | |||
int gridxmin; // Rought X grid limits, pixels | |||
int gridxmax; // Rought X grid limits, pixels | |||
int gridymin; // Rought Y grid limits, pixels | |||
int gridymax; // Rought Y grid limits, pixels | |||
int searchx0; // X grid search limits, pixels | |||
int searchx1; // X grid search limits, pixels | |||
int searchy0; // Y grid search limits, pixels | |||
int searchy1; // Y grid search limits, pixels | |||
int cmean; // Mean grid intensity (0..255) | |||
int cmin; // Minimal and maximal grid intensity | |||
int cmax; // Minimal and maximal grid intensity | |||
float sharpfactor; // Estimated sharpness correction factor | |||
float xpeak; // Base X grid line, pixels | |||
float xstep; // X grid step, pixels | |||
float xangle; // X tilt, radians | |||
float ypeak; // Base Y grid line, pixels | |||
float ystep; // Y grid step, pixels | |||
float yangle; // Y tilt, radians | |||
float blockborder; // Relative width of border around block | |||
int bufdx; // Dimensions of block buffers, pixels | |||
int bufdy; // Dimensions of block buffers, pixels | |||
uchar *buf1; // Rotated and sharpened block | |||
uchar *buf2; // Rotated and sharpened block | |||
int *bufx; // Block grid data finders | |||
int *bufy; // Block grid data finders | |||
uchar *unsharp; // Either buf1 or buf2 | |||
uchar *sharp; // Either buf1 or buf2 | |||
float blockxpeak; // Exact block position in unsharp | |||
float blockypeak; // Exact block position in unsharp | |||
float blockxstep; // Exact block dimensions in unsharp | |||
float blockystep; // Exact block dimensions in unsharp | |||
int nposx; // Number of blocks to scan in X | |||
int nposy; // Number of blocks to scan in X | |||
int posx; // Next block to scan | |||
int posy; // Next block to scan | |||
t_data uncorrected; // Data before ECC for block display | |||
t_block *blocklist; // List of blocks recognized on page | |||
t_superblock superblock; // Page header | |||
int maxdotsize; // Maximal size of the data dot, pixels | |||
int orientation; // Data orientation (-1: unknown) | |||
int ngood; // Page statistics: good blocks | |||
int nbad; // Page statistics: bad blocks | |||
int nsuper; // Page statistics: good superblocks | |||
int nrestored; // Page statistics: restored bytes | |||
} t_procdata; | |||
inline void print_procdata(t_procdata &pd) { | |||
using namespace std; | |||
cout << "==============================================================================" << endl; | |||
cout << "step: " << pd.step << endl; | |||
cout << "mode: " << pd.mode << endl; | |||
cout << "*data: " << *pd.data << endl; | |||
cout << "sizex: " << pd.sizex << endl; | |||
cout << "sizey: " << pd.sizey << endl; | |||
cout << "gridxmin: " << pd.gridxmin << endl; | |||
cout << "gridxmax: " << pd.gridxmax << endl; | |||
cout << "gridymin: " << pd.gridymin << endl; | |||
cout << "gridymax: " << pd.gridymax << endl; | |||
cout << "searchx0: " << pd.searchx0 << endl; | |||
cout << "searchx1: " << pd.searchx1 << endl; | |||
cout << "searchy0: " << pd.searchy0 << endl; | |||
cout << "searchy1: " << pd.searchy1 << endl; | |||
cout << "cmean: " << pd.cmean << endl; | |||
cout << "cmin: " << pd.cmin << endl; | |||
cout << "cmax: " << pd.cmax << endl; | |||
cout << "sharpfactor: " << pd.sharpfactor << endl; | |||
cout << "xpeak: " << pd.xpeak << endl; | |||
cout << "xstep: " << pd.xstep << endl; | |||
cout << "xangle: " << pd.xangle << endl; | |||
cout << "ypeak: " << pd.ypeak << endl; | |||
cout << "ystep: " << pd.ystep << endl; | |||
cout << "yangle: " << pd.yangle << endl; | |||
cout << "blockborder: " << pd.blockborder << endl; | |||
cout << "bufdx: " << pd.bufdx << endl; | |||
cout << "bufdy: " << pd.bufdy << endl; | |||
cout << "*buf1: " << *pd.buf1 << endl; | |||
cout << "*buf2: " << *pd.buf2 << endl; | |||
cout << "*bufx: " << *pd.bufx << endl; | |||
cout << "*bufy: " << *pd.bufy << endl; | |||
if( pd.unsharp == NULL ) | |||
cout << "*unsharp is NULL " << endl; | |||
else | |||
cout << "*unsharp: " << *pd.unsharp << endl; | |||
if( pd.sharp == NULL ) | |||
cout << "*sharp is NULL" << endl; | |||
else | |||
cout << "*sharp: " << *pd.sharp << endl; | |||
cout << "blockxpeak: " << pd.blockxpeak << endl; | |||
cout << "blockypeak: " << pd.blockypeak << endl; | |||
cout << "blockxstep: " << pd.blockxstep << endl; | |||
cout << "blockystep: " << pd.blockystep << endl; | |||
cout << "nposx: " << pd.nposx << endl; | |||
cout << "nposy: " << pd.nposy << endl; | |||
cout << "posx: " << pd.posx << endl; | |||
cout << "posy: " << pd.posy << endl; | |||
print_data(pd.uncorrected); | |||
cout << "*blocklist is non-NULL: " << (pd.blocklist!=0) << endl; | |||
print_superblock(pd.superblock); | |||
cout << "maxdotsize: " << pd.maxdotsize << endl; | |||
cout << "orientation: " << pd.orientation << endl; | |||
cout << "ngood: " << pd.ngood << endl; | |||
cout << "nbad: " << pd.nbad << endl; | |||
cout << "nsuper: " << pd.nsuper << endl; | |||
cout << "nrestored: " << pd.nrestored << endl; | |||
cout << "==============================================================================" << endl; | |||
} | |||
//unique | |||
extern int orientation; // Orientation of bitmap (-1: unknown) | |||
//unique | |||
extern t_procdata procdata; // Descriptor of processed data | |||
//void Nextdataprocessingstep(t_procdata *pdata); | |||
int Decodebitmap(const std::string &fileName); | |||
int Getgridposition(t_procdata *pdata); | |||
int Getgridintensity(t_procdata *pdata); | |||
int Getxangle(t_procdata *pdata); | |||
int Getyangle(t_procdata *pdata); | |||
void Preparefordecoding(t_procdata *pdata); | |||
void Decodenextblock(t_procdata *pdata); | |||
void Finishdecoding(t_procdata *pdata); | |||
void Freeprocdata(t_procdata *pdata); | |||
void Startbitmapdecoding(t_procdata *pdata,uchar *data,int sizex,int sizey); | |||
void Stopbitmapdecoding(t_procdata *pdata); | |||
int Decodeblock(t_procdata *pdata,int posx,int posy,t_data *result); | |||
int ProcessDIB(void *hdata,int offset); | |||
#endif //DECODER_H | |||
@@ -1,260 +0,0 @@ | |||
/* | |||
* ===================================================================================== | |||
* | |||
* Filename: Ecc.h | |||
* | |||
* Description: Reed-Solomon error correcting code data and functions | |||
* | |||
* Version: 1.2 | |||
* Created: 07/26/2017 08:42:39 PM | |||
* Revision: none | |||
* Compiler: gcc | |||
* | |||
* Author: Oleh Yuschuk | |||
* Modified By: scuti@teknik.io | |||
* | |||
* ===================================================================================== | |||
*/ | |||
#ifndef ECC_H | |||
#define ECC_H | |||
#include <string> | |||
typedef unsigned char uchar; | |||
typedef unsigned int uint; | |||
const uchar alpha[] = { | |||
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, | |||
0x87, 0x89, 0x95, 0xad, 0xdd, 0x3d, 0x7a, 0xf4, | |||
0x6f, 0xde, 0x3b, 0x76, 0xec, 0x5f, 0xbe, 0xfb, | |||
0x71, 0xe2, 0x43, 0x86, 0x8b, 0x91, 0xa5, 0xcd, | |||
0x1d, 0x3a, 0x74, 0xe8, 0x57, 0xae, 0xdb, 0x31, | |||
0x62, 0xc4, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, 0x67, | |||
0xce, 0x1b, 0x36, 0x6c, 0xd8, 0x37, 0x6e, 0xdc, | |||
0x3f, 0x7e, 0xfc, 0x7f, 0xfe, 0x7b, 0xf6, 0x6b, | |||
0xd6, 0x2b, 0x56, 0xac, 0xdf, 0x39, 0x72, 0xe4, | |||
0x4f, 0x9e, 0xbb, 0xf1, 0x65, 0xca, 0x13, 0x26, | |||
0x4c, 0x98, 0xb7, 0xe9, 0x55, 0xaa, 0xd3, 0x21, | |||
0x42, 0x84, 0x8f, 0x99, 0xb5, 0xed, 0x5d, 0xba, | |||
0xf3, 0x61, 0xc2, 0x03, 0x06, 0x0c, 0x18, 0x30, | |||
0x60, 0xc0, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, | |||
0x47, 0x8e, 0x9b, 0xb1, 0xe5, 0x4d, 0x9a, 0xb3, | |||
0xe1, 0x45, 0x8a, 0x93, 0xa1, 0xc5, 0x0d, 0x1a, | |||
0x34, 0x68, 0xd0, 0x27, 0x4e, 0x9c, 0xbf, 0xf9, | |||
0x75, 0xea, 0x53, 0xa6, 0xcb, 0x11, 0x22, 0x44, | |||
0x88, 0x97, 0xa9, 0xd5, 0x2d, 0x5a, 0xb4, 0xef, | |||
0x59, 0xb2, 0xe3, 0x41, 0x82, 0x83, 0x81, 0x85, | |||
0x8d, 0x9d, 0xbd, 0xfd, 0x7d, 0xfa, 0x73, 0xe6, | |||
0x4b, 0x96, 0xab, 0xd1, 0x25, 0x4a, 0x94, 0xaf, | |||
0xd9, 0x35, 0x6a, 0xd4, 0x2f, 0x5e, 0xbc, 0xff, | |||
0x79, 0xf2, 0x63, 0xc6, 0x0b, 0x16, 0x2c, 0x58, | |||
0xb0, 0xe7, 0x49, 0x92, 0xa3, 0xc1, 0x05, 0x0a, | |||
0x14, 0x28, 0x50, 0xa0, 0xc7, 0x09, 0x12, 0x24, | |||
0x48, 0x90, 0xa7, 0xc9, 0x15, 0x2a, 0x54, 0xa8, | |||
0xd7, 0x29, 0x52, 0xa4, 0xcf, 0x19, 0x32, 0x64, | |||
0xc8, 0x17, 0x2e, 0x5c, 0xb8, 0xf7, 0x69, 0xd2, | |||
0x23, 0x46, 0x8c, 0x9f, 0xb9, 0xf5, 0x6d, 0xda, | |||
0x33, 0x66, 0xcc, 0x1f, 0x3e, 0x7c, 0xf8, 0x77, | |||
0xee, 0x5b, 0xb6, 0xeb, 0x51, 0xa2, 0xc3, 0x00 | |||
}; | |||
const uchar _index[] = { | |||
255, 0, 1, 99, 2, 198, 100, 106, | |||
3, 205, 199, 188, 101, 126, 107, 42, | |||
4, 141, 206, 78, 200, 212, 189, 225, | |||
102, 221, 127, 49, 108, 32, 43, 243, | |||
5, 87, 142, 232, 207, 172, 79, 131, | |||
201, 217, 213, 65, 190, 148, 226, 180, | |||
103, 39, 222, 240, 128, 177, 50, 53, | |||
109, 69, 33, 18, 44, 13, 244, 56, | |||
6, 155, 88, 26, 143, 121, 233, 112, | |||
208, 194, 173, 168, 80, 117, 132, 72, | |||
202, 252, 218, 138, 214, 84, 66, 36, | |||
191, 152, 149, 249, 227, 94, 181, 21, | |||
104, 97, 40, 186, 223, 76, 241, 47, | |||
129, 230, 178, 63, 51, 238, 54, 16, | |||
110, 24, 70, 166, 34, 136, 19, 247, | |||
45, 184, 14, 61, 245, 164, 57, 59, | |||
7, 158, 156, 157, 89, 159, 27, 8, | |||
144, 9, 122, 28, 234, 160, 113, 90, | |||
209, 29, 195, 123, 174, 10, 169, 145, | |||
81, 91, 118, 114, 133, 161, 73, 235, | |||
203, 124, 253, 196, 219, 30, 139, 210, | |||
215, 146, 85, 170, 67, 11, 37, 175, | |||
192, 115, 153, 119, 150, 92, 250, 82, | |||
228, 236, 95, 74, 182, 162, 22, 134, | |||
105, 197, 98, 254, 41, 125, 187, 204, | |||
224, 211, 77, 140, 242, 31, 48, 220, | |||
130, 171, 231, 86, 179, 147, 64, 216, | |||
52, 176, 239, 38, 55, 12, 17, 68, | |||
111, 120, 25, 154, 71, 116, 167, 193, | |||
35, 83, 137, 251, 20, 93, 248, 151, | |||
46, 75, 185, 96, 15, 237, 62, 229, | |||
246, 135, 165, 23, 58, 163, 60, 183 | |||
}; | |||
const uchar poly[] = { | |||
0, 249, 59, 66, 4, 43, 126, 251, | |||
97, 30, 3, 213, 50, 66, 170, 5, | |||
24, 5, 170, 66, 50, 213, 3, 30, | |||
97, 251, 126, 43, 4, 66, 59, 249, | |||
0 | |||
}; | |||
inline void Encode8(uchar *data,uchar *bb,int pad) { | |||
int i,j; | |||
uchar feedback; | |||
memset(bb,0,32); | |||
for (i=0; i<223-pad; i++) { | |||
feedback=_index[data[i]^bb[0]]; | |||
if (feedback!=255) { | |||
for (j=1; j<32; j++) { | |||
bb[j]^=alpha[(feedback+poly[32-j])%255]; | |||
}; | |||
}; | |||
memmove(bb,bb+1,31); | |||
if (feedback!=255) | |||
bb[31]=alpha[(feedback+poly[0])%255]; | |||
else | |||
bb[31]=0; | |||
; | |||
}; | |||
}; | |||
inline int Decode8(uchar *data,int *eras_pos,int no_eras,int pad) { | |||
int i,j,r,k,deg_lambda,el,deg_omega; | |||
int syn_error,count; | |||
uchar u,q,tmp,num1,num2,den,discr_r; | |||
uchar lambda[33],s[32],b[33],t[33],omega[33]; | |||
uchar root[32],reg[33],loc[32]; | |||
for (i=0; i<32; i++) | |||
s[i]=data[0]; | |||
for (j=1; j<255-pad; j++) { | |||
for (i=0; i<32; i++) { | |||
if (s[i]==0) | |||
s[i]=data[j]; | |||
else | |||
s[i]=data[j]^alpha[(_index[s[i]]+(112+i)*11)%255]; | |||
; | |||
}; | |||
}; | |||
syn_error=0; | |||
for (i=0; i<32; i++) { | |||
syn_error|=s[i]; | |||
s[i]=_index[s[i]]; }; | |||
if (syn_error==0) { | |||
count=0; goto finish; }; | |||
memset(lambda+1,0,32); | |||
lambda[0]=1; | |||
if (no_eras>0) { | |||
lambda[1]=alpha[(11*(254-eras_pos[0]))%255]; | |||
for (i=1; i<no_eras; i++) { | |||
u=(uchar)((11*(254-eras_pos[i]))%255); | |||
for (j=i+1; j>0; j--) { | |||
tmp=_index[lambda[j-1]]; | |||
if (tmp!=255) lambda[j]^=alpha[(u+tmp)%255]; | |||
}; | |||
}; | |||
}; | |||
for (i=0; i<33; i++) | |||
b[i]=_index[lambda[i]]; | |||
r=el=no_eras; | |||
while (++r<=32) { | |||
discr_r=0; | |||
for (i=0; i<r; i++) { | |||
if ((lambda[i]!=0) && (s[r-i-1]!=255)) { | |||
discr_r^=alpha[(_index[lambda[i]]+s[r-i-1])%255]; | |||
}; | |||
}; | |||
discr_r=_index[discr_r]; | |||
if (discr_r==255) { | |||
memmove(b+1,b,32); | |||
b[0]=255; } | |||
else { | |||
t[0]=lambda[0]; | |||
for (i=0; i<32; i++) { | |||
if (b[i]!=255) | |||
t[i+1]=lambda[i+1]^alpha[(discr_r+b[i])%255]; | |||
else | |||
t[i+1]=lambda[i+1]; | |||
; | |||
}; | |||
if (2*el<=r+no_eras-1) { | |||
el=r+no_eras-el; | |||
for (i=0; i<=32; i++) | |||
b[i]=(uchar)(lambda[i]==0?255:(_index[lambda[i]]-discr_r+255)%255); | |||
; } | |||
else { | |||
memmove(b+1,b,32); | |||
b[0]=255; }; | |||
memcpy(lambda,t,33); | |||
}; | |||
}; | |||
deg_lambda=0; | |||
for (i=0; i<33; i++) { | |||
lambda[i]=_index[lambda[i]]; | |||
if (lambda[i]!=255) deg_lambda=i; }; | |||
memcpy(reg+1,lambda+1,32); | |||
count=0; | |||
for (i=1,k=115; i<=255; i++,k=(k+116)%255) { | |||
q=1; | |||
for (j=deg_lambda; j>0; j--) { | |||
if (reg[j]!=255) { | |||
reg[j]=(uchar)((reg[j]+j)%255); | |||
q^=alpha[reg[j]]; | |||
}; | |||
}; | |||
if (q!=0) continue; | |||
root[count]=(uchar)i; | |||
loc[count]=(uchar)k; | |||
if (++count==deg_lambda) break; | |||
}; | |||
if (deg_lambda!=count) { | |||
count=-1; | |||
goto finish; }; | |||
deg_omega=deg_lambda-1; | |||
for (i=0; i<=deg_omega; i++ ) { | |||
tmp=0; | |||
for (j=i; j>=0; j--) { | |||
if ((s[i-j]!=255) && (lambda[j]!=255)) { | |||
tmp^=alpha[(s[i-j]+lambda[j])%255]; | |||
}; | |||
}; | |||
omega[i]=_index[tmp]; | |||
}; | |||
for (j=count-1; j>=0; j--) { | |||
num1=0; | |||
for (i=deg_omega; i>=0; i--) { | |||
if (omega[i]!=255) { | |||
num1^=alpha[(omega[i]+i*root[j])%255]; | |||
}; | |||
}; | |||
num2=alpha[(root[j]*111+255)%255]; | |||
den=0; | |||
for (i=(deg_lambda<31?deg_lambda:31) & ~1; i>=0; i-=2) { | |||
if (lambda[i+1]!=255) { | |||
den^=alpha[(lambda[i+1]+i*root[j])%255]; | |||
}; | |||
}; | |||
if (num1!=0 && loc[j]>=pad) { | |||
data[loc[j]-pad]^=alpha[(_index[num1]+_index[num2]+255-_index[den])%255]; | |||
}; | |||
}; | |||
finish: | |||
if (eras_pos!=NULL) { | |||
for (i=0; i<count; i++) eras_pos[i]=loc[i]; }; | |||
return count; | |||
}; | |||
#endif //ECC_H | |||
@@ -1,430 +0,0 @@ | |||
//////////////////////////////////////////////////////////////////////////////// | |||
// // | |||
// 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. // | |||
// // | |||
//////////////////////////////////////////////////////////////////////////////// | |||
#include <algorithm> | |||
#include <cstring> | |||
#include <math.h> | |||
#include "Fileproc.h" | |||
#include "Resource.h" | |||
#ifdef _WIN32 | |||
#include <windows.h> | |||
#elif __linux__ | |||
#include <cstdio> | |||
#include <sys/stat.h> | |||
#endif | |||
t_fproc fproc; // extern | |||
char outfile[MAXPATH]; | |||
// 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 tmp = {}; | |||
t_fproc *pf = &tmp; | |||
// 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); | |||
}; | |||
};*/ | |||
if (pf->ndata != pf->nblock) { | |||
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 length; | |||
uchar *bufout,*data,*tempdata; | |||
t_fproc *pf; | |||
#ifdef _WIN32 | |||
HANDLE hfile; | |||
uint l; | |||
#elif __linux__ | |||
std::string hfile; | |||
ulong l; | |||
#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) GlobalFree((HGLOBAL)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); | |||
#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); | |||
#endif | |||
//!!! is it necessary to save file attributes? | |||
//SetFileAttributes(outfile,pf->attributes); | |||
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; | |||
}; | |||
@@ -1,75 +0,0 @@ | |||
/* | |||
* ===================================================================================== | |||
* | |||
* 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 | |||
* | |||
* ===================================================================================== | |||
*/ | |||
#ifndef FILEPROC_H | |||
#define FILEPROC_H | |||
#include <string> | |||
#include "Global.h" | |||
#ifdef _WIN32 | |||
#include <windows.h> | |||
#endif | |||
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 | |||
#ifdef _WIN32 | |||
FILETIME modified; // Time of last file modification | |||
#elif __linux__ | |||
time_t modified; // Time of last file modification | |||
#endif | |||
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 | |||
extern 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); | |||
#endif //FILEPROC_H | |||
@@ -1,354 +0,0 @@ | |||
/* | |||
* ===================================================================================== | |||
* | |||
* Filename: Global.h | |||
* | |||
* Description: As paperback was designed around global memory management, some | |||
* must remain global until serious refactoring | |||
* | |||
* Version: 1.2 | |||
* Created: 07/25/2017 09:23:02 AM | |||
* Revision: none | |||
* Compiler: gcc | |||
* | |||
* Author: Oleh Yuschuk | |||
* Modified By: suhrke@teknik.io | |||
* | |||
* ===================================================================================== | |||
*/ | |||
#ifndef GLOBAL_H | |||
#define GLOBAL_H | |||
#include <ctime> | |||
#include <iostream> | |||
#include <string> | |||
#ifdef __WIN32 | |||
#include <windows.h> | |||
#endif | |||
//////////////////////////////////////////////////////////////////////////////// | |||
///////////////////////////// GENERAL DEFINITIONS ////////////////////////////// | |||
typedef unsigned char uchar; | |||
typedef unsigned short ushort; | |||
typedef unsigned int uint; | |||
typedef unsigned long ulong; | |||
#define TEXTLEN 256 // Maximal length of strings | |||
//////////////////////////////////////////////////////////////////////////////// | |||
/////////////////////////////// DATA PROPERTIES //////////////////////////////// | |||
// Don't change the definitions below! Program may crash if any modified! | |||
#define NDOT 32 // Block X and Y size, dots | |||
#define NDATA 90 // Number of data bytes in a block | |||
#define MAXSIZE 0x0FFFFF80 // Maximal (theoretical) length of file | |||
#define SUPERBLOCK 0xFFFFFFFF // Address of superblock | |||
#define NGROUP 5 // For NGROUP blocks (1..15), 1 recovery | |||
#define NGROUPMIN 2 | |||
#define NGROUPMAX 10 | |||
//Values set by Borland compiler | |||
#define MAXPATH 80 | |||
#define MAXFILE 9 | |||
#define MAXEXT 5 | |||
#define MAXDIR 66 | |||
#define MAXDRIVE 3 | |||
// Size required by Reed-Solomon ECC | |||
#define ECC_SIZE 32 | |||
// Oleh's magic numbers | |||
#define FILENAME_SIZE 64 | |||
typedef struct __attribute__ ((packed)) t_data { // Block on paper | |||
uint32_t addr; // Offset of the block or special code | |||
uchar data[NDATA]; // Useful data | |||
uint16_t crc; // Cyclic redundancy of addr and data | |||
uchar ecc[32]; // Reed-Solomon's error correction code | |||
} t_data; | |||
//static_assert(sizeof(t_data)==128); | |||
#define PBM_COMPRESSED 0x01 // Paper backup is compressed | |||
#define PBM_ENCRYPTED 0x02 // Paper backup is encrypted | |||
// FILETIME is 64-bit data type, time_t typically 64-bit, but was 32-bit in | |||
// older *NIX versions. Assertion failure is likely due to this. 128 bytes | |||
// is necessary for ECC to work properly (and multiples of 16 for CRC) | |||
typedef struct __attribute__ ((packed)) t_superdata { // Identification block on paper | |||
uint32_t addr; // Expecting SUPERBLOCK | |||
uint32_t datasize; // Size of (compressed) data | |||
uint32_t pagesize; // Size of (compressed) data on page | |||
uint32_t origsize; // Size of original (uncompressed) data | |||
uchar mode; // Special mode bits, set of PBM_xxx | |||
uchar attributes; // Basic file attributes | |||
uint16_t page; // Actual page (1-based) | |||
#ifdef _WIN32 | |||
FILETIME modified; // Time of last file modification | |||
#elif __linux__ | |||
time_t modified; | |||
#endif | |||
uint16_t filecrc; // CRC of compressed decrypted file | |||
char name[FILENAME_SIZE]; // MULTIUSE; file name, salt, iv | |||
uint16_t crc; // Cyclic redundancy of previous fields | |||
uchar ecc[ECC_SIZE]; // Reed-Solomon's error correction code | |||
} t_superdata; | |||
//static_assert(sizeof(t_superdata)==sizeof(t_data)); | |||
typedef struct t_block { // Block in memory | |||
ulong addr; // Offset of the block | |||
ulong recsize; // 0 for data, or length of covered data | |||
uchar data[NDATA]; // Useful data | |||
} t_block; | |||
typedef struct t_superblock { // Identification block in memory | |||
ulong addr; // Expecting SUPERBLOCK | |||
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 | |||
ushort page; // Actual page (1-based) | |||
#ifdef _WIN32 | |||
FILETIME modified; // Time of last file modification | |||
#elif __linux__ | |||
time_t modified; | |||
#endif | |||
ulong attributes; // Basic file attributes | |||
ulong filecrc; // 16-bit CRC of decrypted packed file | |||
char name[FILENAME_SIZE]; // MULTIUSE; file name, salt, iv | |||
int ngroup; // Actual NGROUP on the page | |||
} t_superblock; | |||
//////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////// OPTIONS /////////////////////////////// | |||
// All unique | |||
extern char infile[MAXPATH]; // Last selected file to read | |||
extern char outbmp[MAXPATH]; // Last selected bitmap to save | |||
extern char inbmp[MAXPATH]; // Last selected bitmap to read | |||
extern char outfile[MAXPATH]; // Last selected data file to save | |||
// All unique | |||
extern int dpi; // Dot raster, dots per inch | |||
extern int dotpercent; // Dot size, percent of dpi | |||
extern int redundancy; // Redundancy (NGROUPMIN..NGROUPMAX) | |||
extern int printheader; // Print header and footer | |||
extern int printborder; // Border around bitmap | |||
extern int autosave; // Autosave completed files | |||
extern int bestquality; // Determine best quality | |||
// All unique | |||
extern int marginunits; // 0:undef, 1:inches, 2:millimeters | |||
extern int marginleft; // Left printer page margin | |||
extern int marginright; // Right printer page margin | |||
extern int margintop; // Top printer page margin | |||
extern int marginbottom; // Bottom printer page margin | |||
//void Options(void); | |||
inline void Reporterror(const std::string &input) { | |||
std::cerr << input << std::endl; | |||
} | |||
inline void Message(const std::string &input, int progress) { | |||
std::cout << input << " @ " << progress << "%" << std::endl; | |||
} | |||
// 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 | |||
inline 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; | |||
}; | |||
inline void print_filetime(FILETIME ftime) { | |||
char str[30]; | |||
int ok = Filetimetotext(&ftime, str, 30); | |||
if (ok) { | |||
std::cout << str << std::endl; | |||
} | |||
} | |||
#endif | |||
// Portable version of Borlands fnsplit | |||
// NOTE: Does not handle wildcard * | |||
// NOTE: does not return bitvector showing what components were found | |||
inline int fnsplit(const char *path, | |||
char *drive, | |||
char *dir, | |||
char *name, | |||
char *ext, | |||
int pathLen) | |||
{ | |||
int i = 0; // for loop iterator set after drive letter, if needed | |||
if (path != NULL && pathLen > 2 && path[1] == ':') { | |||
if (drive != NULL) | |||
strncat (drive, path, 2); | |||
i = 2; | |||
} | |||
// path not necessarily terminated by \0 | |||
// parse char by char | |||
char token[pathLen]; | |||
int iToken = 0; | |||
bool hasName = false; | |||
for ( ; i < pathLen; i++) { | |||
// if delimiter, act accordingly | |||
// token is part of the directory | |||
if (path[i] == '/' || path[i] == '\\') { | |||
token[iToken++] = path[i]; | |||
token[iToken++] = '\0'; | |||
if (dir != NULL) | |||
strcat (dir, token); | |||
iToken = 0; | |||
continue; | |||
} | |||
// token is name | |||
else if (path[i] == '.') { | |||
hasName = true; | |||
token[iToken] = '\0'; | |||
if (name != NULL) | |||
strcat (name, token); | |||
iToken = 0; | |||
continue; | |||
} | |||
// token is name or extension | |||
else if (path[i] == '\0' || i >= pathLen - 1 ) { | |||
if (hasName) { | |||
// is extension | |||
token[iToken] = '\0'; | |||
if (ext != NULL) | |||
strcat (ext, token); | |||
// all parts gathered, exit function | |||
break; | |||
} | |||
else { | |||
// is name | |||
token[i] = '\0'; | |||
if (name != NULL) | |||
strcat (name, token); | |||
// all parts gathered, exit | |||
break; | |||
} | |||
} | |||
else { | |||
//if not delimiter, build string | |||
token[iToken++] = path[i]; | |||
} | |||
} | |||
return 0; | |||
} | |||
// Portable version of Borlands fnmerge | |||
inline void fnmerge (char *path, | |||
const char *drive, | |||
const char *dir, | |||
const char *name, | |||
const char * ext) | |||
{ | |||
if (path == NULL) { | |||
return; | |||
} | |||
if (drive != NULL) { | |||
strncat (path, drive, strlen(drive)); | |||
} | |||
if (dir != NULL) { | |||
strncat (path, dir, strlen(dir)); | |||
} | |||
if (name != NULL) { | |||
strncat (path, name, strlen(name)); | |||
} | |||
if (ext != NULL && (strlen(path) + 2) < FILENAME_SIZE) { | |||
path[strlen(path)] = '.'; | |||
path[ strlen(path) + 1 ] = '\0'; | |||
strncat (path, ext, strlen(ext)); | |||
} | |||
} | |||
inline void print_data(t_data &x) { | |||
std::cout | |||
<< "addr: " << x.addr | |||
<< " data: " << x.data | |||
<< " crc: " << x.crc | |||
<< " ecc: " << x.ecc | |||
<< std::endl; | |||
} | |||
//prints because debugging is not so effective with giant structs | |||
inline void print_superblock(t_superblock &x) { | |||
std::cout | |||
<< "addr: " << x.addr | |||
<< " datasize: " << x.datasize | |||
<< " pagesize: " << x.pagesize | |||
<< " origsize: " << x.origsize | |||
<< " mode: " << x.mode | |||
<< " page: " << x.page; | |||
#ifdef _WIN32 | |||
print_filetime(x.modified); | |||
std::cout | |||
#elif __linux__ | |||
std::cout | |||
<< " modified: " << x.attributes | |||
#endif | |||
<< " attributes: " << x.attributes | |||
<< " filecrc: " << x.filecrc | |||
<< " name: " << x.name | |||
<< " ngroup: " << x.ngroup | |||
<< std::endl; | |||
} | |||
inline void print_superdata(t_superdata &x) { | |||
std::cout | |||
<< "addr: " << x.addr | |||
<< " datasize: " << x.datasize | |||
<< " pagesize: " << x.pagesize | |||
<< " origsize: " << x.origsize | |||
<< " mode: " << x.mode | |||
<< " attributes: " << x.attributes | |||
<< " page: " << x.page; | |||
#ifdef _WIN32 | |||
print_filetime(x.modified); | |||
std::cout | |||
#elif __linux | |||
std::cout | |||
<< " modified: " << x.attributes | |||
#endif | |||
<< " filecrc: " << x.filecrc | |||
<< " name: " << x.name | |||
<< " crc: " << x.crc | |||
<< " ecc: " << x.ecc | |||
<< std::endl; | |||
} | |||
#endif //GLOBAL_H | |||
@@ -1,872 +0,0 @@ | |||
/* | |||
* ===================================================================================== | |||
* | |||
* Filename: Printer.cpp | |||
* | |||
* Description: Functions to create a bitmap | |||
* | |||
* Version: 1.2 | |||
* Created: 07/26/2017 11:43:54 PM | |||
* Revision: none | |||
* Compiler: gcc | |||
* | |||
* Author: Oleh Yuschuk | |||
* Modified By: scuti@teknik.io | |||
* surhke@teknik.io | |||
* | |||
* ===================================================================================== | |||
*/ | |||
#include <algorithm> | |||
#include <cmath> | |||
#include <cstdio> | |||
#include <iostream> | |||
#include <time.h> | |||
#include "Printer.h" | |||
#include "Crc16.h" | |||
#include "Ecc.h" | |||
#ifdef _WIN32 | |||
#define OverlayBitmapFileHeader BITMAPFILEHEADER | |||
#endif | |||
// command line program is stripped down to only | |||
// output bitmap files thus a lot of printer functions are unnecessary | |||
// externs/global that were causing linker and all other errors | |||
int dpi; // Dot raster, dots per inch | |||
int dotpercent; // Dot size, percent of dpi | |||
int resx,resy; // Printer resolution, dpi (may be 0!) | |||
int redundancy; // Redundancy (NGROUPMIN..NGROUPMAX) | |||
int printheader; // Print header and footer | |||
int printborder; // Border around bitmap | |||
t_printdata printdata; // extern | |||
// Sends specified file to printer (bmp=NULL) or to bitmap file. | |||
t_printdata Printfile(const std::string &path, const std::string &bmp) | |||
{ | |||
// Prepare descriptor. | |||
// memset(&printdata,0,sizeof(printdata)); | |||
t_printdata printdata = {}; | |||
printdata.infile = path; | |||
if ( bmp.length() > 0 ) { | |||
printdata.outbmp = bmp; | |||
} | |||
// Start printing. | |||
printdata.step=1; | |||
// Updatebuttons(); | |||
return printdata; | |||
}; | |||
// Service function, puts block of data to bitmap as a grid of 32x32 dots in | |||
// the position with given index. Bitmap is treated as a continuous line of | |||
// cells, where end of the line is connected to the start of the next line. | |||
static void Drawblock(int index,t_data *block,uchar *bits,int width,int height, | |||
int border,int nx,int ny,int dx,int dy,int px,int py,int black | |||
) { | |||
int i,j,x,y,m,n; | |||
ulong t; | |||
// Convert cell index into the X-Y bitmap coordinates. | |||
x=(index%nx)*(NDOT+3)*dx+2*dx+border; | |||
y=(index/nx)*(NDOT+3)*dy+2*dy+border; | |||
bits+=(height-y-1)*width+x; | |||
// Add CRC. | |||
block->crc=(ushort)(Crc16((uchar *)block,NDATA+sizeof(ulong))^0x55AA); | |||
// Add error correction code. | |||
Encode8((uchar *)block,block->ecc,127); | |||
// Print block. To increase the reliability of empty or half-empty blocks | |||
// and close-to-0 addresses, I XOR all data with 55 or AA. | |||
for (j=0; j<32; j++) { | |||
t=((ulong *)block)[j]; | |||
if ((j & 1)==0) | |||
t^=0x55555555; | |||
else | |||
t^=0xAAAAAAAA; | |||
x=0; | |||
for (i=0; i<32; i++) { | |||
if (t & 1) { | |||
for (m=0; m<py; m++) { | |||
for (n=0; n<px; n++) { | |||
bits[x-m*width+n]=(uchar)black; | |||
}; | |||
}; | |||
}; | |||
t>>=1; | |||
x+=dx; | |||
}; | |||
bits-=dy*width; | |||
}; | |||
}; | |||
// Service function, clips regular 32x32-dot raster to bitmap in the position | |||
// with given block coordinates (may be outside the bitmap). | |||
static void Fillblock(int blockx,int blocky,uchar *bits,int width,int height, | |||
int border,int nx,int ny,int dx,int dy,int px,int py,int black | |||
) { | |||
int i,j,x0,y0,x,y,m,n; | |||
ulong t; | |||
// Convert cell coordinates into the X-Y bitmap coordinates. | |||
x0=blockx*(NDOT+3)*dx+2*dx+border; | |||
y0=blocky*(NDOT+3)*dy+2*dy+border; | |||
// Print raster. | |||
for (j=0; j<32; j++) { | |||
if ((j & 1)==0) | |||
t=0x55555555; | |||
else { | |||
if (blocky<0 && j<=24) t=0; | |||
else if (blocky>=ny && j>8) t=0; | |||
else if (blockx<0) t=0xAA000000; | |||
else if (blockx>=nx) t=0x000000AA; | |||
else t=0xAAAAAAAA; }; | |||
for (i=0; i<32; i++) { | |||
if (t & 1) { | |||
for (m=0; m<py; m++) { | |||
for (n=0; n<px; n++) { | |||
x=x0+i*dx+n; | |||
y=y0+j*dy+m; | |||
if (x<0 || x>=width || y<0 || y>=height) | |||
continue; | |||
bits[(height-y-1)*width+x]=(uchar)black; | |||
}; | |||
}; | |||
}; | |||
t>>=1; | |||
}; | |||
}; | |||
}; | |||
// Opens input file and allocates memory buffers. | |||
int Preparefiletoprint(t_printdata *print) { | |||
ulong l=0; | |||
#ifdef _WIN32 | |||
FILETIME created, accessed, modified; | |||
// Get file attributes. | |||
print->attributes=GetFileAttributes(print->infile.c_str()); | |||
if (print->attributes==0xFFFFFFFF) | |||
print->attributes=FILE_ATTRIBUTE_NORMAL; | |||
// Open input file. | |||
print->hfile = CreateFile(print->infile.c_str(),GENERIC_READ,FILE_SHARE_READ, | |||
NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); | |||
if (print->hfile==INVALID_HANDLE_VALUE) { | |||
Reporterror("Unable to open file"); | |||
Stopprinting(print); | |||
return -1; | |||
}; | |||
// Get time of last file modification. | |||
GetFileTime(print->hfile,&created,&accessed,&modified); | |||
if (modified.dwHighDateTime==0) | |||
print->modified=created; | |||
else | |||
print->modified=modified; | |||
// Get original (uncompressed) file size. | |||
print->origsize=GetFileSize(print->hfile, (LPDWORD)&l); | |||
if (print->origsize == 0 | |||
|| print -> origsize == INVALID_FILE_SIZE | |||
|| print->origsize>MAXSIZE | |||
|| l!=0 | |||
) { | |||
Reporterror("Invalid file size"); | |||
Stopprinting(print); | |||
return -1; | |||
}; | |||
#elif __linux__ | |||
// Get file attributes | |||
if ( stat(print->infile.c_str(), &(print->attributes)) != 0 ) { | |||
Reporterror("Unable to get input file attributes"); | |||
Stopprinting(print); | |||
return -1; | |||
} | |||
// Open input file. | |||
print->hfile = fopen( print->infile.c_str(), "rb" ); | |||
if (print->hfile == NULL) { | |||
Reporterror("Unable to open file"); | |||
Stopprinting(print); | |||
return -1; | |||
} | |||
// Get time of last file modification. | |||
print->modified = print->attributes.st_mtime; | |||
// Get original (uncompressed) file size. | |||
print->origsize = print->attributes.st_size; | |||
if (print->origsize==0 || print->origsize>MAXSIZE) { | |||
Reporterror("Invalid file size"); | |||
Stopprinting(print); | |||
return -1; | |||
} | |||
#endif | |||
print->readsize=0; | |||
// Allocate buffer for compressed file. (If compression is off, buffer will | |||
// contain uncompressed data). As AES encryption works on 16-byte records, | |||
// buffer is aligned to next 16-bit border. | |||
print->bufsize=(print->origsize+15) & 0xFFFFFFF0; | |||
print->buf=(uchar *)malloc(print->bufsize); | |||
if (print->buf==NULL) { | |||
Reporterror("Not enough memory for output file"); | |||
Stopprinting(print); | |||
return -1; | |||
}; | |||
// Allocate read buffer. Because compression may take significant time, I | |||
// pack data in pieces of PACKLEN bytes. | |||
print->readbuf=(uchar *)malloc(PACKLEN); | |||
if (print->readbuf==NULL) { | |||
Reporterror("Not enough memory for read buffer"); | |||
Stopprinting(print); | |||
return -1; | |||
}; | |||
// Set options. | |||
// print->compression=compression; | |||
// print->encryption=encryption; | |||
print->printheader=printheader; | |||
print->printborder=printborder; | |||
print->redundancy=redundancy; | |||
// Step finished. | |||
print->step++; | |||
return 0; | |||
}; | |||
int Initializeprinting(t_printdata *print, uint pageWidth, uint pageHeight) { | |||
int i,dx,dy,px,py,width,height,success,rastercaps; | |||
long nx, ny; // Number of blocks in each row and column | |||
char fil[MAXPATH],nam[MAXFILE],ext[MAXEXT],jobname[TEXTLEN]; | |||
BITMAPINFO *pbmi; | |||
//SIZE extent; | |||
//PRINTDLG printdlg; | |||
//DOCINFO dinfo; | |||
//DEVNAMES *pdevnames; | |||
// Prepare superdata. | |||
print->superdata.addr=SUPERBLOCK; | |||
print->superdata.origsize=print->origsize; | |||
//if (print->compression) | |||
// print->superdata.mode|=PBM_COMPRESSED; | |||
//if (print->encryption) | |||
// print->superdata.mode|=PBM_ENCRYPTED; | |||
#ifdef __WIN32 | |||
print->superdata.attributes=(uchar)(print->attributes & | |||
(FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN| | |||
FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_ARCHIVE| | |||
FILE_ATTRIBUTE_NORMAL)); | |||
print->superdata.modified=print->modified; | |||
#elif __linux__ | |||
//!!! get attributes needed to recreate file from stat | |||
//set print->modified | |||
#endif | |||
print->superdata.filecrc=(ushort)print->bufcrc; | |||
//fnsplit(print->infile,NULL,NULL,nam,ext); | |||
//fnmerge(fil,NULL,NULL,nam,ext); | |||
// Note that name in superdata may be not null-terminated. | |||
strncpy(print->superdata.name,fil,32); // don't overwrite the salt and iv at the end of this buffer | |||
print->superdata.name[31] = '\0'; // ensure that later string operations don't overflow into binary data | |||
// If printing to paper, ask user to select printer and, if necessary, adjust | |||
// parameters. I do not enforce high quality or high resolution - the user is | |||
// the king (well, a sort of). | |||
//if (print->outbmp[0]=='\0') { | |||
// // Open standard Print dialog box. | |||
// memset(&printdlg,0,sizeof(PRINTDLG)); | |||
// printdlg.lStructSize=sizeof(PRINTDLG); | |||
// printdlg.hwndOwner=hwmain; | |||
// printdlg.hDevMode=pagesetup.hDevMode; | |||
// printdlg.hDevNames=pagesetup.hDevNames; | |||
// printdlg.hDC=NULL; // Returns DC | |||
// printdlg.Flags=PD_ALLPAGES|PD_RETURNDC|PD_NOSELECTION|PD_PRINTSETUP; | |||
// printdlg.nFromPage=1; // It's hard to calculate the number of | |||
// printdlg.nToPage=9999; // pages in advance. | |||
// printdlg.nMinPage=1; | |||
// printdlg.nMaxPage=9999; | |||
// printdlg.nCopies=1; | |||
// printdlg.hInstance=hinst; | |||
// success=PrintDlg(&printdlg); | |||
// // Save important information. | |||
// print->dc=printdlg.hDC; | |||
// print->frompage=printdlg.nFromPage-1; | |||
// print->topage=printdlg.nToPage-1; | |||
// // Clean up to prevent memory leaks. | |||
// if (pagesetup.hDevMode==NULL) | |||
// pagesetup.hDevMode=printdlg.hDevMode; | |||
// else if (printdlg.hDevMode!=pagesetup.hDevMode) | |||
// GlobalFree(printdlg.hDevMode); | |||
// if (pagesetup.hDevNames==NULL) | |||
// pagesetup.hDevNames=printdlg.hDevNames; | |||
// else if (printdlg.hDevNames!=pagesetup.hDevNames) | |||
// GlobalFree(printdlg.hDevNames); | |||
// // Analyse results. | |||
// if (success==0) { // User cancelled printing | |||
// Message("",0); | |||
// Stopprinting(print); | |||
// return; }; | |||
// if (print->dc==NULL) { // Printer DC is unavailable | |||
// Reporterror("Unable to access printer"); | |||
// Stopprinting(print); | |||
// return; }; | |||
// // Assure that printer is capable of displaying bitmaps. | |||
// rastercaps=GetDeviceCaps(print->dc,RASTERCAPS); | |||
// if ((rastercaps & RC_DIBTODEV)==0) { | |||
// Reporterror("The selected printer can't print bitmaps"); | |||
// Stopprinting(print); | |||
// return; }; | |||
// // Get resolution and size of print area in pixels. | |||
// print->ppix=GetDeviceCaps(print->dc,LOGPIXELSX); | |||
// print->ppiy=GetDeviceCaps(print->dc,LOGPIXELSY); | |||
// width=GetDeviceCaps(print->dc,HORZRES); | |||
// height=GetDeviceCaps(print->dc,VERTRES); | |||
// // Create fonts to draw title and comment. If system is unable to create | |||
// // any font, I get standard one. Of course, standard font will be almost | |||
// // invisible with printer's resolution. | |||
// if (print->printheader) { | |||
// print->hfont6=CreateFont(print->ppiy/6,0,0,0,FW_LIGHT,0,0,0, | |||
// ANSI_CHARSET,OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS, | |||
// PROOF_QUALITY,FF_SWISS,NULL); | |||
// print->hfont10=CreateFont(print->ppiy/10,0,0,0,FW_LIGHT,0,0,0, | |||
// ANSI_CHARSET,OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS, | |||
// PROOF_QUALITY,FF_SWISS,NULL); | |||
// if (print->hfont6==NULL) | |||
// print->hfont6=(HFONT)GetStockObject(SYSTEM_FONT); | |||
// if (print->hfont10==NULL) | |||
// print->hfont10=(HFONT)GetStockObject(SYSTEM_FONT); | |||
// // Set text color (gray) and alignment (centered). | |||
// SetTextColor(print->dc,RGB(128,128,128)); | |||
// SetTextAlign(print->dc,TA_TOP|TA_CENTER); | |||
// // Calculate height of title and info lines on the paper. | |||
// SelectObject(print->dc,print->hfont6); | |||
// if (GetTextExtentPoint32(print->dc,"Page",4,&extent)==0) | |||
// print->extratop=print->ppiy/4; | |||
// else | |||
// print->extratop=extent.cy+print->ppiy/16; | |||
// SelectObject(print->dc,print->hfont10); | |||
// if (GetTextExtentPoint32(print->dc,"Page",4,&extent)==0) | |||
// print->extrabottom=print->ppiy/6; | |||
// else | |||
// print->extrabottom=extent.cy+print->ppiy/24; | |||
// ; } | |||
// else { | |||
// print->hfont6=NULL; | |||
// print->hfont10=NULL; | |||
// print->extratop=print->extrabottom=0; }; | |||
// // Dots on paper are black (palette index 0 in the memory bitmap that will | |||
// // be created later in this subroutine). | |||
print->black=0; //} | |||
// I treat printing to bitmap as a debugging feature and set some more or | |||
// less sound defaults. | |||
// print->dc=NULL; | |||
print->frompage=0; | |||
print->topage=9999; | |||
if (resx==0 || resy==0) { | |||
print->ppix=300; print->ppiy=300; | |||
} else { | |||
print->ppix=resx; print->ppiy=resy; | |||
} | |||
// if (pagesetup.Flags & PSD_INTHOUSANDTHSOFINCHES) { | |||
// width=pagesetup.ptPaperSize.x*print->ppix/1000; | |||
// height=pagesetup.ptPaperSize.y*print->ppiy/1000; | |||
// } else if (pagesetup.Flags & PSD_INHUNDREDTHSOFMILLIMETERS) { | |||
// width=pagesetup.ptPaperSize.x*print->ppix/2540; | |||
// height=pagesetup.ptPaperSize.y*print->ppiy/2540; | |||
// } else { // Use default A4 size (210x292 mm)*/ | |||
// width=print->ppix*8270/1000; | |||
// height=print->ppiy*11690/1000; | |||
// }; | |||
// print->hfont6=NULL; | |||
// print->hfont10=NULL; | |||
// print->extratop=print->extrabottom=0; | |||
// // To simplify recognition of grid on high-contrast bitmap, dots on the | |||
// // bitmap are dark gray. | |||
print->black=64; | |||
// Calculate page borders in the pixels of printer's resolution. | |||
// if (pagesetup.Flags & PSD_INTHOUSANDTHSOFINCHES) { | |||
// print->borderleft=pagesetup.rtMargin.left*print->ppix/1000; | |||
// print->borderright=pagesetup.rtMargin.right*print->ppix/1000; | |||
// print->bordertop=pagesetup.rtMargin.top*print->ppiy/1000; | |||
// print->borderbottom=pagesetup.rtMargin.bottom*print->ppiy/1000; | |||
// } | |||
// else if (pagesetup.Flags & PSD_INHUNDREDTHSOFMILLIMETERS) { | |||
// print->borderleft=pagesetup.rtMargin.left*print->ppix/2540; | |||
// print->borderright=pagesetup.rtMargin.right*print->ppix/2540; | |||
// print->bordertop=pagesetup.rtMargin.top*print->ppiy/2540; | |||
// print->borderbottom=pagesetup.rtMargin.bottom*print->ppiy/2540; | |||
// } else { | |||
print->borderleft=print->ppix/2; | |||
print->borderright=print->ppix/2; | |||
print->bordertop=print->ppiy/2; | |||
print->borderbottom=print->ppiy/2; | |||
// } | |||
// Calculate size of printable area, in the pixels of printer's resolution. | |||
// Truncation of pageWidth * ppix and pageHeight * ppiy is INTENDED behavior | |||
width = pageWidth * print->ppix - print->borderleft+print->borderright; | |||
height = pageHeight * print->ppiy - print->bordertop+print->borderbottom+print->extratop+print->extrabottom; | |||
// Calculate data point raster (dx,dy) and size of the point (px,py) in the | |||
// pixels of printer's resolution. Note that pixels, at least in theory, may | |||
// be non-rectangular. | |||
dx=std::max(print->ppix/dpi,2); | |||
px=std::max((dx*dotpercent)/100,1); | |||
dy=std::max(print->ppiy/dpi,2); | |||
py=std::max((dy*dotpercent)/100,1); | |||
// Calculate width of the border around the data grid. | |||
if (print->printborder) | |||
print->border=dx*16; | |||
else if ( print->outbmp.length() > 0 ) | |||
print->border=25; | |||
else | |||
print->border=0; | |||
// Calculate the number of data blocks that fit onto the single page. Single | |||
// page must contain at least redundancy data blocks plus 1 recovery checksum, | |||
// and redundancy+1 superblocks with name and size of the data. Data and | |||
// recovery blocks should be placed into different columns. | |||
nx=(width-px-2*print->border)/(NDOT*dx+3*dx); | |||
ny=(height-py-2*print->border)/(NDOT*dy+3*dy); | |||
//std::cout << "nx: " << nx << std::endl; | |||
//std::cout << "ny: " << ny << std::endl; | |||
//std::cout << "width: " << width << std::endl; | |||
//std::cout << "height: " << height << std::endl; | |||
//std::cout << "px: " << px << std::endl; | |||
//std::cout << "py: " << py << std::endl; | |||
//std::cout << "NDOT: " << NDOT << std::endl; | |||
//std::cout << "dx: " << dx <<std::endl; | |||
//std::cout << "dy: " << dy << std::endl; | |||
long multResult = nx*ny; | |||
if ( nx > 0 && ny > 0 && multResult < 0 ) { | |||
std::cerr << "Input file is too large to back up. Please break the file apart" << std::endl; | |||
return -1; | |||
} | |||
if (nx<print->redundancy+1 || ny<3 || nx*ny<2*print->redundancy+2) { | |||
Reporterror("Printable area is too small, reduce borders or block size"); | |||
Stopprinting(print); | |||
return -1; | |||
}; | |||
// Calculate final size of the bitmap where I will draw the image. | |||
width=(nx*(NDOT+3)*dx+px+2*print->border+3) & 0xFFFFFFFC; | |||
height=ny*(NDOT+3)*dy+py+2*print->border; | |||
// Fill in bitmap header. To simplify processing, I use 256-color bitmap | |||
// (1 byte per pixel). | |||
pbmi=(BITMAPINFO *)print->bmi; | |||
memset(pbmi,0,sizeof(BITMAPINFOHEADER)); | |||
pbmi->bmiHeader.biSize=sizeof(BITMAPINFOHEADER); | |||
pbmi->bmiHeader.biWidth=width; | |||
pbmi->bmiHeader.biHeight=height; | |||
pbmi->bmiHeader.biPlanes=1; | |||
pbmi->bmiHeader.biBitCount=8; | |||
pbmi->bmiHeader.biCompression=BI_RGB; | |||
pbmi->bmiHeader.biSizeImage=0; | |||
pbmi->bmiHeader.biXPelsPerMeter=0; | |||
pbmi->bmiHeader.biYPelsPerMeter=0; | |||
pbmi->bmiHeader.biClrUsed=256; | |||
pbmi->bmiHeader.biClrImportant=256; | |||
for (i=0; i<256; i++) { | |||
pbmi->bmiColors[i].rgbBlue=(uchar)i; | |||
pbmi->bmiColors[i].rgbGreen=(uchar)i; | |||
pbmi->bmiColors[i].rgbRed=(uchar)i; | |||
pbmi->bmiColors[i].rgbReserved=0; }; | |||
// Create bitmap. Direct drawing is faster than tens of thousands of API | |||
// calls. | |||
if ( print->outbmp.empty() ) { | |||
Reporterror("Outbmp unspecified, can not create BMP"); | |||
Stopprinting(print); | |||
return -1; | |||
} | |||