Skip to content

Commit 1afef88

Browse files
author
Adam Dickmeiss
committed
Allow character set conversion for yaz_record's array method, e.g.
yaz_record($id,$pos,"array;charset=marc8,iso-8859-1")
1 parent 4ee4d27 commit 1afef88

File tree

1 file changed

+105
-25
lines changed

1 file changed

+105
-25
lines changed

ext/yaz/php_yaz.c

Lines changed: 105 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,74 @@ static void retval_array2_grs1(zval *return_value, Z_GenericRecord *p)
898898
}
899899
}
900900

901+
static int iconv_grs1(Z_GenericRecord *p, ODR odr,
902+
const char *to, const char *from)
903+
{
904+
size_t outbuf_size = 10;
905+
char *outbuf = (char*) odr_malloc(odr, outbuf_size);
906+
907+
Z_GenericRecord *grs[20];
908+
int eno[20];
909+
int level = 0;
910+
yaz_iconv_t cd;
911+
if (!to || to[0]==0)
912+
to = "UTF-8";
913+
if (!from || !to)
914+
return 0;
915+
cd = yaz_iconv_open(to, from);
916+
if (!cd)
917+
return -1;
918+
919+
eno[level] = 0;
920+
grs[level] = p;
921+
922+
while(level >= 0) {
923+
Z_TaggedElement *e = 0;
924+
Z_GenericRecord *p = grs[level];
925+
926+
if (eno[level] >= p->num_elements) {
927+
--level;
928+
if (level >= 0)
929+
eno[level]++;
930+
continue;
931+
}
932+
e = grs[level]->elements[eno[level]];
933+
switch (e->content->which) {
934+
case Z_ElementData_string:
935+
while(1) {
936+
size_t inbytesleft = strlen(e->content->u.string);
937+
const char *inp = e->content->u.string;
938+
size_t outbytesleft = outbuf_size;
939+
char *outp = outbuf;
940+
size_t r = yaz_iconv(cd, (char**) &inp, &inbytesleft,
941+
&outp, &outbytesleft);
942+
if (r == (size_t) (-1)) {
943+
int e = yaz_iconv_error(cd);
944+
if (e != YAZ_ICONV_E2BIG || outbuf_size > 200000)
945+
break;
946+
outbuf_size = outbuf_size * 2 + 30;
947+
outbuf = (char*) odr_malloc(odr, outbuf_size);
948+
} else {
949+
e->content->u.string = odr_malloc(odr, 1+(outp-outbuf));
950+
memcpy(e->content->u.string, outbuf, outp-outbuf);
951+
e->content->u.string[outp-outbuf] = '\0';
952+
break;
953+
}
954+
}
955+
break;
956+
case Z_ElementData_subtree:
957+
if (level < 20) {
958+
level++;
959+
grs[level] = e->content->u.subtree;
960+
eno[level] = -1;
961+
}
962+
}
963+
eno[level]++;
964+
}
965+
yaz_iconv_close(cd);
966+
return 0;
967+
}
968+
901969
static void retval_array1_grs1(zval *return_value, Z_GenericRecord *p)
902970
{
903971
Z_GenericRecord *grs[20];
@@ -918,13 +986,10 @@ static void retval_array1_grs1(zval *return_value, Z_GenericRecord *p)
918986

919987
if (eno[level] >= p->num_elements) {
920988
--level;
921-
if (level >= 0) {
989+
if (level >= 0)
922990
eno[level]++;
923-
}
924991
continue;
925992
}
926-
/* eno[level]++; */
927-
928993
*tag = '\0';
929994
for (i = 0; i <= level; i++) {
930995
int tag_type = 3;
@@ -966,11 +1031,12 @@ static void retval_array1_grs1(zval *return_value, Z_GenericRecord *p)
9661031
add_next_index_long(my_zval, *e->content->u.trueOrFalse);
9671032
break;
9681033
case Z_ElementData_subtree:
969-
level++;
970-
grs[level] = e->content->u.subtree;
971-
eno[level] = -1;
1034+
if (level < 20) {
1035+
level++;
1036+
grs[level] = e->content->u.subtree;
1037+
eno[level] = -1;
1038+
}
9721039
}
973-
9741040
zend_hash_next_index_insert(return_value->value.ht, (void *) &my_zval, sizeof(zval *), NULL);
9751041
eno[level]++;
9761042
}
@@ -1001,54 +1067,68 @@ PHP_FUNCTION(yaz_record)
10011067
type = (*pval_type)->value.str.val;
10021068

