#include <apt-pkg/error.h>
#include <apt-pkg/hashes.h>
+#include <sys/sysctl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <utime.h>
// Internet stuff
#include <netdb.h>
+#include <arpa/inet.h>
+#include <lockdown.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServices.h>
#include <SystemConfiguration/SystemConfiguration.h>
/*}}}*/
using namespace std;
-void CfrsError(CFReadStreamRef rs) {
+CFStringRef Firmware_;
+const char *Machine_;
+CFStringRef UniqueID_;
+
+void CfrsError(const char *name, CFReadStreamRef rs) {
CFStreamError se = CFReadStreamGetError(rs);
if (se.domain == kCFStreamErrorDomainCustom) {
} else if (se.domain == kCFStreamErrorDomainMacOSStatus) {
_error->Error("MacOSStatus: %ld", se.error);
} else if (se.domain == kCFStreamErrorDomainNetDB) {
- _error->Error("NetDB: %s", gai_strerror(se.error));
+ _error->Error("NetDB: %s %s", name, gai_strerror(se.error));
} else if (se.domain == kCFStreamErrorDomainMach) {
_error->Error("Mach: %ld", se.error);
} else if (se.domain == kCFStreamErrorDomainHTTP) {
char *url = strdup(Queue->Uri.c_str());
url:
- CFStringRef sr = CFStringCreateWithCString(kCFAllocatorDefault, url, se);
+ URI uri = std::string(url);
+ std::string hs = uri.Host;
+
+ std::string urs = uri;
+
+ for (;;) {
+ size_t bad = urs.find_first_of("+");
+ if (bad == std::string::npos)
+ break;
+ // XXX: generalize
+ urs = urs.substr(0, bad) + "%2b" + urs.substr(bad + 1);
+ }
+
+ CFStringRef sr = CFStringCreateWithCString(kCFAllocatorDefault, urs.c_str(), se);
CFURLRef ur = CFURLCreateWithString(kCFAllocatorDefault, sr, NULL);
CFRelease(sr);
CFHTTPMessageRef hm = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), ur, kCFHTTPVersion1_1);
sr = CFStringCreateWithCString(kCFAllocatorDefault, TimeRFC1123(SBuf.st_mtime).c_str(), se);
CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("If-Range"), sr);
CFRelease(sr);
+
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("Cache-Control"), CFSTR("no-cache"));
} else if (Queue->LastModified != 0) {
- sr = CFStringCreateWithCString(kCFAllocatorDefault, TimeRFC1123(SBuf.st_mtime).c_str(), se);
+ sr = CFStringCreateWithCString(kCFAllocatorDefault, TimeRFC1123(Queue->LastModified).c_str(), se);
CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("If-Modified-Since"), sr);
CFRelease(sr);
- }
- CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("User-Agent"), CFSTR("Telesphoreo APT-HTTP/1.0.98"));
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("Cache-Control"), CFSTR("no-cache"));
+ } else
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("Cache-Control"), CFSTR("max-age=0"));
+
+ if (Firmware_ != NULL)
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("X-Firmware"), Firmware_);
+
+ sr = CFStringCreateWithCString(kCFAllocatorDefault, Machine_, se);
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("X-Machine"), sr);
+ CFRelease(sr);
+
+ if (UniqueID_ != NULL)
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("X-Unique-ID"), UniqueID_);
+
+ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("User-Agent"), CFSTR("Telesphoreo APT-HTTP/1.0.484"));
+
CFReadStreamRef rs = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, hm);
CFRelease(hm);
//CFReadStreamSetProperty(rs, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue);
CFReadStreamSetProperty(rs, kCFStreamPropertyHTTPAttemptPersistentConnection, kCFBooleanTrue);
- URI uri = Queue->Uri;
-
FetchResult Res;
CFIndex rd;
UInt32 sc;
uint8_t data[10240];
size_t offset = 0;
- Status("Connecting to %s", uri.Host.c_str());
+ Status("Connecting to %s", hs.c_str());
if (!CFReadStreamOpen(rs)) {
- CfrsError(rs);
+ CfrsError("Open", rs);
Fail(true);
goto done;
}
rd = CFReadStreamRead(rs, data, sizeof(data));
if (rd == -1) {
- CfrsError(rs);
+ CfrsError(uri.Host.c_str(), rs);
Fail(true);
goto done;
}
hm = (CFHTTPMessageRef) CFReadStreamCopyProperty(rs, kCFStreamPropertyHTTPResponseHeader);
sc = CFHTTPMessageGetResponseStatusCode(hm);
- if (sc == 302) {
+ if (sc == 301 || sc == 302) {
sr = CFHTTPMessageCopyHeaderFieldValue(hm, CFSTR("Location"));
if (sr == NULL) {
Fail();
URIStart(Res);
read: if (rd == -1) {
- CfrsError(rs);
+ CfrsError("rd", rs);
Fail(true);
} else if (rd == 0) {
if (Res.Size == 0)
setlocale(LC_ALL, "");
HttpMethod Mth;
+
+ size_t size;
+ sysctlbyname("hw.machine", NULL, &size, NULL, 0);
+ char *machine = new char[size];
+ sysctlbyname("hw.machine", machine, &size, NULL, 0);
+ Machine_ = machine;
+
+ const char *path = "/System/Library/CoreServices/SystemVersion.plist";
+ CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (uint8_t *) path, strlen(path), false);
+
+ CFPropertyListRef plist; {
+ CFReadStreamRef stream = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
+ CFReadStreamOpen(stream);
+ plist = CFPropertyListCreateFromStream(kCFAllocatorDefault, stream, 0, kCFPropertyListImmutable, NULL, NULL);
+ CFReadStreamClose(stream);
+ }
+
+ CFRelease(url);
+
+ if (plist != NULL) {
+ Firmware_ = (CFStringRef) CFRetain(CFDictionaryGetValue((CFDictionaryRef) plist, CFSTR("ProductVersion")));
+ CFRelease(plist);
+ }
+
+ if (void *lockdown = lockdown_connect()) {
+ UniqueID_ = lockdown_copy_value(lockdown, NULL, kLockdownUniqueDeviceIDKey);
+ lockdown_disconnect(lockdown);
+ }
return Mth.Loop();
}