UrlPlaylistItem::UrlPlaylistItem(const BMessage* archive) { const char* url = NULL; if (archive->FindString("mediaplayer:url", &url) == B_OK) fUrl = BUrl(url); }
UrlPlaylistItem::UrlPlaylistItem(const UrlPlaylistItem& item) { fUrl = BUrl(item.Url()); }
status_t BHttpRequest::_ProtocolLoop() { // Initialize the request redirection loop int8 maxRedirs = fOptMaxRedirs; bool newRequest; do { newRequest = false; // Result reset fHeaders.Clear(); _ResultHeaders().Clear(); BString host = fUrl.Host(); int port = fSSL ? 443 : 80; if (fUrl.HasPort()) port = fUrl.Port(); if (fContext->UseProxy()) { host = fContext->GetProxyHost(); port = fContext->GetProxyPort(); } status_t result = fInputBuffer.InitCheck(); if (result != B_OK) return result; if (!_ResolveHostName(host, port)) { _EmitDebug(B_URL_PROTOCOL_DEBUG_ERROR, "Unable to resolve hostname (%s), aborting.", fUrl.Host().String()); return B_SERVER_NOT_FOUND; } status_t requestStatus = _MakeRequest(); if (requestStatus != B_OK) return requestStatus; // Prepare the referer for the next request if needed if (fOptAutoReferer) fOptReferer = fUrl.UrlString(); switch (StatusCodeClass(fResult.StatusCode())) { case B_HTTP_STATUS_CLASS_INFORMATIONAL: // Header 100:continue should have been // handled in the _MakeRequest read loop break; case B_HTTP_STATUS_CLASS_SUCCESS: break; case B_HTTP_STATUS_CLASS_REDIRECTION: { // Redirection has been explicitly disabled if (!fOptFollowLocation) break; int code = fResult.StatusCode(); if (code == B_HTTP_STATUS_MOVED_PERMANENTLY || code == B_HTTP_STATUS_FOUND || code == B_HTTP_STATUS_SEE_OTHER || code == B_HTTP_STATUS_TEMPORARY_REDIRECT) { BString locationUrl = fHeaders["Location"]; fUrl = BUrl(fUrl, locationUrl); // 302 and 303 redirections also convert POST requests to GET // (and remove the posted form data) if ((code == B_HTTP_STATUS_FOUND || code == B_HTTP_STATUS_SEE_OTHER) && fRequestMethod == B_HTTP_POST) { SetMethod(B_HTTP_GET); delete fOptPostFields; fOptPostFields = NULL; delete fOptInputData; fOptInputData = NULL; fOptInputDataSize = 0; } if (--maxRedirs > 0) { newRequest = true; // Redirections may need a switch from http to https. if (fUrl.Protocol() == "https") fSSL = true; else if (fUrl.Protocol() == "http") fSSL = false; _EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Following: %s\n", fUrl.UrlString().String()); } } break; } case B_HTTP_STATUS_CLASS_CLIENT_ERROR: if (fResult.StatusCode() == B_HTTP_STATUS_UNAUTHORIZED) { BHttpAuthentication* authentication = &fContext->GetAuthentication(fUrl); status_t status = B_OK; if (authentication->Method() == B_HTTP_AUTHENTICATION_NONE) { // There is no authentication context for this // url yet, so let's create one. BHttpAuthentication newAuth; newAuth.Initialize(fHeaders["WWW-Authenticate"]); fContext->AddAuthentication(fUrl, newAuth); // Get the copy of the authentication we just added. // That copy is owned by the BUrlContext and won't be // deleted (unlike the temporary object above) authentication = &fContext->GetAuthentication(fUrl); } newRequest = false; if (fOptUsername.Length() > 0 && status == B_OK) { // If we received an username and password, add them // to the request. This will either change the // credentials for an existing request, or set them // for a new one we created just above. // // If this request handles HTTP redirections, it will // also automatically retry connecting and send the // login information. authentication->SetUserName(fOptUsername); authentication->SetPassword(fOptPassword); newRequest = true; } } break; case B_HTTP_STATUS_CLASS_SERVER_ERROR: break; default: case B_HTTP_STATUS_CLASS_INVALID: break; } } while (newRequest); _EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "%ld headers and %ld bytes of data remaining", fHeaders.CountHeaders(), fInputBuffer.Size()); if (fResult.StatusCode() == 404) return B_RESOURCE_NOT_FOUND; return B_OK; }
status_t BHttpRequest::_ProtocolLoop() { // Initialize the request redirection loop int8 maxRedirs = fOptMaxRedirs; bool newRequest; do { newRequest = false; // Result reset fOutputHeaders.Clear(); fHeaders.Clear(); _ResultHeaders().Clear(); if (!_ResolveHostName()) { _EmitDebug(B_URL_PROTOCOL_DEBUG_ERROR, "Unable to resolve hostname (%s), aborting.", fUrl.Host().String()); return B_SERVER_NOT_FOUND; } status_t requestStatus = _MakeRequest(); if (requestStatus != B_OK) return requestStatus; // Prepare the referer for the next request if needed if (fOptAutoReferer) fOptReferer = fUrl.UrlString(); switch (StatusCodeClass(fResult.StatusCode())) { case B_HTTP_STATUS_CLASS_INFORMATIONAL: // Header 100:continue should have been // handled in the _MakeRequest read loop break; case B_HTTP_STATUS_CLASS_SUCCESS: break; case B_HTTP_STATUS_CLASS_REDIRECTION: // Redirection has been explicitly disabled if (!fOptFollowLocation) break; // TODO: Some browsers seems to translate POST requests to // GET when following a 302 redirection if (fResult.StatusCode() == B_HTTP_STATUS_MOVED_PERMANENTLY) { BString locationUrl = fHeaders["Location"]; fUrl = BUrl(fUrl, locationUrl); if (--maxRedirs > 0) { newRequest = true; _EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Following: %s\n", fUrl.UrlString().String()); } } break; case B_HTTP_STATUS_CLASS_CLIENT_ERROR: if (fResult.StatusCode() == B_HTTP_STATUS_UNAUTHORIZED) { BHttpAuthentication* authentication = &fContext->GetAuthentication(fUrl); status_t status = B_OK; if (authentication->Method() == B_HTTP_AUTHENTICATION_NONE) { // There is no authentication context for this // url yet, so let's create one. authentication = new(std::nothrow) BHttpAuthentication(); if (authentication == NULL) status = B_NO_MEMORY; else { status = authentication->Initialize( fHeaders["WWW-Authenticate"]); fContext->AddAuthentication(fUrl, authentication); } } newRequest = false; if (fOptUsername.Length() > 0 && status == B_OK) { // If we received an username and password, add them // to the request. This will either change the // credentials for an existing request, or set them // for a new one we created just above. // // If this request handles HTTP redirections, it will // also automatically retry connecting and send the // login information. authentication->SetUserName(fOptUsername); authentication->SetPassword(fOptPassword); newRequest = true; } } break; case B_HTTP_STATUS_CLASS_SERVER_ERROR: break; default: case B_HTTP_STATUS_CLASS_INVALID: break; } } while (newRequest); _EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "%ld headers and %ld bytes of data remaining", fHeaders.CountHeaders(), fInputBuffer.Size()); if (fResult.StatusCode() == 404) return B_RESOURCE_NOT_FOUND; return B_OK; }
status_t BGeolocation::LocateSelf(float& latitude, float& longitude) { // Enumerate wifi network and build JSON message BNetworkRoster& roster = BNetworkRoster::Default(); uint32 interfaceCookie = 0; BNetworkInterface interface; BString query("{\n\t\"wifiAccessPoints\": ["); int32 count = 0; while (roster.GetNextInterface(&interfaceCookie, interface) == B_OK) { uint32 networkCookie = 0; wireless_network network; BNetworkDevice device(interface.Name()); // TODO is that the correct way to enumerate devices? while (device.GetNextNetwork(networkCookie, network) == B_OK) { if (count != 0) query += ','; count++; query += "\n\t\t{ \"macAddress\": \""; query += network.address.ToString().ToUpper(); query += "\", \"signalStrength\": "; query << (int)network.signal_strength; query += ", \"signalToNoiseRatio\": "; query << (int)network.noise_level; query += " }"; } } query += "\n\t]\n}\n"; // Check that we have enough data (we need at least 2 networks) if (count < 2) return B_DEVICE_NOT_FOUND; class GeolocationListener: public BUrlProtocolListener { public: virtual ~GeolocationListener() {}; void DataReceived(BUrlRequest*, const char* data, off_t position, ssize_t size) { result.WriteAt(position, data, size); } BMallocIO result; }; GeolocationListener listener; // Send Request (POST JSON message) BUrlRequest* request = BUrlProtocolRoster::MakeRequest(fService, &listener); if (request == NULL) return B_BAD_DATA; BHttpRequest* http = dynamic_cast<BHttpRequest*>(request); if (http == NULL) { delete request; return B_BAD_DATA; } http->SetMethod(B_HTTP_POST); BMemoryIO* io = new BMemoryIO(query.String(), query.Length()); http->AdoptInputData(io, query.Length()); status_t result = http->Run(); if (result < 0) { delete http; return result; } while (http->IsRunning()) snooze(10000); // Parse reply const BHttpResult& reply = (const BHttpResult&)http->Result(); if (reply.StatusCode() != 200) { delete http; return B_ERROR; } BMessage data; result = BJson::Parse(data, (char*)listener.result.Buffer()); delete http; if (result != B_OK) { return result; } BMessage location; result = data.FindMessage("location", &location); if (result != B_OK) return result; double lat, lon; result = location.FindDouble("lat", &lat); if (result == B_OK) result = location.FindDouble("lng", &lon); latitude = lat; longitude = lon; return result; }
void UrlWrapper::ArgvReceived(int32 argc, char** argv) { if (argc <= 1) return; const char* failc = " || read -p 'Press any key'"; const char* pausec = " ; read -p 'Press any key'"; char* args[] = { (char *)"/bin/sh", (char *)"-c", NULL, NULL}; status_t err; BUrl url(argv[1]); BString full = BUrl(url).SetProtocol(BString()).UrlString(); BString proto = url.Protocol(); BString host = url.Host(); BString port = BString() << url.Port(); BString user = url.UserInfo(); BString pass = url.Password(); BString path = url.Path(); if (!url.IsValid()) { fprintf(stderr, "malformed url: '%s'\n", url.UrlString().String()); return; } // XXX: debug PRINT(("PROTO='%s'\n", proto.String())); PRINT(("HOST='%s'\n", host.String())); PRINT(("PORT='%s'\n", port.String())); PRINT(("USER='******'\n", user.String())); PRINT(("PASS='******'\n", pass.String())); PRINT(("PATH='%s'\n", path.String())); if (proto == "about") { app_info info; BString sig; // BUrl could get an accessor for the full - proto part... sig = host << "/" << path; BMessage msg(B_ABOUT_REQUESTED); if (be_roster->GetAppInfo(sig.String(), &info) == B_OK) { BMessenger msgr(sig.String()); msgr.SendMessage(&msg); return; } if (be_roster->Launch(sig.String(), &msg) == B_OK) return; be_roster->Launch("application/x-vnd.Haiku-About"); return; } if (proto == "telnet") { BString cmd("telnet "); if (url.HasUserInfo()) cmd << "-l " << user << " "; cmd << host; if (url.HasPort()) cmd << " " << port; PRINT(("CMD='%s'\n", cmd.String())); cmd << failc; args[2] = (char*)cmd.String(); be_roster->Launch(kTerminalSig, 3, args); return; } // see draft: // http://tools.ietf.org/wg/secsh/draft-ietf-secsh-scp-sftp-ssh-uri/ if (proto == "ssh") { BString cmd("ssh "); if (url.HasUserInfo()) cmd << "-l " << user << " "; if (url.HasPort()) cmd << "-oPort=" << port << " "; cmd << host; PRINT(("CMD='%s'\n", cmd.String())); cmd << failc; args[2] = (char*)cmd.String(); be_roster->Launch(kTerminalSig, 3, args); // TODO: handle errors return; } if (proto == "ftp") { BString cmd("ftp "); cmd << proto << "://"; /* if (user.Length()) cmd << "-l " << user << " "; cmd << host; */ cmd << full; PRINT(("CMD='%s'\n", cmd.String())); cmd << failc; args[2] = (char*)cmd.String(); be_roster->Launch(kTerminalSig, 3, args); // TODO: handle errors return; } if (proto == "sftp") { BString cmd("sftp "); //cmd << url; if (url.HasPort()) cmd << "-oPort=" << port << " "; if (url.HasUserInfo()) cmd << user << "@"; cmd << host; if (url.HasPath()) cmd << ":" << path; PRINT(("CMD='%s'\n", cmd.String())); cmd << failc; args[2] = (char*)cmd.String(); be_roster->Launch(kTerminalSig, 3, args); // TODO: handle errors return; } if (proto == "finger") { BString cmd("/bin/finger "); if (url.HasUserInfo()) cmd << user; if (url.HasHost() == 0) host = "127.0.0.1"; cmd << "@" << host; PRINT(("CMD='%s'\n", cmd.String())); cmd << pausec; args[2] = (char*)cmd.String(); be_roster->Launch(kTerminalSig, 3, args); // TODO: handle errors return; } if (proto == "http" || proto == "https" /*|| proto == "ftp"*/) { BString cmd("/bin/wget "); //cmd << url; cmd << proto << "://"; if (url.HasUserInfo()) cmd << user << "@"; cmd << full; PRINT(("CMD='%s'\n", cmd.String())); cmd << pausec; args[2] = (char*)cmd.String(); be_roster->Launch(kTerminalSig, 3, args); // TODO: handle errors return; } if (proto == "file") { BMessage m(B_REFS_RECEIVED); entry_ref ref; _DecodeUrlString(path); if (get_ref_for_path(path.String(), &ref) < B_OK) return; m.AddRef("refs", &ref); be_roster->Launch(kTrackerSig, &m); return; } // XXX:TODO: split options if (proto == "query") { // mktemp ? BString qname("/tmp/query-url-temp-"); qname << getpid() << "-" << system_time(); BFile query(qname.String(), O_CREAT|O_EXCL); // XXX: should check for failure BString s; int32 v; _DecodeUrlString(full); // TODO: handle options (list of attrs in the column, ...) v = 'qybF'; // QuerY By Formula XXX: any #define for that ? query.WriteAttr("_trk/qryinitmode", B_INT32_TYPE, 0LL, &v, sizeof(v)); s = "TextControl"; query.WriteAttr("_trk/focusedView", B_STRING_TYPE, 0LL, s.String(), s.Length()+1); s = full; PRINT(("QUERY='%s'\n", s.String())); query.WriteAttr("_trk/qryinitstr", B_STRING_TYPE, 0LL, s.String(), s.Length()+1); query.WriteAttr("_trk/qrystr", B_STRING_TYPE, 0LL, s.String(), s.Length()+1); s = "application/x-vnd.Be-query"; query.WriteAttr("BEOS:TYPE", 'MIMS', 0LL, s.String(), s.Length()+1); BEntry e(qname.String()); entry_ref er; if (e.GetRef(&er) >= B_OK) be_roster->Launch(&er); return; } if (proto == "sh") { BString cmd(full); if (_Warn(url.UrlString()) != B_OK) return; PRINT(("CMD='%s'\n", cmd.String())); cmd << pausec; args[2] = (char*)cmd.String(); be_roster->Launch(kTerminalSig, 3, args); // TODO: handle errors return; } if (proto == "beshare") { team_id team; BMessenger msgr(kBeShareSig); // if no instance is running, or we want a specific server, start it. if (!msgr.IsValid() || url.HasHost()) { be_roster->Launch(kBeShareSig, (BMessage*)NULL, &team); msgr = BMessenger(NULL, team); } if (url.HasHost()) { BMessage mserver('serv'); mserver.AddString("server", host); msgr.SendMessage(&mserver); } if (url.HasPath()) { BMessage mquery('quer'); mquery.AddString("query", path); msgr.SendMessage(&mquery); } // TODO: handle errors return; } if (proto == "icq" || proto == "msn") { // TODO team_id team; be_roster->Launch(kIMSig, (BMessage*)NULL, &team); BMessenger msgr(NULL, team); if (url.HasHost()) { BMessage mserver(B_REFS_RECEIVED); mserver.AddString("server", host); msgr.SendMessage(&mserver); } // TODO: handle errors return; } if (proto == "mms" || proto == "rtp" || proto == "rtsp") { args[0] = (char*)url.UrlString().String(); be_roster->Launch(kVLCSig, 1, args); return; } if (proto == "nfs") { BString parameter(host); _DecodeUrlString(path); if (url.HasPort()) parameter << ":" << port; //XXX: should not always be absolute! FIXME parameter << ":/" << path; BString prettyPath(path); prettyPath.Remove(0, prettyPath.FindLast("/") + 1); if (path == "" || path == "/") prettyPath = "root"; prettyPath << " on " << host; prettyPath.Prepend("/"); if (mkdir(prettyPath.String(), 0755) < 0) { perror("mkdir"); return; } dev_t volume; uint32 flags = 0; fprintf(stderr, "parms:'%s'\n", parameter.String()); volume = fs_mount_volume(prettyPath.String(), NULL, "nfs4", flags, parameter.String()); if (volume < B_OK) { fprintf(stderr, "fs_mount_volume: %s\n", strerror(volume)); return; } BMessage m(B_REFS_RECEIVED); entry_ref ref; if (get_ref_for_path(prettyPath.String(), &ref) < B_OK) return; m.AddRef("refs", &ref); be_roster->Launch(kTrackerSig, &m); return; } if (proto == "doi") { BString url("http://dx.doi.org/"); BString mimetype; url << full; BUrl u(url.String()); args[0] = const_cast<char*>("urlwrapper"); //XXX args[1] = (char*)u.UrlString().String(); args[2] = NULL; mimetype = kURLHandlerSigBase; mimetype += u.Protocol(); err = be_roster->Launch(mimetype.String(), 1, args + 1); if (err != B_OK && err != B_ALREADY_RUNNING) err = be_roster->Launch(kAppSig, 1, args + 1); // TODO: handle errors return; } /* More ? cf. http://en.wikipedia.org/wiki/URI_scheme cf. http://www.iana.org/assignments/uri-schemes.html Audio: (SoundPlay specific, identical to http:// to a shoutcast server) vnc: ? irc: ? im: http://tools.ietf.org/html/rfc3860 svn: handled by checkitout cvs: handled by checkitout git: handled by checkitout rsync: handled by checkitout - http://tools.ietf.org/html/rfc5781 smb: cifsmount ? nfs: mount_nfs ? http://tools.ietf.org/html/rfc2224 ipp: http://tools.ietf.org/html/rfc3510 mailto: ? Mail & Beam both handle it already (not fully though). imap: to describe mail accounts ? http://tools.ietf.org/html/rfc5092 pop: http://tools.ietf.org/html/rfc2384 mid: cid: as per RFC 2392 http://www.rfc-editor.org/rfc/rfc2392.txt query MAIL:cid message:<MID> http://daringfireball.net/2007/12/message_urls_leopard_mail itps: pcast: podcast: s//http/ + parse xml to get url to mp3 stream... audio: s//http:/ + default MediaPlayer -- see http://forums.winamp.com/showthread.php?threadid=233130 gps: ? I should submit an RFC for that one :) webcal: (is http: to .ics file) data: (but it's dangerous) */ }