/* search */ int zsearch(register os_ptr op) { os_ptr op1 = op - 1; uint size = r_size(op); uint count; byte *ptr; check_read_type(*op1, t_string); check_read_type(*op, t_string); if ( size > r_size(op1) ) /* can't match */ { make_bool(op, 0); return 0; } count = r_size(op1) - size; ptr = op1->value.bytes; do { if ( !memcmp(ptr, op->value.bytes, size) ) { op->tas.type_attrs = op1->tas.type_attrs; op->value.bytes = ptr; r_set_size(op, size); push(1); *op = *op1; r_set_size(op, ptr - op->value.bytes); op1->value.bytes = ptr + size; r_set_size(op1, count); push(1); make_bool(op, 1); return 0; } ptr++; } while ( count-- ); /* No match */ make_bool(op, 0); return 0; }
/* <string> print - */ static int zprint(i_ctx_t *i_ctx_p) { os_ptr op = osp; stream *s; int status; ref rstdout; int code; check_read_type(*op, t_string); code = zget_stdout(i_ctx_p, &s); if (code < 0) return code; status = write_string(op, s); if (status >= 0) { pop(1); return 0; } /* Convert print to writestring on the fly. */ make_stream_file(&rstdout, s, "w"); code = handle_write_status(i_ctx_p, status, &rstdout, NULL, zwritestring); if (code != o_push_estack) return code; push(1); *op = op[-1]; op[-1] = rstdout; return code; }
/* <proc> <string> kshow - */ static int zkshow(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_text_enum_t *penum; int code; check_read_type(*op, t_string); check_proc(op[-1]); /* * Per PLRM Section xx.x, kshow is illegal if the current font is a * composite font. The graphics library does not have this limitation, * so we check for it here. */ if (gs_currentfont(igs)->FontType == ft_composite) return_error(e_invalidfont); if ((code = op_show_setup(i_ctx_p, op)) != 0 || (code = gs_kshow_begin(igs, op->value.bytes, r_size(op), imemory, &penum)) < 0) return code; *(op_proc_t *)&penum->enum_client_data = zkshow; if ((code = op_show_finish_setup(i_ctx_p, penum, 2, finish_show)) < 0) { ifree_object(penum, "op_show_enum_setup"); return code; } sslot = op[-1]; /* save kerning proc */ return op_show_continue_pop(i_ctx_p, 2); }
/* <mark> <name> <value> ... <iodevice> .putdevparams */ static int zputdevparams(i_ctx_t *i_ctx_p) { os_ptr op = osp; gx_io_device *iodev; stack_param_list list; gs_param_list *const plist = (gs_param_list *) & list; int code; password system_params_password; check_read_type(*op, t_string); iodev = gs_findiodevice(imemory, op->value.bytes, r_size(op)); if (iodev == 0) return_error(e_undefined); code = stack_param_list_read(&list, &o_stack, 1, NULL, false, iimemory); if (code < 0) return code; code = dict_read_password(&system_params_password, systemdict, "SystemParamsPassword"); if (code < 0) return code; code = param_check_password(plist, &system_params_password); if (code != 0) { iparam_list_release(&list); return_error(code < 0 ? code : e_invalidaccess); } code = gs_putdevparams(iodev, plist); iparam_list_release(&list); if (code < 0) return code; ref_stack_pop(&o_stack, list.count * 2 + 2); return 0; }
/* [4] is for r/w, +, b, \0. */ static int parse_file_access_string(const ref *op, char file_access[4]) { const byte *astr; check_read_type(*op, t_string); astr = op->value.const_bytes; switch (r_size(op)) { case 2: if (astr[1] != '+') return_error(e_invalidfileaccess); file_access[1] = '+'; file_access[2] = 0; break; case 1: file_access[1] = 0; break; default: return_error(e_invalidfileaccess); } switch (astr[0]) { case 'r': case 'w': case 'a': break; default: return_error(e_invalidfileaccess); } file_access[0] = astr[0]; return 0; }
/* Convert a string from the current locale's character set to UTF-8. * Unfortunately, "current locale" can mean a few different things on * Windows -- we use the default ANSI code page, which does the right * thing for command-line arguments (like "-sPDFPassword=foo") and * for strings typed as input to gswin32.exe. It doesn't work for * strings typed as input to gswin32c.exe, which are normally in the * default OEM code page instead. * <string> .locale_to_utf8 <string> */ static int zlocale_to_utf8(i_ctx_t *i_ctx_p) { #define LOCALE_TO_UTF8_BUFFER_SIZE 1024 os_ptr op = osp; char *input; WCHAR wide_buffer[LOCALE_TO_UTF8_BUFFER_SIZE]; char utf8_buffer[LOCALE_TO_UTF8_BUFFER_SIZE]; int success; int code; check_read_type(*op, t_string); input = ref_to_string(op, imemory, "locale_to_utf8 input"); if (input == 0) return_error(gs_error_VMerror); success = MultiByteToWideChar(CP_ACP, 0, input, -1, wide_buffer, LOCALE_TO_UTF8_BUFFER_SIZE); ifree_string((byte *)input, r_size(op) + 1, "locale_to_utf8 input"); if (success == 0) return_error(gs_error_ioerror); success = WideCharToMultiByte(CP_UTF8, 0, wide_buffer, -1, utf8_buffer, LOCALE_TO_UTF8_BUFFER_SIZE, NULL, NULL); if (success == 0) return_error(gs_error_ioerror); code = string_to_ref(utf8_buffer, op, iimemory, "locale_to_utf8 output"); if (code < 0) return code; return 0; #undef LOCALE_TO_UTF8_BUFFER_SIZE }
/* <string> .pcachequery false */ static int zpcachequery(i_ctx_t *i_ctx_p) { os_ptr op = osp; int len; char *key; byte *string; int code = 0; check_read_type(*op, t_string); len = r_size(op); key = op->value.bytes; len = gp_cache_query(GP_CACHE_TYPE_TEST, key, len, (void**)&string, &pcache_alloc_callback, i_ctx_p); if (len < 0) { make_false(op); return 0; } if (string == NULL) return_error(e_VMerror); make_string(op, a_all | icurrent_space, len, string); push(1); make_true(op); return code; }
/* <obj> <pattern> .stringmatch <bool> */ static int zstringmatch(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; bool result; check_read_type(*op, t_string); switch (r_type(op1)) { case t_string: check_read(*op1); goto cmp; case t_name: name_string_ref(imemory, op1, op1); /* can't fail */ cmp: result = string_match(op1->value.const_bytes, r_size(op1), op->value.const_bytes, r_size(op), NULL); break; default: result = (r_size(op) == 1 && *op->value.bytes == '*'); } make_bool(op1, result); pop(1); return 0; }
/* Common functionality of zgethardwareparms & zgetdeviceparams */ static int zget_device_params(i_ctx_t *i_ctx_p, bool is_hardware) { os_ptr op = osp; ref rkeys; gx_device *dev; stack_param_list list; int code; ref *pmark; check_read_type(op[-1], t_device); rkeys = *op; dev = op[-1].value.pdevice; pop(1); stack_param_list_write(&list, &o_stack, &rkeys, iimemory); code = gs_get_device_or_hardware_params(dev, (gs_param_list *) & list, is_hardware); if (code < 0) { /* We have to put back the top argument. */ if (list.count > 0) ref_stack_pop(&o_stack, list.count * 2 - 1); else ref_stack_push(&o_stack, 1); *osp = rkeys; return code; } pmark = ref_stack_index(&o_stack, list.count * 2); make_mark(pmark); return 0; }
/* <dict> .buildcolorrendering1 <crd> */ static int zbuildcolorrendering1(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_memory_t *mem = gs_state_memory(igs); int code; es_ptr ep = esp; gs_cie_render *pcrd; ref_cie_render_procs procs; check_read_type(*op, t_dictionary); check_dict_read(*op); code = gs_cie_render1_build(&pcrd, mem, ".buildcolorrendering1"); if (code < 0) return code; code = zcrd1_params(op, pcrd, &procs, mem); if (code < 0 || (code = cache_colorrendering1(i_ctx_p, pcrd, &procs, (gs_ref_memory_t *) mem)) < 0 ) { rc_free_struct(pcrd, ".buildcolorrendering1"); esp = ep; return code; } /****** FIX refct ******/ /*rc_decrement(pcrd, ".buildcolorrendering1"); *//* build sets rc = 1 */ istate->colorrendering.dict = *op; make_istruct_new(op, a_readonly, pcrd); return (esp == ep ? 0 : o_push_estack); }
/* <string> getenv false */ static int zgetenv(i_ctx_t *i_ctx_p) { os_ptr op = osp; char *str; byte *value; int len = 0; check_read_type(*op, t_string); str = ref_to_string(op, imemory, "getenv key"); if (str == 0) return_error(e_VMerror); if (gp_getenv(str, (char *)0, &len) > 0) { /* key missing */ ifree_string((byte *) str, r_size(op) + 1, "getenv key"); make_false(op); return 0; } value = ialloc_string(len, "getenv value"); if (value == 0) { ifree_string((byte *) str, r_size(op) + 1, "getenv key"); return_error(e_VMerror); } DISCARD(gp_getenv(str, (char *)value, &len)); /* can't fail */ ifree_string((byte *) str, r_size(op) + 1, "getenv key"); /* Delete the stupid C string terminator. */ value = iresize_string(value, len, len - 1, "getenv value"); /* can't fail */ push(1); make_string(op - 1, a_all | icurrent_space, len - 1, value); make_true(op); return 0; }
static int type1crypt(i_ctx_t *i_ctx_p, int (*proc)(byte *, const byte *, uint, ushort *)) { os_ptr op = osp; crypt_state state; uint ssize; check_type(op[-2], t_integer); state = op[-2].value.intval; if (op[-2].value.intval != state) return_error(e_rangecheck); /* state value was truncated */ check_read_type(op[-1], t_string); check_write_type(*op, t_string); ssize = r_size(op - 1); if (r_size(op) < ssize) return_error(e_rangecheck); discard((*proc)(op->value.bytes, op[-1].value.const_bytes, ssize, &state)); /* can't fail */ op[-2].value.intval = state; op[-1] = *op; r_set_size(op - 1, ssize); pop(1); return 0; }
/* <string> cvn <name> */ static int zcvn(i_ctx_t *i_ctx_p) { os_ptr op = osp; check_read_type(*op, t_string); return name_from_string(imemory, op, op); }
/* See gsfname.c for details. */ static int parse_real_file_name(const ref *op, gs_parsed_file_name_t *pfn, gs_memory_t *mem, client_name_t cname) { check_read_type(*op, t_string); return gs_parse_real_file_name(pfn, (const char *)op->value.const_bytes, r_size(op), mem, cname); }
/* anchorsearch */ int zanchorsearch(register os_ptr op) { os_ptr op1 = op - 1; uint size = r_size(op); check_read_type(*op1, t_string); check_read_type(*op, t_string); if ( size <= r_size(op1) && !memcmp(op1->value.bytes, op->value.bytes, size) ) { *op = *op1; r_set_size(op, size); op1->value.bytes += size; r_inc_size(op1, -size); push(1); make_bool(op, 1); } else make_bool(op, 0); return 0; }
/* Common setup */ static int bt_setup(os_ptr op, stream_BT_state * pbts) { check_read_type(*op, t_string); if (r_size(op) != 256) return_error(e_rangecheck); memcpy(pbts->table, op->value.const_bytes, 256); return 0; }
int display_set_callback(gs_main_instance *minst, display_callback *callback) { i_ctx_t *i_ctx_p; bool was_open; int code; int exit_code = 0; os_ptr op; gx_device *dev; gx_device_display *ddev; /* If display device exists, copy prototype if needed and return * device true * If it doesn't exist, return * false */ const char getdisplay[] = "devicedict /display known dup { /display finddevice exch } if"; code = gs_main_run_string(minst, getdisplay, 0, &exit_code, &minst->error_object); if (code < 0) return code; i_ctx_p = minst->i_ctx_p; /* run_string may change i_ctx_p if GC */ op = osp; check_type(*op, t_boolean); if (op->value.boolval) { /* display device was included in Ghostscript so we need * to set the callback structure pointer within it. * If the device is already open, close it before * setting callback, then reopen it. */ check_read_type(op[-1], t_device); dev = op[-1].value.pdevice; was_open = dev->is_open; if (was_open) { code = gs_closedevice(dev); if (code < 0) return_error(code); } ddev = (gx_device_display *) dev; ddev->callback = callback; if (was_open) { code = gs_opendevice(dev); if (code < 0) { dprintf("**** Unable to open the display device, quitting.\n"); return_error(code); } } pop(1); /* device */ } pop(1); /* boolean */ return 0; }
/* <name> .filenamesplit <dir> <base> <extension> */ static int zfilenamesplit(i_ctx_t *i_ctx_p) { os_ptr op = osp; check_read_type(*op, t_string); /****** NOT IMPLEMENTED YET ******/ return_error(e_undefined); }
/* <string> <pattern> search <string> -false- */ static int zsearch(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; uint size = r_size(op); uint count; byte *pat; byte *ptr; byte ch; check_read_type(*op1, t_string); check_read_type(*op, t_string); if (size > r_size(op1)) { /* can't match */ make_false(op); return 0; } count = r_size(op1) - size; ptr = op1->value.bytes; if (size == 0) goto found; pat = op->value.bytes; ch = pat[0]; do { if (*ptr == ch && (size == 1 || !memcmp(ptr, pat, size))) goto found; ptr++; } while (count--); /* No match */ make_false(op); return 0; found: op->tas.type_attrs = op1->tas.type_attrs; op->value.bytes = ptr; r_set_size(op, size); push(2); op[-1] = *op1; r_set_size(op - 1, ptr - op[-1].value.bytes); op1->value.bytes = ptr + size; r_set_size(op1, count); make_true(op); return 0; }
/* Given a UTF-8 password string, convert it to the canonical form * defined by SASLprep (RFC 4013). This is a permissive implementation, * suitable for verifying existing passwords but not for creating new * ones -- if you want to create a new password, you'll need to add a * strict mode that returns stringprep errors to the user, and uses the * STRINGPREP_NO_UNASSIGNED flag to disallow unassigned characters. * <string> .saslprep <string> */ static int zsaslprep(i_ctx_t *i_ctx_p) { os_ptr op = osp; uint input_size = r_size(op); byte *buffer; uint buffer_size; uint output_size; Stringprep_rc err; check_read_type(*op, t_string); /* According to http://unicode.org/faq/normalization.html, converting * a UTF-8 string to normalization form KC has a worst-case expansion * factor of 11, so we allocate 11 times the length of the string plus * 1 for the NUL terminator. If somehow that's still not big enough, * stringprep will return STRINGPREP_TOO_SMALL_BUFFER; there's no * danger of corrupting memory. */ buffer_size = input_size * 11 + 1; buffer = ialloc_string(buffer_size, "saslprep result"); if (buffer == 0) return_error(e_VMerror); memcpy(buffer, op->value.bytes, input_size); buffer[input_size] = '\0'; err = stringprep((char *)buffer, buffer_size, 0, stringprep_saslprep); if (err != STRINGPREP_OK) { ifree_string(buffer, buffer_size, "saslprep result"); /* Since we're just verifying the password to an existing * document here, we don't care about "invalid input" errors * like STRINGPREP_CONTAINS_PROHIBITED. In these cases, we * ignore the error and return the original string unchanged -- * chances are it's not the right password anyway, and if it * is we shouldn't gratuitously fail to decrypt the document. * * On the other hand, errors like STRINGPREP_NFKC_FAILED are * real errors, and should be returned to the user. * * Fortunately, the stringprep error codes are sorted to make * this easy: the errors we want to ignore are the ones with * codes less than 100. */ if ((int)err < 100) return 0; return_error(e_ioerror); } output_size = strlen((char *)buffer); buffer = iresize_string(buffer, buffer_size, output_size, "saslprep result"); /* can't fail */ make_string(op, a_all | icurrent_space, output_size, buffer); return 0; }
/* <string> <charstring> .stringbreak <int|null> */ static int zstringbreak(i_ctx_t *i_ctx_p) { os_ptr op = osp; uint i, j; check_read_type(op[-1], t_string); check_read_type(*op, t_string); /* We can't use strpbrk here, because C doesn't allow nulls in strings. */ for (i = 0; i < r_size(op - 1); ++i) for (j = 0; j < r_size(op); ++j) if (op[-1].value.const_bytes[i] == op->value.const_bytes[j]) { make_int(op - 1, i); goto done; } make_null(op - 1); done: pop(1); return 0; }
/* <names> .installsystemnames - */ static int zinstallsystemnames(i_ctx_t *i_ctx_p) { os_ptr op = osp; if (r_space(op) != avm_global || imemory_save_level(iimemory_global) != 0) return_error(gs_error_invalidaccess); check_read_type(*op, t_shortarray); ref_assign_old(NULL, system_names_p, op, ".installsystemnames"); pop(1); return 0; }
static int zwritehexstring_at(i_ctx_t *i_ctx_p, os_ptr op, uint odd) { register stream *s; register byte ch; register const byte *p; register const char *const hex_digits = "0123456789abcdef"; register uint len; int status; #define MAX_HEX 128 byte buf[MAX_HEX]; check_write_file(s, op - 1); check_read_type(*op, t_string); p = op->value.bytes; len = r_size(op); while (len) { uint len1 = min(len, MAX_HEX / 2); register byte *q = buf; uint count = len1; ref rbuf; do { ch = *p++; *q++ = hex_digits[ch >> 4]; *q++ = hex_digits[ch & 0xf]; } while (--count); r_set_size(&rbuf, (len1 << 1) - odd); rbuf.value.bytes = buf + odd; status = write_string(&rbuf, s); switch (status) { default: return_error(e_ioerror); case 0: len -= len1; odd = 0; continue; case INTC: case CALLC: count = rbuf.value.bytes - buf; op->value.bytes += count >> 1; r_set_size(op, len - (count >> 1)); count &= 1; return handle_write_status(i_ctx_p, status, op - 1, &count, zwritehexstring_continue); } } pop(2); return 0; #undef MAX_HEX }
/* <device> .devicename <string> */ static int zdevicename(i_ctx_t *i_ctx_p) { os_ptr op = osp; const char *dname; check_read_type(*op, t_device); dname = op->value.pdevice->dname; make_const_string(op, avm_foreign | a_readonly, strlen(dname), (const byte *)dname); return 0; }
/* <device> copydevice <newdevice> */ private int zcopydevice(register os_ptr op) { gx_device *new_dev; int code; check_read_type(*op, t_device); code = gs_copydevice(&new_dev, op->value.pdevice, imemory); if ( code < 0 ) return code; new_dev->memory = imemory; make_tav(op, t_device, icurrent_space | a_all, pdevice, new_dev); return 0; }
/* <string> <pattern> anchorsearch <string> -false- */ static int zanchorsearch(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; uint size = r_size(op); check_read_type(*op, t_string); check_read_type(*op1, t_string); if (size <= r_size(op1) && !memcmp(op1->value.bytes, op->value.bytes, size)) { os_ptr op0 = op; push(1); *op0 = *op1; r_set_size(op0, size); op1->value.bytes += size; r_dec_size(op1, size); make_true(op); } else make_false(op); return 0; }
/* <string> <string> .pcacheinsert */ static int zpcacheinsert(i_ctx_t *i_ctx_p) { os_ptr op = osp; char *key, *buffer; int keylen, buflen; int code = 0; check_read_type(*op, t_string); keylen = r_size(op); key = op->value.bytes; check_read_type(*(op - 1), t_string); buflen = r_size(op - 1); buffer = (op - 1)->value.bytes; code = gp_cache_insert(0, key, keylen, buffer, buflen); if (code < 0) return code; pop(2); return code; }
/* <bytestring1> <index> <string2> putinterval - */ static int zputinterval(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr opindex = op - 1; os_ptr opto = opindex - 1; int code; switch (r_type(opto)) { default: return_error(e_typecheck); case t__invalid: if (r_type(op) != t_array && r_type(op) != t_string && r_type(op) != t__invalid) return_error(e_typecheck); /* to match Distiller */ else return_error(e_stackunderflow); case t_mixedarray: case t_shortarray: return_error(e_invalidaccess); case t_array: case t_string: check_write(*opto); check_int_leu(*opindex, r_size(opto)); code = copy_interval(i_ctx_p, opto, (uint)(opindex->value.intval), op, "putinterval"); break; case t_astruct: { uint dsize, ssize, index; check_write(*opto); if (gs_object_type(imemory, opto->value.pstruct) != &st_bytes) return_error(e_typecheck); dsize = gs_object_size(imemory, opto->value.pstruct); check_int_leu(*opindex, dsize); index = (uint)opindex->value.intval; check_read_type(*op, t_string); ssize = r_size(op); if (ssize > dsize - index) return_error(e_rangecheck); memcpy(r_ptr(opto, byte) + index, op->value.const_bytes, ssize); code = 0; break; } } if (code >= 0) pop(3); return code; }
int array_indexed_param_list_read(dict_param_list * plist, const ref * parray, const ref * ppolicies, bool require_all, gs_ref_memory_t *ref_memory) { iparam_list *const iplist = (iparam_list *) plist; int code; check_read_type(*parray, t_array); plist->u.r.read = array_indexed_param_read; plist->dict = *parray; code = ref_param_read_init(iplist, r_size(parray), ppolicies, require_all, ref_memory); plist->int_keys = true; return code; }
/* <string> <bool> .setdebug - */ static int zsetdebug(i_ctx_t *i_ctx_p) { os_ptr op = osp; check_read_type(op[-1], t_string); check_type(*op, t_boolean); { int i; for (i = 0; i < r_size(op - 1); i++) gs_debug[op[-1].value.bytes[i] & 127] = op->value.boolval; } pop(2); return 0; }