IO_stat MCCdata::load(IO_handle stream, MCObject *parent, const char *version) { IO_stat stat; if ((stat = IO_read_uint4(&id, stream)) != IO_NORMAL) return stat; if (parent->gettype() == CT_BUTTON) { uint1 set; stat = IO_read_uint1(&set, stream); data = (void *)(set ? 1 : 0); return stat; } else { if (id & COMPACT_PARAGRAPHS) { char *string; if ((stat = IO_read_string(string, stream, sizeof(uint1))) != IO_NORMAL) return stat; data = string; } else { MCParagraph *paragraphs = NULL; while (True) { uint1 type; if ((stat = IO_read_uint1(&type, stream)) != IO_NORMAL) return stat; switch (type) { // MW-2012-03-04: [[ StackFile5500 ]] Handle either the paragraph or extended // paragraph tag. case OT_PARAGRAPH: case OT_PARAGRAPH_EXT: { MCParagraph *newpar = new MCParagraph; newpar->setparent((MCField *)parent); // MW-2012-03-04: [[ StackFile5500 ]] If the paragraph tab was the extended // variant, then pass the correct is_ext parameter. if ((stat = newpar->load(stream, version, type == OT_PARAGRAPH_EXT)) != IO_NORMAL) { delete newpar; return stat; } newpar->appendto(paragraphs); } break; default: data = paragraphs; MCS_seek_cur(stream, -1); return IO_NORMAL; } } } } return IO_NORMAL; }
IO_stat MCStyledText::load(IO_handle p_stream, const char *p_version) { IO_stat stat; MCParagraph *paragraphs = NULL; while (True) { uint1 type; if ((stat = IO_read_uint1(&type, p_stream)) != IO_NORMAL) return stat; switch (type) { // MW-2012-03-04: [[ StackFile5500 ]] Handle both the paragraph and extended // paragraph record. case OT_PARAGRAPH: case OT_PARAGRAPH_EXT: { MCParagraph *newpar = new MCParagraph; newpar->setparent((MCField *)parent); // MW-2012-03-04: [[ StackFile5500 ]] If the record is extended then // pass in 'true' for 'is_ext'. if ((stat = newpar->load(p_stream, p_version, type == OT_PARAGRAPH_EXT)) != IO_NORMAL) { delete newpar; return stat; } newpar->appendto(paragraphs); } break; default: m_paragraphs = paragraphs; MCS_seek_cur(p_stream, -1); return IO_NORMAL; } } return IO_NORMAL; }
IO_stat IO_read_string(char *&r_string, uint32_t &r_length, IO_handle p_stream, uint8_t p_size, bool p_includes_null, bool p_translate) { IO_stat stat; uint32_t t_length = 0; uint32_t t_bytes = 0; switch (p_size) { case 1: { uint8_t t_len; if ((stat = IO_read_uint1(&t_len, p_stream)) != IO_NORMAL) return stat; t_bytes = t_len; break; } case 2: { uint16_t t_len; if ((stat = IO_read_uint2(&t_len, p_stream)) != IO_NORMAL) return stat; t_bytes = t_len; break; } case 4: { uint32_t t_len; if ((stat = IO_read_uint4(&t_len, p_stream)) != IO_NORMAL) return stat; t_bytes = t_len; break; } } char *t_string = nil; if (t_bytes != 0) { t_length = p_includes_null ? t_bytes - 1 : t_bytes; /* UNCHECKED */ t_string = new char[t_bytes]; stat = MCStackSecurityRead(t_string, t_length, p_stream); if (stat == IO_NORMAL && p_includes_null) stat = IO_read_uint1((uint1*)t_string + t_length, p_stream); if (stat != IO_NORMAL) { delete t_string; return stat; } if (MCtranslatechars && p_translate) { #ifdef __MACROMAN__ IO_iso_to_mac(t_string, t_length); #else IO_mac_to_iso(t_string, t_length); #endif } } r_string = t_string; r_length = t_length; return IO_NORMAL; }
void MCArraysEvalArrayDecode(MCExecContext& ctxt, MCDataRef p_encoding, MCArrayRef& r_array) { bool t_success; t_success = true; IO_handle t_stream_handle; t_stream_handle = nil; if (t_success) { t_stream_handle = MCS_fakeopen(MCDataGetBytePtr(p_encoding), MCDataGetLength(p_encoding)); if (t_stream_handle == nil) t_success = false; } uint8_t t_type; if (t_success) if (IO_read_uint1(&t_type, t_stream_handle) != IO_NORMAL) t_success = false; // AL-2014-05-01: [[ Bug 11989 ]] If the type is 'empty' then just return the empty array. if (t_success && t_type == kMCEncodedValueTypeEmpty) { r_array = MCValueRetain(kMCEmptyArray); return; } // AL-2014-05-15: [[ Bug 12203 ]] Check initial byte for version 7.0 encoded array. bool t_legacy; t_legacy = t_type < kMCEncodedValueTypeArray; MCArrayRef t_array; t_array = nil; if (t_success) t_success = MCArrayCreateMutable(t_array); if (t_legacy) { if (t_success) if (MCS_putback(t_type, t_stream_handle) != IO_NORMAL) t_success = false; MCObjectInputStream *t_stream; t_stream = nil; if (t_success) { t_stream = new MCObjectInputStream(t_stream_handle, MCDataGetLength(p_encoding), false); if (t_stream == nil) t_success = false; } if (t_success) if (t_stream -> ReadU8(t_type) != IO_NORMAL) t_success = false; if (t_success) if (MCArrayLoadFromStreamLegacy(t_array, *t_stream) != IO_NORMAL) t_success = false; delete t_stream; } else { if (t_success) if (IO_read_valueref_new((MCValueRef &)t_array, t_stream_handle) != IO_NORMAL) t_success = false; } MCS_close(t_stream_handle); if (t_success) { r_array = t_array; return; } MCValueRelease(t_array); ctxt . Throw(); }
// MW-2012-02-17: [[ LogFonts ]] Actually load the stack file (wrapped by readfile // to handle font table cleanup). IO_stat MCDispatch::doreadfile(const char *openpath, const char *inname, IO_handle &stream, MCStack *&sptr) { Boolean loadhome = False; char version[8]; if (readheader(stream, version) == IO_NORMAL) { if (strcmp(version, MCversionstring) > 0) { MCresult->sets("stack was produced by a newer version"); return IO_ERROR; } // MW-2008-10-20: [[ ParentScripts ]] Set the boolean flag that tells us whether // parentscript resolution is required to false. s_loaded_parent_script_reference = false; uint1 charset, type; char *newsf; if (IO_read_uint1(&charset, stream) != IO_NORMAL || IO_read_uint1(&type, stream) != IO_NORMAL || IO_read_string(newsf, stream) != IO_NORMAL) { MCresult->sets("stack is corrupted, check for ~ backup file"); return IO_ERROR; } delete newsf; // stackfiles is obsolete MCtranslatechars = charset != CHARSET; sptr = nil; /* UNCHECKED */ MCStackSecurityCreateStack(sptr); if (stacks == NULL) sptr->setparent(this); else sptr->setparent(stacks); sptr->setfilename(strclone(openpath)); if (MCModeCanLoadHome() && type == OT_HOME) { char *lstring = NULL; char *cstring = NULL; IO_read_string(lstring, stream); IO_read_string(cstring, stream); delete lstring; delete cstring; } MCresult -> clear(); if (IO_read_uint1(&type, stream) != IO_NORMAL || type != OT_STACK && type != OT_ENCRYPT_STACK || sptr->load(stream, version, type) != IO_NORMAL) { if (MCresult -> isclear()) MCresult->sets("stack is corrupted, check for ~ backup file"); destroystack(sptr, False); sptr = NULL; return IO_ERROR; } // MW-2011-08-09: [[ Groups ]] Make sure F_GROUP_SHARED is set // appropriately. sptr -> checksharedgroups(); if (sptr->load_substacks(stream, version) != IO_NORMAL || IO_read_uint1(&type, stream) != IO_NORMAL || type != OT_END) { if (MCresult -> isclear()) MCresult->sets("stack is corrupted, check for ~ backup file"); destroystack(sptr, False); sptr = NULL; return IO_ERROR; } if (stacks != NULL) { MCStack *tstk = stacks; do { if (sptr->hasname(tstk->getname())) { MCAutoNameRef t_stack_name; /* UNCHECKED */ t_stack_name . Clone(sptr -> getname()); delete sptr; sptr = NULL; if (strequal(tstk->getfilename(), openpath)) sptr = tstk; else { MCdefaultstackptr->getcard()->message_with_args(MCM_reload_stack, MCNameGetOldString(tstk->getname()), openpath); tstk = stacks; do { if (MCNameIsEqualTo(t_stack_name, tstk->getname(), kMCCompareCaseless)) { sptr = tstk; break; } tstk = (MCStack *)tstk->next(); } while (tstk != stacks); } return IO_NORMAL; } tstk = (MCStack *)tstk->next(); } while (tstk != stacks); } appendstack(sptr); sptr->extraopen(false); // MW-2008-10-28: [[ ParentScript ]] // We just loaded a stackfile, so check to see if parentScript resolution // is required and if so do it. // MW-2009-01-28: [[ Inherited parentScripts ]] // Resolving parentScripts may allocate memory, so 'resolveparentscripts' // will return false if it fails to allocate what it needs. At some point // this needs to be dealt with by deleting the stack and returning an error, // *However* at the time of writing, 'readfile' isn't designed to handle // this - so we just ignore the result for now (note that all the 'load' // methods *fail* to check for no-memory errors!). if (s_loaded_parent_script_reference) sptr -> resolveparentscripts(); } else { MCS_seek_set(stream, 0); if (stacks == NULL) { MCnoui = True; MCscreen = new MCUIDC; /* UNCHECKED */ MCStackSecurityCreateStack(stacks); MCdefaultstackptr = MCstaticdefaultstackptr = stacks; stacks->setparent(this); stacks->setname_cstring("revScript"); uint4 size = (uint4)MCS_fsize(stream); char *script = new char[size + 2]; script[size] = '\n'; script[size + 1] = '\0'; if (IO_read(script, sizeof(char), size, stream) != IO_NORMAL || !stacks->setscript(script)) { delete script; return IO_ERROR; } } else { char *tname = strclone(inname); // MW-2008-06-12: [[ Bug 6476 ]] Media won't open HC stacks if (!MCdispatcher->cut(True) || hc_import(tname, stream, sptr) != IO_NORMAL) { MCresult->sets("file is not a stack"); delete tname; return IO_ERROR; } } } return IO_NORMAL; }
// This method reads a stack from the given stream. The stack is set to // have parent MCDispatch, and filename MCcmd. It is designed to be used // for embedded stacks/deployed stacks/revlet stacks. IO_stat MCDispatch::readstartupstack(IO_handle stream, MCStack*& r_stack) { char version[8]; uint1 charset, type; char *newsf; if (readheader(stream, version) != IO_NORMAL || IO_read_uint1(&charset, stream) != IO_NORMAL || IO_read_uint1(&type, stream) != IO_NORMAL || IO_read_string(newsf, stream) != IO_NORMAL) return IO_ERROR; // MW-2008-10-20: [[ ParentScripts ]] Set the boolean flag that tells us whether // parentscript resolution is required to false. s_loaded_parent_script_reference = false; MCtranslatechars = charset != CHARSET; delete newsf; // stackfiles is obsolete MCStack *t_stack = nil; /* UNCHECKED */ MCStackSecurityCreateStack(t_stack); t_stack -> setparent(this); // MM-2013-10-30: [[ Bug 11333 ]] Set the filename of android mainstack to apk/mainstack (previously was just apk). // This solves relative file path referencing issues. #ifdef TARGET_SUBPLATFORM_ANDROID char *t_filename; /* UNCHECKED */ MCMemoryNewArray(MCCStringLength(MCcmd) + 11, t_filename); MCCStringFormat(t_filename, "%s/mainstack", MCcmd); t_stack -> setfilename(t_filename); #else t_stack -> setfilename(strclone(MCcmd)); #endif if (IO_read_uint1(&type, stream) != IO_NORMAL || type != OT_STACK && type != OT_ENCRYPT_STACK || t_stack->load(stream, version, type) != IO_NORMAL) { delete t_stack; return IO_ERROR; } if (t_stack->load_substacks(stream, version) != IO_NORMAL || IO_read_uint1(&type, stream) != IO_NORMAL || type != OT_END) { delete t_stack; return IO_ERROR; } // We are reading the startup stack, so this becomes the root of the // stack list. stacks = t_stack; r_stack = t_stack; #ifndef _MOBILE // Make sure parent script references are up to date. if (s_loaded_parent_script_reference) t_stack -> resolveparentscripts(); #else // Mark the stack as needed parentscript resolution. This is done after // aux stacks have been loaded. if (s_loaded_parent_script_reference) t_stack -> setextendedstate(True, ECS_USES_PARENTSCRIPTS); #endif return IO_NORMAL; }
IO_stat MCCdata::load(IO_handle stream, MCObject *parent, uint32_t version) { IO_stat stat; if ((stat = IO_read_uint4(&id, stream)) != IO_NORMAL) return checkloadstat(stat); if (parent->gettype() == CT_BUTTON) { uint1 set; stat = IO_read_uint1(&set, stream); data = reinterpret_cast<void *>(set ? 1 : 0); return checkloadstat(stat); } else { if (id & COMPACT_PARAGRAPHS) { // MW-2013-11-19: [[ UnicodeFileFormat ]] This flag is never set by newer engines // so is just legacy. char *string; if ((stat = IO_read_cstring_legacy(string, stream, sizeof(uint1))) != IO_NORMAL) return checkloadstat(stat); data = string; } else { MCParagraph *paragraphs = NULL; while (True) { uint1 type; if ((stat = IO_read_uint1(&type, stream)) != IO_NORMAL) return checkloadstat(stat); switch (type) { // MW-2012-03-04: [[ StackFile5500 ]] Handle either the paragraph or extended // paragraph tag. case OT_PARAGRAPH: case OT_PARAGRAPH_EXT: { MCParagraph *newpar = new (nothrow) MCParagraph; newpar->setparent((MCField *)parent); // MW-2012-03-04: [[ StackFile5500 ]] If the paragraph tab was the extended // variant, then pass the correct is_ext parameter. if ((stat = newpar->load(stream, version, type == OT_PARAGRAPH_EXT)) != IO_NORMAL) { delete newpar; return checkloadstat(stat); } newpar->appendto(paragraphs); } break; default: data = paragraphs; MCS_seek_cur(stream, -1); return IO_NORMAL; } } } } return IO_NORMAL; }
IO_stat MCParagraph::load(IO_handle stream, const char *version) { IO_stat stat; stat = IO_NORMAL; if (stat == IO_NORMAL) stat = IO_read_uint2(&m_text_size, stream); if (m_text_size == 1) { if (stat == IO_NORMAL) { char t_temp; uint4 t_temp_count; t_temp_count = 1; stat = IO_read(&t_temp, sizeof(uint1), t_temp_count, stream); } if (stat == IO_NORMAL) m_text_size = 0; } else if (m_text_size > 1) { if (stat == IO_NORMAL) { m_text = malloc(m_text_size); if (m_text == NULL) stat = IO_ERROR; } if (stat == IO_NORMAL) { uint4 t_temp_text_size; t_temp_text_size = m_text_size; stat = IO_read(m_text, sizeof(uint1), t_temp_text_size, stream); } if (stat == IO_NORMAL) { if (MCencryptstring != NULL) MCX_passde((char *)m_text, MCencryptstring, m_text_size); m_text_size -= 1; } } while(stat == IO_NORMAL) { uint1 t_type; stat = IO_read_uint1(&t_type, stream); if (stat != IO_NORMAL) break; uint4 t_block_offset, t_block_length, t_block_style; stat = load_block(stream, version, t_block_offset, t_block_length, t_block_style); if (stat != IO_NORMAL) break; // Make sure the block doesn't overrun the text buffer (shouldn't ever be // necessary...) t_block_length = MCU_min(m_text_size - t_block_offset, t_block_length); // Byte-swap the text to native byte-order if its unicode, otherwise translate // Mac<->ISO if necessary. const MCParagraphCharStyle *t_style_info; t_style_info = FetchCharStyle(t_block_style); if (t_style_info -> is_unicode) { uint4 t_length; t_length = t_block_length / 2; uint2 *t_ptr; t_ptr = (uint2 *)((uint1 *)m_text + t_block_offset); for(; t_length > 0; t_length -= 1) swap_uint2(t_ptr++); } else if (MCtranslatechars) { #ifdef _MACOSX IO_iso_to_mac((char *)m_text + t_block_offset, t_block_length); #else IO_mac_to_iso((char *)m_text + t_block_offset, t_block_length); #endif } // Replace the style in the given range with the style ReplaceStyles(t_block_offset, t_block_length, t_block_style); } if (stat == IO_NORMAL) { // If no styles were applied, we need to translate the text if (m_styles_size == 0 && MCtranslatechars && m_text_size > 0) #ifdef _MACOSX IO_iso_to_mac((char *)m_text, m_text_size); #else IO_mac_to_iso((char *)m_text, m_text_size); #endif Compact(); MCS_seek_cur(stream, -1); } return stat; }