int oid_dotstring_to_oid(const char *name, Odr_oid *oid) { int i = 0; int val = 0; while (yaz_isdigit (*name)) { val = val*10 + (*name - '0'); name++; if (*name == '.') { if (i < OID_SIZE-1) oid[i++] = val; val = 0; name++; } } if (i == 0) return -1; oid[i] = val; oid[i+1] = -1; return 0; }
static int cs_complete_http(const char *buf, int len, int head_only) { /* deal with HTTP request/response */ int i, content_len = 0, chunked = 0; /* need at least one line followed by \n or \r .. */ for (i = 0; ; i++) if (i == len) return 0; /* incomplete */ else if (buf[i] == '\n' || buf[i] == '\r') break; /* check to see if it's a response with content */ if (!head_only && !memcmp(buf, "HTTP/", 5)) { int j; for (j = 5; j < i; j++) if (buf[j] == ' ') { ++j; if (buf[j] == '1') /* 1XX */ ; else if (!memcmp(buf + j, "204", 3)) ; else if (!memcmp(buf + j, "304", 3)) ; else content_len = -1; break; } } #if 0 printf("len = %d\n", len); fwrite (buf, 1, len, stdout); printf("----------\n"); #endif for (i = 2; i <= len-2; ) { if (i > 8192) { return i; /* do not allow more than 8K HTTP header */ } if (skip_crlf(buf, len, &i)) { if (skip_crlf(buf, len, &i)) { /* inside content */ if (chunked) return cs_read_chunk(buf, i, len); else { /* not chunked ; inside body */ if (content_len == -1) return 0; /* no content length */ else if (len >= i + content_len) { return i + content_len; } } break; } else if (i < len - 20 && !yaz_strncasecmp((const char *) buf+i, "Transfer-Encoding:", 18)) { i+=18; while (buf[i] == ' ') i++; if (i < len - 8) if (!yaz_strncasecmp((const char *) buf+i, "chunked", 7)) chunked = 1; } else if (i < len - 17 && !yaz_strncasecmp((const char *)buf+i, "Content-Length:", 15)) { i+= 15; while (buf[i] == ' ') i++; content_len = 0; while (i <= len-4 && yaz_isdigit(buf[i])) content_len = content_len*10 + (buf[i++] - '0'); if (content_len < 0) /* prevent negative offsets */ content_len = 0; } else i++; } else i++; } return 0; }
static int cs_read_chunk(const char *buf, int i, int len) { /* inside chunked body .. */ while (1) { int chunk_len = 0; #if CHUNK_DEBUG if (i < len-2) { int j; printf ("\n<<<"); for (j = i; j <= i+3; j++) printf ("%c", buf[j]); printf (">>>\n"); } #endif /* read chunk length */ while (1) if (i >= len-2) { #if CHUNK_DEBUG printf ("returning incomplete read at 1\n"); printf ("i=%d len=%d\n", i, len); #endif return 0; } else if (yaz_isdigit(buf[i])) chunk_len = chunk_len * 16 + (buf[i++] - '0'); else if (yaz_isupper(buf[i])) chunk_len = chunk_len * 16 + (buf[i++] - ('A'-10)); else if (yaz_islower(buf[i])) chunk_len = chunk_len * 16 + (buf[i++] - ('a'-10)); else break; if (chunk_len == 0) break; if (chunk_len < 0) return i; while (1) { if (i >= len -1) return 0; if (skip_crlf(buf, len, &i)) break; i++; } /* got CRLF */ #if CHUNK_DEBUG printf ("chunk_len=%d\n", chunk_len); #endif i += chunk_len; if (i >= len-2) return 0; if (!skip_crlf(buf, len, &i)) return 0; } /* consider trailing headers .. */ while (i < len) { if (skip_crlf(buf, len, &i)) { if (skip_crlf(buf, len, &i)) return i; } else i++; } #if CHUNK_DEBUG printf ("returning incomplete read at 2\n"); printf ("i=%d len=%d\n", i, len); #endif return 0; }
static int cql_transform_parse_tok_line(cql_transform_t ct, const char *pattern, yaz_tok_parse_t tp) { int ae_num = 0; Z_AttributeElement *ae[20]; int ret = 0; /* 0=OK, != 0 FAIL */ int t; t = yaz_tok_move(tp); while (t == YAZ_TOK_STRING && ae_num < 20) { WRBUF type_str = wrbuf_alloc(); WRBUF set_str = 0; Z_AttributeElement *elem = 0; const char *value_str = 0; /* attset type=value OR type=value */ elem = (Z_AttributeElement *) nmem_malloc(ct->nmem, sizeof(*elem)); elem->attributeSet = 0; ae[ae_num] = elem; wrbuf_puts(ct->w, yaz_tok_parse_string(tp)); wrbuf_puts(type_str, yaz_tok_parse_string(tp)); t = yaz_tok_move(tp); if (t == YAZ_TOK_EOF) { wrbuf_destroy(type_str); if (set_str) wrbuf_destroy(set_str); break; } if (t == YAZ_TOK_STRING) { wrbuf_puts(ct->w, " "); wrbuf_puts(ct->w, yaz_tok_parse_string(tp)); set_str = type_str; elem->attributeSet = yaz_string_to_oid_nmem(yaz_oid_std(), CLASS_ATTSET, wrbuf_cstr(set_str), ct->nmem); type_str = wrbuf_alloc(); wrbuf_puts(type_str, yaz_tok_parse_string(tp)); t = yaz_tok_move(tp); } elem->attributeType = nmem_intdup(ct->nmem, 0); if (sscanf(wrbuf_cstr(type_str), ODR_INT_PRINTF, elem->attributeType) != 1) { wrbuf_destroy(type_str); if (set_str) wrbuf_destroy(set_str); yaz_log(YLOG_WARN, "Expected numeric attribute type"); ret = -1; break; } wrbuf_destroy(type_str); if (set_str) wrbuf_destroy(set_str); if (t != '=') { yaz_log(YLOG_WARN, "Expected = after after attribute type"); ret = -1; break; } t = yaz_tok_move(tp); if (t != YAZ_TOK_STRING) /* value */ { yaz_log(YLOG_WARN, "Missing attribute value"); ret = -1; break; } value_str = yaz_tok_parse_string(tp); if (yaz_isdigit(*value_str)) { elem->which = Z_AttributeValue_numeric; elem->value.numeric = nmem_intdup(ct->nmem, atoi(value_str)); } else { Z_ComplexAttribute *ca = (Z_ComplexAttribute *) nmem_malloc(ct->nmem, sizeof(*ca)); elem->which = Z_AttributeValue_complex; elem->value.complex = ca; ca->num_list = 1; ca->list = (Z_StringOrNumeric **) nmem_malloc(ct->nmem, sizeof(Z_StringOrNumeric *)); ca->list[0] = (Z_StringOrNumeric *) nmem_malloc(ct->nmem, sizeof(Z_StringOrNumeric)); ca->list[0]->which = Z_StringOrNumeric_string; ca->list[0]->u.string = nmem_strdup(ct->nmem, value_str); ca->num_semanticAction = 0; ca->semanticAction = 0; } wrbuf_puts(ct->w, "="); wrbuf_puts(ct->w, yaz_tok_parse_string(tp)); t = yaz_tok_move(tp); wrbuf_puts(ct->w, " "); ae_num++; } if (ret == 0) /* OK? */ { struct cql_prop_entry **pp = &ct->entry; while (*pp) pp = &(*pp)->next; *pp = (struct cql_prop_entry *) xmalloc(sizeof(**pp)); (*pp)->pattern = xstrdup(pattern); (*pp)->value = xstrdup(wrbuf_cstr(ct->w)); (*pp)->attr_list.num_attributes = ae_num; if (ae_num == 0) (*pp)->attr_list.attributes = 0; else { (*pp)->attr_list.attributes = (Z_AttributeElement **) nmem_malloc(ct->nmem, ae_num * sizeof(Z_AttributeElement *)); memcpy((*pp)->attr_list.attributes, ae, ae_num * sizeof(Z_AttributeElement *)); } (*pp)->next = 0; if (0) { ODR pr = odr_createmem(ODR_PRINT); Z_AttributeList *alp = &(*pp)->attr_list; odr_setprint(pr, yaz_log_file()); z_AttributeList(pr, &alp, 0, 0); odr_setprint(pr, 0); odr_destroy(pr); } } return ret; }
static void emit_term(cql_transform_t ct, struct cql_node *cn, const char *term, int length, void (*pr)(const char *buf, void *client_data), void *client_data) { int i; const char *ns = cn->u.st.index_uri; int z3958_mode = 0; int process_term = 1; if (has_modifier(cn, "regexp")) process_term = 0; else if (cql_lookup_property(ct, "truncation", 0, "cql")) { process_term = 0; cql_pr_attr(ct, "truncation", "cql", 0, pr, client_data, YAZ_SRW_MASKING_CHAR_UNSUPP); } assert(cn->which == CQL_NODE_ST); if (process_term) { unsigned anchor = 0; unsigned trunc = 0; for (i = 0; i < length; i++) { if (term[i] == '\\' && i < length - 1) i++; else { switch (term[i]) { case '^': if (i == 0) anchor |= 1; else if (i == length - 1) anchor |= 2; break; case '*': if (i == 0) trunc |= 1; else if (i == length - 1) trunc |= 2; else z3958_mode = 1; break; case '?': z3958_mode = 1; break; } } } if (anchor == 3) { cql_pr_attr(ct, "position", "firstAndLast", 0, pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); term++; length -= 2; } else if (anchor == 1) { cql_pr_attr(ct, "position", "first", 0, pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); term++; length--; } else if (anchor == 2) { cql_pr_attr(ct, "position", "last", 0, pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); length--; } else { cql_pr_attr(ct, "position", "any", 0, pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); } if (z3958_mode == 0) { if (trunc == 3 && cql_pr_attr(ct, "truncation", "both", 0, pr, client_data, 0)) { term++; length -= 2; } else if (trunc == 1 && cql_pr_attr(ct, "truncation", "left", 0, pr, client_data, 0)) { term++; length--; } else if (trunc == 2 && cql_pr_attr(ct, "truncation", "right", 0, pr, client_data, 0)) { length--; } else if (trunc) z3958_mode = 1; else cql_pr_attr(ct, "truncation", "none", 0, pr, client_data, 0); } if (z3958_mode) cql_pr_attr(ct, "truncation", "z3958", 0, pr, client_data, YAZ_SRW_MASKING_CHAR_UNSUPP); } if (ns) { cql_pr_attr_uri(ct, "index", ns, cn->u.st.index, "serverChoice", pr, client_data, YAZ_SRW_UNSUPP_INDEX); } if (cn->u.st.modifiers) { struct cql_node *mod = cn->u.st.modifiers; for (; mod; mod = mod->u.st.modifiers) { cql_pr_attr(ct, "relationModifier", mod->u.st.index, 0, pr, client_data, YAZ_SRW_UNSUPP_RELATION_MODIFIER); } } (*pr)("\"", client_data); if (process_term) for (i = 0; i < length; i++) { char x[2]; /* temp buffer */ if (term[i] == '\\' && i < length - 1) { i++; if (strchr("\"\\", term[i])) pr("\\", client_data); if (z3958_mode && strchr("#?", term[i])) pr("\\\\", client_data); /* double \\ to survive PQF parse */ x[0] = term[i]; x[1] = '\0'; pr(x, client_data); } else if (z3958_mode && term[i] == '*') { pr("?", client_data); if (i < length - 1 && yaz_isdigit(term[i+1])) pr("\\\\", client_data); /* dbl \\ to survive PQF parse */ } else if (z3958_mode && term[i] == '?') { pr("#", client_data); } else { if (term[i] == '\"') pr("\\", client_data); if (z3958_mode && strchr("#?", term[i])) pr("\\\\", client_data); /* dbl \\ to survive PQF parse */ x[0] = term[i]; x[1] = '\0'; pr(x, client_data); } } else { for (i = 0; i < length; i++) { char x[2]; x[0] = term[i]; x[1] = '\0'; pr(x, client_data); } } (*pr)("\" ", client_data); }
static int decode_headers_content(ODR o, int off, Z_HTTP_Header **headers, char **content_buf, int *content_len) { int i = off; int chunked = 0; *headers = 0; while (i < o->size-1 && o->buf[i] == '\n') { int po; i++; if (o->buf[i] == '\r' && i < o->size-1 && o->buf[i+1] == '\n') { i++; break; } if (o->buf[i] == '\n') break; for (po = i; ; i++) { if (i == o->size) { o->error = OHTTP; return 0; } else if (o->buf[i] == ':') break; } *headers = (Z_HTTP_Header *) odr_malloc(o, sizeof(**headers)); (*headers)->name = (char*) odr_malloc(o, i - po + 1); memcpy ((*headers)->name, o->buf + po, i - po); (*headers)->name[i - po] = '\0'; i++; while (i < o->size-1 && o->buf[i] == ' ') i++; for (po = i; i < o->size-1 && !strchr("\r\n", o->buf[i]); i++) ; (*headers)->value = (char*) odr_malloc(o, i - po + 1); memcpy ((*headers)->value, o->buf + po, i - po); (*headers)->value[i - po] = '\0'; if (!strcasecmp((*headers)->name, "Transfer-Encoding") && !strcasecmp((*headers)->value, "chunked")) chunked = 1; headers = &(*headers)->next; if (i < o->size-1 && o->buf[i] == '\r') i++; } *headers = 0; if (o->buf[i] != '\n') { o->error = OHTTP; return 0; } i++; if (chunked) { int off = 0; /* we know buffer will be smaller than o->size - i*/ *content_buf = (char*) odr_malloc(o, o->size - i); while (1) { /* chunk length .. */ int chunk_len = 0; for (; i < o->size-2; i++) if (yaz_isdigit(o->buf[i])) chunk_len = chunk_len * 16 + (o->buf[i] - '0'); else if (yaz_isupper(o->buf[i])) chunk_len = chunk_len * 16 + (o->buf[i] - ('A'-10)); else if (yaz_islower(o->buf[i])) chunk_len = chunk_len * 16 + (o->buf[i] - ('a'-10)); else break; /* chunk extension ... */ while (o->buf[i] != '\r' && o->buf[i+1] != '\n') { if (i >= o->size-2) { o->error = OHTTP; return 0; } i++; } i += 2; /* skip CRLF */ if (chunk_len == 0) break; if (chunk_len < 0 || off + chunk_len > o->size) { o->error = OHTTP; return 0; } /* copy chunk .. */ memcpy (*content_buf + off, o->buf + i, chunk_len); i += chunk_len + 2; /* skip chunk+CRLF */ off += chunk_len; } if (!off) *content_buf = 0; *content_len = off; } else { if (i > o->size) { o->error = OHTTP; return 0; } else if (i == o->size) { *content_buf = 0; *content_len = 0; } else { *content_len = o->size - i; *content_buf = (char*) odr_malloc(o, *content_len + 1); memcpy(*content_buf, o->buf + i, *content_len); (*content_buf)[*content_len] = '\0'; } } return 1; }
int yaz_marc_read_iso2709(yaz_marc_t mt, const char *buf, int bsize) { int entry_p; int record_length; int indicator_length; int identifier_length; int end_of_directory; int base_address; int length_data_entry; int length_starting; int length_implementation; yaz_marc_reset(mt); if (!atoi_n_check(buf, 5, &record_length)) { yaz_marc_cprintf(mt, "Bad leader"); return -1; } if (record_length < 25) { yaz_marc_cprintf(mt, "Record length %d < 24", record_length); return -1; } /* ballout if bsize is known and record_length is less than that */ if (bsize != -1 && record_length > bsize) { yaz_marc_cprintf(mt, "Record appears to be larger than buffer %d < %d", record_length, bsize); return -1; } if (yaz_marc_get_debug(mt)) yaz_marc_cprintf(mt, "Record length %5d", record_length); yaz_marc_set_leader(mt, buf, &indicator_length, &identifier_length, &base_address, &length_data_entry, &length_starting, &length_implementation); /* First pass. determine length of directory & base of data */ for (entry_p = 24; buf[entry_p] != ISO2709_FS; ) { /* length of directory entry */ int l = 3 + length_data_entry + length_starting; if (entry_p + l >= record_length) { yaz_marc_cprintf(mt, "Directory offset %d: end of record." " Missing FS char", entry_p); return -1; } if (yaz_marc_get_debug(mt)) { WRBUF hex = wrbuf_alloc(); wrbuf_puts(hex, "Tag "); wrbuf_write_escaped(hex, buf + entry_p, 3); wrbuf_puts(hex, ", length "); wrbuf_write_escaped(hex, buf + entry_p + 3, length_data_entry); wrbuf_puts(hex, ", starting "); wrbuf_write_escaped(hex, buf + entry_p + 3 + length_data_entry, length_starting); yaz_marc_cprintf(mt, "Directory offset %d: %s", entry_p, wrbuf_cstr(hex)); wrbuf_destroy(hex); } /* Check for digits in length+starting info */ while (--l >= 3) if (!yaz_isdigit(buf[entry_p + l])) break; if (l >= 3) { WRBUF hex = wrbuf_alloc(); /* Not all digits, so stop directory scan */ wrbuf_write_escaped(hex, buf + entry_p, length_data_entry + length_starting + 3); yaz_marc_cprintf(mt, "Directory offset %d: Bad value for data" " length and/or length starting (%s)", entry_p, wrbuf_cstr(hex)); wrbuf_destroy(hex); break; } entry_p += 3 + length_data_entry + length_starting; } end_of_directory = entry_p; if (base_address != entry_p+1) { yaz_marc_cprintf(mt, "Base address not at end of directory," " base %d, end %d", base_address, entry_p+1); } /* Second pass. parse control - and datafields */ for (entry_p = 24; entry_p != end_of_directory; ) { int data_length; int data_offset; int end_offset; int i; char tag[4]; int identifier_flag = 0; int entry_p0 = entry_p; memcpy (tag, buf+entry_p, 3); entry_p += 3; tag[3] = '\0'; data_length = atoi_n(buf+entry_p, length_data_entry); entry_p += length_data_entry; data_offset = atoi_n(buf+entry_p, length_starting); entry_p += length_starting; i = data_offset + base_address; end_offset = i+data_length-1; if (data_length <= 0 || data_offset < 0) break; if (yaz_marc_get_debug(mt)) { yaz_marc_cprintf(mt, "Tag: %s. Directory offset %d: data-length %d," " data-offset %d", tag, entry_p0, data_length, data_offset); } if (end_offset >= record_length) { yaz_marc_cprintf(mt, "Directory offset %d: Data out of bounds %d >= %d", entry_p0, end_offset, record_length); break; } if (memcmp (tag, "00", 2)) identifier_flag = 1; /* if not 00X assume subfields */ else if (indicator_length < 4 && indicator_length > 0) { /* Danmarc 00X have subfields */ if (buf[i + indicator_length] == ISO2709_IDFS) identifier_flag = 1; else if (buf[i + indicator_length + 1] == ISO2709_IDFS) identifier_flag = 2; } if (identifier_flag) { /* datafield */ i += identifier_flag-1; if (indicator_length) { /* skip RS/FS bytes in indicator. They are not allowed there */ int j; for (j = indicator_length; --j >= 0; ) if (buf[j+i] < ' ') { j++; i += j; end_offset += j; yaz_marc_cprintf(mt, "Bad indicator data. " "Skipping %d bytes", j); break; } yaz_marc_add_datafield(mt, tag, buf+i, indicator_length); i += indicator_length; } while (i < end_offset && buf[i] != ISO2709_RS && buf[i] != ISO2709_FS) { int code_offset = i+1; i ++; while (i < end_offset && buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS && buf[i] != ISO2709_FS) i++; if (i > code_offset) yaz_marc_add_subfield(mt, buf+code_offset, i - code_offset); } } else { /* controlfield */ int i0 = i; while (i < end_offset && buf[i] != ISO2709_RS && buf[i] != ISO2709_FS) i++; yaz_marc_add_controlfield(mt, tag, buf+i0, i-i0); } if (i < end_offset) { yaz_marc_cprintf(mt, "Separator but not at end of field length=%d", data_length); } if (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS) { yaz_marc_cprintf(mt, "No separator at end of field length=%d", data_length); } } return record_length; }