mirror of
https://codeberg.org/scip/pcp.git
synced 2025-12-17 20:00:58 +01:00
finally fixed all stream related problems, z85 transparent en/decoding works, unittests all ok.
This commit is contained in:
@@ -125,11 +125,16 @@ byte *buffer_get(Buffer *b) {
|
||||
}
|
||||
|
||||
size_t buffer_get_chunk(Buffer *b, void *buf, size_t len) {
|
||||
if(len > b->end - b->offset || len == 0) {
|
||||
if(len > b->end - b->offset) {
|
||||
fatal("[buffer %s] attempt to read %ld bytes data from buffer with %ld bytes left at offset %ld\n",
|
||||
b->name, len, b->end - b->offset, b->offset);
|
||||
return 0;
|
||||
}
|
||||
else if(len == 0) {
|
||||
/* FIXME: check how this happens */
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(buf, b->buf + b->offset, len);
|
||||
|
||||
b->offset += len;
|
||||
@@ -137,11 +142,15 @@ size_t buffer_get_chunk(Buffer *b, void *buf, size_t len) {
|
||||
}
|
||||
|
||||
size_t buffer_get_chunk_tobuf(Buffer *b, Buffer *dst, size_t len) {
|
||||
if(len > b->end - b->offset || len == 0) {
|
||||
if(len > b->end - b->offset) {
|
||||
fatal("[buffer %s] attempt to read %ld bytes data from buffer with %ld bytes left at offset %ld\n",
|
||||
b->name, len, b->end - b->offset, b->offset);
|
||||
return 0;
|
||||
}
|
||||
else if(len == 0) {
|
||||
/* FIXME: check how this happens */
|
||||
return 0;
|
||||
}
|
||||
|
||||
buffer_resize(dst, len);
|
||||
memcpy(dst->buf+buffer_size(dst), b->buf + b->offset, len);
|
||||
|
||||
@@ -178,7 +178,7 @@ size_t pcp_decrypt_stream(Pcpstream *in, Pcpstream* out, pcp_key_t *s, byte *sym
|
||||
|
||||
nrec = recmatch = self = 0;
|
||||
|
||||
if(ps_tell(in) == 1) {
|
||||
if(ps_tell(in) > 1) {
|
||||
/* header has already been determined outside the lib */
|
||||
if(symkey != NULL)
|
||||
self = 1;
|
||||
@@ -233,7 +233,7 @@ size_t pcp_decrypt_stream(Pcpstream *in, Pcpstream* out, pcp_key_t *s, byte *sym
|
||||
for(nrec=0; nrec<lenrec; nrec++) {
|
||||
cur_bufsize = ps_read(in, &rec_buf, PCP_ASYM_RECIPIENT_SIZE); /* fread(&rec_buf, 1, PCP_ASYM_RECIPIENT_SIZE, in); */
|
||||
if(cur_bufsize != PCP_ASYM_RECIPIENT_SIZE && !ps_end(in) && !ps_err(in)) {
|
||||
fatal("Error: input file corrupted, incomplete or no recipients\n");
|
||||
fatal("Error: input file corrupted, incomplete or no recipients (got %ld, exp %ld)\n", cur_bufsize, PCP_ASYM_RECIPIENT_SIZE );
|
||||
goto errdef1;
|
||||
}
|
||||
recmatch = 0;
|
||||
@@ -262,17 +262,18 @@ size_t pcp_decrypt_stream(Pcpstream *in, Pcpstream* out, pcp_key_t *s, byte *sym
|
||||
fatal("Sorry, there's no matching public key in your vault for decryption\n");
|
||||
goto errdef1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* step 5, actually decrypt the file, finally */
|
||||
if(verify) {
|
||||
pcp_rec_t *rec = pcp_rec_new(reccipher, nrec * PCP_ASYM_RECIPIENT_SIZE, NULL, cur);
|
||||
return pcp_decrypt_stream_sym(in, out, symkey, rec);
|
||||
size_t s = pcp_decrypt_stream_sym(in, out, symkey, rec);
|
||||
pcp_rec_free(rec);
|
||||
return s;
|
||||
}
|
||||
else {
|
||||
size_t s = pcp_decrypt_stream_sym(in, out, symkey, NULL);
|
||||
return s;
|
||||
}
|
||||
else
|
||||
return pcp_decrypt_stream_sym(in, out, symkey, NULL);
|
||||
|
||||
|
||||
errdef1:
|
||||
return 0;
|
||||
|
||||
@@ -60,8 +60,8 @@ void ps_setdetermine(Pcpstream *stream, size_t blocksize) {
|
||||
stream->determine = 1;
|
||||
stream->blocksize = blocksize + (5 - (blocksize % 5));
|
||||
if(stream->cache == NULL) {
|
||||
stream->cache = buffer_new(32, "Pcpstreamcache");
|
||||
stream->next = buffer_new(32, "Pcpstreamcachenext");
|
||||
stream->cache = buffer_new(32, "Pcpstreamcachedetermine");
|
||||
stream->next = buffer_new(32, "Pcpstreamcachenextdetermin");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,10 @@ void ps_armor(Pcpstream *stream, size_t blocksize) {
|
||||
}
|
||||
}
|
||||
|
||||
void ps_unarmor(Pcpstream *stream) {
|
||||
stream->armor = 0;
|
||||
}
|
||||
|
||||
size_t ps_read_raw(Pcpstream *stream, void *buf, size_t readbytes) {
|
||||
size_t gotbytes = 0;
|
||||
|
||||
@@ -107,18 +111,28 @@ size_t ps_read_raw(Pcpstream *stream, void *buf, size_t readbytes) {
|
||||
/* return readbytes from cache. if it is more than left in the cache
|
||||
fetch (and decode) the next chunk, append it to cache and return from
|
||||
that */
|
||||
|
||||
size_t ps_read_cached(Pcpstream *stream, void *buf, size_t readbytes) {
|
||||
if(buffer_left(stream->cache) <= readbytes && buffer_left(stream->cache) > 0 && readbytes <= stream->blocksize) {
|
||||
/*
|
||||
fprintf(stderr, "%ld <= %ld && %ld <= %ld\n",
|
||||
readbytes, buffer_left(stream->cache), readbytes, stream->blocksize) ;
|
||||
|
||||
fprintf(stderr, "%d == 1 && %ld >= %ld\n", ps_left(stream), readbytes, buffer_left(stream->cache));
|
||||
*/
|
||||
if(readbytes <= buffer_left(stream->cache) && readbytes <= stream->blocksize) {
|
||||
/* enough left in current cache */
|
||||
return buffer_get_chunk(stream->cache, buf, readbytes);
|
||||
}
|
||||
else if(ps_left(stream) == 1 && readbytes >= buffer_left(stream->cache)) {
|
||||
return buffer_get_chunk(stream->cache, buf, buffer_left(stream->cache));
|
||||
}
|
||||
else {
|
||||
/* request for chunk larger than what we've got in the cache */
|
||||
Buffer *tmp = buffer_new(stream->blocksize, "Pcpreadover");
|
||||
Buffer *tmp = buffer_new(stream->blocksize, "Pcpreadchunktmp");
|
||||
|
||||
if( buffer_left(stream->cache) > 0) {
|
||||
/* put the remaining cache into dest */
|
||||
buffer_get_chunk_tobuf(stream->cache, tmp, buffer_size(stream->cache));
|
||||
buffer_get_chunk_tobuf(stream->cache, tmp, buffer_left(stream->cache));
|
||||
}
|
||||
|
||||
/* how much left to fetch */
|
||||
@@ -170,26 +184,31 @@ size_t ps_read_cached(Pcpstream *stream, void *buf, size_t readbytes) {
|
||||
|
||||
/* read and decode the next chunk and put it into stream->next */
|
||||
size_t ps_read_next(Pcpstream *stream) {
|
||||
if(stream->armor == 1) {
|
||||
/* fetch next chunk and decode it */
|
||||
return ps_read_decode(stream, NULL, 0);
|
||||
}
|
||||
else {
|
||||
/* unencoded source, fetch as is */
|
||||
void *buf = ucmalloc(stream->blocksize);
|
||||
size_t got = ps_read_raw(stream, buf, stream->blocksize);
|
||||
buffer_add(stream->next, buf, got);
|
||||
return got;
|
||||
if(ps_left(stream) == 0) {
|
||||
if(stream->armor == 1) {
|
||||
/* fetch next chunk and decode it */
|
||||
return ps_read_decode(stream, NULL, 0);
|
||||
}
|
||||
else {
|
||||
/* unencoded source, fetch as is */
|
||||
void *buf = ucmalloc(stream->blocksize);
|
||||
size_t got = ps_read_raw(stream, buf, stream->blocksize);
|
||||
buffer_add(stream->next, buf, got);
|
||||
return got;
|
||||
}
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ps_read(Pcpstream *stream, void *buf, size_t readbytes) {
|
||||
size_t got = 0;
|
||||
if(stream->cache == NULL) {
|
||||
return ps_read_raw(stream, buf, readbytes);
|
||||
got = ps_read_raw(stream, buf, readbytes);
|
||||
}
|
||||
else if(buffer_size(stream->cache) > 0) {
|
||||
/* use cache */
|
||||
return ps_read_cached(stream, buf, readbytes);
|
||||
got = ps_read_cached(stream, buf, readbytes);
|
||||
}
|
||||
else {
|
||||
/* no cache yet */
|
||||
@@ -197,18 +216,22 @@ size_t ps_read(Pcpstream *stream, void *buf, size_t readbytes) {
|
||||
/* fetch the first chunk into the cache and decode, if required,
|
||||
recursively call ps_read() again to return the apropriate data */
|
||||
ps_determine(stream);
|
||||
return ps_read(stream, buf, readbytes);
|
||||
got = ps_read(stream, buf, readbytes);
|
||||
}
|
||||
else if(stream->armor == 1) {
|
||||
/* z85 encoding has already been determined, therefore the cache
|
||||
is now filled, use it then */
|
||||
return ps_read_cached(stream, buf, readbytes);
|
||||
got = ps_read_cached(stream, buf, readbytes);
|
||||
}
|
||||
else {
|
||||
/* read directly from source */
|
||||
return ps_read_raw(stream, buf, readbytes);
|
||||
got = ps_read_raw(stream, buf, readbytes);
|
||||
}
|
||||
}
|
||||
|
||||
stream->pos += got;
|
||||
|
||||
return got;
|
||||
}
|
||||
|
||||
void ps_determine(Pcpstream *stream) {
|
||||
@@ -285,6 +308,8 @@ size_t ps_read_decode(Pcpstream *stream, void *buf, size_t bufsize) {
|
||||
size_t ps_write(Pcpstream *stream, void *buf, size_t writebytes) {
|
||||
Buffer *z = buffer_new(32, "Pcpwritetemp");
|
||||
|
||||
stream->is_output = 1;
|
||||
|
||||
if(stream->armor == 1) {
|
||||
if(buffer_size(stream->cache) + writebytes < stream->blocksize) {
|
||||
/* just put it into the cache and done with it */
|
||||
@@ -350,13 +375,16 @@ size_t ps_write(Pcpstream *stream, void *buf, size_t writebytes) {
|
||||
/* actually put it out */
|
||||
size_t outsize = ps_write_buf(stream, z);
|
||||
buffer_free(z);
|
||||
return outsize;
|
||||
writebytes = outsize;
|
||||
}
|
||||
else {
|
||||
/* buf has been put into the cache only, no writing required */
|
||||
buffer_free(z);
|
||||
return writebytes;
|
||||
}
|
||||
|
||||
stream->pos += writebytes;
|
||||
|
||||
return writebytes;
|
||||
}
|
||||
|
||||
void ps_write_encode(Pcpstream *stream, Buffer *dst) {
|
||||
@@ -372,14 +400,14 @@ void ps_write_encode(Pcpstream *stream, Buffer *dst) {
|
||||
}
|
||||
|
||||
/* z85 encode */
|
||||
zlen = (buffer_size(stream->cache) * 5 / 4);
|
||||
zlen = (buffer_size(stream->cache) * 5 / 4) + 1;
|
||||
char *z85 = ucmalloc(zlen);
|
||||
|
||||
zmq_z85_encode(z85, buffer_get(stream->cache), buffer_size(stream->cache));
|
||||
|
||||
/* add newlines */
|
||||
pos = stream->linewr;
|
||||
for(i=0; i<zlen; ++i) {
|
||||
for(i=0; i<zlen-1; ++i) {
|
||||
if(pos >= 71) {
|
||||
buffer_add8(dst, '\r');
|
||||
buffer_add8(dst, '\n');
|
||||
@@ -445,7 +473,11 @@ size_t ps_print(Pcpstream *stream, const char * fmt, ...) {
|
||||
|
||||
void ps_close(Pcpstream *stream) {
|
||||
if(stream->cache != NULL) {
|
||||
assert(buffer_left(stream->cache) == 0); /* there's something left in the cache, call ps_finish() */
|
||||
if(stream->is_output == 1) {
|
||||
if(buffer_left(stream->cache) != 0)
|
||||
buffer_info(stream->cache);
|
||||
assert(buffer_left(stream->cache) == 0); /* there's something left in the cache, call ps_finish() */
|
||||
}
|
||||
buffer_free(stream->cache);
|
||||
}
|
||||
|
||||
@@ -467,25 +499,31 @@ void ps_close(Pcpstream *stream) {
|
||||
int ps_end(Pcpstream *stream) {
|
||||
/* simulate open file if there's still something in the cache */
|
||||
if(stream->cache != NULL)
|
||||
if(buffer_left(stream->cache) > 0)
|
||||
if(buffer_left(stream->cache) > 0) {
|
||||
return 0;
|
||||
}
|
||||
return stream->eof;
|
||||
}
|
||||
|
||||
int ps_left(Pcpstream *stream) {
|
||||
/* used internally to determine if we reached end of source */
|
||||
if(stream->is_buffer) {
|
||||
if(buffer_left(stream->b) == 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return feof(stream->fd);
|
||||
}
|
||||
}
|
||||
|
||||
int ps_err(Pcpstream *stream) {
|
||||
return stream->err;
|
||||
}
|
||||
|
||||
size_t ps_tell(Pcpstream *stream) {
|
||||
if(stream->is_buffer) {
|
||||
if(stream->b->end > stream->b->offset)
|
||||
return stream->b->end; /* write buffer */
|
||||
else
|
||||
return stream->b->offset; /* read buffer */
|
||||
}
|
||||
else {
|
||||
return ftell(stream->fd);
|
||||
}
|
||||
return stream->pos;
|
||||
}
|
||||
|
||||
Buffer *ps_buffer(Pcpstream *stream) {
|
||||
|
||||
Reference in New Issue
Block a user