Browse Source

all compile, printer has issues writing name but blocks recognized by original paperbak

master
suhrke 3 years ago
parent
commit
dd57d9b899
8 changed files with 304 additions and 464 deletions
  1. 3
    2
      Makefile
  2. 40
    38
      src/Decoder.cpp
  3. 75
    68
      src/Fileproc.cpp
  4. 1
    1
      src/PortLibCpp
  5. 19
    22
      src/Printer.cpp
  6. 34
    228
      src/Scanner.cpp
  7. 14
    11
      src/main.cpp
  8. 118
    94
      src/paperbak.h

+ 3
- 2
Makefile View File

@@ -1,11 +1,12 @@
EX=paperback-cli
SDIR=./src
CC=g++
CFLAGS=-std=c++11 -I"$(SDIR)" -I"$(SDIR)/PortLibCpp/src" -I"$(SDIR)/cxxopts/include" -I"$(SDIR)/AES" -I"$(SDIR)/BZLIB"
PORTDIR=$(SDIR)/PortLibCpp/src
CFLAGS=-std=c++11 -I"$(SDIR)" -I"$(PORTDIR)" -I"$(SDIR)/cxxopts/include" -I"$(SDIR)/AES" -I"$(SDIR)/BZLIB"

all: main

main: $(SDIR)/main.cpp $(SDIR)/Printer.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 #$(SDIR)/Fileproc.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 $(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
$(CC) $^ $(CFLAGS) -o $(EX)

msys: $(SDIR)/main.cpp $(SDIR)/Printer.cpp $(SDIR)/Fileproc.cpp $(SDIR)/Decoder.cpp

+ 40
- 38
src/Decoder.cpp View File

@@ -32,6 +32,8 @@
#include <windows.h>
#endif
#include <stdlib.h>
#include <algorithm>
#include <math.h>
#include "bzlib.h"
#include "aes.h"

@@ -63,12 +65,12 @@ static float Findpeaks(int *h,int n,float *bestpeak,float *beststep) {
d=(amax-amin+16)/32;
ampl=h[0];
for (i=0; i<n; i++) {
l[i]=ampl=max(ampl-d,h[i]); };
l[i]=ampl=std::max(ampl-d,h[i]); };
amax=0;
for (i=n-1; i>=0; i--) {
ampl=max(ampl-d,l[i]);
ampl=std::max(ampl-d,l[i]);
l[i]=ampl-h[i];
amax=max(amax,l[i]); };
amax=std::max(amax,l[i]); };

// TRY TO COMPARE WITH SECOND LARGE PEAK?

