/* Given a URL, it returns a parsed_url, any fields of which may be null if they are not present or parsable in the URL. */ parsed_url url_parse(char *url) { substr scheme, user, passwd, host, port, path; parsed_url r; char *cursor; scheme = user = passwd = host = port = path = (substr) { 0, 0 }; cursor = url_scheme(url, &scheme); cursor = url_user_pass(cursor, &user, &passwd); cursor = url_host(cursor, &host); cursor = url_port(cursor, &port); url_path(cursor, &path); cut_piece(r.scheme, scheme); cut_piece(r.user, user); cut_piece(r.passwd, passwd); cut_piece(r.host, host); cut_piece(r.path, path); if(port.start != NULL) r.port = atoi(port.start); else r.port = 0; return r; }
url resolve_in_path (url u) { if (use_which) { string name = escape_sh (as_string (u)); string which= var_eval_system ("which " * name * " 2> /dev/null"); if (ends (which, name)) return which; else if ((which != "") && (!starts (which, "which: ")) && (!starts (which, "no "))) cout << "TeXmacs] " << which << "\n"; } return resolve (url_path ("$PATH") * u, "x"); }
url url_general (string name, int type= URL_SYSTEM) { if (starts (name, "local:")) return url_local (name (6, N (name))); if (starts (name, "file://")) return url_file (name (7, N (name))); if (starts (name, "http://")) return url_http (name (7, N (name))); if (starts (name, "https://")) return url_https (name (8, N (name))); if (starts (name, "ftp://")) return url_ftp (name (6, N (name))); if (starts (name, "tmfs://")) return url_tmfs (name (7, N (name))); if (starts (name, "//")) return url_blank (name (2, N (name))); if (heuristic_is_path (name, type)) return url_path (name, type); if (heuristic_is_default (name, type)) return url_default (name, type); if (heuristic_is_mingw_default (name, type)) return url_mingw_default (name, type); if (heuristic_is_http (name)) return url_http (name); if (heuristic_is_ftp (name)) return url_ftp (name); return url_get_name (name, type); }
char *url_to_path(const char *url) { char *path; char *respath; url_func_result res; /* result from url routines */ res = url_path(url, &path); if (res != URL_FUNC_OK) { return NULL; } res = url_unescape(path, &respath); free(path); if (res != URL_FUNC_OK) { return NULL; } return respath; }
struct gui_download_window *gui_download_window_create(download_context *ctx, struct gui_window *gui) { const char *url = download_context_get_url(ctx); const char *mime_type = download_context_get_mime_type(ctx); const char *temp_name; char *scheme = NULL; char *filename = NULL; struct gui_download_window *dw; bool space_warning = false; os_error *error; url_func_result res; char *local_path; utf8_convert_ret err; size_t i, last_dot; dw = malloc(sizeof *dw); if (!dw) { warn_user("NoMemory", 0); return 0; } dw->ctx = ctx; dw->saved = false; dw->close_confirmed = false; dw->error = false; dw->query = QUERY_INVALID; dw->received = 0; dw->total_size = download_context_get_total_length(ctx); strncpy(dw->url, url, sizeof dw->url); dw->url[sizeof dw->url - 1] = 0; dw->status[0] = 0; gettimeofday(&dw->start_time, 0); dw->last_time = dw->start_time; dw->last_received = 0; dw->file_type = 0; dw->average_rate = 0; dw->average_points = 0; /* Get scheme from URL */ res = url_scheme(url, &scheme); if (res == URL_FUNC_NOMEM) { warn_user("NoMemory", 0); free(dw); return 0; } else if (res == URL_FUNC_OK) { /* If we have a scheme and it's "file", then * attempt to use the local filetype directly */ if (strcasecmp(scheme, "file") == 0) { char *path = NULL; res = url_path(url, &path); if (res == URL_FUNC_NOMEM) { warn_user("NoMemory", 0); free(scheme); free(dw); return 0; } else if (res == URL_FUNC_OK) { char *raw_path = curl_unescape(path, strlen(path)); if (raw_path == NULL) { warn_user("NoMemory", 0); free(path); free(scheme); free(dw); return 0; } dw->file_type = ro_filetype_from_unix_path(raw_path); curl_free(raw_path); free(path); } } free(scheme); } /* If we still don't have a filetype (i.e. failed reading local * one or fetching a remote object), then use the MIME type */ if (dw->file_type == 0) { /* convert MIME type to RISC OS file type */ error = xmimemaptranslate_mime_type_to_filetype(mime_type, &(dw->file_type)); if (error) { LOG(("xmimemaptranslate_mime_type_to_filetype: 0x%x: %s", error->errnum, error->errmess)); warn_user("MiscError", error->errmess); dw->file_type = 0xffd; } } /* open temporary output file */ temp_name = ro_gui_download_temp_name(dw); if (!ro_gui_download_check_space(dw, temp_name, NULL)) { /* issue a warning but continue with the download because the user can save it to another medium whilst it's downloading */ space_warning = true; } error = xosfind_openoutw(osfind_NO_PATH | osfind_ERROR_IF_DIR, temp_name, 0, &dw->file); if (error) { LOG(("xosfind_openoutw: 0x%x: %s", error->errnum, error->errmess)); warn_user("SaveError", error->errmess); free(dw); return 0; } /* fill in download window icons */ download_template->icons[ICON_DOWNLOAD_URL].data.indirected_text.text = dw->url; download_template->icons[ICON_DOWNLOAD_URL].data.indirected_text.size = sizeof dw->url; download_template->icons[ICON_DOWNLOAD_STATUS].data.indirected_text. text = dw->status; download_template->icons[ICON_DOWNLOAD_STATUS].data.indirected_text. size = sizeof dw->status; sprintf(dw->sprite_name, "file_%.3x", dw->file_type); if (!ro_gui_wimp_sprite_exists(dw->sprite_name)) strcpy(dw->sprite_name, "file_xxx"); download_template->icons[ICON_DOWNLOAD_ICON].data.indirected_sprite.id = (osspriteop_id) dw->sprite_name; /* Get a suitable path- and leafname for the download. */ temp_name = download_context_get_filename(dw->ctx); if (temp_name == NULL) temp_name = messages_get("SaveObject"); if (temp_name != NULL) filename = strdup(temp_name); if (filename == NULL) { LOG(("Failed to establish download filename.")); warn_user("SaveError", error->errmess); free(dw); return 0; } for (i = 0, last_dot = (size_t) -1; filename[i] != '\0'; i++) { const char c = filename[i]; if (c == '.') { last_dot = i; filename[i] = '/'; } else if (c <= ' ' || strchr(":*#$&@^%\\", c) != NULL) filename[i] = '_'; } if (option_strip_extensions && last_dot != (size_t) -1) filename[last_dot] = '\0'; if (download_dir != NULL && strlen(download_dir) > 0) snprintf(dw->path, RO_DOWNLOAD_MAX_PATH_LEN, "%s.%s", download_dir, filename); else snprintf(dw->path, RO_DOWNLOAD_MAX_PATH_LEN, "%s", filename); err = utf8_to_local_encoding(dw->path, 0, &local_path); if (err != UTF8_CONVERT_OK) { /* badenc should never happen */ assert(err != UTF8_CONVERT_BADENC); LOG(("utf8_to_local_encoding failed")); warn_user("NoMemory", 0); free(dw); return 0; } else { strncpy(dw->path, local_path, sizeof dw->path); free(local_path); } download_template->icons[ICON_DOWNLOAD_PATH].data.indirected_text.text = dw->path; download_template->icons[ICON_DOWNLOAD_PATH].data.indirected_text.size = sizeof dw->path; download_template->icons[ICON_DOWNLOAD_DESTINATION].data. indirected_text.text = dw->path; download_template->icons[ICON_DOWNLOAD_DESTINATION].data. indirected_text.size = sizeof dw->path; download_template->icons[ICON_DOWNLOAD_DESTINATION].flags |= wimp_ICON_DELETED; /* create and open the download window */ error = xwimp_create_window(download_template, &dw->window); if (error) { LOG(("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess)); warn_user("WimpError", error->errmess); free(dw); return 0; } dw->prev = 0; dw->next = download_window_list; if (download_window_list) download_window_list->prev = dw; download_window_list = dw; ro_gui_download_update_status(dw); ro_gui_dialog_open(dw->window); ro_gui_wimp_event_set_user_data(dw->window, dw); ro_gui_wimp_event_register_mouse_click(dw->window, ro_gui_download_click); ro_gui_wimp_event_register_keypress(dw->window, ro_gui_download_keypress); ro_gui_wimp_event_register_close_window(dw->window, ro_gui_download_close); /* issue the warning now, so that it appears in front of the download * window! */ if (space_warning) warn_user("DownloadWarn", messages_get("NoDiscSpace")); return dw; }
bool is_secure (url u) { return descends (u, expand (url_path ("$TEXMACS_SECURE_PATH"))); }
void link_check::do_url( const string & url, const string & library_name, const path & source_path, bool no_link_errors, bool allow_external_content, std::string::const_iterator contents_begin, std::string::const_iterator url_start ) // precondition: source_path.is_complete() { if(!no_link_errors && url.empty()) { ++m_invalid_errors; int ln = std::count( contents_begin, url_start, '\n' ) + 1; error( library_name, source_path, "Empty URL.", ln ); return; } // Decode ampersand encoded characters. string decoded_url = is_css(source_path) ? url : decode_ampersands(url); if(decoded_url.empty()) { if(!no_link_errors) { ++m_invalid_errors; int ln = std::count( contents_begin, url_start, '\n' ) + 1; error( library_name, source_path, "Invalid URL (invalid ampersand encodings): " + url, ln ); } return; } boost::smatch m; if(!boost::regex_match(decoded_url, m, url_decompose_regex)) { if(!no_link_errors) { ++m_invalid_errors; int ln = std::count( contents_begin, url_start, '\n' ) + 1; error( library_name, source_path, "Invalid URL: " + decoded_url, ln ); } return; } bool scheme_matched = m[2].matched, authority_matched = m[4].matched, //query_matched = m[7].matched, fragment_matched = m[9].matched; std::string scheme(m[2]), authority(m[4]), url_path(m[5]), //query(m[7]), fragment(m[9]); // Check for external content if(!allow_external_content && (authority_matched || scheme_matched)) { if(!no_link_errors) { ++m_invalid_errors; int ln = std::count( contents_begin, url_start, '\n' ) + 1; error( library_name, source_path, "External content: " + decoded_url, ln ); } } // Protocol checks if(scheme_matched) { if(scheme == "http" || scheme == "https") { // All http links should have a hostname. Generally if they don't // it's by mistake. If they shouldn't, then a protocol isn't // required. if(!authority_matched) { if(!no_link_errors) { ++m_invalid_errors; int ln = std::count( contents_begin, url_start, '\n' ) + 1; error( library_name, source_path, "No hostname: " + decoded_url, ln ); } } return; } else if(scheme == "file") { if(!no_link_errors) { ++m_invalid_errors; int ln = std::count( contents_begin, url_start, '\n' ) + 1; error( library_name, source_path, "Invalid URL (hardwired file): " + decoded_url, ln ); } } else if(scheme == "mailto" || scheme == "ftp" || scheme == "news" || scheme == "javascript") { if ( !no_link_errors && is_css(source_path) ) { ++m_invalid_errors; int ln = std::count( contents_begin, url_start, '\n' ) + 1; error( library_name, source_path, "Invalid protocol for css: " + decoded_url, ln ); } } else { if(!no_link_errors) { ++m_invalid_errors; int ln = std::count( contents_begin, url_start, '\n' ) + 1; error( library_name, source_path, "Unknown protocol: '" + scheme + "' in url: " + decoded_url, ln ); } } return; } // Hostname without protocol. if(authority_matched) { if(!no_link_errors) { ++m_invalid_errors; int ln = std::count( contents_begin, url_start, '\n' ) + 1; error( library_name, source_path, "Invalid URL (hostname without protocol): " + decoded_url, ln ); } } // Check the fragment identifier if ( fragment_matched ) { if ( is_css(source_path) ) { if ( !no_link_errors ) { ++m_invalid_errors; int ln = std::count( contents_begin, url_start, '\n' ) + 1; error( library_name, source_path, "Fragment link in CSS: " + decoded_url, ln ); } } else { if ( !no_link_errors && fragment.find( '#' ) != string::npos ) { ++m_bookmark_errors; int ln = std::count( contents_begin, url_start, '\n' ) + 1; error( library_name, source_path, "Invalid bookmark: " + decoded_url, ln ); } else if ( !no_link_errors && url_path.empty() && !fragment.empty() // w3.org recommends case-sensitive broken bookmark checking // since some browsers do a case-sensitive match. && bookmarks.find(decode_percents(fragment)) == bookmarks.end() ) { ++m_broken_errors; int ln = std::count( contents_begin, url_start, '\n' ) + 1; error( library_name, source_path, "Unknown bookmark: " + decoded_url, ln ); } } // No more to do if it's just a fragment identifier if(url_path.empty()) return; } // Detect characters banned by RFC2396: if ( !no_link_errors && decoded_url.find_first_of( " <>\"{}|\\^[]'" ) != string::npos ) { ++m_invalid_errors; int ln = std::count( contents_begin, url_start, '\n' ) + 1; error( library_name, source_path, "Invalid character in URL: " + decoded_url, ln ); } // Check that we actually have a path. if(url_path.empty()) { if(!no_link_errors) { ++m_invalid_errors; int ln = std::count( contents_begin, url_start, '\n' ) + 1; error( library_name, source_path, "Invalid URL (empty path in relative url): " + decoded_url, ln ); } } // Decode percent encoded characters. string decoded_path = decode_percents(url_path); if(decoded_path.empty()) { if(!no_link_errors) { ++m_invalid_errors; int ln = std::count( contents_begin, url_start, '\n' ) + 1; error( library_name, source_path, "Invalid URL (invalid character encodings): " + decoded_url, ln ); } return; } // strip url of references to current dir if ( decoded_path[0]=='.' && decoded_path[1]=='/' ) decoded_path.erase( 0, 2 ); // url is relative source_path.branch() // convert to target_path, which is_complete() path target_path; try { target_path = source_path.branch_path() /= path( decoded_path ); } catch ( const fs::filesystem_error & ) { if(!no_link_errors) { int ln = std::count( contents_begin, url_start, '\n' ) + 1; ++m_invalid_errors; error( library_name, source_path, "Invalid URL (error resolving path): " + decoded_url, ln ); } return; } // create a m_paths entry if necessary std::pair< const string, int > entry( relative_to( target_path, search_root_path() ), 0 ); m_path_map::iterator itr( m_paths.find( entry.first ) ); if ( itr == m_paths.end() ) { if ( fs::exists( target_path ) ) entry.second = m_present; itr = m_paths.insert( entry ).first; } // itr now points to the m_paths entry itr->second |= m_linked_to; // if target isn't present, the link is broken if ( !no_link_errors && (itr->second & m_present) == 0 ) { ++m_broken_errors; int ln = std::count( contents_begin, url_start, '\n' ) + 1; error( library_name, source_path, "Broken link: " + decoded_url, ln ); } }