vfs: check userland buffers before reading them.
[haiku.git] / src / kits / shared / Geolocation.cpp
blobdb712fb9d4700ccf312a4f983a1ddc0641f6e182
1 /*
2 * Copyright 2014, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 */
7 #include <Geolocation.h>
9 #include <HttpRequest.h>
10 #include <Json.h>
11 #include <NetworkDevice.h>
12 #include <NetworkInterface.h>
13 #include <NetworkRoster.h>
14 #include <String.h>
15 #include <UrlProtocolRoster.h>
16 #include <UrlRequest.h>
19 namespace BPrivate {
22 BGeolocation::BGeolocation()
23 : fService(kDefaultService)
28 BGeolocation::BGeolocation(const BUrl& service)
29 : fService(service)
34 status_t
35 BGeolocation::LocateSelf(float& latitude, float& longitude)
37 // Enumerate wifi network and build JSON message
38 BNetworkRoster& roster = BNetworkRoster::Default();
39 uint32 interfaceCookie = 0;
40 BNetworkInterface interface;
42 BString query("{\n\t\"wifiAccessPoints\": [");
43 int32 count = 0;
45 while (roster.GetNextInterface(&interfaceCookie, interface) == B_OK) {
46 uint32 networkCookie = 0;
47 wireless_network network;
49 BNetworkDevice device(interface.Name());
50 // TODO is that the correct way to enumerate devices?
52 while (device.GetNextNetwork(networkCookie, network) == B_OK) {
53 if (count != 0)
54 query += ',';
56 count++;
58 query += "\n\t\t{ \"macAddress\": \"";
59 query += network.address.ToString().ToUpper();
60 query += "\", \"signalStrength\": ";
61 query << (int)network.signal_strength;
62 query += ", \"signalToNoiseRatio\": ";
63 query << (int)network.noise_level;
64 query += " }";
69 query += "\n\t]\n}\n";
71 // Check that we have enough data (we need at least 2 networks)
72 if (count < 2)
73 return B_DEVICE_NOT_FOUND;
75 class GeolocationListener: public BUrlProtocolListener
77 public:
78 virtual ~GeolocationListener() {};
80 void DataReceived(BUrlRequest*, const char* data, off_t position,
81 ssize_t size) {
82 result.WriteAt(position, data, size);
84 BMallocIO result;
87 GeolocationListener listener;
89 // Send Request (POST JSON message)
90 BUrlRequest* request = BUrlProtocolRoster::MakeRequest(fService, &listener);
91 if (request == NULL)
92 return B_BAD_DATA;
94 BHttpRequest* http = dynamic_cast<BHttpRequest*>(request);
95 if (http == NULL) {
96 delete request;
97 return B_BAD_DATA;
100 http->SetMethod(B_HTTP_POST);
101 BMemoryIO* io = new BMemoryIO(query.String(), query.Length());
102 http->AdoptInputData(io, query.Length());
104 status_t result = http->Run();
105 if (result < 0) {
106 delete http;
107 return result;
110 while (http->IsRunning())
111 snooze(10000);
113 // Parse reply
114 const BHttpResult& reply = (const BHttpResult&)http->Result();
115 if (reply.StatusCode() != 200) {
116 delete http;
117 return B_ERROR;
120 BMessage data;
121 result = BJson::Parse((char*)listener.result.Buffer(), data);
122 delete http;
123 if (result != B_OK) {
124 return result;
127 BMessage location;
128 result = data.FindMessage("location", &location);
129 if (result != B_OK)
130 return result;
132 double lat, lon;
133 result = location.FindDouble("lat", &lat);
134 if (result == B_OK)
135 result = location.FindDouble("lng", &lon);
137 latitude = lat;
138 longitude = lon;
140 return result;
144 #ifdef HAVE_DEFAULT_GEOLOCATION_SERVICE_KEY
146 #include "DefaultGeolocationServiceKey.h"
148 const char* BGeolocation::kDefaultService
149 = "https://location.services.mozilla.com/v1/geolocate?key="
150 DEFAULT_GEOLOCATION_SERVICE_KEY;
152 #else
154 const char* BGeolocation::kDefaultService = "";
156 #endif
159 } // namespace BPrivate