10031069
if (p && p->zoom_set) {
1070+
char type_args[4][60]; /* 0; 1=2,3 (1 is assumed charset) */
1071+
type_args[0][0] = 0;
1072+
type_args[1][0] = 0;
1073+
type_args[2][0] = 0;
1074+
type_args[3][0] = 0;
1075+
sscanf(type, "%59[^;];%59[^=]=%59[^,],%59[^,]", type_args[0],
1076+
type_args[1], type_args[2], type_args[3]);
10041077
ZOOM_record r = ZOOM_resultset_record(p->zoom_set, pos-1);
1005-
if (!strcmp(type, "string")) {
1078+
if (!strcmp(type_args[0], "string")) {
10061079
type = "render";
10071080
}
10081081
if (r) {
1009-
if (!strcmp(type, "array") || !strcmp(type, "array1")) {
1082+
if (!strcmp(type_args[0], "array") ||
1083+
!strcmp(type_args[0], "array1")) {
10101084
Z_External *ext = (Z_External *) ZOOM_record_get(r, "ext", 0);
10111085
if (ext->which == Z_External_OPAC)
10121086
ext = ext->u.opac->bibliographicRecord;
10131087
if (ext) {
10141088
oident *ent = oid_getentbyoid(ext->direct_reference);
1089+
ODR odr = odr_createmem(ODR_DECODE);
10151090

10161091
if (ext->which == Z_External_grs1 && ent->value == VAL_GRS1) {
1092+
if (type_args[2][0])
1093+
iconv_grs1(ext->u.grs1, odr, type_args[3],
1094+
type_args[2]);
10171095
retval_array1_grs1(return_value, ext->u.grs1);
10181096
} else if (ext->which == Z_External_octet) {
10191097
char *buf = (char *) (ext->u.octet_aligned->buf);
1020-
ODR odr = odr_createmem(ODR_DECODE);
10211098
Z_GenericRecord *rec = 0;
10221099

10231100
switch (ent->value) {
10241101
case VAL_SOIF:
10251102
case VAL_HTML:
1026-
break;
10271103
case VAL_TEXT_XML:
10281104
case VAL_APPLICATION_XML:
1029-
/* text2grs1(&buf, &len, t->odr_in, 0, 0); */
10301105
break;
10311106
default:
10321107
rec = marc_to_grs1(buf, odr);
10331108
}
10341109
if (rec) {
1110+
if (type_args[2][0])
1111+
iconv_grs1(rec, odr, type_args[3], type_args[2]);
10351112
retval_array1_grs1(return_value, rec);
10361113
}
1037-
odr_destroy(odr);
10381114
}
1115+
odr_destroy(odr);
10391116
}
1040-
} else if (!strcmp(type, "array2")) {
1117+
} else if (!strcmp(type_args[0], "array2")) {
10411118
Z_External *ext = (Z_External *) ZOOM_record_get(r, "ext", 0);
10421119
if (ext->which == Z_External_OPAC)
10431120
ext = ext->u.opac->bibliographicRecord;
10441121
if (ext) {
10451122
oident *ent = oid_getentbyoid(ext->direct_reference);
1123+
ODR odr = odr_createmem(ODR_DECODE);
10461124

10471125
if (ext->which == Z_External_grs1 && ent->value == VAL_GRS1) {
1126+
if (type_args[2][0])
1127+
iconv_grs1(ext->u.grs1, odr, type_args[3],
1128+
type_args[2]);
10481129
retval_array2_grs1(return_value, ext->u.grs1);
10491130
} else if (ext->which == Z_External_octet) {
10501131
char *buf = (char *) (ext->u.octet_aligned->buf);
1051-
ODR odr = odr_createmem(ODR_DECODE);
10521132
Z_GenericRecord *rec = 0;
10531133

10541134
switch (ent->value) {
@@ -1063,22 +1143,22 @@ PHP_FUNCTION(yaz_record)
10631143
rec = marc_to_grs1(buf, odr);
10641144
}
10651145
if (rec) {
1146+
if (type_args[2][0])
1147+
iconv_grs1(rec, odr, type_args[3], type_args[2]);
10661148
retval_array2_grs1(return_value, rec);
10671149
}
1068-
odr_destroy(odr);
10691150
}
1151+
odr_destroy(odr);
10701152
}
10711153
} else {
10721154
int rlen;
10731155
const char *info = ZOOM_record_get(r, type, &rlen);
1074-
#if 0
1075-
return_value->value.str.len = 1;
1076-
return_value->value.str.val = "X";
1077-
#else
1078-
return_value->value.str.len = (rlen > 0) ? rlen : 0;
1079-
return_value->value.str.val = estrndup(info, return_value->value.str.len);
1080-
#endif
1081-
return_value->type = IS_STRING;
1156+
if (info) {
1157+
return_value->value.str.len = (rlen > 0) ? rlen : 0;
1158+
return_value->value.str.val =
1159+
estrndup(info, return_value->value.str.len);
1160+
return_value->type = IS_STRING;
1161+
}
10821162
}
10831163
}
10841164
}

0 commit comments

Comments
 (0)