void extract_reference_file(const char *name) { char buff[1024]; FILE *in, *out; sprintf(buff, "%s/%s.uu", refdir, name); in = fopen(buff, "r"); failure("Couldn't open reference file %s", buff); assert(in != NULL); if (in == NULL) return; /* Read up to and including the 'begin' line. */ for (;;) { if (fgets(buff, sizeof(buff), in) == NULL) { /* TODO: This is a failure. */ return; } if (memcmp(buff, "begin ", 6) == 0) break; } /* Now, decode the rest and write it. */ /* Not a lot of error checking here; the input better be right. */ out = fopen(name, "w"); while (fgets(buff, sizeof(buff), in) != NULL) { char *p = buff; int bytes; if (memcmp(buff, "end", 3) == 0) break; bytes = UUDECODE(*p++); while (bytes > 0) { int n = 0; /* Write out 1-3 bytes from that. */ if (bytes > 0) { n = UUDECODE(*p++) << 18; n |= UUDECODE(*p++) << 12; fputc(n >> 16, out); --bytes; } if (bytes > 0) { n |= UUDECODE(*p++) << 6; fputc((n >> 8) & 0xFF, out); --bytes; } if (bytes > 0) { n |= UUDECODE(*p++); fputc(n & 0xFF, out); --bytes; } }
static ssize_t uudecode_filter_read(struct archive_read_filter *self, const void **buff) { struct uudecode *uudecode; const unsigned char *b, *d; unsigned char *out; ssize_t avail_in, ravail; ssize_t used; ssize_t total; ssize_t len, llen, nl; uudecode = (struct uudecode *)self->data; read_more: d = __archive_read_filter_ahead(self->upstream, 1, &avail_in); if (d == NULL && avail_in < 0) return (ARCHIVE_FATAL); /* Quiet a code analyzer; make sure avail_in must be zero * when d is NULL. */ if (d == NULL) avail_in = 0; used = 0; total = 0; out = uudecode->out_buff; ravail = avail_in; if (uudecode->state == ST_IGNORE) { used = avail_in; goto finish; } if (uudecode->in_cnt) { /* * If there is remaining data which is saved by * previous calling, use it first. */ if (ensure_in_buff_size(self, uudecode, avail_in + uudecode->in_cnt) != ARCHIVE_OK) return (ARCHIVE_FATAL); memcpy(uudecode->in_buff + uudecode->in_cnt, d, avail_in); d = uudecode->in_buff; avail_in += uudecode->in_cnt; uudecode->in_cnt = 0; } for (;used < avail_in; d += llen, used += llen) { int64_t l, body; b = d; len = get_line(b, avail_in - used, &nl); if (len < 0) { /* Non-ascii character is found. */ if (uudecode->state == ST_FIND_HEAD && (uudecode->total > 0 || total > 0)) { uudecode->state = ST_IGNORE; used = avail_in; goto finish; } archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, "Insufficient compressed data"); return (ARCHIVE_FATAL); } llen = len; if (nl == 0) { /* * Save remaining data which does not contain * NL('\n','\r'). */ if (ensure_in_buff_size(self, uudecode, len) != ARCHIVE_OK) return (ARCHIVE_FATAL); if (uudecode->in_buff != b) memmove(uudecode->in_buff, b, len); uudecode->in_cnt = (int)len; if (total == 0) { /* Do not return 0; it means end-of-file. * We should try to read bytes more. */ __archive_read_filter_consume( self->upstream, ravail); goto read_more; } break; } switch (uudecode->state) { default: case ST_FIND_HEAD: /* Do not read more than UUENCODE_BID_MAX_READ bytes */ if (total + len >= UUENCODE_BID_MAX_READ) { archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid format data"); return (ARCHIVE_FATAL); } if (len - nl >= 11 && memcmp(b, "begin ", 6) == 0) l = 6; else if (len - nl >= 18 && memcmp(b, "begin-base64 ", 13) == 0) l = 13; else l = 0; if (l != 0 && b[l] >= '0' && b[l] <= '7' && b[l+1] >= '0' && b[l+1] <= '7' && b[l+2] >= '0' && b[l+2] <= '7' && b[l+3] == ' ') { if (l == 6) uudecode->state = ST_READ_UU; else uudecode->state = ST_READ_BASE64; } break; case ST_READ_UU: if (total + len * 2 > OUT_BUFF_SIZE) goto finish; body = len - nl; if (!uuchar[*b] || body <= 0) { archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, "Insufficient compressed data"); return (ARCHIVE_FATAL); } /* Get length of undecoded bytes of curent line. */ l = UUDECODE(*b++); body--; if (l > body) { archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, "Insufficient compressed data"); return (ARCHIVE_FATAL); } if (l == 0) { uudecode->state = ST_UUEND; break; } while (l > 0) { int n = 0; if (l > 0) { if (!uuchar[b[0]] || !uuchar[b[1]]) break; n = UUDECODE(*b++) << 18; n |= UUDECODE(*b++) << 12; *out++ = n >> 16; total++; --l; } if (l > 0) { if (!uuchar[b[0]]) break; n |= UUDECODE(*b++) << 6; *out++ = (n >> 8) & 0xFF; total++; --l; } if (l > 0) { if (!uuchar[b[0]]) break; n |= UUDECODE(*b++); *out++ = n & 0xFF; total++; --l; } } if (l) { archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, "Insufficient compressed data"); return (ARCHIVE_FATAL); } break; case ST_UUEND: if (len - nl == 3 && memcmp(b, "end ", 3) == 0) uudecode->state = ST_FIND_HEAD; else { archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, "Insufficient compressed data"); return (ARCHIVE_FATAL); } break; case ST_READ_BASE64: if (total + len * 2 > OUT_BUFF_SIZE) goto finish; l = len - nl; if (l >= 3 && b[0] == '=' && b[1] == '=' && b[2] == '=') { uudecode->state = ST_FIND_HEAD; break; } while (l > 0) { int n = 0; if (l > 0) { if (!base64[b[0]] || !base64[b[1]]) break; n = base64num[*b++] << 18; n |= base64num[*b++] << 12; *out++ = n >> 16; total++; l -= 2; } if (l > 0) { if (*b == '=') break; if (!base64[*b]) break; n |= base64num[*b++] << 6; *out++ = (n >> 8) & 0xFF; total++; --l; } if (l > 0) { if (*b == '=') break; if (!base64[*b]) break; n |= base64num[*b++]; *out++ = n & 0xFF; total++; --l; } } if (l && *b != '=') { archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, "Insufficient compressed data"); return (ARCHIVE_FATAL); } break; } } finish: if (ravail < avail_in) used -= avail_in - ravail; __archive_read_filter_consume(self->upstream, used); *buff = uudecode->out_buff; uudecode->total += total; return (total); }
static int uudecode_bidder_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) { const unsigned char *b; ssize_t avail, ravail; ssize_t len, nl; int l; int firstline; size_t nbytes_read; (void)self; /* UNUSED */ b = __archive_read_filter_ahead(filter, 1, &avail); if (b == NULL) return (0); firstline = 20; ravail = avail; nbytes_read = avail; for (;;) { len = bid_get_line(filter, &b, &avail, &ravail, &nl, &nbytes_read); if (len < 0 || nl == 0) return (0); /* No match found. */ if (len - nl >= 11 && memcmp(b, "begin ", 6) == 0) l = 6; else if (len -nl >= 18 && memcmp(b, "begin-base64 ", 13) == 0) l = 13; else l = 0; if (l > 0 && (b[l] < '0' || b[l] > '7' || b[l+1] < '0' || b[l+1] > '7' || b[l+2] < '0' || b[l+2] > '7' || b[l+3] != ' ')) l = 0; b += len; avail -= len; if (l) break; firstline = 0; /* Do not read more than UUENCODE_BID_MAX_READ bytes */ if (nbytes_read >= UUENCODE_BID_MAX_READ) return (0); } if (!avail) return (0); len = bid_get_line(filter, &b, &avail, &ravail, &nl, &nbytes_read); if (len < 0 || nl == 0) return (0);/* There are non-ascii characters. */ avail -= len; if (l == 6) { if (!uuchar[*b]) return (0); /* Get a length of decoded bytes. */ l = UUDECODE(*b++); len--; if (l > 45) /* Normally, maximum length is 45(character 'M'). */ return (0); while (l && len-nl > 0) { if (l > 0) { if (!uuchar[*b++]) return (0); if (!uuchar[*b++]) return (0); len -= 2; --l; } if (l > 0) { if (!uuchar[*b++]) return (0); --len; --l; } if (l > 0) { if (!uuchar[*b++]) return (0); --len; --l; } } if (len-nl < 0) return (0); if (len-nl == 1 && (uuchar[*b] || /* Check sum. */ (*b >= 'a' && *b <= 'z'))) {/* Padding data(MINIX). */ ++b; --len; } b += nl; if (avail && uuchar[*b]) return (firstline+30); } if (l == 13) { while (len-nl > 0) { if (!base64[*b++]) return (0); --len; } b += nl; if (avail >= 5 && memcmp(b, "====\n", 5) == 0) return (firstline+40); if (avail >= 6 && memcmp(b, "====\r\n", 6) == 0) return (firstline+40); if (avail > 0 && base64[*b]) return (firstline+30); } return (0); }