@@ -89,7 +91,7 @@ static float Findpeaks(int *h,int n,float *bestpeak,float *beststep) {
ampl=l[i]-limit;
area+=ampl;
moment+=ampl*i;
amax=max(amax,l[i]);
amax=std::max(amax,l[i]);
i++; };
// Don't process incomplete peaks.
if (i>=n) break;
@@ -282,10 +284,10 @@ static void Getgridposition(t_procdata *pdata) {
pd=data+j*stepy*sizex;
for (i=0; i<nx; i++,pd+=stepx) {
c=pd[0]; cmin=c; cmax=c;
c=pd[2]; cmin=min(cmin,c); cmax=max(cmax,c);
c=pd[sizex+1]; cmin=min(cmin,c); cmax=max(cmax,c);
c=pd[2*sizex]; cmin=min(cmin,c); cmax=max(cmax,c);
c=pd[2*sizex+2]; cmin=min(cmin,c); cmax=max(cmax,c);
c=pd[2]; cmin=std::min(cmin,c); cmax=std::max(cmax,c);
c=pd[sizex+1]; cmin=std::min(cmin,c); cmax=std::max(cmax,c);
c=pd[2*sizex]; cmin=std::min(cmin,c); cmax=std::max(cmax,c);
c=pd[2*sizex+2]; cmin=std::min(cmin,c); cmax=std::max(cmax,c);
distrx[i]+=cmax-cmin;
distry[j]+=cmax-cmin;
};
@@ -525,10 +527,10 @@ static void Preparefordecoding(t_procdata *pdata) {
// Empirical formula: the larger the angle, the more imprecise is the
// expected position of the block.
if (border<=0.0) {
border=max(fabs(pdata->xangle),fabs(pdata->yangle))*5.0+0.4;
border=std::max(fabs(pdata->xangle),fabs(pdata->yangle))*5.0+0.4;
pdata->blockborder=border; };
// Correct sharpness for known dot size. This correction is empirical.
dotsize=max(xstep,ystep)/(NDOT+3.0);
dotsize=std::max(xstep,ystep)/(NDOT+3.0);
sharpfactor+=1.3/dotsize-0.1;
if (sharpfactor<0.0) sharpfactor=0.0;
else if (sharpfactor>2.0) sharpfactor=2.0;
@@ -554,25 +556,25 @@ static void Preparefordecoding(t_procdata *pdata) {
pdata->nposy=(int)((sizey+maxyshift)/ystep);
// Start new quality map. Note that this call doesn't force map to be
// displayed.
Initqualitymap(pdata->nposx,pdata->nposy);
//Initqualitymap(pdata->nposx,pdata->nposy);
// Allocate block buffers.
dx=xstep*(2.0*border+1.0)+1.0;
dy=ystep*(2.0*border+1.0)+1.0;
pdata->buf1=(uchar *)GlobalAlloc(GMEM_FIXED,dx*dy);
pdata->buf2=(uchar *)GlobalAlloc(GMEM_FIXED,dx*dy);
pdata->bufx=(int *)GlobalAlloc(GMEM_FIXED,dx*sizeof(int));
pdata->bufy=(int *)GlobalAlloc(GMEM_FIXED,dy*sizeof(int));
pdata->buf1=(uchar *)malloc(dx*dy);
pdata->buf2=(uchar *)malloc(dx*dy);
pdata->bufx=(int *)malloc(dx*sizeof(int));
pdata->bufy=(int *)malloc(sizeof(int));
pdata->blocklist=(t_block *)
GlobalAlloc(GMEM_FIXED,pdata->nposx*pdata->nposy*sizeof(t_block));
malloc(pdata->nposx*pdata->nposy*sizeof(t_block));
// Check that we have enough memory.
if (pdata->buf1==NULL || pdata->buf2==NULL ||
pdata->bufx==NULL || pdata->bufy==NULL || pdata->blocklist==NULL
) {
if (pdata->buf1!=NULL) GlobalFree((HGLOBAL)pdata->buf1);
if (pdata->buf2!=NULL) GlobalFree((HGLOBAL)pdata->buf2);
if (pdata->bufx!=NULL) GlobalFree((HGLOBAL)pdata->bufx);
if (pdata->bufy!=NULL) GlobalFree((HGLOBAL)pdata->bufy);
if (pdata->blocklist!=NULL) GlobalFree((HGLOBAL)pdata->blocklist);
if (pdata->buf1!=NULL) free(pdata->buf1);
if (pdata->buf2!=NULL) free(pdata->buf2);
if (pdata->bufx!=NULL) free(pdata->bufx);
if (pdata->bufy!=NULL) free(pdata->bufy);
if (pdata->blocklist!=NULL) free(pdata->blocklist);
Reporterror("Low memory");
pdata->step=0;
return; };
@@ -664,7 +666,7 @@ int Decodeblock(t_procdata *pdata,int posx,int posy,t_data *result) {
if (i==0 || i==dx-1 || j==0 || j==dy-1)
*pdest=*psrc;
else {
*pdest=(uchar)max(cmin,min((int)(psrc[0]*(1.0+4.0*sharpfactor)-
*pdest=(uchar)std::max(cmin,std::min((int)(psrc[0]*(1.0+4.0*sharpfactor)-
(psrc[-dx]+psrc[-1]+psrc[1]+psrc[dx])*sharpfactor),cmax));
};
};
@@ -833,8 +835,8 @@ static void Decodenextblock(t_procdata *pdata) {
goto finish;
// If this is the very first block located on the page, show it in the block
// display window.
if (pdata->ngood==0 && pdata->nbad==0 && pdata->nsuper==0)
Displayblockimage(pdata,pdata->posx,pdata->posy,answer,&result);
//if (pdata->ngood==0 && pdata->nbad==0 && pdata->nsuper==0)
// Displayblockimage(pdata,pdata->posx,pdata->posy,answer,&result);
// Analyze answer.
if (answer>=17) {
// Error, block is unreadable.
@@ -869,7 +871,7 @@ static void Decodenextblock(t_procdata *pdata) {
// of quality.
pdata->nrestored+=answer; };
// Add block to quality map.
Addblocktomap(pdata->posx,pdata->posy,answer);
//Addblocktomap(pdata->posx,pdata->posy,answer);
// Block processed, set new coordinates.
finish:
pdata->posx++;
@@ -912,10 +914,10 @@ void Nextdataprocessingstep(t_procdata *pdata) {
case 0: // Idle data
return;
case 1: // Remove previous images
SetWindowPos(hwmain,HWND_TOP,0,0,0,0,
SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
Initqualitymap(0,0);
Displayblockimage(NULL,0,0,0,NULL);
//SetWindowPos(hwmain,HWND_TOP,0,0,0,0,
// SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
//Initqualitymap(0,0);
//Displayblockimage(NULL,0,0,0,NULL);
pdata->step++;
break;
case 2: // Determine grid size
@@ -943,30 +945,30 @@ void Nextdataprocessingstep(t_procdata *pdata) {
break;
default: break; // Internal error
};
if (pdata->step==0) Updatebuttons(); // Right or wrong, decoding finished
//if (pdata->step==0) Updatebuttons(); // Right or wrong, decoding finished
};

// Frees resources allocated by pdata.
void Freeprocdata(t_procdata *pdata) {
// Free data.
if (pdata->data!=NULL) {
GlobalFree((HGLOBAL)pdata->data);
free(pdata->data);
pdata->data=NULL; };
// Free allocated buffers.
if (pdata->buf1!=NULL) {
GlobalFree((HGLOBAL)pdata->buf1);
free(pdata->buf1);
pdata->buf1=NULL; };
if (pdata->buf2!=NULL) {
GlobalFree((HGLOBAL)pdata->buf2);
free(pdata->buf2);
pdata->buf2=NULL; };
if (pdata->bufx!=NULL) {
GlobalFree((HGLOBAL)pdata->bufx);
free(pdata->bufx);
pdata->bufx=NULL; };
if (pdata->bufy!=NULL) {
GlobalFree((HGLOBAL)pdata->bufy);
free(pdata->bufy);
pdata->bufy=NULL; };
if (pdata->blocklist!=NULL) {
GlobalFree((HGLOBAL)pdata->blocklist);
free(pdata->blocklist);
pdata->blocklist=NULL;
};
};
@@ -983,9 +985,9 @@ void Startbitmapdecoding(t_procdata *pdata,uchar *data,int sizex,int sizey) {
pdata->sizey=sizey;
pdata->blockborder=0.0; // Autoselect
pdata->step=1;
if (bestquality)
if (::pb_bestquality)
pdata->mode|=M_BEST;
Updatebuttons();
//Updatebuttons();
};

// Stops bitmap decoding. Data decoded so far is discarded, but resources

+ 75
- 68
src/Fileproc.cpp View File

@@ -34,8 +34,11 @@
#include <sys/stat.h>
#endif
#include <stdlib.h>
#include <algorithm>
#include <stdint.h>
#include "bzlib.h"
#include "aes.h"
#include "FileAttributes.hpp"

#include "paperbak.h"
#include "Resource.h"
@@ -44,15 +47,15 @@


// Clears descriptor of processed file
void Closefproc() {
//if (slot<0 || slot>=NFILE)
// return; // Error in input data
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
void Closefproc(int slot) {
if (slot<0 || slot>=NFILE)
return; // Error in input data
if (::pb_fproc[slot].datavalid!=NULL)
free(::pb_fproc[slot].datavalid);
if (::pb_fproc[slot].data!=NULL)
free(::pb_fproc[slot].data);
memset(::pb_fproc+slot,0,sizeof(t_fproc));
//Updatefileinfo(slot,::pb_fproc+slot); //GUI
};


@@ -65,10 +68,12 @@ int Startnextpage(t_superblock *superblock) {
// Check whether file is already in the list of processed files. If not,
// initialize new descriptor.
freeslot=-1;
for (slot=0,pf=fproc; slot<NFILE; slot++,pf++) {
for (slot=0,pf=::pb_fproc; slot<NFILE; slot++,pf++) {
if (pf->busy==0) { // Empty descriptor
if (freeslot<0) freeslot=slot;
continue; };

if (strnicmp(pf->name,superblock->name,64)!=0)
continue; // Different file name
if (pf->mode!=superblock->mode)
@@ -91,12 +96,12 @@ int Startnextpage(t_superblock *superblock) {
Reporterror("Maximal number of processed files exceeded");
return -1; };
slot=freeslot;
pf=fproc+slot;
pf=::pb_fproc+slot;
memset(pf,0,sizeof(t_fproc));
// Allocate block and recovery tables.
pf->nblock=(superblock->datasize+NDATA-1)/NDATA;
pf->datavalid=(uchar *)calloc(pf->nblock);
pf->data=(uchar *)calloc(pf->nblock*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);
@@ -125,12 +130,12 @@ int Startnextpage(t_superblock *superblock) {
pf->recoveredblocks=0;
pf->busy=1; };
// Invalidate page limits and report success.
pf=fproc+slot;
pf=::pb_fproc+slot;
pf->page=superblock->page;
pf->ngroup=superblock->ngroup;
pf->minpageaddr=0xFFFFFFFF;
pf->maxpageaddr=0;
Updatefileinfo(slot,pf);
//Updatefileinfo(slot,pf);
return slot;
};

@@ -141,14 +146,14 @@ int Addblock(t_block *block,int slot) {
t_fproc *pf;
if (slot<0 || slot>=NFILE)
return -1; // Invalid index of file descriptor
pf=fproc+slot;
pf=::pb_fproc+slot;
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)
if ((uint32_t)(i*NDATA)!=block->addr)
return -1; // Invalid data alignment
if (i>=pf->nblock)
return -1; // Data outside the data size
@@ -156,11 +161,11 @@ int Addblock(t_block *block,int slot) {
memcpy(pf->data+block->addr,block->data,NDATA);
pf->datavalid[i]=1; // Valid data
pf->ndata++; };
pf->minpageaddr=min(pf->minpageaddr,block->addr);
pf->maxpageaddr=max(pf->maxpageaddr,block->addr+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))
if (block->recsize!=(uint32_t)(pf->ngroup*NDATA))
return -1; // Invalid recovery scope
i=block->addr/block->recsize;
if (i*block->recsize!=block->addr)
@@ -172,8 +177,8 @@ int Addblock(t_block *block,int slot) {
if (pf->datavalid[j]!=0) continue;
memcpy(pf->data+j*NDATA,block->data,NDATA);
pf->datavalid[j]=2; }; // Valid recovery data
pf->minpageaddr=min(pf->minpageaddr,block->addr);
pf->maxpageaddr=max(pf->maxpageaddr,block->addr+block->recsize);
pf->minpageaddr=std::min(pf->minpageaddr,block->addr);
pf->maxpageaddr=std::max(pf->maxpageaddr,block->addr+block->recsize);
};
// Report success.
return 0;
@@ -182,13 +187,13 @@ int Addblock(t_block *block,int slot) {
// 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 slot,int ngood,int nbad,ulong nrestored) {
int Finishpage(int slot,int ngood,int nbad,uint32_t nrestored) {
int i,j,r,rmin,rmax,nrec,irec,firstblock,nrempages;
uchar *pr,*pd;
t_fproc *pf;
if (slot<0 || slot>=NFILE)
return -1; // Invalid index of file descriptor
pf=fproc+slot;
pf=::pb_fproc+slot;
if (pf->busy==0)
return -1; // Index points to unused descriptor
// Update statistics. Note that it grows also when the same page is scanned
@@ -259,9 +264,9 @@ int Finishpage(int slot,int ngood,int nbad,ulong nrestored) {
};
if (nrempages<8)
pf->rempages[nrempages]=0;
Updatefileinfo(slot,pf);
//Updatefileinfo(slot,pf);
if (pf->ndata==pf->nblock) {
if (autosave==0)
if (::pb_autosave==0)
Message("File restored. Press \"Save\" to save it to disk",0);
else {
Message("File complete",0);
@@ -277,7 +282,7 @@ int Finishpage(int slot,int ngood,int nbad,ulong nrestored) {
int Saverestoredfile(int slot,int force) {
int n,success;
ushort filecrc;
ulong l,length;
uint32_t l,length;
uchar *bufout,*data,*tempdata;
t_fproc *pf;
aes_context ctx;
@@ -285,7 +290,7 @@ int Saverestoredfile(int slot,int force) {
FILE *hfile;
if (slot<0 || slot>=NFILE)
return -1; // Invalid index of file descriptor
pf=fproc+slot;
pf=::pb_fproc+slot;
if (pf->busy==0 || pf->nblock==0)
return -1; // Index points to unused descriptor
if (pf->ndata!=pf->nblock && force==0)
@@ -294,37 +299,38 @@ int Saverestoredfile(int slot,int force) {
// 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) {
//FIXME securely get password from user
Reporterror("Encryption/Decryption not supported yet");
return -1;
//if (pf->datasize & 0x0000000F) {
// Reporterror("Encrypted data is not aligned");
// return -1;
//};
//if (Getpassword()!=0)
// return -1; // User cancelled decryption
//tempdata=(uchar *)GlobalAlloc(GMEM_FIXED,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");
// GlobalFree((HGLOBAL)tempdata);
// return -1;
//}
//else {
// GlobalFree((HGLOBAL)pf->data);
// pf->data=tempdata;
// pf->mode&=~PBM_ENCRYPTED;
//};
if (pf->datasize & 0x0000000F) {
Reporterror("Encrypted data is not aligned");
return -1;
};

if (Getpassword()!=0) {
Reporterror("Cancelling bitmap decoding");
return -1; // User cancelled decryption
}

tempdata=(uchar *)malloc(pf->datasize);
if (tempdata==NULL) {
Reporterror("Low memory, can't decrypt data");
return -1;
};
n=strlen(::pb_password);
while (n<PASSLEN) ::pb_password[n++]=0;
memset(&ctx,0,sizeof(ctx));
aes_set_key(&ctx,(uchar *)::pb_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) {
@@ -336,32 +342,32 @@ int Saverestoredfile(int slot,int force) {
// Data is compressed. Create temporary buffer.
if (pf->origsize==0)
pf->origsize=pf->datasize*4; // Weak attempt to recover
bufout=(uchar *)GlobalAlloc(GMEM_FIXED,pf->origsize);
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);
(char*)pf->data,pf->datasize,0,0);
if (success!=BZ_OK) {
GlobalFree((HGLOBAL)bufout);
free (bufout);
Reporterror("Unable to unpack data");
return -1; };
data=bufout; };
// Ask user for file name.
// FIXME selectoutfile must be initialized prior/by arg
if (pf->name!=NULL) {
if (bufout!=NULL) GlobalFree((HGLOBAL)bufout);
if (bufout!=NULL) free (bufout);
return -1;
};
// Open file and save data.
//hfile=CreateFile(outfile,GENERIC_WRITE,0,NULL,
//hfile=CreateFile(::pb_outfile,GENERIC_WRITE,0,NULL,
// CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
hfile = fopen (outfile, "wb");
hfile = fopen (::pb_outfile, "wb");
if (hfile==NULL) {
if (bufout!=NULL)
free(bufout);
free (bufout);
Reporterror("Unable to create file");
return -1;
};
@@ -371,7 +377,7 @@ int Saverestoredfile(int slot,int force) {
// Restore old modification date and time.
#ifdef _WIN32
// open HANDLE and set file time
handleFile=CreateFile(outfile,GENERIC_WRITE,0,NULL,
handleFile=CreateFile(::pb_outfile,GENERIC_WRITE,0,NULL,
CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if (handleFile==INVALID_HANDLE_VALUE) {
if (bufout!=NULL)
@@ -382,7 +388,7 @@ int Saverestoredfile(int slot,int force) {
SetFileTime(handleFile,&pf->modified,&pf->modified,&pf->modified);
// Close file and restore old basic attributes.
CloseHandle(hfile);
SetFileAttributes(outfile,pf->attributes);
SetFileAttributes(::pb_outfile,pf->attributes);
if (bufout!=NULL)
free(bufout);
if (l!=length) {
@@ -401,3 +407,4 @@ int Saverestoredfile(int slot,int force) {
return 0;
};



+ 1
- 1
src/PortLibCpp

@@ -1 +1 @@
Subproject commit 16561114c32a5a14cbb45f4d1e4cec6ef313dbdc
Subproject commit 1f8a8426ac0fcf7163110f973f2d9e998b57535e

+ 19
- 22
src/Printer.cpp View File

@@ -28,12 +28,12 @@
// //
////////////////////////////////////////////////////////////////////////////////

#include <stdlib.h>
#if defined(_WIN32) || defined(__CYGWIN__)
#include <windows.h>
#elif __linux__
#include <sys/stat.h>
#endif
#include <stdlib.h>
#include <algorithm>
#include "bzlib.h"
#include "aes.h"
@@ -194,9 +194,9 @@ static void Preparefiletoprint(t_printdata *print)
// Get time of last file modification.
GetFileTime (h, &created, &accessed, &modified);
if (modified.dwHighDateTime==0)
print->modified=created;
print->modified=(FileTimePortable)created;
else
print->modified=modified;
print->modified=(FileTimePortable)modified;
// Get original (uncompressed) file size.
print->origsize=GetFileSize (h, &l);
if (print->origsize==0 || print->origsize>MAXSIZE || l!=0) {
@@ -212,9 +212,10 @@ static void Preparefiletoprint(t_printdata *print)
Stopprinting(print);
return;
}
print->attributes = (uint32_t)fileInfo.st_mode;
uint32_t mode = (uint32_t)fileInfo.st_mode;
print->attributes = FileAttributes::convertToWindowsAttributes(mode);
// Get time of last file modification.
print->modified = fileInfo.st_mtime;
print->modified = FileAttributes::convertToFileTime(fileInfo.st_mtime);
// Get original (uncompressed) file size.
print->origsize = fileInfo.st_size;
if (print->origsize==0 || print->origsize>MAXSIZE) {
@@ -267,7 +268,8 @@ static void Preparecompressor(t_printdata *print) {
// Check whether compression is requested at all.
if (print->compression==0) {
print->step++;
return; };
return;
};
// Initialize compressor. On error, I silently disable compression.
memset(&print->bzstream,0,sizeof(print->bzstream));
success=BZ2_bzCompressInit(&print->bzstream,
@@ -294,7 +296,7 @@ static void Readandcompress(t_printdata *print) {
//success=ReadFile(print->hfile,print->readbuf,size,&l,NULL);
l = fread ((void*)print->readbuf, sizeof(uchar), size, print->hfile);
if (success==0 || l!=size) {
if (l!=size) {
Reporterror("Unable to read file");
Stopprinting(print);
return; };
@@ -395,18 +397,13 @@ static void Encryptdata(t_printdata *print) {
// Ask for password. If user cancels, skip file.
Message("Encrypting data...",0);
// If we want encryption, securely get it from user here
pb_password = getpass("Enter encryption password: ");
if (pb_password == NULL) { // User cancelled encryption
Message("No password entered, cancelling BMP creation",0);
Stopprinting(print);
return;
};
// Empty password means: leave data unencrypted.
if (pb_password[0]=='\0') {
if (Getpassword() != 0) {
Reporterror("Cancelling encryption and continuing");
print->encryption=0;
print->step++;
return;
};
}

// Encryption routine expects that password is exactly PASSLEN bytes long.
// Fill rest of the password with zeros.
n=strlen(pb_password);
@@ -449,7 +446,7 @@ static void Initializeprinting(t_printdata *print) {
#endif
print->superdata.modified=print->modified;
print->superdata.filecrc=(ushort)print->bufcrc;
fnsplit(print->infile,NULL,NULL,nam,ext, MAXPATH);
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,sizeof(print->superdata.name));
@@ -999,14 +996,14 @@ void Nextdataprintingstep(t_printdata *print) {
// Sends specified file to printer (bmp=NULL) or to bitmap file.
void Printfile(const char *path, const char *bmp) {
// Stop printing of previous file, if any.
//Stopprinting(&pb_printdata);
Stopprinting(&::pb_printdata);
// Prepare descriptor.
memset(&pb_printdata,0,sizeof(pb_printdata));
strncpy(pb_printdata.infile,path,MAXPATH-1);
memset(&::pb_printdata,0,sizeof(pb_printdata));
strncpy(::pb_printdata.infile,path,MAXPATH-1);
if (bmp!=NULL)
strncpy(pb_printdata.outbmp,bmp,MAXPATH-1);
strncpy(::pb_printdata.outbmp,bmp,MAXPATH-1);
// Start printing.
pb_printdata.step=1;
::pb_printdata.step=1;
//Updatebuttons();
};


+ 34
- 228
src/Scanner.cpp View File

@@ -31,24 +31,23 @@
#ifdef _WIN32
#include <windows.h>
#endif
#include <commctrl.h>
#include <stdlib.h>
#include "bzlib.h"
#include "aes.h"
#include "Bitmap.h"

#include "paperbak.h"
#include "Resource.h"

static HINSTANCE htwaindll; // Handle of TWAIN_32.DLL
static DSMENTRYPROC dsmentry; // Address of DSM_Entry()
static TW_IDENTITY appid; // Application's identity structure
static TW_IDENTITY source; // Opened TWAIN source



// Processes data from the scanner.
int ProcessDIB(HGLOBAL hdata,int offset) {
int ProcessDIB(void *hdata,int offset) {
int i,j,sizex,sizey,ncolor;
uchar scale[256],*data,*pdata,*pbits;
BITMAPINFO *pdib;
pdib=(BITMAPINFO *)GlobalLock(hdata);
pdib=(BITMAPINFO *)hdata;
if (pdib==NULL)
return -1; // Something is wrong with this DIB
// Check that bitmap is more or less valid.
@@ -60,15 +59,16 @@ int ProcessDIB(HGLOBAL hdata,int offset) {
pdib->bmiHeader.biWidth<128 || pdib->bmiHeader.biWidth>32768 ||
pdib->bmiHeader.biHeight<128 || pdib->bmiHeader.biHeight>32768
) {
GlobalUnlock(hdata);
return -1; }; // Not a known bitmap!
//GlobalUnlock(hdata);
return -1; // Not a known bitmap!
};
sizex=pdib->bmiHeader.biWidth;
sizey=pdib->bmiHeader.biHeight;
ncolor=pdib->bmiHeader.biClrUsed;
// Convert bitmap to 8-bit grayscale. Note that scan lines are DWORD-aligned.
data=(uchar *)GlobalAlloc(GMEM_FIXED,sizex*sizey);
data=(uchar *)malloc(sizex*sizey);
if (data==NULL) {
GlobalUnlock(hdata);
//GlobalUnlock(hdata);
return -1; };
if (pdib->bmiHeader.biBitCount==8) {
// 8-bit bitmap with palette.
@@ -104,12 +104,14 @@ int ProcessDIB(HGLOBAL hdata,int offset) {
};
};
// Decode bitmap. This is what we are for here.
Startbitmapdecoding(&procdata,data,sizex,sizey);
Startbitmapdecoding(&::pb_procdata,data,sizex,sizey);
// Free original bitmap and report success.
GlobalUnlock(hdata);
//GlobalUnlock(hdata);
return 0;
};



// Opens and decodes bitmap. Returns 0 on success and -1 on error.
int Decodebitmap(char *path) {
int i,size;
@@ -118,35 +120,37 @@ int Decodebitmap(char *path) {
FILE *f;
BITMAPFILEHEADER *pbfh;
BITMAPINFOHEADER *pbih;
HCURSOR prevcursor;
//HCURSOR prevcursor;
// Ask for file name.
if (path==NULL || path[0]=='\0') {
if (Selectinbmp()!=0) return -1; }
else {
strncpy(inbmp,path,sizeof(inbmp));
inbmp[sizeof(inbmp)-1]='\0'; };
fnsplit(inbmp,NULL,NULL,fil,ext);
//if (path==NULL || path[0]=='\0') {
// if (Selectinbmp()!=0) return -1; }
//else {
strncpy(::pb_inbmp,path,sizeof(::pb_inbmp));
::pb_inbmp[sizeof(::pb_inbmp)-1]='\0';
fnsplit(::pb_inbmp,NULL,NULL,fil,ext);
sprintf(s,"Reading %s%s...",fil,ext);
Message(s,0);
Updatebuttons();
//Updatebuttons();
// Open file and verify that this is the valid bitmap of known type.
f=fopen(inbmp,"rb");
f=fopen(::pb_inbmp,"rb");
if (f==NULL) { // Unable to open file
sprintf(s,"Unable to open %s%s",fil,ext);
Reporterror(s);
return -1; };
// Reading 100-MB bitmap may take many seconds. Let's inform user by changing
// mouse pointer.
prevcursor=SetCursor(LoadCursor(NULL,IDC_WAIT));
//prevcursor=SetCursor(LoadCursor(NULL,IDC_WAIT));
i=fread(buf,1,sizeof(buf),f);
SetCursor(prevcursor);
//SetCursor(prevcursor);
if (i!=sizeof(buf)) { // Unable to read file
sprintf(s,"Unable to read %s%s",fil,ext);
Reporterror(s);
fclose(f); return -1; };
fclose(f);
return -1;
};
pbfh=(BITMAPFILEHEADER *)buf;
pbih=(BITMAPINFOHEADER *)(buf+sizeof(BITMAPFILEHEADER));
if (pbfh->bfType!='BM' ||
if (pbfh->bfType!=CHAR_BM ||
pbih->biSize!=sizeof(BITMAPINFOHEADER) || pbih->biPlanes!=1 ||
(pbih->biBitCount!=8 && pbih->biBitCount!=24) ||
(pbih->biBitCount==24 && pbih->biClrUsed!=0) ||
@@ -160,7 +164,7 @@ int Decodebitmap(char *path) {
// Allocate buffer and read file.
fseek(f,0,SEEK_END);
size=ftell(f)-sizeof(BITMAPFILEHEADER);
data=(uchar *)GlobalAlloc(GMEM_FIXED,size);
data=(uchar *)malloc(size);
if (data==NULL) { // Unable to allocate memory
Reporterror("Low memory");
fclose(f); return -1; };
@@ -170,209 +174,11 @@ int Decodebitmap(char *path) {
if (i!=size) { // Unable to read bitmap
sprintf(s,"Unable to read %s%s",fil,ext);
Reporterror(s);
GlobalFree((HGLOBAL)data);
free(data);
return -1; };
// Process bitmap.
ProcessDIB((HGLOBAL)data,pbfh->bfOffBits-sizeof(BITMAPFILEHEADER));
GlobalFree((HGLOBAL)data);
return 0;
};

// Opens TWAIN manager. Returns 0 on success and -1 on error.
int OpenTWAINmanager(void) {
TW_UINT16 result;
if (dsmentry==NULL || twainstate<2)
return -1; // TWAIN DLL was not initialized
if (twainstate>2)
return 0; // Manager is already initialized
appid.Id=0;
appid.Version.MajorNum=VERSIONHI;
appid.Version.MinorNum=VERSIONLO;
appid.Version.Language=TWLG_ENGLISH_USA;
appid.Version.Country=TWCY_USA;
lstrcpy(appid.Version.Info,"PaperBack");
appid.ProtocolMajor=TWON_PROTOCOLMAJOR;
appid.ProtocolMinor=TWON_PROTOCOLMINOR;
appid.SupportedGroups=DG_IMAGE|DG_CONTROL;
lstrcpy(appid.Manufacturer,"");
lstrcpy(appid.ProductFamily,"");
lstrcpy(appid.ProductName,"PaperBack");
result=dsmentry(&appid,NULL,
DG_CONTROL,DAT_PARENT,MSG_OPENDSM,(TW_MEMREF)&hwmain);
if (result!=TWRC_SUCCESS)
return -1;
else {
twainstate=3; // TWAIN source manager open
return 0;
};
};

// Select image source. Returns 0 on success and -1 on error.
int SelectTWAINsource(void) {
TW_UINT16 result;
if (twainstate<3) // Manager inactive, try to initialize
OpenTWAINmanager();
if (twainstate!=3)
return -1; // Not a good time for this operation
result=dsmentry(&appid,NULL,
DG_CONTROL,DAT_IDENTITY,MSG_USERSELECT,(TW_MEMREF)&source);
return (result==TWRC_SUCCESS?0:-1);
};

// Opens and enables TWAIN interface. Returns 0 on success and -1 on error.
int OpenTWAINinterface(void) {
TW_UINT16 result;
TW_USERINTERFACE interf;
if (twainstate<3) // Manager inactive, try to initialize
OpenTWAINmanager();
if (twainstate!=3)
return -1; // Not a good time for this operation
result=dsmentry(&appid,NULL,
DG_CONTROL,DAT_IDENTITY,MSG_OPENDS,(TW_MEMREF)&source);
if (result!=TWRC_SUCCESS) {
// Unable to open source. The message is usually, but not always, correct.
Reporterror("There are no scanner devices on the system");
return -1; };
interf.ShowUI=1;
interf.ModalUI=0;
interf.hParent=(TW_HANDLE)hwmain;
result=dsmentry(&appid,&source,
DG_CONTROL,DAT_USERINTERFACE,MSG_ENABLEDS,&interf);
if (result!=TWRC_SUCCESS) {
dsmentry(&appid,NULL, // Unable to enable, go back to state 3
DG_CONTROL,DAT_IDENTITY,MSG_CLOSEDS,(TW_MEMREF)&source);
Reporterror("Unable to open scanner");
return -1; };
twainstate=5;
return 0;
};

// Gets picture(s) from the TWAIN.
int GetpicturefromTWAIN(void) {
int nextimage;
TW_UINT16 result,xferres;
TW_IMAGEINFO imageinfo;
TW_PENDINGXFERS pending;
HGLOBAL hdata;
if (twainstate!=5)
return -1; // Not a good time to get the picture
nextimage=1;
while (nextimage) {
// Get image information, like resolution and size.
result=dsmentry(&appid,&source,
DG_IMAGE,DAT_IMAGEINFO,MSG_GET,(TW_MEMREF)&imageinfo);
if (result!=TWRC_SUCCESS)
continue; // Is it correct? I follow the TWAIN...
// Start data transfer.
hdata=NULL;
xferres=dsmentry(&appid,&source,
DG_IMAGE,DAT_IMAGENATIVEXFER,MSG_GET,(TW_MEMREF)&hdata);
// After transfer is finished, no matter how, finish transfer.
result=dsmentry(&appid,&source,
DG_CONTROL,DAT_PENDINGXFERS,MSG_ENDXFER,(TW_MEMREF)&pending);
if (result!=TWRC_SUCCESS || pending.Count==0)
nextimage=0;
switch (xferres) {
case TWRC_XFERDONE: // Transfer finished, hbmp valid
if (hdata!=NULL) {
ProcessDIB(hdata,0);
GlobalUnlock(hdata);
GlobalFree(hdata); };
break;
case TWRC_CANCEL: // Bitmap exists but has invalid data
if (hdata!=NULL) {
GlobalUnlock(hdata);
GlobalFree(hdata); };
break;
case TWRC_FAILURE: // Bitmap invalid, stop scanning
dsmentry(&appid,&source,
DG_CONTROL,DAT_PENDINGXFERS,MSG_RESET,(TW_MEMREF)&pending);
nextimage=0;
break;
};
};
return 0;
};

// Disables and closes TWAIN interface. Returns 0 on success and -1 on error.
int CloseTWAINinterface(void) {
TW_UINT16 result;
TW_USERINTERFACE interf;
if (twainstate==5) {
// Disable source.
interf.ShowUI=0;
interf.ModalUI=0;
interf.hParent=(TW_HANDLE)hwmain;
result=dsmentry(&appid,&source,
DG_CONTROL,DAT_USERINTERFACE,MSG_DISABLEDS,&interf);
if (result!=TWRC_SUCCESS) return -1;
twainstate=4; };
if (twainstate==4) {
// Close source.
result=dsmentry(&appid,NULL,
DG_CONTROL,DAT_IDENTITY,MSG_CLOSEDS,(TW_MEMREF)&source);
if (result!=TWRC_SUCCESS) return -1;
twainstate=3; };
ProcessDIB(data,pbfh->bfOffBits-sizeof(BITMAPFILEHEADER));
free(data);
return 0;
};

// Detaches from the TWAIN. Returns 0 on success and -1 on error.
int CloseTWAINmanager(void) {
TW_UINT16 result;
CloseTWAINinterface(); // Reduces state to at least 3
if (twainstate==3) {
result=dsmentry(&appid,NULL,
DG_CONTROL,DAT_PARENT,MSG_OPENDSM,(TW_MEMREF)&hwmain);
if (result!=TWRC_SUCCESS) return -1;
twainstate=2;
};
return 0;
};

int PassmessagetoTWAIN(MSG *msg) {
TW_UINT16 result;
TW_EVENT twevent;
if (dsmentry==NULL)
return TWRC_NOTDSEVENT; // Oops, TWAIN not initialized!
twevent.pEvent=(TW_MEMREF)msg;
twevent.TWMessage=MSG_NULL;
result=dsmentry(&appid,&source,
DG_CONTROL,DAT_EVENT,MSG_PROCESSEVENT,&twevent);
// Check for message from the TWAIN interface.
switch (twevent.TWMessage) {
case MSG_XFERREADY:
GetpicturefromTWAIN();
break;
case MSG_CLOSEDSREQ:
CloseTWAINinterface();
Updatebuttons();
break;
case MSG_CLOSEDSOK:
CloseTWAINinterface();
Updatebuttons();
break;
default: break;
};
return result;
};

int LoadTWAINlibrary(void) {
htwaindll=LoadLibrary("twain_32.dll");
if (htwaindll!=NULL) {
dsmentry=(DSMENTRYPROC)GetProcAddress(htwaindll,"DSM_Entry");
if (dsmentry==NULL) {
FreeLibrary(htwaindll);
htwaindll=NULL; }
else {
twainstate=2;
}; }
else
dsmentry=NULL;
return (dsmentry!=NULL);
};

void CloseTWAINlibrary(void) {
if (htwaindll!=NULL) FreeLibrary(htwaindll);
htwaindll=NULL;
dsmentry=NULL;
};

+ 14
- 11
src/main.cpp View File

@@ -31,6 +31,7 @@ using namespace std;


// Global forward declarations
t_fproc pb_fproc[NFILE]; // Processed file
int pb_resx, pb_resy; // Printer resolution, dpi (may be 0!)
t_printdata pb_printdata; // Print control structure
int pb_orientation; // Orientation of bitmap (-1: unknown)
@@ -178,25 +179,27 @@ int main(int argc, char ** argv) {
std::string infile = options["input"].as<string>();
std::string outfile = options["output"].as<string>();
strcpy (::pb_infile, infile.c_str());
strcpy (::pb_outbmp, outfile.c_str());

if (isEncode) {
strcpy (::pb_outbmp, outfile.c_str());
Printfile(::pb_infile, ::pb_outbmp);
// begin the process to write the bitmap
while (::pb_printdata.step != 0) {
cout << "Step: " << ::pb_printdata.step << endl;
//cout << "Step: " << ::pb_printdata.step << endl;
Nextdataprintingstep (&::pb_printdata);
}
}
//else {
// if (Decodebitmap (infile.c_str()) == 0) {
// while (procdata.step != 0) {
// cout << "Step: " << ::pb_procdata.step << endl;
// Nextdataprocessingstep (&procdata);
// }
// }
//}
}
else {
strcpy (::pb_outfile, outfile.c_str());
Decodebitmap (::pb_infile);
while (::pb_procdata.step != 0) {
//cout << "Step: " << ::pb_procdata.step << endl;
Nextdataprocessingstep (&::pb_procdata);
}
}

return 0;
}
catch (const cxxopts::OptionException& e) {
cerr << "error parsing options: " << e.what() << endl;
exit(1);

+ 118
- 94
src/paperbak.h View File

@@ -13,14 +13,17 @@
////////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <ctype.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#if defined(_WIN32) || defined(__CYGWIN__)
#include <windows.h>
#endif
#include "bzlib.h"
#include "Bitmap.h"
#include "FileAttributes.hpp"



@@ -93,11 +96,7 @@ typedef struct __attribute__ ((packed)) t_superdata { // Id block on paper
uchar mode; // Special mode bits, set of PBM_xxx
uchar attributes; // Basic file attributes
ushort page; // Actual page (1-based)
#if defined(_WIN32) || defined(__CYGWIN__)
FILETIME modified; // last modify time
#elif __linux__
time_t modified; // last modify time
#endif
FileTimePortable modified; // last modify time
ushort filecrc; // CRC of compressed decrypted file
char name[FILENAME_SIZE]; // File name - may have all 64 chars
ushort crc; // Cyclic redundancy of previous fields
@@ -120,11 +119,7 @@ typedef struct t_superblock { // Identification block in memory
uint32_t origsize; // Size of original (uncompressed) data
uint32_t mode; // Special mode bits, set of PBM_xxx
ushort page; // Actual page (1-based)
#if defined(_WIN32) || defined(__CYGWIN__)
FILETIME modified; // last modify time
#elif __linux__
time_t modified; // last modify time
#endif
FileTimePortable modified; // last modify time
uint32_t attributes; // Basic file attributes
uint32_t filecrc; // 16-bit CRC of decrypted packed file
char name[FILENAME_SIZE]; // File name - may have all 64 chars
@@ -155,11 +150,7 @@ typedef struct t_printdata { // Print control structure
char infile[MAXPATH]; // Name of input file
char outbmp[MAXPATH]; // Name of output bitmap (empty: paper)
FILE *hfile; // (Formerly HANDLE) file pointer
#if defined(_WIN32) || defined(__CYGWIN__)
FILETIME modified; // last modify time
#elif __linux__
time_t modified; // last modify time
#endif
FileTimePortable modified; // last modify time
uint32_t attributes; // File attributes
uint32_t origsize; // Original file size, bytes
uint32_t readsize; // Amount of data read from file so far
@@ -197,6 +188,7 @@ typedef struct t_printdata { // Print control structure
int px,py; // Dot size, pixels
int nx,ny; // Grid dimensions, blocks
int border; // Border around the data grid, pixels
//FIXME bitmap file pointer needed?
//HBITMAP hbmp; // Handle of memory bitmap
uchar *dibbits; // Pointer to DIB bits
uchar *drawbits; // Pointer to file bitmap bits
@@ -281,11 +273,7 @@ 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
#if defined(_WIN32) || defined(__CYGWIN__)
FILETIME modified; // last modify time
#elif __linux__
time_t modified; // last modify time
#endif
FileTimePortable modified; // last modify time
uint32_t attributes; // Basic file attrributes
uint32_t datasize; // Size of (compressed) data
uint32_t pagesize; // Size of (compressed) data on page
@@ -311,7 +299,7 @@ typedef struct t_fproc { // Descriptor of processed file
int rempages[8]; // 1-based list of remaining pages
} t_fproc;

extern t_fproc pb_fproc[NFILE]; // Processed files
extern t_fproc pb_fproc[NFILE]; // Processed file

void Closefproc(int slot);
int Startnextpage(t_superblock *superblock);
@@ -353,27 +341,44 @@ extern int pb_marginright; // Right printer page margin
extern int pb_margintop; // Top printer page margin
extern int pb_marginbottom; // Bottom printer page margin
void Options(void);
int Confirmpassword();
int Getpassword(void);


////////////////////////////////////////////////////////////////////////////////
////////////////////////////// SERVICE FUNCTIONS ///////////////////////////////


inline void Reporterror(const char *input) {
inline void Reporterror(const char *input)
{
printf("%s\n", input);
}



inline void Message(const char *input, int progress) {
inline void Message(const char *input, int progress)
{
printf("%s @ %d\%", input, progress);
}



// Formerly standard case insentitive cstring compare
inline int strnicmp (const char *str1, const char *str2, size_t len)
{
char s1[len], s2[len];
strcpy (s1, str1);
strcpy (s2, str2);
for (int i = 0; i < len; i++) {
s1[i] = tolower(s1[i]);
s2[i] = tolower(s1[i]);
if (s1[i] < s2[i]) //s1 less than s2, return negative
return -1;
else if (s1[i] > s2[i]) //s1 more than s2, return positive
return 1;
}

// if all characters are the same, return 0
return 0;
}


// Portable version of Borlands fnsplit
// NOTE: Does not handle wildcard *
@@ -382,77 +387,85 @@ inline int fnsplit(const char *path,
char *drive,
char *dir,
char *name,
char *ext,
int pathLen)
char *ext)
{
int i = 0; // for loop iterator set after drive letter, if needed
if (path != NULL && pathLen > 2 && path[1] == ':') {
if (drive != NULL)
strcat (drive, path);
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;
if (path != NULL) {
if (MAXPATH > 2 && path[1] == ':') {
if (drive != NULL) {
strncat (drive, path, 2);
drive[2] = '\0';
}
i = 2;
}
// token is name or extension
else if (path[i] == '\0' || i >= pathLen - 1 ) {
if (hasName) {
// is extension

// path not necessarily terminated by \0
// parse char by char
char token[MAXPATH];
int iToken = 0;
bool hasName = false;
if (dir != NULL)
dir[0] = '\0';

for ( ; i < MAXPATH; 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 (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;
strcpy (name, token);
token[0] = '.';
iToken = 1;
continue;
}
// token is name or extension
else if (path[i] == '\0' || i >= MAXPATH - 1 ) {
if (hasName) {
// is extension
token[iToken] = '\0';
if (ext != NULL)
strcpy (ext, token);
// all parts gathered, exit function
break;
}
else {
// is name
token[i] = '\0';
if (name != NULL)
strcpy (name, token);
// all parts gathered, exit
break;
}
}
else {
//if not delimiter, build string
token[iToken++] = path[i];
}
}
else {
//if not delimiter, build string
token[iToken++] = path[i];
}
return 0;
}
return 0;
else
return -1;
}



// Portable version of Borlands fnmerge
inline void fnmerge (char *path,
const char *drive,
const char *dir,
const char *name,
const char * ext)
const char *drive,
const char *dir,
const char *name,
const char * ext)
{
if (path == NULL) {
return;
@@ -475,6 +488,27 @@ inline void fnmerge (char *path,
}


// returns 0 on success, -1 on failure
inline int Getpassword()
{
char * pw = getpass("Enter encryption password: ");
int pwLength = strlen(pw);

if (pwLength > 0 && pwLength <= (PASSLEN - 1) ) {
// put password into global password variable
strcpy (::pb_password, pw);
// overwrite pw for security
memset (pw, 0, pwLength);
return 0;
}
else {
Reporterror("Password must be 32 characters or less");
// overwrite pw for security
memset (pw, 0, pwLength);
return -1;
}
}


////////////////////////////////////////////////////////////////////////////////
////////////////////////// WINDOWS SERVICE FUNCTIONS ///////////////////////////
@@ -500,15 +534,5 @@ inline void print_filetime(FILETIME ftime) {
}
}

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;
};

#endif


Loading…
Cancel
Save