bool MCImageDecode(const uint8_t *p_data, uindex_t p_size, MCImageFrame *&r_frames, uindex_t &r_frame_count) { bool t_success = true; IO_handle t_stream = nil; t_success = nil != (t_stream = MCS_fakeopen(MCString((const char*)p_data, p_size))); if (t_success) t_success = MCImageDecode(t_stream, r_frames, r_frame_count); if (t_stream != nil) MCS_close(t_stream); return t_success; }
// This is a helper method for the V1 externals interface. It ensures that the // string is terminated by a NUL, but without affecting the value's size. It // must only be called on value's which are already strings. bool MCVariableValue::ensure_cstring(void) { if (strnum . buffer . size != 0 && strnum . svalue . length < strnum . buffer . size) { strnum . buffer . data[strnum . svalue . length] = '\0'; return true; } if (!append_string(MCString("\0", 1))) return false; strnum . svalue . length -= 1; return true; }
void MCUrlLoadEvent::Dispatch(void) { MCObject *t_object; t_object = m_object -> Get(); if (t_object != nil) { switch (m_status) { case kMCSystemUrlStatusFinished: t_object -> message_with_args(m_message, m_url, "downloaded", MCString(static_cast<char*>(m_data.bytes), m_data.size)); break; case kMCSystemUrlStatusError: t_object -> message_with_args(m_message, m_url, "error", m_error); break; } } }
static void MCFontDrawTextCallback(MCFontRef p_font, const char *p_text, uint32_t p_length, bool p_is_unicode, font_draw_text_context *ctxt) { MCGFont t_font; t_font = MCFontStructToMCGFont(p_font->fontstruct); // MW-2013-12-04: [[ Bug 11535 ]] Pass through the fixed advance. t_font . fixed_advance = p_font -> fixed_advance; // MW-2013-12-04: [[ Bug 11549 ]] Make sure unicode text is short-aligned. MCExecPoint ep; ep . setsvalue(MCString(p_text, p_length)); if (!p_is_unicode) ep . nativetoutf16(); else if ((((uintptr_t)ep . getsvalue() . getstring()) & 1) != 0) ep . grabsvalue(); MCGContextDrawPlatformText(ctxt->m_gcontext, (unichar_t *) ep . getsvalue() . getstring(), ep . getsvalue() . getlength(), MCGPointMake(ctxt->x, ctxt->y), t_font); // The draw position needs to be advanced. Can this be done more efficiently? ctxt -> x += MCGContextMeasurePlatformText(NULL, (unichar_t*)ep.getsvalue().getstring(), ep.getsvalue().getlength(), t_font); }
static void MCFontMeasureTextCallback(MCFontRef p_font, const char *p_text, uint32_t p_length, bool p_is_unicode, font_measure_text_context *ctxt) { if (p_length == 0 || p_text == NULL) return; MCGFont t_font; t_font = MCFontStructToMCGFont(p_font->fontstruct); // MW-2013-12-04: [[ Bug 11535 ]] Pass through the fixed advance. t_font . fixed_advance = p_font -> fixed_advance; // MW-2013-12-04: [[ Bug 11549 ]] Make sure unicode text is short-aligned. MCExecPoint ep; ep . setsvalue(MCString(p_text, p_length)); if (!p_is_unicode) ep . nativetoutf16(); else if ((((uintptr_t)ep . getsvalue() . getstring()) & 1) != 0) ep . grabsvalue(); ctxt -> m_width += MCGContextMeasurePlatformText(NULL, (unichar_t *) ep . getsvalue() . getstring(), ep . getsvalue() . getlength(), t_font); }
void MCS_putintourl(MCObject *p_target, const MCString& p_data, const char *p_url) { bool t_success = true; char *t_processed = nil; MCObjectHandle *t_obj = nil; MCSPutUrlState t_state; t_success = MCSystemProcessUrl(p_url, kMCSystemUrlOperationStrip, t_processed); if (t_success) t_success = nil != (t_obj = p_target->gethandle()); if (t_success) { t_state.url = t_processed; t_state.status = kMCSystemUrlStatusNone; t_state.object = t_obj; t_state.put_sent = 0; t_state.put_length = p_data.getlength(); t_success = MCSystemPutUrl(t_processed, p_data . getstring(), p_data . getlength(), MCS_puturl_callback, &t_state); } if (t_success); { MCurlresult->clear(); while (t_state.status != kMCSystemUrlStatusUploaded && t_state.status != kMCSystemUrlStatusError) MCscreen->wait(60.0, True, True); if (t_state.status == kMCSystemUrlStatusUploaded) MCresult->clear(); else MCresult->sets(MCString(t_state.error)); } MCCStringFree(t_processed); if (t_obj != nil) t_obj->Release(); }
bool MCVariableValue::get_as_real(MCExecPoint& ep, real64_t& r_value) { if (is_number()) { r_value = strnum . nvalue; return true; } if (is_empty()) { r_value = 0.0; return true; } if (is_string()) return MCU_stor8(MCString(strnum . svalue . string, strnum . svalue . length), r_value, ep . getconvertoctals()) == True; assert(is_array()); r_value = 0.0; return true; }
IO_stat IO_write_string(const char *string, uint4 outlen, IO_handle stream, Boolean isunicode, uint1 size) { IO_stat stat = IO_NORMAL; if (isunicode) { uint16_t *t_uniptr = (uint16_t*)string; uint32_t t_len = outlen / 2; while (t_len--) swap_uint2(t_uniptr++); } stat = IO_write_string(MCString(string, outlen), stream, size, true); if (isunicode) { uint16_t *t_uniptr = (uint16_t*)string; uint32_t t_len = outlen / 2; while (t_len--) swap_uint2(t_uniptr++); } return stat; }
bool MCVariableValue::coerce_to_real(MCExecPoint& ep) { assert(!is_real()); if (is_empty()) { assign_real(0.0); return true; } if (is_string()) { if (MCU_stor8(MCString(strnum . svalue . string, strnum . svalue . length), strnum . nvalue, ep . getconvertoctals()) != True) return false; set_type(VF_BOTH); return true; } assert(is_array()); assign_real(0.0); return true; }
void MCExecPoint::setstaticbytes(const void *p_bytes, uindex_t p_length) { setsvalue(MCString((const char *)p_bytes, p_length)); }
TEST(IRC32, GetMessageTags) { EXPECT_EQ(MCString(), CUtils::GetMessageTags("")); EXPECT_EQ(MCString(), CUtils::GetMessageTags(":nick!ident@host PRIVMSG #chan :hello world")); MCString exp; exp["a"] = "b"; EXPECT_EQ(exp, CUtils::GetMessageTags("@a=b")); EXPECT_EQ(exp, CUtils::GetMessageTags("@a=b :nick!ident@host PRIVMSG #chan :hello world")); EXPECT_EQ(exp, CUtils::GetMessageTags("@a=b :rest")); exp.clear(); exp["ab"] = "cdef"; exp["znc.in/gh-ij"] = "klmn,op"; EXPECT_EQ(exp, CUtils::GetMessageTags("@ab=cdef;znc.in/gh-ij=klmn,op :rest")); exp.clear(); exp["a"] = "==b=="; EXPECT_EQ(exp, CUtils::GetMessageTags("@a===b== :rest")); exp.clear(); exp["a"] = ""; exp["b"] = "c"; exp["d"] = ""; EXPECT_EQ(exp, CUtils::GetMessageTags("@a;b=c;d :rest")); exp.clear(); exp["semi-colon"] += ';'; exp["space"] += ' '; exp["NUL"] += '\0'; exp["backslash"] += '\\'; exp["CR"] += '\r'; exp["LF"] += '\n'; EXPECT_EQ(exp, CUtils::GetMessageTags(R"(@semi-colon=\:;space=\s;NUL=\0;backslash=\\;CR=\r;LF=\n :rest)")); exp.clear(); exp["a"] = "; \\\r\n"; EXPECT_EQ(exp, CUtils::GetMessageTags(R"(@a=\:\s\\\r\n :rest)")); exp.clear(); } TEST(IRC32, SetMessageTags) { CString sLine; sLine = ":rest"; CUtils::SetMessageTags(sLine, MCString()); EXPECT_EQ(":rest", sLine); MCString tags; tags["a"] = "b"; CUtils::SetMessageTags(sLine, tags); EXPECT_EQ("@a=b :rest", sLine); tags["c"] = "d"; CUtils::SetMessageTags(sLine, tags); EXPECT_EQ("@a=b;c=d :rest", sLine); tags["e"] = ""; CUtils::SetMessageTags(sLine, tags); EXPECT_EQ("@a=b;c=d;e :rest", sLine); tags.clear(); tags["semi-colon"] += ';'; tags["space"] += ' '; tags["NUL"] += '\0'; tags["backslash"] += '\\'; tags["CR"] += '\r'; tags["LF"] += '\n'; CUtils::SetMessageTags(sLine, tags); EXPECT_EQ(R"(@CR=\r;LF=\n;NUL=\0;backslash=\\;semi-colon=\:;space=\s :rest)", sLine); tags.clear(); tags["a"] = "; \\\r\n"; CUtils::SetMessageTags(sLine, tags); EXPECT_EQ(R"(@a=\:\s\\\r\n :rest)", sLine); }
IO_stat IO_write_string(const char *string, IO_handle stream, uint1 size) { return IO_write_string(MCString(string), stream, size); }
MCString MCString::FromUTF8(const std::string& utf8) { std::wstring utf16; utf8::utf8to16(utf8.begin(), utf8.end(), std::back_inserter(utf16)); return MCString(utf16); }
Exec_stat MCPut::exec_cookie(MCExecPoint &ep) { char *t_name = NULL; char *t_value = NULL; char *t_path = NULL; char *t_domain = NULL; uint32_t t_name_len = 0; uint32_t t_value_len = 0; uint32_t t_path_len = 0; uint32_t t_domain_len = 0; uint32_t t_expires = 0; bool t_success = true; t_value = ep.getsvalue().clone(); t_value_len = ep.getsvalue().getlength(); t_success = (ES_NORMAL == name->eval(ep)); if (t_success) { t_name = ep.getsvalue().clone(); t_name_len = ep.getsvalue().getlength(); if (expires != NULL) t_success = expires->eval(ep); } if (t_success && expires) t_success = ep.isempty() || MCU_stoui4(ep.getsvalue(), t_expires); if (t_success && path) { t_success = path->eval(ep); if (t_success) { t_path = ep.getsvalue().clone(); t_path_len = ep.getsvalue().getlength(); } } if (t_success && domain) { t_success = domain->eval(ep); if (t_success) { t_domain = ep.getsvalue().clone(); t_domain_len = ep.getsvalue().getlength(); } } if(t_success) t_success = MCServerSetCookie(MCString(t_name, t_name_len), MCString(t_value, t_value_len), t_expires, MCString(t_path, t_path_len), MCString(t_domain, t_domain_len), is_secure, is_httponly); MCCStringFree(t_name); MCCStringFree(t_value); MCCStringFree(t_path); MCCStringFree(t_domain); if (!t_success) { MCeerror->add(EE_PUT_CANTSETINTO, line, pos); return ES_ERROR; } ep.clear(); return ES_NORMAL; }
bool cgi_initialize() { // need to ensure PATH_TRANSLATED points to the script and PATH_INFO contains everything that follows cgi_fix_path_variables(); // Resolve the main script that has been requested by the CGI interface. MCserverinitialscript = MCsystem -> ResolvePath(MCS_getenv("PATH_TRANSLATED")); // Set the current folder to be that containing the CGI file. char *t_server_script_folder; t_server_script_folder = strdup(MCserverinitialscript); #ifdef _WINDOWS_SERVER strrchr(t_server_script_folder, '\\')[0] = '\0'; #else strrchr(t_server_script_folder, '/')[0] = '\0'; #endif MCsystem -> SetCurrentFolder(t_server_script_folder); delete t_server_script_folder; // Initialize the headers. MCservercgiheaders = NULL; MCservercgiheaders_sent = false; // Get the document root MCservercgidocumentroot = getenv("DOCUMENT_ROOT"); // Initialize the input wrapper. This creates a cache of the input stream // which is filled as the stream is read from. this allows stdin to be used // to populate the post data arrays, and also to be read from by the script // without conflicting s_cgi_stdin_cache = new MCStreamCache(IO_stdin->handle); IO_stdin = new IO_header(new MCCacheHandle(s_cgi_stdin_cache), 0); // Initialize the output wrapper, this simply ensures we output headers // before any content. IO_stdout = new IO_header(new cgi_stdout, 0); // Need an exec-point for variable creation. MCExecPoint ep; // Construct the _SERVER variable /* UNCHECKED */ MCVariable::createwithname_cstring("$_SERVER", s_cgi_server); s_cgi_server -> setnext(MCglobals); MCglobals = s_cgi_server; for(uint32_t i = 0; environ[i] != NULL; i++) { static const char *s_cgi_vars[] = { "GATEWAY_INTERFACE=", "SERVER_ADDR=", "SERVER_NAME=", "SERVER_SOFTWARE=", "SERVER_PROTOCOL=", "REQUEST_METHOD=", "REQUEST_TIME=", "QUERY_STRING=", "DOCUMENT_ROOT=", "HTTPS=", // MW-2009-08-12: For some reason I missed this first time around :o) "REMOTE_USER="******"REMOTE_ADDR=", "REMOTE_HOST=", "REMOTE_PORT=", // MM-2011-09-08: Added as part of customer support request for REMOTE_USER. // The standard Apache LiveCode server config redirects the script to the server engine. // This appears to mean that REMOTE_USER is never set // (I guess it will only ever be set if the server engine itself is behind authentication) // but REDIRECT_REMOTE_USER is. "REDIRECT_REMOTE_USER="******"SERVER_ADMIN=", "SERVER_PORT=", "SERVER_SIGNATURE=", "PATH_TRANSLATED=", "REQUEST_URI=", "PATH_INFO=", "SCRIPT_NAME=", "SCRIPT_FILENAME=", "CONTENT_TYPE=", "CONTENT_LENGTH=", NULL }; bool t_found; t_found = false; if (strncasecmp(environ[i], "HTTP_", 5) == 0) t_found = true; else for(uint32_t j = 0; s_cgi_vars[j] != NULL && !t_found; j++) if (strncasecmp(environ[i], s_cgi_vars[j], strlen(s_cgi_vars[j])) == 0) t_found = true; if (t_found) { const char *t_value; t_value = strchr(environ[i], '='); if (t_value == NULL) { ep . clear(); t_value = environ[i] + strlen(environ[i]); } else ep . setsvalue(t_value + 1); s_cgi_server -> getvalue() . store_element(ep, MCString(environ[i], t_value - environ[i])); } } // Construct the GET variables by parsing the QUERY_STRING /* UNCHECKED */ MCDeferredVariable::createwithname_cstring("$_GET_RAW", cgi_compute_get_raw_var, nil, s_cgi_get_raw); s_cgi_get_raw -> setnext(MCglobals); MCglobals = s_cgi_get_raw; /* UNCHECKED */ MCDeferredVariable::createwithname_cstring("$_GET", cgi_compute_get_var, nil, s_cgi_get); s_cgi_get -> setnext(MCglobals); MCglobals = s_cgi_get; /* UNCHECKED */ MCDeferredVariable::createwithname_cstring("$_GET_BINARY", cgi_compute_get_binary_var, nil, s_cgi_get_binary); s_cgi_get_binary -> setnext(MCglobals); MCglobals = s_cgi_get_binary; // Construct the _POST variables by reading stdin. /* UNCHECKED */ MCDeferredVariable::createwithname_cstring("$_POST_RAW", cgi_compute_post_raw_var, nil, s_cgi_post_raw); s_cgi_post_raw -> setnext(MCglobals); MCglobals = s_cgi_post_raw; /* UNCHECKED */ MCDeferredVariable::createwithname_cstring("$_POST", cgi_compute_post_var, nil, s_cgi_post); s_cgi_post -> setnext(MCglobals); MCglobals = s_cgi_post; /* UNCHECKED */ MCDeferredVariable::createwithname_cstring("$_POST_BINARY", cgi_compute_post_binary_var, nil, s_cgi_post_binary); s_cgi_post_binary -> setnext(MCglobals); MCglobals = s_cgi_post_binary; // Construct the FILES variable by reading stdin /* UNCHECKED */ MCDeferredVariable::createwithname_cstring("$_FILES", cgi_compute_files_var, nil, s_cgi_files); s_cgi_files -> setnext(MCglobals); MCglobals = s_cgi_files; // Construct the COOKIES variable by parsing HTTP_COOKIE /* UNCHECKED */ MCDeferredVariable::createwithname_cstring("$_COOKIE", cgi_compute_cookie_var, nil, s_cgi_cookie); s_cgi_cookie -> setnext(MCglobals); MCglobals = s_cgi_cookie; // Create the $_SESSION variable explicitly, to be populated upon calls to "start session" // required as implicit references to "$_SESSION" will result in its creation as an env var MCVariable *t_session_var = NULL; /* UNCHECKED */ MCVariable::createwithname_cstring("$_SESSION", t_session_var); t_session_var->setnext(MCglobals); MCglobals = t_session_var; return true; }
bool MCServerStartSession() { // start session: // if MCsessionid is empty - get id from cookie // if MCsessionid not empty - use MCsessionid - clear MCsessionid once opened bool t_success = true; if (s_current_session != NULL) return true; const char *t_session_id = NULL; char *t_cookie_id = NULL; t_session_id = MCsessionid; if (t_session_id == NULL) { t_success = MCServerGetSessionIdFromCookie(t_cookie_id); t_session_id = t_cookie_id; } if (t_success) t_success = MCSessionStart(t_session_id, s_current_session); MCVariable *t_session_var = NULL; if (t_success) { t_session_var = MCVariable::lookupglobal_cstring("$_SESSION"); if (t_session_var == NULL) { t_success = MCVariable::createwithname_cstring("$_SESSION", t_session_var); if (t_success) { t_session_var->setnext(MCglobals); MCglobals = t_session_var; } } } if (t_success) t_session_var->getvalue().assign_empty(); if (t_success) { if (s_current_session->data_length > 0) t_success = t_session_var->getvalue().decode(MCString(s_current_session->data, s_current_session->data_length)); } if (t_success) { // clear MCsessionid - now associated with open session MCCStringFree(MCsessionid); MCsessionid = NULL; } else { MCSessionDiscard(s_current_session); s_current_session = NULL; } MCCStringFree(t_cookie_id); return t_success; }
IO_stat MCLogicalFontTableLoad(IO_handle p_stream) { // Delete any existing font table. MCLogicalFontTableFinish(); // Keep track of any IO errors. IO_stat t_stat; t_stat = IO_NORMAL; // Read the number of entries. uint2 t_count; if (t_stat == IO_NORMAL) t_stat = IO_read_uint2(&t_count, p_stream); // Allocate an array big enough to hold all of them. if (t_stat == IO_NORMAL) if (!MCMemoryNewArray(t_count, s_logical_font_table)) t_stat = IO_ERROR; if (t_stat == IO_NORMAL) { // The size and capacity of the table are equal to the count. s_logical_font_table_size = s_logical_font_table_capacity = t_count; // Iterate t_count times to load each entry in. for(uint32_t i = 0; i < t_count && t_stat == IO_NORMAL; i++) { char *t_textfont; uint2 t_textsize, t_textstyle; t_textfont = nil; // Read in the textSize, textStyle and (original) textFont props. t_stat = IO_read_uint2(&t_textsize, p_stream); if (t_stat == IO_NORMAL) t_stat = IO_read_uint2(&t_textstyle, p_stream); if (t_stat == IO_NORMAL) t_stat = IO_read_string(t_textfont, p_stream); // Now convert the textFont string into a name, splitting off the // lang tag (if any). MCNameRef t_textfont_name; bool t_is_unicode; if (t_stat == IO_NORMAL) { // MW-2012-02-17: [[ Bug ]] It seems possible for the textFont string // to be empty in some cases - so handle this case carefully. const char *t_textfont_tag; if (t_textfont != nil) { t_textfont_tag = strchr(t_textfont, ','); if (t_textfont_tag == nil) { t_textfont_tag = t_textfont + strlen(t_textfont); t_is_unicode = false; } else t_is_unicode = true; } else { t_textfont_tag = nil; t_is_unicode = false; } if (!MCNameCreateWithOldString(MCString(t_textfont, t_textfont_tag - t_textfont), t_textfont_name)) t_stat = IO_ERROR; } // Set the appropriate table entry. if (t_stat == IO_NORMAL) MCLogicalFontTableSetEntry(i, t_textfont_name, t_textstyle, t_textsize, t_is_unicode); // Cleanup the (temporary) original textFont string. delete t_textfont; } } return t_stat; }
bool MCResidentImageRep::GetDataStream(IO_handle &r_stream) { r_stream = MCS_fakeopen(MCString((char*)m_data, m_size)); return r_stream != nil; }
static bool cgi_multipart_body_callback(void *p_context, const char *p_data, uint32_t p_data_length, bool p_finished, bool p_truncated) { cgi_multipart_context_t *t_context = (cgi_multipart_context_t*)p_context; bool t_success = true; if (cgi_context_is_form_data(t_context)) { if (t_context->post_binary_variable != NULL) { t_success = t_context->post_binary_variable->append_string(MCString(p_data, p_data_length)); if (t_success && p_finished) { uint32_t t_native_length; char *t_native = NULL; MCString t_value; t_value = t_context->post_binary_variable->get_string(); if (cgi_native_from_encoding(MCserveroutputtextencoding, t_value.getstring(), t_value.getlength(), t_native, t_native_length)) t_context->post_variable -> assign_buffer(t_native, t_native_length); } } } else if (cgi_context_is_file(t_context)) { if (t_context->file_status == kMCFileStatusOK) { if (IO_NORMAL == MCS_write(p_data, 1, p_data_length, t_context->file_handle)) t_context->file_size += p_data_length; else t_context->file_status = kMCFileStatusIOError; } if (t_success && (p_finished || p_truncated)) { MCExecPoint ep; MCVariableValue *t_file_varvalue = NULL; cgi_fetch_variable_value_for_key(s_cgi_files, t_context->name, MCCStringLength(t_context->name), ep, t_context->file_variable); if (t_context->file_status == kMCFileStatusOK && t_context->file_size == 0) t_context->file_status = kMCFileStatusFailed; if (p_truncated) t_context->file_status = kMCFileStatusStopped; ep.setsvalue(MCString(t_context->file_name)); t_context->file_variable->store_element(ep, MCString("name")); ep.setsvalue(MCString(t_context->type)); t_context->file_variable->store_element(ep, MCString("type")); ep.setsvalue(MCString(t_context->temp_name)); t_context->file_variable->store_element(ep, MCString("filename")); ep.setuint(t_context->file_size); t_context->file_variable->store_element(ep, MCString("size")); if (t_context->file_status != kMCFileStatusOK) { ep.setsvalue(MCMultiPartGetErrorMessage(t_context->file_status)); t_context->file_variable->store_element(ep, MCString("error")); } } } if (t_success && p_finished) { // clear context for next part cgi_dispose_multipart_context(t_context); } return t_success; }