From f6def128a97444384d6c0939eaa04fb0e931d6df Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Wed, 11 Aug 2010 14:24:15 +0200 Subject: [PATCH] Refactor record render to separate source --- include/yaz/Makefile.am | 2 +- include/yaz/record_render.h | 68 +++++++++ src/Makefile.am | 2 +- src/record_render.c | 319 +++++++++++++++++++++++++++++++++++++++++++ src/zoom-c.c | 294 --------------------------------------- src/zoom-p.h | 3 - src/zoom-record-cache.c | 3 +- win/makefile | 1 + 8 files changed, 392 insertions(+), 300 deletions(-) create mode 100644 include/yaz/record_render.h create mode 100644 src/record_render.c diff --git a/include/yaz/Makefile.am b/include/yaz/Makefile.am index f4e6548..125dfa0 100644 --- a/include/yaz/Makefile.am +++ b/include/yaz/Makefile.am @@ -7,7 +7,7 @@ pkginclude_HEADERS= backend.h ccl.h ccl_xml.h cql.h rpn2cql.h comstack.h \ diagbib1.h diagsrw.h diagsru_update.h sortspec.h log.h logrpn.h marcdisp.h \ nmem.h nmem_xml.h odr.h errno.h facet.h \ options.h otherinfo.h pquery.h prt-ext.h querytowrbuf.h \ - readconf.h record_conv.h retrieval.h statserv.h \ + readconf.h record_conv.h record_render.h retrieval.h statserv.h \ tcpip.h test.h timing.h unix.h tpath.h wrbuf.h xmalloc.h \ yaz-ccl.h yaz-iconv.h yaz-util.h yaz-version.h yconfig.h proto.h \ xmlquery.h xmltypes.h snprintf.h query-charset.h \ diff --git a/include/yaz/record_render.h b/include/yaz/record_render.h new file mode 100644 index 0000000..bdc0889 --- /dev/null +++ b/include/yaz/record_render.h @@ -0,0 +1,68 @@ +/* This file is part of the YAZ toolkit. + * Copyright (C) 1995-2010 Index Data. + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Index Data nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file record_render.h + * \brief Record render header + */ + +#ifndef YAZ_RECORD_RENDER_H +#define YAZ_RECORD_RENDER_H + +#include +#include +#include +#include + +YAZ_BEGIN_CDECL + +/** \brief render records (ZOOM style) + \param npr record structure to be rendered (Z39.50) + \param schema for record (if known) + \param wrbuf Working WRBUF + \param type_spec format spec + \param len length of returned buffer + \retval !=0 buffer + \retval =0 record could not be rendered +*/ +YAZ_EXPORT +const char *yaz_record_render(Z_NamePlusRecord *npr, const char *schema, + WRBUF wrbuf, + const char *type_spec, int *len); + +YAZ_END_CDECL + +#endif +/* + * Local variables: + * c-basic-offset: 4 + * c-file-style: "Stroustrup" + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ + diff --git a/src/Makefile.am b/src/Makefile.am index aa685af..95f8d9d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -88,7 +88,7 @@ libyaz_la_SOURCES=version.c options.c log.c \ zget.c yaz-ccl.c diag-entry.c diag-entry.h \ logrpn.c \ otherinfo.c pquery.c sortspec.c charneg.c initopt.c \ - zoom-c.c zoom-z3950.c zoom-query.c zoom-record-cache.c \ + zoom-c.c zoom-z3950.c zoom-query.c zoom-record-cache.c record_render.c \ zoom-socket.c zoom-opt.c zoom-p.h \ grs1disp.c zgdu.c soap.c srw.c srwutil.c uri.c \ opacdisp.c cclfind.c ccltoken.c cclerrms.c cclqual.c cclptree.c cclp.h \ diff --git a/src/record_render.c b/src/record_render.c new file mode 100644 index 0000000..49a2625 --- /dev/null +++ b/src/record_render.c @@ -0,0 +1,319 @@ +/* This file is part of the YAZ toolkit. + * Copyright (C) 1995-2010 Index Data + * See the file LICENSE for details. + */ +/** + * \file record-render.c + * \brief Render Z39.50 records (NamePlusRecord) + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +static yaz_iconv_t iconv_create_charset(const char *record_charset) +{ + char to[40]; + char from[40]; + yaz_iconv_t cd = 0; + + *from = '\0'; + strcpy(to, "UTF-8"); + if (record_charset && *record_charset) + { + /* Use "from,to" or just "from" */ + const char *cp = strchr(record_charset, ','); + size_t clen = strlen(record_charset); + if (cp && cp[1]) + { + strncpy( to, cp+1, sizeof(to)-1); + to[sizeof(to)-1] = '\0'; + clen = cp - record_charset; + } + if (clen > sizeof(from)-1) + clen = sizeof(from)-1; + + if (clen) + strncpy(from, record_charset, clen); + from[clen] = '\0'; + } + if (*from && *to) + cd = yaz_iconv_open(to, from); + return cd; +} + +static const char *return_marc_record(WRBUF wrbuf, + int marc_type, + int *len, + const char *buf, int sz, + const char *record_charset) +{ + yaz_iconv_t cd = iconv_create_charset(record_charset); + yaz_marc_t mt = yaz_marc_create(); + const char *ret_string = 0; + + if (cd) + yaz_marc_iconv(mt, cd); + yaz_marc_xml(mt, marc_type); + if (yaz_marc_decode_wrbuf(mt, buf, sz, wrbuf) > 0) + { + if (len) + *len = wrbuf_len(wrbuf); + ret_string = wrbuf_cstr(wrbuf); + } + yaz_marc_destroy(mt); + if (cd) + yaz_iconv_close(cd); + return ret_string; +} + +static const char *return_opac_record(WRBUF wrbuf, + int marc_type, + int *len, + Z_OPACRecord *opac_rec, + const char *record_charset) +{ + yaz_iconv_t cd = iconv_create_charset(record_charset); + yaz_marc_t mt = yaz_marc_create(); + + if (cd) + yaz_marc_iconv(mt, cd); + yaz_marc_xml(mt, marc_type); + + yaz_opac_decode_wrbuf(mt, opac_rec, wrbuf); + yaz_marc_destroy(mt); + + if (cd) + yaz_iconv_close(cd); + if (len) + *len = wrbuf_len(wrbuf); + return wrbuf_cstr(wrbuf); +} + +static const char *return_string_record(WRBUF wrbuf, + int *len, + const char *buf, int sz, + const char *record_charset) +{ + yaz_iconv_t cd = iconv_create_charset(record_charset); + + if (cd) + { + wrbuf_iconv_write(wrbuf, cd, buf, sz); + wrbuf_iconv_reset(wrbuf, cd); + + buf = wrbuf_cstr(wrbuf); + sz = wrbuf_len(wrbuf); + yaz_iconv_close(cd); + } + if (len) + *len = sz; + return buf; +} + +static const char *return_record_wrbuf(WRBUF wrbuf, int *len, + Z_NamePlusRecord *npr, + int marctype, const char *charset) +{ + Z_External *r = (Z_External *) npr->u.databaseRecord; + const Odr_oid *oid = r->direct_reference; + + wrbuf_rewind(wrbuf); + /* render bibliographic record .. */ + if (r->which == Z_External_OPAC) + { + return return_opac_record(wrbuf, marctype, len, + r->u.opac, charset); + } + if (r->which == Z_External_sutrs) + return return_string_record(wrbuf, len, + (char*) r->u.sutrs->buf, + r->u.sutrs->len, + charset); + else if (r->which == Z_External_octet) + { + if (yaz_oid_is_iso2709(oid)) + { + const char *ret_buf = return_marc_record( + wrbuf, marctype, len, + (const char *) r->u.octet_aligned->buf, + r->u.octet_aligned->len, + charset); + if (ret_buf) + return ret_buf; + /* bad ISO2709. Return fail unless raw (ISO2709) is wanted */ + if (marctype != YAZ_MARC_ISO2709) + return 0; + } + return return_string_record(wrbuf, len, + (const char *) r->u.octet_aligned->buf, + r->u.octet_aligned->len, + charset); + } + else if (r->which == Z_External_grs1) + { + yaz_display_grs1(wrbuf, r->u.grs1, 0); + return return_string_record(wrbuf, len, + wrbuf_buf(wrbuf), + wrbuf_len(wrbuf), + charset); + } + return 0; +} + +static const char *get_record_format(WRBUF wrbuf, int *len, + Z_NamePlusRecord *npr, + int marctype, const char *charset, + const char *format) +{ + const char *res = return_record_wrbuf(wrbuf, len, npr, marctype, charset); +#if YAZ_HAVE_XML2 + if (*format == '1' && len) + { + /* try to XML format res */ + xmlDocPtr doc; + xmlKeepBlanksDefault(0); /* get get xmlDocFormatMemory to work! */ + doc = xmlParseMemory(res, *len); + if (doc) + { + xmlChar *xml_mem; + int xml_size; + xmlDocDumpFormatMemory(doc, &xml_mem, &xml_size, 1); + wrbuf_rewind(wrbuf); + wrbuf_write(wrbuf, (const char *) xml_mem, xml_size); + xmlFree(xml_mem); + xmlFreeDoc(doc); + res = wrbuf_cstr(wrbuf); + *len = wrbuf_len(wrbuf); + } + } +#endif + return res; +} + +const char *yaz_record_render(Z_NamePlusRecord *npr, const char *schema, + WRBUF wrbuf, + const char *type_spec, int *len) +{ + size_t i; + char type[40]; + char charset[40]; + char format[3]; + const char *cp = type_spec; + + for (i = 0; cp[i] && cp[i] != ';' && cp[i] != ' ' && i < sizeof(type)-1; + i++) + type[i] = cp[i]; + type[i] = '\0'; + charset[0] = '\0'; + format[0] = '\0'; + while (1) + { + while (cp[i] == ' ') + i++; + if (cp[i] != ';') + break; + i++; + while (cp[i] == ' ') + i++; + if (!strncmp(cp + i, "charset=", 8)) + { + size_t j = 0; + i = i + 8; /* skip charset= */ + for (j = 0; cp[i] && cp[i] != ';' && cp[i] != ' '; i++) + { + if (j < sizeof(charset)-1) + charset[j++] = cp[i]; + } + charset[j] = '\0'; + } + else if (!strncmp(cp + i, "format=", 7)) + { + size_t j = 0; + i = i + 7; + for (j = 0; cp[i] && cp[i] != ';' && cp[i] != ' '; i++) + { + if (j < sizeof(format)-1) + format[j++] = cp[i]; + } + format[j] = '\0'; + } + } + if (!strcmp(type, "database")) + { + if (len) + *len = (npr->databaseName ? strlen(npr->databaseName) : 0); + return npr->databaseName; + } + else if (!strcmp(type, "schema")) + { + if (len) + *len = schema ? strlen(schema) : 0; + return schema; + } + else if (!strcmp(type, "syntax")) + { + const char *desc = 0; + if (npr->which == Z_NamePlusRecord_databaseRecord) + { + Z_External *r = (Z_External *) npr->u.databaseRecord; + desc = yaz_oid_to_string(yaz_oid_std(), r->direct_reference, 0); + } + if (!desc) + desc = "none"; + if (len) + *len = strlen(desc); + return desc; + } + if (npr->which != Z_NamePlusRecord_databaseRecord) + return 0; + + /* from now on - we have a database record .. */ + if (!strcmp(type, "render")) + { + return get_record_format(wrbuf, len, npr, YAZ_MARC_LINE, charset, format); + } + else if (!strcmp(type, "xml")) + { + return get_record_format(wrbuf, len, npr, YAZ_MARC_MARCXML, charset, + format); + } + else if (!strcmp(type, "txml")) + { + return get_record_format(wrbuf, len, npr, YAZ_MARC_TURBOMARC, charset, + format); + } + else if (!strcmp(type, "raw")) + { + return get_record_format(wrbuf, len, npr, YAZ_MARC_ISO2709, charset, + format); + } + else if (!strcmp(type, "ext")) + { + if (len) *len = -1; + return (const char *) npr->u.databaseRecord; + } + else if (!strcmp(type, "opac")) + { + if (npr->u.databaseRecord->which == Z_External_OPAC) + return get_record_format(wrbuf, len, npr, YAZ_MARC_MARCXML, charset, + format); + } + return 0; +} + +/* + * Local variables: + * c-basic-offset: 4 + * c-file-style: "Stroustrup" + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ + diff --git a/src/zoom-c.c b/src/zoom-c.c index 3c1e14e..fa3e7ee 100644 --- a/src/zoom-c.c +++ b/src/zoom-c.c @@ -16,11 +16,9 @@ #include #include #include -#include #include #include #include -#include #include #include @@ -1368,298 +1366,6 @@ ZOOM_API(ZOOM_record) return rec; } -static yaz_iconv_t iconv_create_charset(const char *record_charset) -{ - char to[40]; - char from[40]; - yaz_iconv_t cd = 0; - - *from = '\0'; - strcpy(to, "UTF-8"); - if (record_charset && *record_charset) - { - /* Use "from,to" or just "from" */ - const char *cp = strchr(record_charset, ','); - size_t clen = strlen(record_charset); - if (cp && cp[1]) - { - strncpy( to, cp+1, sizeof(to)-1); - to[sizeof(to)-1] = '\0'; - clen = cp - record_charset; - } - if (clen > sizeof(from)-1) - clen = sizeof(from)-1; - - if (clen) - strncpy(from, record_charset, clen); - from[clen] = '\0'; - } - if (*from && *to) - cd = yaz_iconv_open(to, from); - return cd; -} - -static const char *return_marc_record(WRBUF wrbuf, - int marc_type, - int *len, - const char *buf, int sz, - const char *record_charset) -{ - yaz_iconv_t cd = iconv_create_charset(record_charset); - yaz_marc_t mt = yaz_marc_create(); - const char *ret_string = 0; - - if (cd) - yaz_marc_iconv(mt, cd); - yaz_marc_xml(mt, marc_type); - if (yaz_marc_decode_wrbuf(mt, buf, sz, wrbuf) > 0) - { - if (len) - *len = wrbuf_len(wrbuf); - ret_string = wrbuf_cstr(wrbuf); - } - yaz_marc_destroy(mt); - if (cd) - yaz_iconv_close(cd); - return ret_string; -} - -static const char *return_opac_record(WRBUF wrbuf, - int marc_type, - int *len, - Z_OPACRecord *opac_rec, - const char *record_charset) -{ - yaz_iconv_t cd = iconv_create_charset(record_charset); - yaz_marc_t mt = yaz_marc_create(); - - if (cd) - yaz_marc_iconv(mt, cd); - yaz_marc_xml(mt, marc_type); - - yaz_opac_decode_wrbuf(mt, opac_rec, wrbuf); - yaz_marc_destroy(mt); - - if (cd) - yaz_iconv_close(cd); - if (len) - *len = wrbuf_len(wrbuf); - return wrbuf_cstr(wrbuf); -} - -static const char *return_string_record(WRBUF wrbuf, - int *len, - const char *buf, int sz, - const char *record_charset) -{ - yaz_iconv_t cd = iconv_create_charset(record_charset); - - if (cd) - { - wrbuf_iconv_write(wrbuf, cd, buf, sz); - wrbuf_iconv_reset(wrbuf, cd); - - buf = wrbuf_cstr(wrbuf); - sz = wrbuf_len(wrbuf); - yaz_iconv_close(cd); - } - if (len) - *len = sz; - return buf; -} - -static const char *return_record_wrbuf(WRBUF wrbuf, int *len, - Z_NamePlusRecord *npr, - int marctype, const char *charset) -{ - Z_External *r = (Z_External *) npr->u.databaseRecord; - const Odr_oid *oid = r->direct_reference; - - wrbuf_rewind(wrbuf); - /* render bibliographic record .. */ - if (r->which == Z_External_OPAC) - { - return return_opac_record(wrbuf, marctype, len, - r->u.opac, charset); - } - if (r->which == Z_External_sutrs) - return return_string_record(wrbuf, len, - (char*) r->u.sutrs->buf, - r->u.sutrs->len, - charset); - else if (r->which == Z_External_octet) - { - if (yaz_oid_is_iso2709(oid)) - { - const char *ret_buf = return_marc_record( - wrbuf, marctype, len, - (const char *) r->u.octet_aligned->buf, - r->u.octet_aligned->len, - charset); - if (ret_buf) - return ret_buf; - /* bad ISO2709. Return fail unless raw (ISO2709) is wanted */ - if (marctype != YAZ_MARC_ISO2709) - return 0; - } - return return_string_record(wrbuf, len, - (const char *) r->u.octet_aligned->buf, - r->u.octet_aligned->len, - charset); - } - else if (r->which == Z_External_grs1) - { - yaz_display_grs1(wrbuf, r->u.grs1, 0); - return return_string_record(wrbuf, len, - wrbuf_buf(wrbuf), - wrbuf_len(wrbuf), - charset); - } - return 0; -} - -static const char *get_record_format(WRBUF wrbuf, int *len, - Z_NamePlusRecord *npr, - int marctype, const char *charset, - const char *format) -{ - const char *res = return_record_wrbuf(wrbuf, len, npr, marctype, charset); -#if YAZ_HAVE_XML2 - if (*format == '1' && len) - { - /* try to XML format res */ - xmlDocPtr doc; - xmlKeepBlanksDefault(0); /* get get xmlDocFormatMemory to work! */ - doc = xmlParseMemory(res, *len); - if (doc) - { - xmlChar *xml_mem; - int xml_size; - xmlDocDumpFormatMemory(doc, &xml_mem, &xml_size, 1); - wrbuf_rewind(wrbuf); - wrbuf_write(wrbuf, (const char *) xml_mem, xml_size); - xmlFree(xml_mem); - xmlFreeDoc(doc); - res = wrbuf_cstr(wrbuf); - *len = wrbuf_len(wrbuf); - } - } -#endif - return res; -} - - -const char *ZOOM_npr_format(Z_NamePlusRecord *npr, const char *schema, - WRBUF wrbuf, - const char *type_spec, int *len) -{ - size_t i; - char type[40]; - char charset[40]; - char format[3]; - const char *cp = type_spec; - - for (i = 0; cp[i] && cp[i] != ';' && cp[i] != ' ' && i < sizeof(type)-1; - i++) - type[i] = cp[i]; - type[i] = '\0'; - charset[0] = '\0'; - format[0] = '\0'; - while (1) - { - while (cp[i] == ' ') - i++; - if (cp[i] != ';') - break; - i++; - while (cp[i] == ' ') - i++; - if (!strncmp(cp + i, "charset=", 8)) - { - size_t j = 0; - i = i + 8; /* skip charset= */ - for (j = 0; cp[i] && cp[i] != ';' && cp[i] != ' '; i++) - { - if (j < sizeof(charset)-1) - charset[j++] = cp[i]; - } - charset[j] = '\0'; - } - else if (!strncmp(cp + i, "format=", 7)) - { - size_t j = 0; - i = i + 7; - for (j = 0; cp[i] && cp[i] != ';' && cp[i] != ' '; i++) - { - if (j < sizeof(format)-1) - format[j++] = cp[i]; - } - format[j] = '\0'; - } - } - if (!strcmp(type, "database")) - { - if (len) - *len = (npr->databaseName ? strlen(npr->databaseName) : 0); - return npr->databaseName; - } - else if (!strcmp(type, "schema")) - { - if (len) - *len = schema ? strlen(schema) : 0; - return schema; - } - else if (!strcmp(type, "syntax")) - { - const char *desc = 0; - if (npr->which == Z_NamePlusRecord_databaseRecord) - { - Z_External *r = (Z_External *) npr->u.databaseRecord; - desc = yaz_oid_to_string(yaz_oid_std(), r->direct_reference, 0); - } - if (!desc) - desc = "none"; - if (len) - *len = strlen(desc); - return desc; - } - if (npr->which != Z_NamePlusRecord_databaseRecord) - return 0; - - /* from now on - we have a database record .. */ - if (!strcmp(type, "render")) - { - return get_record_format(wrbuf, len, npr, YAZ_MARC_LINE, charset, format); - } - else if (!strcmp(type, "xml")) - { - return get_record_format(wrbuf, len, npr, YAZ_MARC_MARCXML, charset, - format); - } - else if (!strcmp(type, "txml")) - { - return get_record_format(wrbuf, len, npr, YAZ_MARC_TURBOMARC, charset, - format); - } - else if (!strcmp(type, "raw")) - { - return get_record_format(wrbuf, len, npr, YAZ_MARC_ISO2709, charset, - format); - } - else if (!strcmp(type, "ext")) - { - if (len) *len = -1; - return (const char *) npr->u.databaseRecord; - } - else if (!strcmp(type, "opac")) - { - if (npr->u.databaseRecord->which == Z_External_OPAC) - return get_record_format(wrbuf, len, npr, YAZ_MARC_MARCXML, charset, - format); - } - return 0; -} - ZOOM_API(ZOOM_scanset) ZOOM_connection_scan(ZOOM_connection c, const char *start) { diff --git a/src/zoom-p.h b/src/zoom-p.h index 2763d56..06d4b29 100644 --- a/src/zoom-p.h +++ b/src/zoom-p.h @@ -288,9 +288,6 @@ Z_Query *ZOOM_query_get_Z_Query(ZOOM_query s); Z_SortKeySpecList *ZOOM_query_get_sortspec(ZOOM_query s); char *ZOOM_query_get_query_string(ZOOM_query s); -const char *ZOOM_npr_format(Z_NamePlusRecord *npr, const char *schema, - WRBUF wrbuf, - const char *type_spec, int *len); int ZOOM_uri_to_code(const char *uri); /* diff --git a/src/zoom-record-cache.c b/src/zoom-record-cache.c index e90ef02..9bc4e15 100644 --- a/src/zoom-record-cache.c +++ b/src/zoom-record-cache.c @@ -13,6 +13,7 @@ #include "zoom-p.h" #include +#include #include #if SHPTR @@ -232,7 +233,7 @@ ZOOM_API(const char *) rec->wrbuf = wrbuf_alloc(); wrbuf = rec->wrbuf; #endif - return ZOOM_npr_format(rec->npr, rec->schema, wrbuf, type_spec, len); + return yaz_record_render(rec->npr, rec->schema, wrbuf, type_spec, len); } ZOOM_API(int) diff --git a/win/makefile b/win/makefile index 4e16baa..7a1c94a 100644 --- a/win/makefile +++ b/win/makefile @@ -476,6 +476,7 @@ MISC_OBJS= \ $(OBJDIR)\zoom-record-cache.obj \ $(OBJDIR)\zoom-z3950.obj \ $(OBJDIR)\zoom-query.obj \ + $(OBJDIR)\record-render.obj \ $(OBJDIR)\facet.obj \ $(OBJDIR)\zoom-opt.obj \ $(OBJDIR)\zoom-socket.obj \ -- 1.7.10.4