/* Cydia - iPhone UIKit Front-End for Debian APT
- * Copyright (C) 2008-2014 Jay Freeman (saurik)
+ * Copyright (C) 2008-2015 Jay Freeman (saurik)
*/
/* GNU General Public License, Version 3 {{{ */
#include <UIKit/UIKit.h>
#include "iPhonePrivate.h"
-#include <IOKit/IOKitLib.h>
-
#include <QuartzCore/CALayer.h>
#include <WebCore/WebCoreThread.h>
-#include <WebKit/DOMHTMLIFrameElement.h>
#include <algorithm>
+#include <fstream>
#include <iomanip>
#include <set>
#include <sstream>
#include <string>
-#include <ext/stdio_filebuf.h>
+#include "fdstream.hpp"
#undef ABS
+#include "apt.h"
#include <apt-pkg/acquire.h>
#include <apt-pkg/acquire-item.h>
#include <apt-pkg/algorithms.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/tagfile.h>
-#include <apr-1/apr_pools.h>
-
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/mount.h>
#include <sys/reboot.h>
+#include <dirent.h>
#include <fcntl.h>
#include <notify.h>
#include <dlfcn.h>
#include <Cytore.hpp>
#include "Sources.h"
-#include <CydiaSubstrate/CydiaSubstrate.h>
+#include "Substrate.hpp"
#include "Menes/Menes.h"
-#include "CyteKit/IndirectDelegate.h"
-#include "CyteKit/PerlCompatibleRegEx.hpp"
-#include "CyteKit/TableViewCell.h"
-#include "CyteKit/TabBarController.h"
-#include "CyteKit/WebScriptObject-Cyte.h"
-#include "CyteKit/WebViewController.h"
-#include "CyteKit/WebViewTableViewCell.h"
-#include "CyteKit/stringWithUTF8Bytes.h"
+#include "CyteKit/CyteKit.h"
+#include "CyteKit/RegEx.hpp"
#include "Cydia/MIMEAddress.h"
#include "Cydia/LoadingViewController.h"
#include "Cydia/ProgressEvent.h"
-
-#include "SDURLCache/SDURLCache.h"
/* }}} */
/* Profiler {{{ */
#define _end }
/* }}} */
-// XXX: I hate clang. Apple: please get over your petty hatred of GPL and fix your gcc fork
-#define synchronized(lock) \
- synchronized(static_cast<NSObject *>(lock))
-
extern NSString *Cydia_;
#define lprintf(args...) fprintf(stderr, args)
};
// }}}
-#define seteugid(uid, gid) do { \
- _assert(setreuid(0, uid) != -1); \
- _assert(setregid(0, gid) != -1); \
-} while (false)
-
-#define seteguid(uid, gid) do { \
- _assert(setregid(0, gid) != -1); \
- _assert(setreuid(0, uid) != -1); \
-} while (false)
-
-struct Root {
- Root() {
- _trace();
- seteugid(0, 0);
- _assert(pthread_setugid_np(0, 0) != -1);
- seteguid(501, 501);
- }
-
- ~Root() {
- _trace();
- seteugid(0, 0);
- _assert(pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE) != -1);
- seteguid(501, 501);
- }
-};
-
-#define _root(code) \
- ({ Root _root; code; })
-
static NSString *Colon_;
NSString *Elision_;
static NSString *Error_;
[NSString stringWithFormat:@"%@/%s", Cache_, file]
static void (*$SBSSetInterceptsMenuButtonForever)(bool);
+static NSData *(*$SBSCopyIconImagePNGDataForDisplayIdentifier)(NSString *);
static CFStringRef (*$MGCopyAnswer)(CFStringRef);
return [(id)$MGCopyAnswer(CFSTR("UniqueDeviceID")) autorelease];
}
-static bool IsReachable(const char *name) {
- SCNetworkReachabilityFlags flags; {
- SCNetworkReachabilityRef reachability(SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, name));
- SCNetworkReachabilityGetFlags(reachability, &flags);
- CFRelease(reachability);
- }
-
- // XXX: this elaborate mess is what Apple is using to determine this? :(
- // XXX: do we care if the user has to intervene? maybe that's ok?
- return
- (flags & kSCNetworkReachabilityFlagsReachable) != 0 && (
- (flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0 || (
- (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) != 0 ||
- (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0
- ) && (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0 ||
- (flags & kSCNetworkReachabilityFlagsIsWWAN) != 0
- )
- ;
-}
-
static const NSUInteger UIViewAutoresizingFlexibleBoth(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
static _finline NSString *CydiaURL(NSString *path) {
return [[NSString stringWithUTF8String:page] stringByAppendingString:path];
}
-static void ReapZombie(pid_t pid) {
- int status;
- wait:
- if (waitpid(pid, &status, 0) == -1)
- if (errno == EINTR)
- goto wait;
- else _assert(false);
+static NSString *ShellEscape(NSString *value) {
+ return [NSString stringWithFormat:@"'%@'", [value stringByReplacingOccurrencesOfString:@"'" withString:@"'\\''"]];
}
static _finline void UpdateExternalStatus(uint64_t newStatus) {
notify_post("com.saurik.Cydia.status");
}
-static CGFloat CYStatusBarHeight() {
- CGSize size([[UIApplication sharedApplication] statusBarFrame].size);
- return UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]) ? size.height : size.width;
-}
-
/* NSForcedOrderingSearch doesn't work on the iPhone */
static const NSStringCompareOptions MatchCompareOptions_ = NSLiteralSearch | NSCaseInsensitiveSearch;
static const NSStringCompareOptions LaxCompareOptions_ = NSNumericSearch | NSDiacriticInsensitiveSearch | NSWidthInsensitiveSearch | NSCaseInsensitiveSearch;
/* Insertion Sort {{{ */
-CFIndex SKBSearch_(const void *element, CFIndex elementSize, const void *list, CFIndex count, CFComparatorFunction comparator, void *context) {
- const char *ptr = (const char *)list;
- while (0 < count) {
- CFIndex half = count / 2;
- const char *probe = ptr + elementSize * half;
- CFComparisonResult cr = comparator(element, probe, context);
- if (0 == cr) return (probe - (const char *)list) / elementSize;
- ptr = (cr < 0) ? ptr : probe + elementSize;
- count = (cr < 0) ? half : (half + (count & 1) - 1);
- }
- return (ptr - (const char *)list) / elementSize;
-}
-
-CFIndex CFBSearch_(const void *element, CFIndex elementSize, const void *list, CFIndex count, CFComparatorFunction comparator, void *context) {
+template <typename Type_>
+size_t CFBSearch_(const Type_ &element, const void *list, size_t count, CFComparisonResult (*comparator)(Type_, Type_, void *), void *context) {
const char *ptr = (const char *)list;
while (0 < count) {
- CFIndex half = count / 2;
- const char *probe = ptr + elementSize * half;
- CFComparisonResult cr = comparator(element, probe, context);
- if (0 == cr) return (probe - (const char *)list) / elementSize;
- ptr = (cr < 0) ? ptr : probe + elementSize;
+ size_t half = count / 2;
+ const char *probe = ptr + sizeof(Type_) * half;
+ CFComparisonResult cr = comparator(element, * (const Type_ *) probe, context);
+ if (0 == cr) return (probe - (const char *)list) / sizeof(Type_);
+ ptr = (cr < 0) ? ptr : probe + sizeof(Type_);
count = (cr < 0) ? half : (half + (count & 1) - 1);
}
- return (ptr - (const char *)list) / elementSize;
+ return (ptr - (const char *)list) / sizeof(Type_);
}
-void CFArrayInsertionSortValues(CFMutableArrayRef array, CFRange range, CFComparatorFunction comparator, void *context) {
- if (range.length == 0)
+template <typename Type_>
+void CYArrayInsertionSortValues(Type_ *values, size_t length, CFComparisonResult (*comparator)(Type_, Type_, void *), void *context) {
+ if (length == 0)
return;
- const void **values(new const void *[range.length]);
- CFArrayGetValues(array, range, values);
#if HistogramInsertionSort > 0
- uint32_t total(0), *offsets(new uint32_t[range.length]);
+ uint32_t total(0), *offsets(new uint32_t[length]);
#endif
- for (CFIndex index(1); index != range.length; ++index) {
- const void *value(values[index]);
- //CFIndex correct(SKBSearch_(&value, sizeof(const void *), values, index, comparator, context));
- CFIndex correct(index);
+ for (size_t index(1); index != length; ++index) {
+ Type_ value(values[index]);
+#if 0
+ size_t correct(CFBSearch_(value, values, index, comparator, context));
+#else
+ size_t correct(index);
while (comparator(value, values[correct - 1], context) == kCFCompareLessThan) {
#if HistogramInsertionSort > 1
NSLog(@"%@ < %@", value, values[correct - 1]);
#endif
if (--correct == 0)
break;
+ if (index - correct >= 8) {
+ correct = CFBSearch_(value, values, correct, comparator, context);
+ break;
+ }
}
+#endif
if (correct != index) {
size_t offset(index - correct);
#if HistogramInsertionSort
}
}
- CFArrayReplaceValues(array, range, values, range.length);
- delete [] values;
-
#if HistogramInsertionSort > 0
- for (CFIndex index(0); index != range.length; ++index)
+ for (size_t index(0); index != range.length; ++index)
if (offsets[index] != 0)
NSLog(@"Insertion Displacement [%u]: %u", index, offsets[index]);
NSLog(@"Average Insertion Displacement: %f", double(total) / range.length);
/* }}} */
-/* Apple Bug Fixes {{{ */
-@implementation UIWebDocumentView (Cydia)
-
-- (void) _setScrollerOffset:(CGPoint)offset {
- UIScroller *scroller([self _scroller]);
-
- CGSize size([scroller contentSize]);
- CGSize bounds([scroller bounds].size);
-
- CGPoint max;
- max.x = size.width - bounds.width;
- max.y = size.height - bounds.height;
-
- // wtf Apple?!
- if (max.x < 0)
- max.x = 0;
- if (max.y < 0)
- max.y = 0;
-
- offset.x = offset.x < 0 ? 0 : offset.x > max.x ? max.x : offset.x;
- offset.y = offset.y < 0 ? 0 : offset.y > max.y ? max.y : offset.y;
-
- [scroller setOffset:offset];
-}
-
-@end
-/* }}} */
-
-NSUInteger DOMNodeList$countByEnumeratingWithState$objects$count$(DOMNodeList *self, SEL sel, NSFastEnumerationState *state, id *objects, NSUInteger count) {
- size_t length([self length] - state->state);
- if (length <= 0)
- return 0;
- else if (length > count)
- length = count;
- for (size_t i(0); i != length; ++i)
- objects[i] = [self item:state->state++];
- state->itemsPtr = objects;
- state->mutationsPtr = (unsigned long *) self;
- return length;
-}
-
/* Cydia NSString Additions {{{ */
@interface NSString (Cydia)
- (NSComparisonResult) compareByPath:(NSString *)other;
CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const uint8_t *>(data), size, kCFStringEncodingISOLatin1, NO, kCFAllocatorNull);
}
+static _finline CFStringRef CYStringCreate(const std::string &data) {
+ return CYStringCreate(data.data(), data.size());
+}
+
static _finline CFStringRef CYStringCreate(const char *data) {
return CYStringCreate(data, strlen(data));
}
cache_ = reinterpret_cast<CFStringRef>(CFRetain(rhs.cache_));
}
- void copy(apr_pool_t *pool) {
- char *temp(reinterpret_cast<char *>(apr_palloc(pool, size_ + 1)));
+ void copy(CYPool *pool) {
+ char *temp(pool->malloc<char>(size_ + 1));
memcpy(temp, data_, size_);
temp[size_] = '\0';
data_ = temp;
}
- void set(apr_pool_t *pool, const char *data, size_t size) {
+ void set(CYPool *pool, const char *data, size_t size) {
if (size == 0)
clear();
else {
}
}
- _finline void set(apr_pool_t *pool, const char *data) {
+ _finline void set(CYPool *pool, const char *data) {
set(pool, data, data == NULL ? 0 : strlen(data));
}
- _finline void set(apr_pool_t *pool, const std::string &rhs) {
+ _finline void set(CYPool *pool, const std::string &rhs) {
set(pool, rhs.data(), rhs.size());
}
static int Finish_;
static bool RestartSubstrate_;
-static bool UpgradeCydia_;
static NSArray *Finishes_;
#define SpringBoard_ "/System/Library/LaunchDaemons/com.apple.SpringBoard.plist"
static _H<UIFont> Font18Bold_;
static _H<UIFont> Font22Bold_;
-static const char *Machine_ = NULL;
-static _H<NSString> System_;
-static NSString *SerialNumber_ = nil;
-static NSString *ChipID_ = nil;
-static NSString *BBSNum_ = nil;
-static _H<NSString> Token_;
static _H<NSString> UniqueID_;
-static _H<NSString> UserAgent_;
-static _H<NSString> Product_;
-static _H<NSString> Safari_;
static _H<NSLocale> CollationLocale_;
static _H<NSArray> CollationThumbs_;
static NSArray *Languages_;
static CGColorSpaceRef space_;
+#define CacheState_ "/var/mobile/Library/Caches/com.saurik.Cydia/CacheState.plist"
+#define SavedState_ "/var/mobile/Library/Caches/com.saurik.Cydia/SavedState.plist"
+
static NSDictionary *SectionMap_;
-static NSMutableDictionary *Metadata_;
-static _transient NSMutableDictionary *Settings_;
-static _transient NSMutableDictionary *Packages_;
+static _H<NSDate> Backgrounded_;
static _transient NSMutableDictionary *Values_;
static _transient NSMutableDictionary *Sections_;
_H<NSMutableDictionary> Sources_;
static _transient NSNumber *Version_;
-bool Changed_;
static time_t now_;
-bool IsWildcat_;
-CGFloat ScreenScale_;
-static NSString *Idiom_;
-static _H<NSString> Firmware_;
-static NSString *Major_;
-
static _H<NSMutableDictionary> SessionData_;
-static _H<NSObject> HostConfig_;
static _H<NSMutableSet> BridgedHosts_;
-static _H<NSMutableSet> TokenHosts_;
static _H<NSMutableSet> InsecureHosts_;
-static _H<NSMutableSet> PipelinedHosts_;
-static _H<NSMutableSet> CachedURLs_;
static NSString *kCydiaProgressEventTypeError = @"Error";
static NSString *kCydiaProgressEventTypeInformation = @"Information";
/* }}} */
/* Display Helpers {{{ */
-inline float Interpolate(float begin, float end, float fraction) {
- return (end - begin) * fraction + begin;
-}
-
-static inline double Retina(double value) {
- value *= ScreenScale_;
- value = round(value);
- value /= ScreenScale_;
- return value;
-}
-
-static inline CGRect Retina(CGRect value) {
- value.origin.x *= ScreenScale_;
- value.origin.y *= ScreenScale_;
- value.size.width *= ScreenScale_;
- value.size.height *= ScreenScale_;
- value = CGRectIntegral(value);
- value.origin.x /= ScreenScale_;
- value.origin.y /= ScreenScale_;
- value.size.width /= ScreenScale_;
- value.size.height /= ScreenScale_;
- return value;
-}
-
static _finline const char *StripVersion_(const char *version) {
const char *colon(strchr(version, ':'));
return colon == NULL ? version : colon + 1;
}
NSString *LocalizeSection(NSString *section) {
- static Pcre title_r("^(.*?) \\((.*)\\)$");
+ static RegEx title_r("(.*?) \\((.*)\\)");
if (title_r(section)) {
NSString *parent(title_r[1]);
NSString *child(title_r[2]);
const char *data = [title UTF8String];
size_t size = [title lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
- static Pcre square_r("^\\[(.*)\\]$");
+ static RegEx square_r("\\[(.*)\\]");
if (square_r(data, size))
return Simplify(square_r[1]);
- static Pcre paren_r("^\\((.*)\\)$");
+ static RegEx paren_r("\\((.*)\\)");
if (paren_r(data, size))
return Simplify(paren_r[1]);
- static Pcre title_r("^(.*?) \\((.*)\\)$");
+ static RegEx title_r("(.*?) \\((.*)\\)");
if (title_r(data, size))
return Simplify(title_r[1]);
}
/* }}} */
-NSString *GetLastUpdate() {
- NSDate *update = [Metadata_ objectForKey:@"LastUpdate"];
-
- if (update == nil)
- return UCLocalize("NEVER_OR_UNKNOWN");
-
- CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle);
- CFStringRef formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) update);
-
- CFRelease(formatter);
-
- return [(NSString *) formatted autorelease];
-}
-
bool isSectionVisible(NSString *section) {
NSDictionary *metadata([Sections_ objectForKey:(section ?: @"")]);
NSNumber *hidden(metadata == nil ? nil : [metadata objectForKey:@"Hidden"]);
return hidden == nil || ![hidden boolValue];
}
-static NSObject *CYIOGetValue(const char *path, NSString *property) {
- io_registry_entry_t entry(IORegistryEntryFromPath(kIOMasterPortDefault, path));
- if (entry == MACH_PORT_NULL)
- return nil;
-
- CFTypeRef value(IORegistryEntryCreateCFProperty(entry, (CFStringRef) property, kCFAllocatorDefault, 0));
- IOObjectRelease(entry);
-
- if (value == NULL)
- return nil;
- return [(id) value autorelease];
-}
+static NSString *VerifySource(NSString *href) {
+ static RegEx href_r("(http(s?)://|file:///)[^# ]*");
+ if (!href_r(href)) {
+ [[[[UIAlertView alloc]
+ initWithTitle:[NSString stringWithFormat:Colon_, Error_, UCLocalize("INVALID_URL")]
+ message:UCLocalize("INVALID_URL_EX")
+ delegate:nil
+ cancelButtonTitle:UCLocalize("OK")
+ otherButtonTitles:nil
+ ] autorelease] show];
-static NSString *CYHex(NSData *data, bool reverse = false) {
- if (data == nil)
return nil;
+ }
- size_t length([data length]);
- uint8_t bytes[length];
- [data getBytes:bytes];
-
- char string[length * 2 + 1];
- for (size_t i(0); i != length; ++i)
- sprintf(string + i * 2, "%.2x", bytes[reverse ? length - i - 1 : i]);
-
- return [NSString stringWithUTF8String:string];
+ if (![href hasSuffix:@"/"])
+ href = [href stringByAppendingString:@"/"];
+ return href;
}
@class Cydia;
- (void) _saveConfig;
- (void) syncData;
- (void) addSource:(NSDictionary *)source;
-- (void) addTrivialSource:(NSString *)href;
+- (BOOL) addTrivialSource:(NSString *)href;
- (UIProgressHUD *) addProgressHUD;
- (void) removeProgressHUD:(UIProgressHUD *)hud;
- (void) showActionSheet:(UIActionSheet *)sheet fromItem:(UIBarButtonItem *)item;
@interface Database : NSObject {
NSZone *zone_;
- apr_pool_t *pool_;
+ CYPool pool_;
unsigned era_;
+ _H<NSDate> delock_;
pkgCacheFile cache_;
pkgDepCache::Policy *policy_;
SourceMap sourceMap_;
_H<NSMutableArray> sourceList_;
- CFMutableArrayRef packages_;
+ _H<NSArray> packages_;
_transient NSObject<DatabaseDelegate> *delegate_;
_transient NSObject<ProgressDelegate> *progress_;
+ (Database *) sharedInstance;
- (unsigned) era;
+- (bool) hasPackages;
- (void) _readCydia:(NSNumber *)fd;
- (void) _readStatus:(NSNumber *)fd;
}
//printf("Set(%s, %s)\n", fetch ? "true" : "false", uri.c_str());
- [database_ setFetch:fetch forURI:uri.c_str()];
+
+ auto slash(uri.rfind('/'));
+ if (slash != std::string::npos)
+ [database_ setFetch:fetch forURI:uri.substr(0, slash).c_str()];
}
_finline void Set(bool fetch, pkgAcquire::Item *item) {
char version_[8];
char name_[];
-};
+} _packed;
struct MetaValue :
Cytore::Block
{
uint32_t active_;
Cytore::Offset<PackageValue> packages_[1 << 16];
-};
+} _packed;
static Cytore::File<MetaValue> MetaFile_;
// }}}
}
// }}}
+static NSDate *GetStatusDate() {
+ return [[[NSFileManager defaultManager] attributesOfItemAtPath:@"/var/lib/dpkg/status" error:NULL] fileModificationDate];
+}
+
+static void SaveConfig(NSObject *lock) {
+ @synchronized (lock) {
+ _trace();
+ MetaFile_.Sync();
+ _trace();
+ }
+
+ CFPreferencesSetMultiple((CFDictionaryRef) [NSDictionary dictionaryWithObjectsAndKeys:
+ Values_, @"CydiaValues",
+ Sections_, @"CydiaSections",
+ (id) Sources_, @"CydiaSources",
+ Version_, @"CydiaVersion",
+ nil], NULL, CFSTR("com.saurik.Cydia"), kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
+
+ if (!CFPreferencesAppSynchronize(CFSTR("com.saurik.Cydia")))
+ NSLog(@"CFPreferencesAppSynchronize(com.saurik.Cydia) == false");
+
+ CydiaWriteSources();
+}
+
/* Source Class {{{ */
@interface Source : NSObject {
unsigned era_;
_transient NSObject<SourceDelegate> *delegate_;
}
-- (Source *) initWithMetaIndex:(metaIndex *)index forDatabase:(Database *)database inPool:(apr_pool_t *)pool;
+- (Source *) initWithMetaIndex:(metaIndex *)index forDatabase:(Database *)database inPool:(CYPool *)pool;
- (NSComparisonResult) compareByName:(Source *)source;
return index_;
}
-- (void) setMetaIndex:(metaIndex *)index inPool:(apr_pool_t *)pool {
+- (void) setMetaIndex:(metaIndex *)index inPool:(CYPool *)pool {
trusted_ = index->IsTrusted();
uri_.set(pool, index->GetURI());
_profile(Source$setMetaIndex$DescURI)
for (pkgAcquire::ItemIterator item(acquire.ItemsBegin()); item != acquire.ItemsEnd(); item++) {
std::string file((*item)->DescURI());
- files_.insert(file);
- if (file.length() < sizeof("Packages.bz2") || file.substr(file.length() - sizeof("Packages.bz2")) != "/Packages.bz2")
+ auto slash(file.rfind('/'));
+ if (slash == std::string::npos)
continue;
- file = file.substr(0, file.length() - 4);
- files_.insert(file);
- files_.insert(file + ".gz");
- files_.insert(file + "Index");
+ files_.insert(file.substr(0, slash));
}
_end
authority_ = [url path];
}
-- (Source *) initWithMetaIndex:(metaIndex *)index forDatabase:(Database *)database inPool:(apr_pool_t *)pool {
+- (Source *) initWithMetaIndex:(metaIndex *)index forDatabase:(Database *)database inPool:(CYPool *)pool {
if ((self = [super init]) != nil) {
era_ = [database era];
database_ = database;
if (record_ == nil)
return;
else if (NSMutableArray *sections = [record_ objectForKey:@"Sections"]) {
- if (![sections containsObject:section]) {
+ if (![sections containsObject:section])
[sections addObject:section];
- Changed_ = true;
- }
- } else {
+ } else
[record_ setObject:[NSMutableArray arrayWithObject:section] forKey:@"Sections"];
- Changed_ = true;
- }
}
- (bool) addSection:(NSString *)section {
return;
if (NSMutableArray *sections = [record_ objectForKey:@"Sections"])
- if ([sections containsObject:section]) {
+ if ([sections containsObject:section])
[sections removeObject:section];
- Changed_ = true;
- }
}
- (bool) removeSection:(NSString *)section {
- (void) _remove {
[Sources_ removeObjectForKey:[self key]];
- Changed_ = true;
}
- (bool) remove {
uint32_t ignored_ : 1;
uint32_t pooled_ : 1;
- apr_pool_t *pool_;
+ CYPool *pool_;
uint32_t rank_;
_H<NSMutableArray> tags_;
}
-- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database;
-+ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database;
+- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database;
++ (Package *) newPackageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database;
+
++ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database;
- (pkgCache::PkgIterator) iterator;
- (void) parse;
- (NSString *) installed;
- (BOOL) uninstalled;
-- (BOOL) valid;
- (BOOL) upgradableAndEssential:(BOOL)essential;
- (BOOL) essential;
- (BOOL) broken;
- (void) dealloc {
if (!pooled_)
- apr_pool_destroy(pool_);
+ delete pool_;
if (parsed_ != NULL)
delete parsed_;
[super dealloc];
_end
_profile(Package$parse$Tagline)
- const char *start, *end;
- if (parser->ShortDesc(start, end)) {
- const char *stop(reinterpret_cast<const char *>(memchr(start, '\n', end - start)));
- if (stop == NULL)
- stop = end;
- while (stop != start && stop[-1] == '\r')
- --stop;
- parsed->tagline_.set(pool_, start, stop - start);
- }
+ parsed->tagline_.set(pool_, parser->ShortDesc());
_end
_profile(Package$parse$Retain)
_end
} }
-- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database {
+- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database {
if ((self = [super init]) != nil) {
_profile(Package$initWithVersion)
if (pool == NULL)
- apr_pool_create(&pool_, NULL);
+ pool_ = new CYPool();
else {
pool_ = pool;
pooled_ = true;
version_ = version;
- pkgCache::PkgIterator iterator(version.ParentPkg());
+ pkgCache::PkgIterator iterator(version_.ParentPkg());
iterator_ = iterator;
_profile(Package$initWithVersion$Version)
- if (!version_.end())
- file_ = version_.FileList();
- else {
- pkgCache &cache([database_ cache]);
- file_ = pkgCache::VerFileIterator(cache, cache.VerFileP);
- }
+ file_ = version_.FileList();
_end
_profile(Package$initWithVersion$Cache)
- name_.set(NULL, iterator.Display());
+ name_.set(NULL, version_.Display());
latest_.set(NULL, StripVersion_(version_.VerStr()));
char *transform;
_profile(Package$initWithVersion$Transliterate$apr_palloc)
- transform = static_cast<char *>(apr_palloc(pool_, length));
+ transform = pool_->malloc<char>(length);
_end
_profile(Package$initWithVersion$Transliterate$u_strToUTF8WithSub$transform)
u_strToUTF8WithSub(transform, length, NULL, CollationString_.data(), CollationString_.size(), 0xfffd, NULL, &code);
} while (false); _end
_profile(Package$initWithVersion$Tags)
+#ifdef __arm64__
+ pkgCache::TagIterator tag(version_.TagList());
+#else
pkgCache::TagIterator tag(iterator.TagList());
+#endif
if (!tag.end()) {
tags_ = [NSMutableArray arrayWithCapacity:8];
_end } return self;
}
-+ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database {
++ (Package *) newPackageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database {
pkgCache::VerIterator version;
_profile(Package$packageWithIterator$GetCandidateVer)
];
_end
- _profile(Package$packageWithIterator$Autorelease)
- package = [package autorelease];
- _end
-
return package;
}
+// XXX: just in case a Cydia extension is using this (I bet this is unlikely, though, due to CYPool?)
++ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database {
+ return [[self newPackageWithIterator:iterator withZone:zone inPool:pool database:database] autorelease];
+}
+
- (pkgCache::PkgIterator) iterator {
return iterator_;
}
+- (NSArray *) downgrades {
+ NSMutableArray *versions([NSMutableArray arrayWithCapacity:4]);
+
+ for (auto version(iterator_.VersionList()); !version.end(); ++version) {
+ if (version == version_)
+ continue;
+ Package *package([[[Package allocWithZone:NULL] initWithVersion:version withZone:NULL inPool:NULL database:database_] autorelease]);
+ if ([package source] == nil)
+ continue;
+ [versions addObject:package];
+ }
+
+ return versions;
+}
+
- (NSString *) section {
if (section$_ == nil) {
if (section_ == NULL)
}
- (NSString *) longSection {
- return LocalizeSection([self section]);
+ if (NSString *section = [self section])
+ return LocalizeSection(section);
+ else
+ return nil;
}
- (NSString *) shortSection {
@synchronized (database_) {
pkgRecords::Parser &parser([database_ records]->Lookup(file_));
-
- const char *start, *end;
- if (!parser.ShortDesc(start, end))
+ std::string value(parser.ShortDesc());
+ if (value.empty())
return nil;
-
- if (end - start > 200)
- end = start + 200;
-
- /*
- if (const char *stop = reinterpret_cast<const char *>(memchr(start, '\n', end - start)))
- end = stop;
-
- while (end != start && end[-1] == '\r')
- --end;
- */
-
- return [(id) CYStringCreate(start, end - start) autorelease];
+ if (value.size() > 200)
+ value.resize(200);
+ return [(id) CYStringCreate(value) autorelease];
} }
- (unichar) index {
return installed_.empty();
}
-- (BOOL) valid {
- return !version_.end();
-}
-
- (BOOL) upgradableAndEssential:(BOOL)essential {
_profile(Package$upgradableAndEssential)
pkgCache::VerIterator current(iterator_.CurrentVer());
if (current.end())
return essential && essential_;
else
- return !version_.end() && version_ != current;
+ return version_ != current;
_end
}
NSMutableArray *applications([NSMutableArray arrayWithCapacity:2]);
- static Pcre application_r("^/Applications/(.*)\\.app/Info.plist$");
+ static RegEx application_r("/Applications/(.*)\\.app/Info.plist");
if (NSArray *files = [self files])
for (NSString *file in files)
if (application_r(file)) {
NSDictionary *info([NSDictionary dictionaryWithContentsOfFile:file]);
+ if (info == nil)
+ continue;
NSString *id([info objectForKey:@"CFBundleIdentifier"]);
- if ([id isEqualToString:me])
+ if (id == nil || [id isEqualToString:me])
continue;
NSString *display([info objectForKey:@"CFBundleDisplayName"]);
}
- (void) setIndex:(size_t)index {
- if (metadata_->index_ != index)
- metadata_->index_ = index;
+ if (metadata_->index_ != index + 1)
+ metadata_->index_ = index + 1;
}
- (CYString &) cyname {
- (void) clear {
@synchronized (database_) {
+ if ([database_ era] != era_ || file_.end())
+ return;
+
pkgProblemResolver *resolver = [database_ resolver];
resolver->Clear(iterator_);
- (void) install {
@synchronized (database_) {
+ if ([database_ era] != era_ || file_.end())
+ return;
+
pkgProblemResolver *resolver = [database_ resolver];
resolver->Clear(iterator_);
resolver->Protect(iterator_);
pkgCacheFile &cache([database_ cache]);
+ cache->SetCandidateVersion(version_);
cache->SetReInstall(iterator_, false);
cache->MarkInstall(iterator_, false);
- (void) remove {
@synchronized (database_) {
+ if ([database_ era] != era_ || file_.end())
+ return;
+
pkgProblemResolver *resolver = [database_ resolver];
resolver->Clear(iterator_);
resolver->Remove(iterator_);
}
- (void) releasePackages {
- CFArrayApplyFunction(packages_, CFRangeMake(0, CFArrayGetCount(packages_)), reinterpret_cast<CFArrayApplierFunction>(&CFRelease), NULL);
- CFArrayRemoveAllValues(packages_);
+ packages_ = nil;
+}
+
+- (bool) hasPackages {
+ return [packages_ count] != 0;
}
- (void) dealloc {
// XXX: actually implement this thing
_assert(false);
[self releasePackages];
- apr_pool_destroy(pool_);
NSRecycleZone(zone_);
[super dealloc];
}
- (void) _readCydia:(NSNumber *)fd {
- __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
- std::istream is(&ib);
+ boost::fdistream is([fd intValue]);
std::string line;
- static Pcre finish_r("^finish:([^:]*)$");
+ static RegEx finish_r("finish:([^:]*)");
while (std::getline(is, line)) {
NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
}
- (void) _readStatus:(NSNumber *)fd {
- __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
- std::istream is(&ib);
+ boost::fdistream is([fd intValue]);
std::string line;
- static Pcre conffile_r("^status: [^ ]* : conffile-prompt : (.*?) *$");
- static Pcre pmstatus_r("^([^:]*):([^:]*):([^:]*):(.*)$");
+ static RegEx conffile_r("status: [^ ]* : conffile-prompt : (.*?) *");
+ static RegEx pmstatus_r("([^:]*):([^:]*):([^:]*):(.*)");
while (std::getline(is, line)) {
NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
}
- (void) _readOutput:(NSNumber *)fd {
- __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
- std::istream is(&ib);
+ boost::fdistream is([fd intValue]);
std::string line;
while (std::getline(is, line)) {
@synchronized (self) {
if (static_cast<pkgDepCache *>(cache_) == NULL)
return nil;
- pkgCache::PkgIterator iterator(cache_->FindPkg([name UTF8String]));
- return iterator.end() ? nil : [Package packageWithIterator:iterator withZone:NULL inPool:NULL database:self];
+ pkgCache::PkgIterator iterator(cache_->FindPkg([name UTF8String]
+#ifdef __arm64__
+ , "any"
+#endif
+ ));
+ return iterator.end() ? nil : [[Package newPackageWithIterator:iterator withZone:NULL inPool:NULL database:self] autorelease];
} }
- (id) init {
lock_ = NULL;
zone_ = NSCreateZone(1024 * 1024, 256 * 1024, NO);
- apr_pool_create(&pool_, NULL);
- size_t capacity(MetaFile_->active_);
- if (capacity == 0)
- capacity = 16384;
- else
- capacity += 1024;
-
- packages_ = CFArrayCreateMutable(kCFAllocatorDefault, capacity, NULL);
sourceList_ = [NSMutableArray arrayWithCapacity:16];
int fds[2];
}
- (NSArray *) packages {
- return (NSArray *) packages_;
+ return packages_;
}
- (NSArray *) sources {
lprintf("%c:[%s]\n", warning ? 'W' : 'E', error.c_str());
- static Pcre no_pubkey("^GPG error:.* NO_PUBKEY .*$");
+ static RegEx no_pubkey("GPG error:.* NO_PUBKEY .*");
if (warning && no_pubkey(error.c_str()))
continue;
return [self popErrorWithTitle:title] || !success;
}
+- (bool) popErrorWithTitle:(NSString *)title forReadList:(pkgSourceList &)list {
+ if ([self popErrorWithTitle:title forOperation:list.ReadMainList()])
+ return true;
+ return false;
+
+ list.Reset();
+
+ bool error(false);
+
+ if (access("/etc/apt/sources.list", F_OK) == 0)
+ error |= [self popErrorWithTitle:title forOperation:list.ReadAppend("/etc/apt/sources.list")];
+
+ std::string base("/etc/apt/sources.list.d");
+ if (DIR *sources = opendir(base.c_str())) {
+ while (dirent *source = readdir(sources))
+ if (source->d_name[0] != '.' && source->d_namlen > 5 && strcmp(source->d_name + source->d_namlen - 5, ".list") == 0 && strcmp(source->d_name, "cydia.list") != 0)
+ error |= [self popErrorWithTitle:title forOperation:list.ReadAppend((base + "/" + source->d_name).c_str())];
+ closedir(sources);
+ }
+
+ error |= [self popErrorWithTitle:title forOperation:list.ReadAppend(SOURCES_LIST)];
+
+ return error;
+}
+
- (void) reloadDataWithInvocation:(NSInvocation *)invocation {
@synchronized (self) {
++era_;
cache_.Close();
- apr_pool_clear(pool_);
+ pool_.~CYPool();
+ new (&pool_) CYPool();
NSRecycleZone(zone_);
zone_ = NSCreateZone(1024 * 1024, 256 * 1024, NO);
list_ = new pkgSourceList();
_profile(reloadDataWithInvocation$ReadMainList)
- if ([self popErrorWithTitle:title forOperation:list_->ReadMainList()])
+ if ([self popErrorWithTitle:title forReadList:*list_])
return;
_end
_profile(reloadDataWithInvocation$Source$initWithMetaIndex)
for (pkgSourceList::const_iterator source = list_->begin(); source != list_->end(); ++source) {
- Source *object([[[Source alloc] initWithMetaIndex:*source forDatabase:self inPool:pool_] autorelease]);
+ Source *object([[[Source alloc] initWithMetaIndex:*source forDatabase:self inPool:&pool_] autorelease]);
[sourceList_ addObject:object];
}
_end
- _root(_system->Lock());
-
_trace();
OpProgress progress;
bool opened;
open:
+ delock_ = GetStatusDate();
_profile(reloadDataWithInvocation$pkgCacheFile)
opened = cache_.Open(progress, false);
_end
if (!opened) {
- // XXX: what if there are errors, but Open() == true? this should be merged with popError:
+ // XXX: this block should probably be merged with popError: in some way
while (!_error->empty()) {
std::string error;
bool warning(!_error->PopMessage(error));
}
}
- _system->UnLock();
return;
- }
+ } else if ([self popErrorWithTitle:title forOperation:true])
+ return;
_trace();
unlink("/tmp/cydia.chk");
}
{
- /*std::vector<Package *> packages;
- packages.reserve(std::max(10000U, [packages_ count] + 1000));
- packages_ = nil;*/
+ size_t capacity(MetaFile_->active_);
+ if (capacity == 0)
+ capacity = 128*1024;
+ else
+ capacity += 1024;
+ std::vector<Package *> packages;
+ packages.reserve(capacity);
+ size_t lost(0);
+
+ size_t last(0);
_profile(reloadDataWithInvocation$packageWithIterator)
for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator)
- if (Package *package = [Package packageWithIterator:iterator withZone:zone_ inPool:pool_ database:self])
- //packages.push_back(package);
- CFArrayAppendValue(packages_, CFRetain(package));
+ if (Package *package = [Package newPackageWithIterator:iterator withZone:zone_ inPool:&pool_ database:self]) {
+ if (unsigned index = package.metadata->index_) {
+ --index;
+ if (packages.size() == index) {
+ packages.push_back(package);
+ } else if (packages.size() <= index) {
+ packages.resize(index + 1, nil);
+ packages[index] = package;
+ continue;
+ } else {
+ std::swap(package, packages[index]);
+ if (package != nil) {
+ if (package.metadata->index_ == index + 1)
+ ++lost;
+ goto lost;
+ }
+ if (last != index)
+ continue;
+ }
+ } else {
+ ++lost;
+ lost: if (last == packages.size())
+ packages.push_back(package);
+ else
+ packages[last] = package;
+ ++last;
+ }
+
+ for (; last != packages.size(); ++last)
+ if (packages[last] == nil)
+ break;
+ }
_end
+ for (size_t next(last + 1); last != packages.size(); ++last, ++next) {
+ while (true) {
+ if (next == packages.size())
+ goto done;
+ if (packages[next] != nil)
+ break;
+ ++next;
+ }
+
+ std::swap(packages[last], packages[next]);
+ } done:;
- /*if (packages.empty())
- packages_ = [[NSArray alloc] init];
- else
- packages_ = [[NSArray alloc] initWithObjects:&packages.front() count:packages.size()];
- _trace();*/
+ packages.resize(last);
- _profile(reloadDataWithInvocation$radix$8)
- [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(8)];
- _end
+ if (lost > 128) {
+ NSLog(@"lost = %zu", lost);
- _profile(reloadDataWithInvocation$radix$4)
- [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(4)];
- _end
+ _profile(reloadDataWithInvocation$radix$8)
+ CYRadixSortUsingFunction(packages.data(), packages.size(), reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix), reinterpret_cast<void *>(8));
+ _end
- _profile(reloadDataWithInvocation$radix$0)
- [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(0)];
- _end
+ _profile(reloadDataWithInvocation$radix$4)
+ CYRadixSortUsingFunction(packages.data(), packages.size(), reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix), reinterpret_cast<void *>(4));
+ _end
+
+ _profile(reloadDataWithInvocation$radix$0)
+ CYRadixSortUsingFunction(packages.data(), packages.size(), reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix), reinterpret_cast<void *>(0));
+ _end
+ }
_profile(reloadDataWithInvocation$insertion)
- CFArrayInsertionSortValues(packages_, CFRangeMake(0, CFArrayGetCount(packages_)), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare), NULL);
+ CYArrayInsertionSortValues(packages.data(), packages.size(), &PackageNameCompare, NULL);
_end
+ packages_ = [[[NSArray alloc] initWithObjects:packages.data() count:packages.size()] autorelease];
+
/*_profile(reloadDataWithInvocation$CFQSortArray)
CFQSortArray(&packages.front(), packages.size(), sizeof(packages.front()), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare_), NULL);
_end*/
[packages_ sortUsingFunction:reinterpret_cast<NSComparisonResult (*)(id, id, void *)>(&PackageNameCompare) context:NULL];
_end*/
-
- size_t count(CFArrayGetCount(packages_));
- MetaFile_->active_ = count;
- for (size_t index(0); index != count; ++index)
- [(Package *) CFArrayGetValueAtIndex(packages_, index) setIndex:index];
+ MetaFile_->active_ = packages.size();
+ for (size_t index(0), count(packages.size()); index != count; ++index) {
+ auto package(packages[index]);
+ [package setIndex:index];
+ [package release];
+ }
}
} }
} }
- (void) configure {
- NSString *dpkg = [NSString stringWithFormat:@"dpkg --configure -a --status-fd %u", statusfd_];
+ NSString *dpkg = [NSString stringWithFormat:@"/usr/libexec/cydo --configure -a --status-fd %u", statusfd_];
_trace();
- _root(system([dpkg UTF8String]));
+ system([dpkg UTF8String]);
_trace();
}
return false;
pkgSourceList list;
- if ([self popErrorWithTitle:title forOperation:list.ReadMainList()])
+ if ([self popErrorWithTitle:title forReadList:list])
return false;
manager_ = (_system->CreatePM(cache_));
NSMutableArray *before = [NSMutableArray arrayWithCapacity:16]; {
pkgSourceList list;
- if ([self popErrorWithTitle:title forOperation:list.ReadMainList()])
+ if ([self popErrorWithTitle:title forReadList:list])
return;
for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source)
[before addObject:[NSString stringWithUTF8String:(*source)->GetURI().c_str()]];
if (substrate)
RestartSubstrate_ = true;
- _system->UnLock();
- pkgPackageManager::OrderResult result(_root(manager_->DoInstall(statusfd_)));
+ if (![delock_ isEqual:GetStatusDate()]) {
+ [delegate_ addProgressEventOnMainThread:[CydiaProgressEvent eventWithMessage:UCLocalize("DPKG_LOCKED") ofType:kCydiaProgressEventTypeError] forTask:title];
+ return;
+ }
+
+ delock_ = nil;
+
+ pkgPackageManager::OrderResult result(manager_->DoInstall(statusfd_));
+
+ NSString *oextended(@"/var/lib/apt/extended_states");
+ NSString *nextended(Cache("extended_states"));
+
+ struct stat info;
+ if (stat([nextended UTF8String], &info) != -1 && (info.st_mode & S_IFMT) == S_IFREG)
+ system([[NSString stringWithFormat:@"/usr/libexec/cydia/cydo /bin/cp --remove-destination %@ %@", ShellEscape(nextended), ShellEscape(oextended)] UTF8String]);
+
+ unlink([nextended UTF8String]);
+ symlink([oextended UTF8String], [nextended UTF8String]);
+
if ([self popErrorWithTitle:title])
return;
NSMutableArray *after = [NSMutableArray arrayWithCapacity:16]; {
pkgSourceList list;
- if ([self popErrorWithTitle:title forOperation:list.ReadMainList()])
+ if ([self popErrorWithTitle:title forReadList:list])
return;
for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source)
[after addObject:[NSString stringWithUTF8String:(*source)->GetURI().c_str()]];
[self update];
}
+- (bool) delocked {
+ return ![delock_ isEqual:GetStatusDate()];
+}
+
- (bool) upgrade {
NSString *title(UCLocalize("UPGRADE"));
if ([self popErrorWithTitle:title forOperation:pkgDistUpgrade(cache_)])
NSString *title(UCLocalize("REFRESHING_DATA"));
pkgSourceList list;
- if ([self popErrorWithTitle:title forOperation:list.ReadMainList()])
+ if ([self popErrorWithTitle:title forReadList:list])
return;
FileFd lock;
_error->Discard();
else {
[self popErrorWithTitle:title forOperation:success];
- [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"];
- Changed_ = true;
+
+ [[NSDictionary dictionaryWithObjectsAndKeys:
+ [NSDate date], @"LastUpdate",
+ nil] writeToFile:@ CacheState_ atomically:YES];
}
[delegate_ performSelectorOnMainThread:@selector(releaseNetworkActivityIndicator) withObject:nil waitUntilDone:YES];
@end
/* }}} */
-static _H<NSMutableSet> Diversions_;
-
-@interface Diversion : NSObject {
- Pcre pattern_;
- _H<NSString> key_;
- _H<NSString> format_;
-}
-
-@end
-
-@implementation Diversion
-
-- (id) initWithFrom:(NSString *)from to:(NSString *)to {
- if ((self = [super init]) != nil) {
- pattern_ = [from UTF8String];
- key_ = from;
- format_ = to;
- } return self;
-}
-
-- (NSString *) divert:(NSString *)url {
- return !pattern_(url) ? nil : pattern_->*format_;
-}
-
-+ (NSURL *) divertURL:(NSURL *)url {
- divert:
- NSString *href([url absoluteString]);
-
- for (Diversion *diversion in (id) Diversions_)
- if (NSString *diverted = [diversion divert:href]) {
-#if !ForRelease
- NSLog(@"div: %@", diverted);
-#endif
- url = [NSURL URLWithString:diverted];
- goto divert;
- }
-
- return url;
-}
-
-- (NSString *) key {
- return key_;
-}
-
-- (NSUInteger) hash {
- return [key_ hash];
-}
-
-- (BOOL) isEqual:(Diversion *)object {
- return self == object || [self class] == [object class] && [key_ isEqual:[object key]];
-}
-
-@end
-
-@interface CydiaObject : NSObject {
- _H<CyteWebViewController> indirect_;
+@interface CydiaObject : CyteObject {
_transient id delegate_;
}
-- (id) initWithDelegate:(IndirectDelegate *)indirect;
-
@end
-@class CydiaObject;
-
@interface CydiaWebViewController : CyteWebViewController {
_H<CydiaObject> cydia_;
}
-+ (void) addDiversion:(Diversion *)diversion;
+ (NSURLRequest *) requestWithHeaders:(NSURLRequest *)request;
+ (void) didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame withCydia:(CydiaObject *)cydia;
- (void) setDelegate:(id)delegate;
/* Web Scripting {{{ */
@implementation CydiaObject
-- (id) initWithDelegate:(IndirectDelegate *)indirect {
- if ((self = [super init]) != nil) {
- indirect_ = (CyteWebViewController *) indirect;
- } return self;
-}
-
- (void) setDelegate:(id)delegate {
delegate_ = delegate;
}
-+ (NSArray *) _attributeKeys {
- return [NSArray arrayWithObjects:
- @"bbsnum",
- @"build",
- @"coreFoundationVersionNumber",
+- (NSArray *) attributeKeys {
+ return [[NSArray arrayWithObjects:
+ @"cells",
@"device",
- @"ecid",
- @"firmware",
- @"hostname",
- @"idiom",
@"mcc",
@"mnc",
- @"model",
@"operator",
@"role",
- @"serial",
- @"token",
@"version",
- nil];
-}
-
-- (NSArray *) attributeKeys {
- return [[self class] _attributeKeys];
-}
-
-+ (BOOL) isKeyExcludedFromWebScript:(const char *)name {
- return ![[self _attributeKeys] containsObject:[NSString stringWithUTF8String:name]] && [super isKeyExcludedFromWebScript:name];
+ nil] arrayByAddingObjectsFromArray:[super attributeKeys]];
}
- (NSString *) version {
return Cydia_;
}
-- (NSString *) build {
- return System_;
-}
-
-- (NSString *) coreFoundationVersionNumber {
- return [NSString stringWithFormat:@"%.2f", kCFCoreFoundationVersionNumber];
-}
-
- (NSString *) device {
return UniqueIdentifier();
}
-- (NSString *) firmware {
- return [[UIDevice currentDevice] systemVersion];
-}
+- (NSArray *) cells {
+ auto *$_CTServerConnectionCreate(reinterpret_cast<id (*)(void *, void *, void *)>(dlsym(RTLD_DEFAULT, "_CTServerConnectionCreate")));
+ if ($_CTServerConnectionCreate == NULL)
+ return nil;
-- (NSString *) hostname {
- return [[UIDevice currentDevice] name];
-}
+ struct CTResult { int flag; int error; };
+ auto *$_CTServerConnectionCellMonitorCopyCellInfo(reinterpret_cast<CTResult (*)(CFTypeRef, void *, CFArrayRef *)>(dlsym(RTLD_DEFAULT, "_CTServerConnectionCellMonitorCopyCellInfo")));
+ if ($_CTServerConnectionCellMonitorCopyCellInfo == NULL)
+ return nil;
+
+ _H<const void> connection($_CTServerConnectionCreate(NULL, NULL, NULL), true);
+ if (connection == nil)
+ return nil;
+
+ int count(0);
+ CFArrayRef cells(NULL);
+ auto result($_CTServerConnectionCellMonitorCopyCellInfo(connection, &count, &cells));
+ if (result.flag != 0)
+ return nil;
-- (NSString *) idiom {
- return (id) Idiom_ ?: [NSNull null];
+ return [(NSArray *) cells autorelease];
}
- (NSString *) mcc {
return nil;
}
-- (NSString *) bbsnum {
- return (id) BBSNum_ ?: [NSNull null];
-}
-
-- (NSString *) ecid {
- return (id) ChipID_ ?: [NSNull null];
-}
-
-- (NSString *) serial {
- return SerialNumber_;
-}
-
- (NSString *) role {
return (id) [NSNull null];
}
-- (NSString *) model {
- return [NSString stringWithUTF8String:Machine_];
-}
-
-- (NSString *) token {
- return (id) Token_ ?: [NSNull null];
-}
-
+ (NSString *) webScriptNameForSelector:(SEL)selector {
if (false);
else if (selector == @selector(addBridgedHost:))
return @"addBridgedHost";
else if (selector == @selector(addInsecureHost:))
return @"addInsecureHost";
- else if (selector == @selector(addInternalRedirect::))
- return @"addInternalRedirect";
- else if (selector == @selector(addPipelinedHost:scheme:))
- return @"addPipelinedHost";
else if (selector == @selector(addSource:::))
return @"addSource";
- else if (selector == @selector(addTokenHost:))
- return @"addTokenHost";
else if (selector == @selector(addTrivialSource:))
return @"addTrivialSource";
- else if (selector == @selector(close))
- return @"close";
else if (selector == @selector(du:))
return @"du";
- else if (selector == @selector(stringWithFormat:arguments:))
- return @"format";
else if (selector == @selector(getAllSources))
return @"getAllSources";
else if (selector == @selector(getApplicationInfo:value:))
return @"getApplicationInfoValue";
- else if (selector == @selector(getKernelNumber:))
- return @"getKernelNumber";
- else if (selector == @selector(getKernelString:))
- return @"getKernelString";
+ else if (selector == @selector(getDisplayIdentifiers))
+ return @"getDisplayIdentifiers";
+ else if (selector == @selector(getLocalizedNameForDisplayIdentifier:))
+ return @"getLocalizedNameForDisplayIdentifier";
else if (selector == @selector(getInstalledPackages))
return @"getInstalledPackages";
- else if (selector == @selector(getIORegistryEntry::))
- return @"getIORegistryEntry";
- else if (selector == @selector(getLocaleIdentifier))
- return @"getLocaleIdentifier";
- else if (selector == @selector(getPreferredLanguages))
- return @"getPreferredLanguages";
else if (selector == @selector(getPackageById:))
return @"getPackageById";
else if (selector == @selector(getMetadataKeys))
return @"getSessionValue";
else if (selector == @selector(installPackages:))
return @"installPackages";
- else if (selector == @selector(isReachable:))
- return @"isReachable";
- else if (selector == @selector(localizedStringForKey:value:table:))
- return @"localize";
- else if (selector == @selector(popViewController:))
- return @"popViewController";
else if (selector == @selector(refreshSources))
return @"refreshSources";
- else if (selector == @selector(registerFrame:))
- return @"registerFrame";
- else if (selector == @selector(removeButton))
- return @"removeButton";
else if (selector == @selector(saveConfig))
return @"saveConfig";
else if (selector == @selector(setMetadataValue::))
return @"setSessionValue";
else if (selector == @selector(substitutePackageNames:))
return @"substitutePackageNames";
- else if (selector == @selector(scrollToBottom:))
- return @"scrollToBottom";
- else if (selector == @selector(setAllowsNavigationAction:))
- return @"setAllowsNavigationAction";
- else if (selector == @selector(setBadgeValue:))
- return @"setBadgeValue";
- else if (selector == @selector(setButtonImage:withStyle:toFunction:))
- return @"setButtonImage";
- else if (selector == @selector(setButtonTitle:withStyle:toFunction:))
- return @"setButtonTitle";
- else if (selector == @selector(setHidesBackButton:))
- return @"setHidesBackButton";
- else if (selector == @selector(setHidesNavigationBar:))
- return @"setHidesNavigationBar";
- else if (selector == @selector(setNavigationBarStyle:))
- return @"setNavigationBarStyle";
- else if (selector == @selector(setNavigationBarTintRed:green:blue:alpha:))
- return @"setNavigationBarTintColor";
- else if (selector == @selector(setPasteboardString:))
- return @"setPasteboardString";
- else if (selector == @selector(setPasteboardURL:))
- return @"setPasteboardURL";
- else if (selector == @selector(setScrollAlwaysBounceVertical:))
- return @"setScrollAlwaysBounceVertical";
- else if (selector == @selector(setScrollIndicatorStyle:))
- return @"setScrollIndicatorStyle";
else if (selector == @selector(setToken:))
return @"setToken";
- else if (selector == @selector(setViewportWidth:))
- return @"setViewportWidth";
- else if (selector == @selector(statfs:))
- return @"statfs";
- else if (selector == @selector(supports:))
- return @"supports";
- else if (selector == @selector(unload))
- return @"unload";
else
return nil;
}
return [self webScriptNameForSelector:selector] == nil;
}
-- (BOOL) supports:(NSString *)feature {
- return [feature isEqualToString:@"window.open"];
-}
-
-- (void) unload {
- [delegate_ performSelectorOnMainThread:@selector(unloadData) withObject:nil waitUntilDone:NO];
-}
-
-- (void) setScrollAlwaysBounceVertical:(NSNumber *)value {
- [indirect_ performSelectorOnMainThread:@selector(setScrollAlwaysBounceVerticalNumber:) withObject:value waitUntilDone:NO];
-}
-
-- (void) setScrollIndicatorStyle:(NSString *)style {
- [indirect_ performSelectorOnMainThread:@selector(setScrollIndicatorStyleWithName:) withObject:style waitUntilDone:NO];
-}
-
-- (void) addInternalRedirect:(NSString *)from :(NSString *)to {
- [CydiaWebViewController performSelectorOnMainThread:@selector(addDiversion:) withObject:[[[Diversion alloc] initWithFrom:from to:to] autorelease] waitUntilDone:NO];
-}
-
- (NSDictionary *) getApplicationInfo:(NSString *)display value:(NSString *)key {
char path[1024];
if (SBBundlePathForDisplayIdentifier(SBSSpringBoardServerPort(), [display UTF8String], path) != 0)
return [info objectForKey:key];
}
+- (NSArray *) getDisplayIdentifiers {
+ return SBSCopyApplicationDisplayIdentifiers(false, false);
+}
+
+- (NSString *) getLocalizedNameForDisplayIdentifier:(NSString *)identifier {
+ return [SBSCopyLocalizedApplicationNameForDisplayIdentifier(identifier) autorelease] ?: (id) [NSNull null];
+}
+
- (NSNumber *) getKernelNumber:(NSString *)name {
const char *string([name UTF8String]);
return [NSNumber numberWithInt:value];
}
-- (NSString *) getKernelString:(NSString *)name {
- const char *string([name UTF8String]);
-
- size_t size;
- if (sysctlbyname(string, NULL, &size, NULL, 0) == -1)
- return (id) [NSNull null];
-
- char value[size + 1];
- if (sysctlbyname(string, value, &size, NULL, 0) == -1)
- return (id) [NSNull null];
-
- // XXX: just in case you request something ludicrous
- value[size] = '\0';
-
- return [NSString stringWithCString:value];
-}
-
-- (NSObject *) getIORegistryEntry:(NSString *)path :(NSString *)entry {
- NSObject *value(CYIOGetValue([path UTF8String], entry));
-
- if (value != nil)
- if ([value isKindOfClass:[NSData class]])
- value = CYHex((NSData *) value);
-
- return value;
-}
-
- (NSArray *) getMetadataKeys {
@synchronized (Values_) {
return [Values_ allKeys];
} }
-- (void) registerFrame:(DOMHTMLIFrameElement *)iframe {
- WebFrame *frame([iframe contentFrame]);
- [indirect_ registerFrame:frame];
-}
-
- (id) getMetadataValue:(NSString *)key {
@synchronized (Values_) {
return [Values_ objectForKey:key];
[Values_ removeObjectForKey:key];
else
[Values_ setObject:value forKey:key];
-
- [delegate_ performSelectorOnMainThread:@selector(updateValues) withObject:nil waitUntilDone:YES];
} }
- (id) getSessionValue:(NSString *)key {
} }
- (void) addBridgedHost:(NSString *)host {
-@synchronized (HostConfig_) {
+@synchronized (BridgedHosts_) {
[BridgedHosts_ addObject:host];
} }
- (void) addInsecureHost:(NSString *)host {
-@synchronized (HostConfig_) {
+@synchronized (InsecureHosts_) {
[InsecureHosts_ addObject:host];
} }
-- (void) addTokenHost:(NSString *)host {
-@synchronized (HostConfig_) {
- [TokenHosts_ addObject:host];
-} }
-
-- (void) addPipelinedHost:(NSString *)host scheme:(NSString *)scheme {
-@synchronized (HostConfig_) {
- if (scheme != (id) [WebUndefined undefined])
- host = [NSString stringWithFormat:@"%@:%@", [scheme lowercaseString], host];
-
- [PipelinedHosts_ addObject:host];
-} }
-
-- (void) popViewController:(NSNumber *)value {
- if (value == (id) [WebUndefined undefined])
- value = [NSNumber numberWithBool:YES];
- [indirect_ performSelectorOnMainThread:@selector(popViewControllerWithNumber:) withObject:value waitUntilDone:NO];
-}
-
- (void) addSource:(NSString *)href :(NSString *)distribution :(WebScriptObject *)sections {
NSMutableArray *array([NSMutableArray arrayWithCapacity:[sections count]]);
nil] waitUntilDone:NO];
}
-- (void) addTrivialSource:(NSString *)href {
+- (BOOL) addTrivialSource:(NSString *)href {
+ href = VerifySource(href);
+ if (href == nil)
+ return NO;
[delegate_ performSelectorOnMainThread:@selector(addTrivialSource:) withObject:href waitUntilDone:NO];
+ return YES;
}
- (void) refreshSources {
return (Package *) [NSNull null];
}
-- (NSString *) getLocaleIdentifier {
- return Locale_ == NULL ? (NSString *) [NSNull null] : (NSString *) CFLocaleGetIdentifier(Locale_);
-}
-
-- (NSArray *) getPreferredLanguages {
- return Languages_;
-}
-
-- (NSArray *) statfs:(NSString *)path {
- struct statfs stat;
-
- if (path == nil || statfs([path UTF8String], &stat) == -1)
- return nil;
-
- return [NSArray arrayWithObjects:
- [NSNumber numberWithUnsignedLong:stat.f_bsize],
- [NSNumber numberWithUnsignedLong:stat.f_blocks],
- [NSNumber numberWithUnsignedLong:stat.f_bfree],
- nil];
-}
-
- (NSNumber *) du:(NSString *)path {
NSNumber *value(nil);
- int fds[2];
- _assert(pipe(fds) != -1);
-
- pid_t pid(ExecFork());
- if (pid == 0) {
- _assert(dup2(fds[1], 1) != -1);
- _assert(close(fds[0]) != -1);
- _assert(close(fds[1]) != -1);
- /* XXX: this should probably not use du */
- _root(execl("/usr/libexec/cydia/du", "du", "-s", [path UTF8String], NULL));
- exit(1);
- } else {
- _assert(close(fds[1]) != -1);
-
- if (FILE *du = fdopen(fds[0], "r")) {
- char line[1024];
- while (fgets(line, sizeof(line), du) != NULL) {
- size_t length(strlen(line));
- while (length != 0 && line[length - 1] == '\n')
- line[--length] = '\0';
- if (char *tab = strchr(line, '\t')) {
- *tab = '\0';
- value = [NSNumber numberWithUnsignedLong:strtoul(line, NULL, 0)];
- }
+ FILE *du(popen([[NSString stringWithFormat:@"/usr/libexec/cydia/cydo /usr/libexec/cydia/du -ks %@", ShellEscape(path)] UTF8String], "r"));
+ if (du != NULL) {
+ char line[1024];
+ while (fgets(line, sizeof(line), du) != NULL) {
+ size_t length(strlen(line));
+ while (length != 0 && line[length - 1] == '\n')
+ line[--length] = '\0';
+ if (char *tab = strchr(line, '\t')) {
+ *tab = '\0';
+ value = [NSNumber numberWithUnsignedLong:strtoul(line, NULL, 0)];
}
-
- fclose(du);
- } else
- _assert(close(fds[0]) != -1);
- } ReapZombie(pid);
+ }
+ pclose(du);
+ }
return value;
}
-- (void) close {
- [indirect_ performSelectorOnMainThread:@selector(close) withObject:nil waitUntilDone:NO];
-}
-
-- (NSNumber *) isReachable:(NSString *)name {
- return [NSNumber numberWithBool:IsReachable([name UTF8String])];
-}
-
- (void) installPackages:(NSArray *)packages {
[delegate_ performSelectorOnMainThread:@selector(installPackages:) withObject:packages waitUntilDone:NO];
}
- (NSString *) substitutePackageNames:(NSString *)message {
+ auto database([Database sharedInstance]);
+
+ // XXX: this check is less racy than you'd expect, but this entire concept is a little awkward
+ if (![database hasPackages])
+ return message;
+
NSMutableArray *words([[[message componentsSeparatedByString:@" "] mutableCopy] autorelease]);
for (size_t i(0), e([words count]); i != e; ++i) {
NSString *word([words objectAtIndex:i]);
- if (Package *package = [[Database sharedInstance] packageWithName:word])
+ if (Package *package = [database packageWithName:word])
[words replaceObjectAtIndex:i withObject:[package name]];
}
return [words componentsJoinedByString:@" "];
}
-- (void) removeButton {
- [indirect_ removeButton];
-}
-
-- (void) setButtonImage:(NSString *)button withStyle:(NSString *)style toFunction:(id)function {
- [indirect_ setButtonImage:button withStyle:style toFunction:function];
-}
-
-- (void) setButtonTitle:(NSString *)button withStyle:(NSString *)style toFunction:(id)function {
- [indirect_ setButtonTitle:button withStyle:style toFunction:function];
-}
-
-- (void) setBadgeValue:(id)value {
- [indirect_ performSelectorOnMainThread:@selector(setBadgeValue:) withObject:value waitUntilDone:NO];
-}
-
-- (void) setAllowsNavigationAction:(NSString *)value {
- [indirect_ performSelectorOnMainThread:@selector(setAllowsNavigationActionByNumber:) withObject:value waitUntilDone:NO];
-}
-
-- (void) setHidesBackButton:(NSString *)value {
- [indirect_ performSelectorOnMainThread:@selector(setHidesBackButtonByNumber:) withObject:value waitUntilDone:NO];
-}
-
-- (void) setHidesNavigationBar:(NSString *)value {
- [indirect_ performSelectorOnMainThread:@selector(setHidesNavigationBarByNumber:) withObject:value waitUntilDone:NO];
-}
-
-- (void) setNavigationBarStyle:(NSString *)value {
- [indirect_ performSelectorOnMainThread:@selector(setNavigationBarStyle:) withObject:value waitUntilDone:NO];
-}
-
-- (void) setNavigationBarTintRed:(NSNumber *)red green:(NSNumber *)green blue:(NSNumber *)blue alpha:(NSNumber *)alpha {
- float opacity(alpha == (id) [WebUndefined undefined] ? 1 : [alpha floatValue]);
- UIColor *color([UIColor colorWithRed:[red floatValue] green:[green floatValue] blue:[blue floatValue] alpha:opacity]);
- [indirect_ performSelectorOnMainThread:@selector(setNavigationBarTintColor:) withObject:color waitUntilDone:NO];
-}
-
-- (void) setPasteboardString:(NSString *)value {
- [[objc_getClass("UIPasteboard") generalPasteboard] setString:value];
-}
-
-- (void) setPasteboardURL:(NSString *)value {
- [[objc_getClass("UIPasteboard") generalPasteboard] setURL:[NSURL URLWithString:value]];
-}
-
-- (void) _setToken:(NSString *)token {
- Token_ = token;
-
- if (token == nil)
- [Metadata_ removeObjectForKey:@"Token"];
- else
- [Metadata_ setObject:Token_ forKey:@"Token"];
-
- Changed_ = true;
-}
-
- (void) setToken:(NSString *)token {
- [self performSelectorOnMainThread:@selector(_setToken:) withObject:token waitUntilDone:NO];
-}
-
-- (void) scrollToBottom:(NSNumber *)animated {
- [indirect_ performSelectorOnMainThread:@selector(scrollToBottomAnimated:) withObject:animated waitUntilDone:NO];
-}
-
-- (void) setViewportWidth:(float)width {
- [indirect_ setViewportWidthOnMainThread:width];
-}
-
-- (NSString *) stringWithFormat:(NSString *)format arguments:(WebScriptObject *)arguments {
- //NSLog(@"SWF:\"%@\" A:%@", format, [arguments description]);
- unsigned count([arguments count]);
- id values[count];
- for (unsigned i(0); i != count; ++i)
- values[i] = [arguments objectAtIndex:i];
- return [[[NSString alloc] initWithFormat:format arguments:reinterpret_cast<va_list>(values)] autorelease];
-}
-
-- (NSString *) localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)table {
- if (reinterpret_cast<id>(value) == [WebUndefined undefined])
- value = nil;
- if (reinterpret_cast<id>(table) == [WebUndefined undefined])
- table = nil;
- return [[NSBundle mainBundle] localizedStringForKey:key value:value table:table];
+ // XXX: the website expects this :/
}
@end
if ([[[self scheme] lowercaseString] isEqualToString:@"https"])
return true;
- @synchronized (HostConfig_) {
+ @synchronized (InsecureHosts_) {
if ([InsecureHosts_ containsObject:[self host]])
return true;
}
@implementation CydiaWebViewController
- (NSURL *) navigationURL {
- return request_ == nil ? nil : [NSURL URLWithString:[NSString stringWithFormat:@"cydia://url/%@", [[request_ URL] absoluteString]]];
-}
-
-+ (void) _initialize {
- [super _initialize];
-
- Diversions_ = [NSMutableSet setWithCapacity:0];
-}
-
-+ (void) addDiversion:(Diversion *)diversion {
- [Diversions_ addObject:diversion];
+ if (NSURLRequest *request = self.request)
+ return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://url/%@", [[request URL] absoluteString]]];
+ else
+ return nil;
}
- (void) webView:(WebView *)view didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame {
bool bridged(false);
- @synchronized (HostConfig_) {
+ @synchronized (BridgedHosts_) {
if ([scheme isEqualToString:@"file"])
bridged = true;
else if ([scheme isEqualToString:@"https"])
[controller addAttachmentData:[NSData dataWithContentsOfFile:@"/tmp/dpkgl.log"] mimeType:@"text/plain" fileName:@"dpkgl.log"];
}
-- (NSURL *) URLWithURL:(NSURL *)url {
- return [Diversion divertURL:url];
-}
-
- (NSURLRequest *) webView:(WebView *)view resource:(id)resource willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response fromDataSource:(WebDataSource *)source {
return [CydiaWebViewController requestWithHeaders:[super webView:view resource:resource willSendRequest:request redirectResponse:response fromDataSource:source]];
}
if (Machine_ != NULL && [copy valueForHTTPHeaderField:@"X-Machine"] == nil)
[copy setValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"];
- bool bridged;
- bool token;
-
- @synchronized (HostConfig_) {
+ bool bridged; @synchronized (BridgedHosts_) {
bridged = [BridgedHosts_ containsObject:host];
- token = [TokenHosts_ containsObject:host];
}
- if ([url isCydiaSecure]) {
- if (bridged) {
- if (UniqueID_ != nil && [copy valueForHTTPHeaderField:@"X-Cydia-Id"] == nil)
- [copy setValue:UniqueID_ forHTTPHeaderField:@"X-Cydia-Id"];
- } else if (token) {
- if (Token_ != nil && [copy valueForHTTPHeaderField:@"X-Cydia-Token"] == nil)
- [copy setValue:Token_ forHTTPHeaderField:@"X-Cydia-Token"];
- }
- }
+ if ([url isCydiaSecure] && bridged && UniqueID_ != nil && [copy valueForHTTPHeaderField:@"X-Cydia-Id"] == nil)
+ [copy setValue:UniqueID_ forHTTPHeaderField:@"X-Cydia-Id"];
return copy;
}
[cydia_ setDelegate:delegate];
}
-- (NSString *) applicationNameForUserAgent {
- return UserAgent_;
-}
-
- (id) init {
if ((self = [super initWithWidth:0 ofClass:[CydiaWebViewController class]]) != nil) {
- cydia_ = [[[CydiaObject alloc] initWithDelegate:indirect_] autorelease];
+ cydia_ = [[[CydiaObject alloc] initWithDelegate:self.indirect] autorelease];
} return self;
}
@end
/* }}} */
-// CydiaScript {{{
-@interface NSObject (CydiaScript)
-- (id) Cydia$webScriptObjectInContext:(WebScriptObject *)context;
-@end
-
-@implementation NSObject (CydiaScript)
-
-- (id) Cydia$webScriptObjectInContext:(WebScriptObject *)context {
- return self;
-}
-
-@end
-
-@implementation NSArray (CydiaScript)
-
-- (id) Cydia$webScriptObjectInContext:(WebScriptObject *)context {
- WebScriptObject *object([context evaluateWebScript:@"[]"]);
- for (size_t i(0), e([self count]); i != e; ++i)
- [object setWebScriptValueAtIndex:i value:[[self objectAtIndex:i] Cydia$webScriptObjectInContext:context]];
- return object;
-}
-
-@end
-
-@implementation NSDictionary (CydiaScript)
-
-- (id) Cydia$webScriptObjectInContext:(WebScriptObject *)context {
- WebScriptObject *object([context evaluateWebScript:@"({})"]);
- for (id i in self)
- [object setValue:[[self objectForKey:i] Cydia$webScriptObjectInContext:context] forKey:i];
- return object;
-}
-
-@end
-// }}}
-
/* Confirmation Controller {{{ */
bool DepSubstrate(const pkgCache::VerIterator &iterator) {
if (!iterator.end())
- (void) complete {
if (substrate_)
RestartSubstrate_ = true;
- [delegate_ confirmWithNavigationController:[self navigationController]];
+ [self.delegate confirmWithNavigationController:[self navigationController]];
}
- (void) alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)button {
}
- (void) _doContinue {
- [delegate_ cancelAndClear:NO];
+ [self.delegate cancelAndClear:NO];
[self dismissModalViewControllerAnimated:YES];
}
issues_ = [NSMutableArray arrayWithCapacity:4];
- UpgradeCydia_ = false;
-
for (Package *package in packages) {
pkgCache::PkgIterator iterator([package iterator]);
NSString *name([package id]);
pkgDepCache::StateCache &state(cache[iterator]);
- static Pcre special_r("^(firmware$|gsc\\.|cy\\+)");
+ static RegEx special_r("(firmware|gsc\\..*|cy\\+.*)");
if (state.NewInstall())
[installs addObject:name];
[removes addObject:name];
}
- if ([name isEqualToString:@"cydia"])
- UpgradeCydia_ = true;
-
substrate_ |= DepSubstrate(policy->GetCandidateVer(iterator));
substrate_ |= DepSubstrate(iterator.CurrentVer());
}
#endif
- (void) cancelButtonClicked {
- [delegate_ cancelAndClear:YES];
+ [self.delegate cancelAndClear:YES];
[self dismissModalViewControllerAnimated:YES];
}
- (id) initWithDatabase:(Database *)database delegate:(id)delegate {
if ((self = [super init]) != nil) {
database_ = database;
- delegate_ = delegate;
+ self.delegate = delegate;
[database_ setProgressDelegate:self];
[self setURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/#!/progress/", UI_]]];
- [scroller_ setBackgroundColor:[UIColor blackColor]];
+ [self setPageColor:[UIColor blackColor]];
[[self navigationItem] setHidesBackButton:YES];
[super viewWillAppear:animated];
}
-- (void) reloadSpringBoard {
- if (kCFCoreFoundationVersionNumber > 700) { // XXX: iOS 6.x
- system("/bin/launchctl stop com.apple.backboardd");
- sleep(15);
- system("/usr/bin/killall backboardd SpringBoard sbreload");
- return;
- }
-
- pid_t pid(ExecFork());
- if (pid == 0) {
- if (setsid() == -1)
- perror("setsid");
-
- pid_t pid(ExecFork());
- if (pid == 0) {
- _root(execl("/usr/bin/sbreload", "sbreload", NULL));
- perror("sbreload");
-
- exit(0);
- } ReapZombie(pid);
-
- exit(0);
- } ReapZombie(pid);
-
- sleep(15);
- system("/usr/bin/killall backboardd SpringBoard sbreload");
-}
-
- (void) close {
UpdateExternalStatus(0);
if (Finish_ > 1)
- [delegate_ saveState];
+ [self.delegate saveState];
switch (Finish_) {
case 0:
- [delegate_ returnToCydia];
+ [self.delegate returnToCydia];
break;
case 1:
- [delegate_ terminateWithSuccess];
- /*if ([delegate_ respondsToSelector:@selector(suspendWithAnimation:)])
- [delegate_ suspendWithAnimation:YES];
+ [self.delegate terminateWithSuccess];
+ /*if ([self.delegate respondsToSelector:@selector(suspendWithAnimation:)])
+ [self.delegate suspendWithAnimation:YES];
else
- [delegate_ suspend];*/
+ [self.delegate suspend];*/
break;
case 2:
goto reload;
reload: {
- UIProgressHUD *hud([delegate_ addProgressHUD]);
+ UIProgressHUD *hud([self.delegate addProgressHUD]);
[hud setText:UCLocalize("LOADING")];
- [self performSelector:@selector(reloadSpringBoard) withObject:nil afterDelay:0.5];
+ [self.delegate performSelector:@selector(reloadSpringBoard) withObject:nil afterDelay:0.5];
return;
}
- (PackageCell *) init {
CGRect frame(CGRectMake(0, 0, 320, 74));
if ((self = [super initWithFrame:frame reuseIdentifier:@"Package"]) != nil) {
- UIView *content([self contentView]);
- CGRect bounds([content bounds]);
-
- content_ = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease];
- [content_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
- [content addSubview:content_];
-
- [content_ setDelegate:self];
- [content_ setOpaque:YES];
+ [self.content setOpaque:YES];
} return self;
}
placard_ = nil;
if (package == nil)
- [content_ setBackgroundColor:[UIColor whiteColor]];
+ [self.content setBackgroundColor:[UIColor whiteColor]];
else {
[package parse];
placard = nil;
}
- [content_ setBackgroundColor:color];
+ [self.content setBackgroundColor:color];
if (placard != nil)
placard_ = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/%@.png", App_, placard]];
}
[self setNeedsDisplay];
- [content_ setNeedsDisplay];
+ [self.content setNeedsDisplay];
}
- (void) drawSummaryContentRect:(CGRect)rect {
- bool highlighted(highlighted_);
+ bool highlighted(self.highlighted);
float width([self bounds].size.width);
if (icon_ != nil) {
}
- (void) drawNormalContentRect:(CGRect)rect {
- bool highlighted(highlighted_);
+ bool highlighted(self.highlighted);
float width([self bounds].size.width);
if (icon_ != nil) {
switch_ = [[[UISwitch alloc] initWithFrame:CGRectMake(218, 9, 60, 25)] autorelease];
[switch_ addTarget:self action:@selector(onSwitch:) forEvents:UIControlEventValueChanged];
- UIView *content([self contentView]);
- CGRect bounds([content bounds]);
-
- content_ = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease];
- [content_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
- [content addSubview:content_];
- [content_ setBackgroundColor:[UIColor whiteColor]];
-
- [content_ setDelegate:self];
+ [self.content setBackgroundColor:[UIColor whiteColor]];
} return self;
}
}
[metadata setObject:[NSNumber numberWithBool:([switch_ isOn] == NO)] forKey:@"Hidden"];
- Changed_ = true;
}
- (void) setSection:(Section *)section editing:(BOOL)editing {
[self setAccessoryType:editing ? UITableViewCellAccessoryNone : UITableViewCellAccessoryDisclosureIndicator];
[self setSelectionStyle:editing ? UITableViewCellSelectionStyleNone : UITableViewCellSelectionStyleBlue];
- [content_ setNeedsDisplay];
+ [self.content setNeedsDisplay];
}
- (void) setFrame:(CGRect)frame {
}
- (void) drawContentRect:(CGRect)rect {
- bool highlighted(highlighted_ && !editing_);
+ bool highlighted(self.highlighted && !editing_);
[icon_ drawInRect:CGRectMake(7, 7, 32, 32)];
/* }}} */
/* File Table {{{ */
-@interface FileTable : CyteViewController <
+@interface FileTable : CyteListController <
UITableViewDataSource,
UITableViewDelegate
> {
_H<Package> package_;
_H<NSString> name_;
_H<NSMutableArray> files_;
- _H<UITableView, 2> list_;
}
-- (id) initWithDatabase:(Database *)database;
-- (void) setPackage:(Package *)package;
+- (id) initWithDatabase:(Database *)database forPackage:(NSString *)name;
@end
return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@/files", [package_ id]]];
}
-- (void) loadView {
- list_ = [[[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease];
- [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
- [list_ setRowHeight:24.0f];
- [(UITableView *) list_ setDataSource:self];
- [list_ setDelegate:self];
- [self setView:list_];
-}
-
-- (void) viewDidLoad {
- [super viewDidLoad];
-
- [[self navigationItem] setTitle:UCLocalize("INSTALLED_FILES")];
+- (CGFloat) rowHeight {
+ return 24;
}
- (void) releaseSubviews {
- list_ = nil;
-
package_ = nil;
files_ = nil;
[super releaseSubviews];
}
-- (id) initWithDatabase:(Database *)database {
- if ((self = [super init]) != nil) {
+- (id) initWithDatabase:(Database *)database forPackage:(NSString *)name {
+ if ((self = [super initWithTitle:UCLocalize("INSTALLED_FILES")]) != nil) {
database_ = database;
+ name_ = name;
} return self;
}
-- (void) setPackage:(Package *)package {
- package_ = nil;
- name_ = nil;
+- (bool) shouldYield {
+ return false;
+}
- files_ = [NSMutableArray arrayWithCapacity:32];
+- (void) _reloadData {
+ files_ = nil;
- if (package != nil) {
- package_ = package;
- name_ = [package id];
+ package_ = [database_ packageWithName:name_];
+ if (package_ != nil) {
+ files_ = [NSMutableArray arrayWithCapacity:32];
- if (NSArray *files = [package files])
+ if (NSArray *files = [package_ files])
[files_ addObjectsFromArray:files];
if ([files_ count] != 0) {
NSString *directory = [stack lastObject];
[stack addObject:[file stringByAppendingString:@"/"]];
[files_ replaceObjectAtIndex:i withObject:[NSString stringWithFormat:@"%*s%@",
- ([stack count] - 2) * 3, "",
+ int(([stack count] - 2) * 3), "",
[file substringFromIndex:[directory length]]
]];
}
}
}
- [list_ reloadData];
-}
-
-- (void) reloadData {
- [super reloadData];
-
- [self setPackage:[database_ packageWithName:name_]];
+ [super _reloadData];
}
@end
_H<NSString> name_;
bool commercial_;
std::vector<std::pair<_H<NSString>, _H<NSString>>> buttons_;
+ _H<UIActionSheet> sheet_;
_H<UIBarButtonItem> button_;
+ _H<NSArray> versions_;
}
- (id) initWithDatabase:(Database *)database forPackage:(NSString *)name withReferrer:(NSString *)referrer;
return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@", (id) name_]];
}
+- (void) _clickButtonWithPackage:(Package *)package {
+ [self.delegate installPackage:package];
+}
+
- (void) _clickButtonWithName:(NSString *)name {
if ([name isEqualToString:@"CLEAR"])
- [delegate_ clearPackage:package_];
- else if ([name isEqualToString:@"INSTALL"])
- [delegate_ installPackage:package_];
- else if ([name isEqualToString:@"REINSTALL"])
- [delegate_ installPackage:package_];
+ return [self.delegate clearPackage:package_];
else if ([name isEqualToString:@"REMOVE"])
- [delegate_ removePackage:package_];
- else if ([name isEqualToString:@"UPGRADE"])
- [delegate_ installPackage:package_];
+ return [self.delegate removePackage:package_];
+ else if ([name isEqualToString:@"DOWNGRADE"]) {
+ sheet_ = [[[UIActionSheet alloc]
+ initWithTitle:nil
+ delegate:self
+ cancelButtonTitle:nil
+ destructiveButtonTitle:nil
+ otherButtonTitles:nil
+ ] autorelease];
+
+ for (Package *version in (id) versions_)
+ [sheet_ addButtonWithTitle:[version latest]];
+ [sheet_ setContext:@"version"];
+
+ [self.delegate showActionSheet:sheet_ fromItem:[[self navigationItem] rightBarButtonItem]];
+ return;
+ }
+
+ else if ([name isEqualToString:@"INSTALL"]);
+ else if ([name isEqualToString:@"REINSTALL"]);
+ else if ([name isEqualToString:@"UPGRADE"]);
else _assert(false);
+
+ [self.delegate installPackage:package_];
}
- (void) actionSheet:(UIActionSheet *)sheet clickedButtonAtIndex:(NSInteger)button {
NSString *context([sheet context]);
+ if (sheet_ == sheet)
+ sheet_ = nil;
if ([context isEqualToString:@"modify"]) {
if (button != [sheet cancelButtonIndex]) {
[self _clickButtonWithName:buttons_[button].first];
}
+ [sheet dismissWithClickedButtonIndex:button animated:YES];
+ } else if ([context isEqualToString:@"version"]) {
+ if (button != [sheet cancelButtonIndex]) {
+ Package *version([versions_ objectAtIndex:button]);
+ if (IsWildcat_)
+ [self performSelector:@selector(_clickButtonWithPackage:) withObject:version afterDelay:0];
+ else
+ [self _clickButtonWithPackage:version];
+ }
+
[sheet dismissWithClickedButtonIndex:button animated:YES];
}
}
#if !AlwaysReload
- (void) _customButtonClicked {
+ if (commercial_ && self.isLoading && [package_ uninstalled])
+ return [self reloadURLWithCache:NO];
+
size_t count(buttons_.size());
if (count == 0)
return;
for (const auto &button : buttons_)
[buttons addObject:button.second];
- UIActionSheet *sheet = [[[UIActionSheet alloc]
+ sheet_ = [[[UIActionSheet alloc]
initWithTitle:nil
delegate:self
cancelButtonTitle:nil
otherButtonTitles:nil
] autorelease];
- for (NSString *button in buttons) [sheet addButtonWithTitle:button];
- if (!IsWildcat_) {
- [sheet addButtonWithTitle:UCLocalize("CANCEL")];
- [sheet setCancelButtonIndex:[sheet numberOfButtons] - 1];
- }
- [sheet setContext:@"modify"];
+ for (NSString *button in buttons)
+ [sheet_ addButtonWithTitle:button];
+ [sheet_ setContext:@"modify"];
- [delegate_ showActionSheet:sheet fromItem:[[self navigationItem] rightBarButtonItem]];
+ [self.delegate showActionSheet:sheet_ fromItem:[[self navigationItem] rightBarButtonItem]];
}
}
-- (void) reloadButtonClicked {
- if (commercial_ && function_ == nil && [package_ uninstalled])
- return;
- [self customButtonClicked];
-}
-
- (void) applyLoadingTitle {
// Don't show "Loading" as the title. Ever.
}
- (void) reloadData {
[super reloadData];
+ [sheet_ dismissWithClickedButtonIndex:[sheet_ cancelButtonIndex] animated:YES];
+ sheet_ = nil;
+
package_ = [database_ packageWithName:name_];
+ versions_ = [package_ downgrades];
buttons_.clear();
buttons_.push_back(std::make_pair(@"REINSTALL", UCLocalize("REINSTALL")));
if (![package_ uninstalled])
buttons_.push_back(std::make_pair(@"REMOVE", UCLocalize("REMOVE")));
+ if ([versions_ count] != 0)
+ buttons_.push_back(std::make_pair(@"DOWNGRADE", UCLocalize("DOWNGRADE")));
}
NSString *title;
/* }}} */
/* Package List Controller {{{ */
-@interface PackageListController : CyteViewController <
+@interface PackageListController : CyteListController <
UITableViewDataSource,
UITableViewDelegate
> {
unsigned era_;
_H<NSArray> packages_;
_H<NSArray> sections_;
- _H<UITableView, 2> list_;
_H<NSArray> thumbs_;
std::vector<NSInteger> offset_;
- _H<NSString> title_;
unsigned reloading_;
}
- (id) initWithDatabase:(Database *)database title:(NSString *)title;
-- (void) setDelegate:(id)delegate;
-- (void) resetCursor;
-- (void) clearData;
- (NSArray *) sectionsForPackages:(NSMutableArray *)packages;
return true;
}
-- (void) deselectWithAnimation:(BOOL)animated {
- [list_ deselectRowAtIndexPath:[list_ indexPathForSelectedRow] animated:animated];
-}
-
-- (void) resizeForKeyboardBounds:(CGRect)bounds duration:(NSTimeInterval)duration curve:(UIViewAnimationCurve)curve {
- CGRect base = [[self view] bounds];
- base.size.height -= bounds.size.height;
- base.origin = [list_ frame].origin;
-
- [UIView beginAnimations:nil context:NULL];
- [UIView setAnimationBeginsFromCurrentState:YES];
- [UIView setAnimationCurve:curve];
- [UIView setAnimationDuration:duration];
- [list_ setFrame:base];
- [UIView commitAnimations];
-}
-
-- (void) resizeForKeyboardBounds:(CGRect)bounds duration:(NSTimeInterval)duration {
- [self resizeForKeyboardBounds:bounds duration:duration curve:UIViewAnimationCurveLinear];
-}
-
-- (void) resizeForKeyboardBounds:(CGRect)bounds {
- [self resizeForKeyboardBounds:bounds duration:0];
-}
-
-- (void) getKeyboardCurve:(UIViewAnimationCurve *)curve duration:(NSTimeInterval *)duration forNotification:(NSNotification *)notification {
- if (&UIKeyboardAnimationCurveUserInfoKey == NULL)
- *curve = UIViewAnimationCurveEaseInOut;
- else
- [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:curve];
-
- if (&UIKeyboardAnimationDurationUserInfoKey == NULL)
- *duration = 0.3;
- else
- [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:duration];
-}
-
-- (void) keyboardWillShow:(NSNotification *)notification {
- CGRect bounds;
- CGPoint center;
- [[[notification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] getValue:&bounds];
- [[[notification userInfo] objectForKey:UIKeyboardCenterEndUserInfoKey] getValue:¢er];
-
- NSTimeInterval duration;
- UIViewAnimationCurve curve;
- [self getKeyboardCurve:&curve duration:&duration forNotification:notification];
-
- CGRect kbframe = CGRectMake(Retina(center.x - bounds.size.width / 2), Retina(center.y - bounds.size.height / 2), bounds.size.width, bounds.size.height);
- UIViewController *base = self;
- while ([base parentOrPresentingViewController] != nil)
- base = [base parentOrPresentingViewController];
- CGRect viewframe = [[base view] convertRect:[list_ frame] fromView:[list_ superview]];
- CGRect intersection = CGRectIntersection(viewframe, kbframe);
-
- if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_3_0) // XXX: _UIApplicationLinkedOnOrAfter(4)
- intersection.size.height += CYStatusBarHeight();
-
- [self resizeForKeyboardBounds:intersection duration:duration curve:curve];
-}
-
-- (void) keyboardWillHide:(NSNotification *)notification {
- NSTimeInterval duration;
- UIViewAnimationCurve curve;
- [self getKeyboardCurve:&curve duration:&duration forNotification:notification];
-
- [self resizeForKeyboardBounds:CGRectZero duration:duration curve:curve];
-}
-
-- (void) viewWillAppear:(BOOL)animated {
- [super viewWillAppear:animated];
-
- [self resizeForKeyboardBounds:CGRectZero];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
-}
-
-- (void) viewWillDisappear:(BOOL)animated {
- [super viewWillDisappear:animated];
-
- [self resizeForKeyboardBounds:CGRectZero];
- [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
- [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
-}
-
-- (void) viewDidAppear:(BOOL)animated {
- [super viewDidAppear:animated];
- [self deselectWithAnimation:animated];
-}
-
- (void) didSelectPackage:(Package *)package {
CYPackageController *view([[[CYPackageController alloc] initWithDatabase:database_ forPackage:[package id] withReferrer:[[self referrerURL] absoluteString]] autorelease]);
- [view setDelegate:delegate_];
+ [view setDelegate:self.delegate];
[[self navigationController] pushViewController:view animated:YES];
}
return offset_[index];
}
-- (void) updateHeight {
- [list_ setRowHeight:([self isSummarized] ? 38 : 73)];
+- (CGFloat) rowHeight {
+ return [self isSummarized] ? 38 : 73;
}
- (id) initWithDatabase:(Database *)database title:(NSString *)title {
- if ((self = [super init]) != nil) {
+ if ((self = [super initWithTitle:title]) != nil) {
database_ = database;
- title_ = [title copy];
- [[self navigationItem] setTitle:title_];
} return self;
}
-- (void) loadView {
- UIView *view([[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]);
- [view setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
- [self setView:view];
-
- list_ = [[[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain] autorelease];
- [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
- [view addSubview:list_];
-
- // XXX: is 20 the most optimal number here?
- [list_ setSectionIndexMinimumDisplayRowCount:20];
-
- [(UITableView *) list_ setDataSource:self];
- [list_ setDelegate:self];
-
- [self updateHeight];
-}
-
- (void) releaseSubviews {
- list_ = nil;
-
packages_ = nil;
sections_ = nil;
[super releaseSubviews];
}
-- (void) setDelegate:(id)delegate {
- delegate_ = delegate;
-}
-
-- (bool) shouldYield {
- return false;
-}
-
- (bool) shouldBlock {
return false;
}
if (![self shouldBlock])
hud = nil;
else {
- hud = [delegate_ addProgressHUD];
+ hud = [self.delegate addProgressHUD];
[hud setText:UCLocalize("LOADING")];
}
packages = [self yieldToSelector:@selector(_reloadPackages)];
if (hud != nil)
- [delegate_ removeProgressHUD:hud];
+ [self.delegate removeProgressHUD:hud];
} while (reloading_ == 2);
} else {
packages = [self _reloadPackages];
sections_ = [NSArray arrayWithObject:section];
}
- [self updateHeight];
-
- _profile(PackageTable$reloadData$List)
- [(UITableView *) list_ setDataSource:self];
- [list_ reloadData];
- _end
+ [super _reloadData];
}
PrintTimes();
return sections;
}
-- (void) reloadData {
- [super reloadData];
-
- if ([self shouldYield])
- [self performSelector:@selector(_reloadData) withObject:nil afterDelay:0];
- else
- [self _reloadData];
-}
-
-- (void) resetCursor {
- [list_ scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
-}
-
-- (void) clearData {
- [self updateHeight];
-
- [list_ setDataSource:nil];
- [list_ reloadData];
-
- [self resetCursor];
-}
-
@end
/* }}} */
/* Filtered Package List Controller {{{ */
_profile(PackageTable$reloadData$Filter)
for (Package *package in packages)
- if ([package valid] && filter(package))
+ if (filter(package))
[filtered addObject:package];
_end
[alert setCancelButtonIndex:0];
[alert setMessage:
- @"Copyright \u00a9 2008-2014\n"
+ @"Copyright \u00a9 2008-2015\n"
"SaurikIT, LLC\n"
"\n"
"Jay Freeman (saurik)\n"
@end
/* }}} */
-/* Cydia Navigation Controller Interface {{{ */
-@interface UINavigationController (Cydia)
-
-- (NSArray *) navigationURLCollection;
-- (void) unloadData;
-
-@end
-/* }}} */
-
/* Cydia Tab Bar Controller {{{ */
@interface CydiaTabBarController : CyteTabBarController <
UITabBarControllerDelegate,
_transient NSObject<CydiaDelegate> *updatedelegate_;
}
-- (NSArray *) navigationURLCollection;
- (void) beginUpdate;
- (BOOL) updating;
@implementation CydiaTabBarController
-- (NSArray *) navigationURLCollection {
- NSMutableArray *items([NSMutableArray array]);
-
- // XXX: Should this deal with transient view controllers?
- for (id navigation in [self viewControllers]) {
- NSArray *stack = [navigation performSelector:@selector(navigationURLCollection)];
- if (stack != nil)
- [items addObject:stack];
- }
-
- return items;
-}
-
- (id) initWithDatabase:(Database *)database {
if ((self = [super init]) != nil) {
database_ = database;
} return self;
}
-- (void) setUpdate:(NSDate *)date {
- [self beginUpdate];
-}
-
- (void) beginUpdate {
if (updating_)
return;
@end
/* }}} */
-/* Cydia Navigation Controller Implementation {{{ */
-@implementation UINavigationController (Cydia)
-
-- (NSArray *) navigationURLCollection {
- NSMutableArray *stack([NSMutableArray array]);
-
- for (CyteViewController *controller in [self viewControllers]) {
- NSString *url = [[controller navigationURL] absoluteString];
- if (url != nil)
- [stack addObject:url];
- }
-
- return stack;
-}
-
-- (void) reloadData {
- [super reloadData];
-
- UIViewController *visible([self visibleViewController]);
- if (visible != nil)
- [visible reloadData];
-
- // on the iPad, this view controller is ALSO visible. :(
- if (IsWildcat_)
- if (UIViewController *modal = [self modalViewController])
- if ([modal modalPresentationStyle] == UIModalPresentationFormSheet)
- if (UIViewController *top = [self topViewController])
- if (top != visible)
- [top reloadData];
-}
-
-- (void) unloadData {
- for (CyteViewController *page in [self viewControllers])
- [page unloadData];
-
- [super unloadData];
-}
-
-@end
-/* }}} */
-
/* Cydia:// Protocol {{{ */
-@interface CydiaURLProtocol : NSURLProtocol {
+@interface CydiaURLProtocol : CyteURLProtocol {
}
@end
@implementation CydiaURLProtocol
-+ (BOOL) canInitWithRequest:(NSURLRequest *)request {
- NSURL *url([request URL]);
- if (url == nil)
- return NO;
-
- NSString *scheme([[url scheme] lowercaseString]);
- if (scheme != nil && [scheme isEqualToString:@"cydia"])
- return YES;
- if ([[url absoluteString] hasPrefix:@"about:cydia-"])
- return YES;
-
- return NO;
-}
-
-+ (NSURLRequest *) canonicalRequestForRequest:(NSURLRequest *)request {
- return request;
-}
-
-- (void) _returnPNGWithImage:(UIImage *)icon forRequest:(NSURLRequest *)request {
- id<NSURLProtocolClient> client([self client]);
- if (icon == nil)
- [client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist userInfo:nil]];
- else {
- NSData *data(UIImagePNGRepresentation(icon));
-
- NSURLResponse *response([[[NSURLResponse alloc] initWithURL:[request URL] MIMEType:@"image/png" expectedContentLength:-1 textEncodingName:nil] autorelease]);
- [client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
- [client URLProtocol:self didLoadData:data];
- [client URLProtocolDidFinishLoading:self];
- }
++ (NSString *) scheme {
+ return @"cydia";
}
-- (void) startLoading {
- id<NSURLProtocolClient> client([self client]);
- NSURLRequest *request([self request]);
-
- NSURL *url([request URL]);
- NSString *href([url absoluteString]);
- NSString *scheme([[url scheme] lowercaseString]);
-
- NSString *path;
-
- if ([scheme isEqualToString:@"cydia"])
- path = [href substringFromIndex:8];
- else if ([scheme isEqualToString:@"about"])
- path = [href substringFromIndex:12];
- else _assert(false);
-
+- (bool) loadForPath:(NSString *)path ofRequest:(NSURLRequest *)request {
NSRange slash([path rangeOfString:@"/"]);
NSString *command;
path = [path substringFromIndex:(slash.location + 1)];
}
- Database *database([Database sharedInstance]);
+ Database *database([Database sharedInstance]);
+
+ if (false);
+ else if ([command isEqualToString:@"application-icon"]) {
+ if (path == nil)
+ goto fail;
+ path = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
+
+ UIImage *icon(nil);
+
+ if (icon == nil && $SBSCopyIconImagePNGDataForDisplayIdentifier != NULL) {
+ NSData *data([$SBSCopyIconImagePNGDataForDisplayIdentifier(path) autorelease]);
+ icon = [UIImage imageWithData:data];
+ }
+
+ if (icon == nil)
+ if (NSString *file = SBSCopyIconImagePathForDisplayIdentifier(path))
+ icon = [UIImage imageAtPath:file];
+
+ if (icon == nil)
+ icon = [UIImage imageNamed:@"unknown.png"];
- if ([command isEqualToString:@"package-icon"]) {
+ [self _returnPNGWithImage:icon forRequest:request];
+ } else if ([command isEqualToString:@"package-icon"]) {
if (path == nil)
goto fail;
path = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
icon = [UIImage imageNamed:@"unknown.png"];
[self _returnPNGWithImage:icon forRequest:request];
} else fail: {
- [client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorResourceUnavailable userInfo:nil]];
+ return [super loadForPath:path ofRequest:request];
}
-}
-- (void) stopLoading {
+ return true;
}
@end
if (editing)
[list_ reloadData];
else
- [delegate_ updateData];
+ [self.delegate updateData];
[self updateNavigationItem];
}
source:[self source]
section:[section name]
] autorelease];
- [controller setDelegate:delegate_];
+ [controller setDelegate:self.delegate];
[[self navigationController] pushViewController:controller animated:YES];
}
[section addToCount];
_profile(SectionsView$reloadData$Filter)
- if (![package valid] || ![package visible])
+ if (![package visible])
continue;
_end
}
- (void) setLeftBarButtonItem {
- if ([delegate_ updating])
+ if ([self.delegate updating])
[[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
initWithTitle:UCLocalize("CANCEL")
style:UIBarButtonItemStyleDone
}
- (void) refreshButtonClicked {
- if ([delegate_ requestUpdate])
+ if ([self.delegate requestUpdate])
[self setLeftBarButtonItem];
}
- (void) cancelButtonClicked {
- [delegate_ cancelUpdate];
+ [self.delegate cancelUpdate];
}
- (void) upgradeButtonClicked {
- [delegate_ distUpgrade];
+ [self.delegate distUpgrade];
[[self navigationItem] setRightBarButtonItem:nil animated:YES];
}
if (upgrades_ != 0)
[sections insertObject:upgradable atIndex:0];
- [list_ reloadData];
-
[[self navigationItem] setRightBarButtonItem:(upgrades_ == 0 ? nil : [[[UIBarButtonItem alloc]
initWithTitle:[NSString stringWithFormat:UCLocalize("PARENTHETICAL"), UCLocalize("UPGRADE"), [NSString stringWithFormat:@"%u", upgrades_]]
style:UIBarButtonItemStylePlain
if (package_ == nil)
return;
if ([package_ setSubscribed:value])
- [delegate_ updateData];
+ [self.delegate updateData];
}
- (void) _updateIgnored {
const char *package([name_ UTF8String]);
bool on([ignoredSwitch_ isOn]);
- pid_t pid(ExecFork());
- if (pid == 0) {
- FILE *dpkg(_root(popen("dpkg --set-selections", "w")));
- fwrite(package, strlen(package), 1, dpkg);
-
- if (on)
- fwrite(" hold\n", 6, 1, dpkg);
- else
- fwrite(" install\n", 9, 1, dpkg);
+ FILE *dpkg(popen("/usr/libexec/cydia/cydo --set-selections", "w"));
+ fwrite(package, strlen(package), 1, dpkg);
- pclose(dpkg);
+ if (on)
+ fwrite(" hold\n", 6, 1, dpkg);
+ else
+ fwrite(" install\n", 9, 1, dpkg);
- exit(0);
- } ReapZombie(pid);
+ pclose(dpkg);
}
- (void) onIgnored:(id)control {
[invocation setTarget:self];
[invocation setSelector:@selector(_updateIgnored)];
- [delegate_ reloadDataWithInvocation:invocation];
+ [self.delegate reloadDataWithInvocation:invocation];
}
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
#if !AlwaysReload
- (void) queueButtonClicked {
- [delegate_ queue];
+ [self.delegate queue];
}
#endif
- (void) _setImage:(NSArray *)data {
if ([url_ isEqual:[data objectAtIndex:0]]) {
icon_ = [data objectAtIndex:1];
- [content_ setNeedsDisplay];
+ [self.content setNeedsDisplay];
}
}
origin_ = [source name];
label_ = [source rooturi];
- [content_ setNeedsDisplay];
+ [self.content setNeedsDisplay];
url_ = [source iconURL];
[NSThread detachNewThreadSelector:@selector(_setSource:) toTarget:self withObject:url_];
icon_ = [UIImage imageNamed:@"folder.png"];
origin_ = UCLocalize("ALL_SOURCES");
label_ = UCLocalize("ALL_SOURCES_EX");
- [content_ setNeedsDisplay];
+ [self.content setNeedsDisplay];
}
- (SourceCell *) initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
if ((self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier]) != nil) {
- UIView *content([self contentView]);
- CGRect bounds([content bounds]);
-
- content_ = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease];
- [content_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
- [content_ setBackgroundColor:[UIColor whiteColor]];
- [content addSubview:content_];
-
- [content_ setDelegate:self];
- [content_ setOpaque:YES];
+ [self.content setBackgroundColor:[UIColor whiteColor]];
+ [self.content setOpaque:YES];
indicator_ = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGraySmall] autorelease];
[indicator_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin];// | UIViewAutoresizingFlexibleBottomMargin];
- [content addSubview:indicator_];
+ [[self contentView] addSubview:indicator_];
- [[content_ layer] setContentsGravity:kCAGravityTopLeft];
+ [[self.content layer] setContentsGravity:kCAGravityTopLeft];
} return self;
}
}
- (void) drawContentRect:(CGRect)rect {
- bool highlighted(highlighted_);
+ bool highlighted(self.highlighted);
float width(rect.size.width);
if (icon_ != nil) {
source:[self sourceAtIndexPath:indexPath]
] autorelease]);
- [controller setDelegate:delegate_];
+ [controller setDelegate:self.delegate];
[[self navigationController] pushViewController:controller animated:YES];
}
if (source == nil) return;
[Sources_ removeObjectForKey:[source key]];
- Changed_ = true;
- [delegate_ _saveConfig];
- [delegate_ reloadDataWithInvocation:nil];
+ [self.delegate syncData];
}
}
}
- (void) complete {
- [delegate_ addTrivialSource:href_];
+ [self.delegate addTrivialSource:href_];
href_ = nil;
- [delegate_ syncData];
+ [self.delegate syncData];
}
- (NSString *) getWarning {
) {
NSString *warning(cydia_ ? [self yieldToSelector:@selector(getWarning)] : nil);
- [delegate_ releaseNetworkActivityIndicator];
+ [self.delegate releaseNetworkActivityIndicator];
- [delegate_ removeProgressHUD:hud_];
+ [self.delegate removeProgressHUD:hud_];
hud_ = nil;
if (cydia_) {
switch (button) {
case 1: {
NSString *href = [[alert textField] text];
-
- static Pcre href_r("^(http(s?)://|file:///)[^# ]*$");
- if (!href_r(href)) {
- UIAlertView *alert = [[[UIAlertView alloc]
- initWithTitle:[NSString stringWithFormat:Colon_, Error_, UCLocalize("INVALID_URL")]
- message:UCLocalize("INVALID_URL_EX")
- delegate:self
- cancelButtonTitle:UCLocalize("OK")
- otherButtonTitles:nil
- ] autorelease];
-
- [alert setContext:@"badurl"];
- [alert show];
-
+ href = VerifySource(href);
+ if (href == nil)
break;
- }
-
- if (![href hasSuffix:@"/"])
- href_ = [href stringByAppendingString:@"/"];
- else
- href_ = href;
+ href_ = href;
trivial_bz2_ = [[self _requestHRef:[href_ stringByAppendingString:@"Packages.bz2"] method:@"HEAD"] retain];
trivial_gz_ = [[self _requestHRef:[href_ stringByAppendingString:@"Packages.gz"] method:@"HEAD"] retain];
cydia_ = false;
// XXX: this is stupid
- hud_ = [delegate_ addProgressHUD];
+ hud_ = [self.delegate addProgressHUD];
[hud_ setText:UCLocalize("VERIFYING_URL")];
- [delegate_ retainNetworkActivityIndicator];
+ [self.delegate retainNetworkActivityIndicator];
} break;
case 0:
target:self
action:@selector(addButtonClicked)
] autorelease] animated:animated];
- else if ([delegate_ updating])
+ else if ([self.delegate updating])
[[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
initWithTitle:UCLocalize("CANCEL")
style:UIBarButtonItemStyleDone
[alert setNumberOfRows:1];
[alert addTextFieldWithValue:@"http://" label:@""];
- UITextInputTraits *traits = [[alert textField] textInputTraits];
+ NSObject<UITextInputTraits> *traits = [[alert textField] textInputTraits];
[traits setAutocapitalizationType:UITextAutocapitalizationTypeNone];
[traits setAutocorrectionType:UITextAutocorrectionTypeNo];
[traits setKeyboardType:UIKeyboardTypeURL];
}
- (void) refreshButtonClicked {
- if ([delegate_ requestUpdate])
+ if ([self.delegate requestUpdate])
[self updateButtonsForEditingStatusAnimated:YES];
}
- (void) cancelButtonClicked {
- [delegate_ cancelUpdate];
+ [self.delegate cancelUpdate];
}
- (void) editButtonClicked {
@end
/* }}} */
-@interface CYURLCache : SDURLCache {
-}
-
-@end
-
-@implementation CYURLCache
-
-- (void) logEvent:(NSString *)event forRequest:(NSURLRequest *)request {
-#if !ForRelease
- if (false);
- else if ([event isEqualToString:@"no-cache"])
- event = @"!!!";
- else if ([event isEqualToString:@"store"])
- event = @">>>";
- else if ([event isEqualToString:@"invalid"])
- event = @"???";
- else if ([event isEqualToString:@"memory"])
- event = @"mem";
- else if ([event isEqualToString:@"disk"])
- event = @"ssd";
- else if ([event isEqualToString:@"miss"])
- event = @"---";
-
- NSLog(@"%@: %@", event, [[request URL] absoluteString]);
-#endif
-}
-
-- (void) storeCachedResponse:(NSCachedURLResponse *)cached forRequest:(NSURLRequest *)request {
- if (NSURLResponse *response = [cached response])
- if (NSString *mime = [response MIMEType])
- if ([mime isEqualToString:@"text/cache-manifest"]) {
- NSURL *url([response URL]);
-
-#if !ForRelease
- NSLog(@"###: %@", [url absoluteString]);
-#endif
-
- @synchronized (HostConfig_) {
- [CachedURLs_ addObject:url];
- }
- }
-
- [super storeCachedResponse:cached forRequest:request];
-}
-
-- (void) createDiskCachePath {
- [super createDiskCachePath];
- _root(chown([[self diskCachePath] UTF8String], 501, 501));
-}
-
-@end
-
-@interface Cydia : UIApplication <
+@interface Cydia : CyteApplication <
ConfirmationControllerDelegate,
DatabaseDelegate,
CydiaDelegate
> {
- _H<UIWindow> window_;
+ _H<CyteWindow> window_;
_H<CydiaTabBarController> tabbar_;
_H<CyteTabBarController> emulated_;
_H<AppCacheController> appcache_;
_H<NSURL> starturl_;
unsigned locked_;
- unsigned activity_;
_H<StashController> stash_;
}
- (bool) requestUpdate {
- if (IsReachable("cydia.saurik.com")) {
+ if (CyteIsReachable("cydia.saurik.com")) {
[self beginUpdate];
return true;
} else {
[self _loaded];
}
-- (void) _saveConfig {
- @synchronized (database_) {
- _trace();
- MetaFile_.Sync();
- _trace();
- }
-
- if (Changed_) {
- NSString *error(nil);
-
- if (NSData *data = [NSPropertyListSerialization dataFromPropertyList:Metadata_ format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error]) {
- _trace();
- NSError *error(nil);
- if (!_root([data writeToFile:@"/var/lib/cydia/metadata.plist" options:NSAtomicWrite error:&error]))
- NSLog(@"failure to save metadata data: %@", error);
- _trace();
-
- Changed_ = false;
- } else {
- NSLog(@"failure to serialize metadata: %@", error);
- }
- }
+- (void) reloadSpringBoard {
+ if (kCFCoreFoundationVersionNumber >= 700) // XXX: iOS 6.x
+ system("/usr/libexec/cydia/cydo /bin/launchctl stop com.apple.backboardd");
+ else
+ system("/usr/libexec/cydia/cydo /bin/launchctl stop com.apple.SpringBoard");
+ sleep(15);
+ system("/usr/bin/killall backboardd SpringBoard");
+}
- _root(CydiaWriteSources());
+- (void) _saveConfig {
+ SaveConfig(database_);
}
// Navigation controller for the queuing badge.
return [controllers objectAtIndex:3];
}
-- (void) unloadData {
- [tabbar_ unloadData];
-}
-
- (void) _updateData {
[self _saveConfig];
- [self unloadData];
+ [window_ unloadData];
UINavigationController *navigation = [self queueNavigationController];
[[navigation tabBarItem] setBadgeValue:(Queuing_ ? UCLocalize("Q_D") : nil)];
}
-- (void) _refreshIfPossible:(NSDate *)update {
+- (void) _refreshIfPossible {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSDate *update([[NSDictionary dictionaryWithContentsOfFile:@ CacheState_] objectForKey:@"LastUpdate"]);
+
bool recently = false;
if (update != nil) {
NSTimeInterval interval([update timeIntervalSinceNow]);
// - We already auto-refreshed this launch.
// - Auto-refresh is disabled.
// - Cydia's server is not reachable
- if (recently || loaded_ || ManualRefresh || !IsReachable("cydia.saurik.com")) {
+ if (recently || loaded_ || ManualRefresh || !CyteIsReachable("cydia.saurik.com")) {
// If we are cancelling, we need to make sure it knows it's already loaded.
loaded_ = true;
// We are going to load, so remember that.
loaded_ = true;
- [tabbar_ performSelectorOnMainThread:@selector(setUpdate:) withObject:update waitUntilDone:NO];
+ [tabbar_ performSelectorOnMainThread:@selector(beginUpdate) withObject:nil waitUntilDone:NO];
}
[pool release];
}
- (void) refreshIfPossible {
- [NSThread detachNewThreadSelector:@selector(_refreshIfPossible:) toTarget:self withObject:[Metadata_ objectForKey:@"LastUpdate"]];
+ [NSThread detachNewThreadSelector:@selector(_refreshIfPossible) toTarget:self withObject:nil];
}
- (void) reloadDataWithInvocation:(NSInvocation *)invocation {
if (emulated_ == nil)
return;
- if ([window_ respondsToSelector:@selector(setRootViewController:)])
- [window_ setRootViewController:tabbar_];
- else {
- [window_ addSubview:[tabbar_ view]];
- [[emulated_ view] removeFromSuperview];
- }
-
+ [window_ setRootViewController:tabbar_];
emulated_ = nil;
+
[window_ setUserInteractionEnabled:YES];
}
CydiaAddSource(href, distribution, sections);
}
-- (void) addTrivialSource:(NSString *)href {
+// XXX: this method should not return anything
+- (BOOL) addTrivialSource:(NSString *)href {
CydiaAddSource(href, @"./");
-}
-
-- (void) updateValues {
- Changed_ = true;
+ return YES;
}
- (void) resolve {
- (void) _uicache {
_trace();
-
- if (UpgradeCydia_ && Finish_ > 0) {
- seteugid(0, 0);
- system("su -c /usr/bin/uicache mobile");
- } else {
- system("/usr/bin/uicache");
- }
-
+ system("/usr/bin/uicache");
_trace();
}
[self unlockSuspend];
}
-- (void) retainNetworkActivityIndicator {
- if (activity_++ == 0)
- [self setNetworkActivityIndicatorVisible:YES];
-
-#if TraceLogging
- NSLog(@"retainNetworkActivityIndicator->%d", activity_);
-#endif
-}
-
-- (void) releaseNetworkActivityIndicator {
- if (--activity_ == 0)
- [self setNetworkActivityIndicatorVisible:NO];
-
-#if TraceLogging
- NSLog(@"releaseNetworkActivityIndicator->%d", activity_);
-#endif
-
-}
-
- (void) cancelAndClear:(bool)clear {
@synchronized (self) {
if (clear) {
@synchronized (self) {
for (Package *broken in (id) broken_) {
[broken remove];
- NSString *id = [broken id];
-
- _root({
- unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.prerm", id] UTF8String]);
- unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.postrm", id] UTF8String]);
- unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.preinst", id] UTF8String]);
- unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.postinst", id] UTF8String]);
- });
+ NSString *id(ShellEscape([broken id]));
+ system([[NSString stringWithFormat:@"/usr/libexec/cydia/cydo /bin/rm -f"
+ " /var/lib/dpkg/info/%@.prerm"
+ " /var/lib/dpkg/info/%@.postrm"
+ " /var/lib/dpkg/info/%@.preinst"
+ " /var/lib/dpkg/info/%@.postinst"
+ " /var/lib/dpkg/info/%@.extrainst_"
+ "", id, id, id, id, id] UTF8String]);
}
[self resolve];
NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
_trace();
- _root(system([command UTF8String]));
+ system([command UTF8String]);
_trace();
[pool release];
[super applicationSuspend];
}
-- (void) applicationSuspend:(__GSEvent *)event {
+- (void) applicationSuspend:(GSEventRef)event {
if ([self isSafeToSuspend])
[super applicationSuspend:event];
}
controller = [[[SectionController alloc] initWithDatabase:database_ source:nil section:argument] autorelease];
}
- if (!external && [base isEqualToString:@"sources"]) {
+ if ([base isEqualToString:@"sources"]) {
if ([argument isEqualToString:@"add"]) {
controller = [[[SourcesController alloc] initWithDatabase:database_] autorelease];
[(SourcesController *)controller showAddSourcePrompt];
if ([arg2 isEqualToString:@"settings"]) {
controller = [[[PackageSettingsController alloc] initWithDatabase:database_ package:arg1] autorelease];
} else if ([arg2 isEqualToString:@"files"]) {
- if (Package *package = [database_ packageWithName:arg1]) {
- controller = [[[FileTable alloc] initWithDatabase:database_] autorelease];
- [(FileTable *)controller setPackage:package];
- }
+ controller = [[[FileTable alloc] initWithDatabase:database_ forPackage:arg1] autorelease];
}
}
}
- (void) saveState {
- [Metadata_ setObject:[tabbar_ navigationURLCollection] forKey:@"InterfaceState"];
- [Metadata_ setObject:[NSDate date] forKey:@"LastClosed"];
- [Metadata_ setObject:[NSNumber numberWithInt:[tabbar_ selectedIndex]] forKey:@"InterfaceIndex"];
- Changed_ = true;
+ [[NSDictionary dictionaryWithObjectsAndKeys:
+ @"InterfaceState", [tabbar_ navigationURLCollection],
+ @"LastClosed", [NSDate date],
+ @"InterfaceIndex", [NSNumber numberWithInt:[tabbar_ selectedIndex]],
+ nil] writeToFile:@ SavedState_ atomically:YES];
[self _saveConfig];
}
- (void) applicationDidEnterBackground:(UIApplication *)application {
if (kCFCoreFoundationVersionNumber < 1000 && [self isSafeToSuspend])
return [self terminateWithSuccess];
+ Backgrounded_ = [NSDate date];
[self saveState];
}
- (void) applicationWillEnterForeground:(UIApplication *)application {
- NSDate *closed = [Metadata_ objectForKey:@"LastClosed"];
- if (closed == nil)
+ if (Backgrounded_ == nil)
return;
- NSTimeInterval interval([closed timeIntervalSinceNow]);
+ NSTimeInterval interval([Backgrounded_ timeIntervalSinceNow]);
if (interval <= -(30*60)) {
[tabbar_ setSelectedIndex:0];
}
if (interval <= -(15*60)) {
- if (IsReachable("cydia.saurik.com")) {
+ if (CyteIsReachable("cydia.saurik.com")) {
[tabbar_ beginUpdate];
[appcache_ reloadURLWithCache:YES];
}
}
+
+ if ([database_ delocked])
+ [self reloadData];
}
- (void) setConfigurationData:(NSString *)data {
- static Pcre conffile_r("^'(.*)' '(.*)' ([01]) ([01])$");
+ static RegEx conffile_r("'(.*)' '(.*)' ([01]) ([01])");
if (!conffile_r(data)) {
lprintf("E:invalid conffile\n");
- (void) stash {
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque];
UpdateExternalStatus(1);
- [self yieldToSelector:@selector(system:) withObject:@"/usr/libexec/cydia/free.sh"];
+ [self yieldToSelector:@selector(system:) withObject:@"/usr/libexec/cydia/cydo /usr/libexec/cydia/free.sh"];
UpdateExternalStatus(0);
[self removeStashController];
-
- pid_t pid(ExecFork());
- if (pid == 0) {
- execlp("launchctl", "launchctl", "stop", "com.apple.SpringBoard", NULL);
- perror("launchctl stop");
-
- exit(0);
- } ReapZombie(pid);
-}
-
-- (void) setupViewControllers {
- tabbar_ = [[[CydiaTabBarController alloc] initWithDatabase:database_] autorelease];
-
- NSMutableArray *items;
- if (kCFCoreFoundationVersionNumber < 800) {
- items = [NSMutableArray arrayWithObjects:
- [[[UITabBarItem alloc] initWithTitle:@"Cydia" image:[UIImage imageNamed:@"home.png"] tag:0] autorelease],
- [[[UITabBarItem alloc] initWithTitle:UCLocalize("SOURCES") image:[UIImage imageNamed:@"install.png"] tag:0] autorelease],
- [[[UITabBarItem alloc] initWithTitle:UCLocalize("CHANGES") image:[UIImage imageNamed:@"changes.png"] tag:0] autorelease],
- [[[UITabBarItem alloc] initWithTitle:UCLocalize("INSTALLED") image:[UIImage imageNamed:@"manage.png"] tag:0] autorelease],
- [[[UITabBarItem alloc] initWithTitle:UCLocalize("SEARCH") image:[UIImage imageNamed:@"search.png"] tag:0] autorelease],
- nil];
- } else {
- items = [NSMutableArray arrayWithObjects:
- [[[UITabBarItem alloc] initWithTitle:@"Cydia" image:[UIImage imageNamed:@"home7.png"] selectedImage:[UIImage imageNamed:@"home7s.png"]] autorelease],
- [[[UITabBarItem alloc] initWithTitle:UCLocalize("SOURCES") image:[UIImage imageNamed:@"install7.png"] selectedImage:[UIImage imageNamed:@"install7s.png"]] autorelease],
- [[[UITabBarItem alloc] initWithTitle:UCLocalize("CHANGES") image:[UIImage imageNamed:@"changes7.png"] selectedImage:[UIImage imageNamed:@"changes7s.png"]] autorelease],
- [[[UITabBarItem alloc] initWithTitle:UCLocalize("INSTALLED") image:[UIImage imageNamed:@"manage7.png"] selectedImage:[UIImage imageNamed:@"manage7s.png"]] autorelease],
- [[[UITabBarItem alloc] initWithTitle:UCLocalize("SEARCH") image:[UIImage imageNamed:@"search7.png"] selectedImage:[UIImage imageNamed:@"search7s.png"]] autorelease],
- nil];
- }
-
- NSMutableArray *controllers([NSMutableArray array]);
- for (UITabBarItem *item in items) {
- UINavigationController *controller([[[UINavigationController alloc] init] autorelease]);
- [controller setTabBarItem:item];
- [controllers addObject:controller];
- }
- [tabbar_ setViewControllers:controllers];
-
- [tabbar_ setUpdateDelegate:self];
-}
-
-- (void) _sendMemoryWarningNotification {
- if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_3_0) // XXX: maybe 4_0?
- [[NSNotificationCenter defaultCenter] postNotificationName:@"UIApplicationMemoryWarningNotification" object:[UIApplication sharedApplication]];
- else
- [[NSNotificationCenter defaultCenter] postNotificationName:@"UIApplicationDidReceiveMemoryWarningNotification" object:[UIApplication sharedApplication]];
-}
-
-- (void) _sendMemoryWarningNotifications {
- while (true) {
- [self performSelectorOnMainThread:@selector(_sendMemoryWarningNotification) withObject:nil waitUntilDone:NO];
- sleep(2);
- //usleep(2000000);
- }
-}
-
-- (void) applicationDidReceiveMemoryWarning:(UIApplication *)application {
- NSLog(@"--");
- [[NSURLCache sharedURLCache] removeAllCachedResponses];
+ [self reloadSpringBoard];
}
- (void) applicationDidFinishLaunching:(id)unused {
- //[NSThread detachNewThreadSelector:@selector(_sendMemoryWarningNotifications) toTarget:self withObject:nil];
-
-_trace();
- if ([self respondsToSelector:@selector(setApplicationSupportsShakeToEdit:)])
- [self setApplicationSupportsShakeToEdit:NO];
-
- @synchronized (HostConfig_) {
- [BridgedHosts_ addObject:[[NSURL URLWithString:CydiaURL(@"")] host]];
- }
-
- [NSURLCache setSharedURLCache:[[[CYURLCache alloc]
- initWithMemoryCapacity:524288
- diskCapacity:10485760
- diskPath:Cache("SDURLCache")
- ] autorelease]];
+ [super applicationDidFinishLaunching:unused];
+ [CyteWebViewController _initialize];
- [CydiaWebViewController _initialize];
+ [BridgedHosts_ addObject:[[NSURL URLWithString:CydiaURL(@"")] host]];
[NSURLProtocol registerClass:[CydiaURLProtocol class]];
appcache_ = [[[AppCacheController alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/appcache/", UI_]]] autorelease];
[appcache_ reloadData];
- window_ = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
+ window_ = [[[CyteWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
[window_ orderFront:self];
[window_ makeKey:self];
[window_ setHidden:NO];
+ if (access("/.cydia_no_stash", F_OK) == 0);
+ else {
+
if (false) stash: {
[self addStashController];
// XXX: this would be much cleaner as a yieldToSelector:
Stash_("/Library/Wallpaper");
//Stash_("/usr/bin");
Stash_("/usr/include");
- Stash_("/usr/lib/pam");
Stash_("/usr/share");
//Stash_("/var/lib");
+ }
+
database_ = [Database sharedInstance];
[database_ setDelegate:self];
[window_ setUserInteractionEnabled:NO];
- [self setupViewControllers];
+
+ tabbar_ = [[[CydiaTabBarController alloc] initWithDatabase:database_] autorelease];
+
+ [tabbar_ addViewControllers:nil,
+ @"Cydia", @"home.png", @"home7.png", @"home7s.png",
+ UCLocalize("SOURCES"), @"install.png", @"install7.png", @"install7s.png",
+ UCLocalize("CHANGES"), @"changes.png", @"changes7.png", @"changes7s.png",
+ UCLocalize("INSTALLED"), @"manage.png", @"manage7.png", @"manage7s.png",
+ UCLocalize("SEARCH"), @"search.png", @"search7.png", @"search7s.png",
+ nil];
+
+ [tabbar_ setUpdateDelegate:self];
CydiaLoadingViewController *loading([[[CydiaLoadingViewController alloc] init] autorelease]);
UINavigationController *navigation([[[UINavigationController alloc] init] autorelease]);
if ([emulated_ respondsToSelector:@selector(concealTabBarSelection)])
[emulated_ concealTabBarSelection];
- if ([window_ respondsToSelector:@selector(setRootViewController:)])
- [window_ setRootViewController:emulated_];
- else
- [window_ addSubview:[emulated_ view]];
+ [window_ setRootViewController:emulated_];
[self performSelector:@selector(loadData) withObject:nil afterDelay:0];
_trace();
[self refreshIfPossible];
[self disemulate];
- int savedIndex = [[Metadata_ objectForKey:@"InterfaceIndex"] intValue];
- NSArray *saved = [[[Metadata_ objectForKey:@"InterfaceState"] mutableCopy] autorelease];
+ NSDictionary *state([NSDictionary dictionaryWithContentsOfFile:@ SavedState_]);
+
+ int savedIndex = [[state objectForKey:@"InterfaceIndex"] intValue];
+ NSArray *saved = [[[state objectForKey:@"InterfaceState"] mutableCopy] autorelease];
int standardIndex = 0;
NSArray *standard = [self defaultStartPages];
if (saved == nil)
valid = NO;
- NSDate *closed = [Metadata_ objectForKey:@"LastClosed"];
+ NSDate *closed = [state objectForKey:@"LastClosed"];
if (valid && closed != nil) {
NSTimeInterval interval([closed timeIntervalSinceNow]);
if (interval <= -(30*60))
}
- (void) showActionSheet:(UIActionSheet *)sheet fromItem:(UIBarButtonItem *)item {
+ if (!IsWildcat_) {
+ [sheet addButtonWithTitle:UCLocalize("CANCEL")];
+ [sheet setCancelButtonIndex:[sheet numberOfButtons] - 1];
+ }
+
if (item != nil && IsWildcat_) {
[sheet showFromBarButtonItem:item animated:YES];
} else {
return object;
}*/
-Class $NSURLConnection;
-
-MSHook(id, NSURLConnection$init$, NSURLConnection *self, SEL _cmd, NSURLRequest *request, id delegate, BOOL usesCache, int64_t maxContentLength, BOOL startImmediately, NSDictionary *connectionProperties) {
- NSMutableURLRequest *copy([[request mutableCopy] autorelease]);
-
- NSURL *url([copy URL]);
-
- NSString *host([url host]);
- NSString *scheme([[url scheme] lowercaseString]);
-
- NSString *compound([NSString stringWithFormat:@"%@:%@", scheme, host]);
-
- @synchronized (HostConfig_) {
- if ([copy respondsToSelector:@selector(setHTTPShouldUsePipelining:)])
- if ([PipelinedHosts_ containsObject:host] || [PipelinedHosts_ containsObject:compound])
- [copy setHTTPShouldUsePipelining:YES];
-
- if (NSString *control = [copy valueForHTTPHeaderField:@"Cache-Control"])
- if ([control isEqualToString:@"max-age=0"])
- if ([CachedURLs_ containsObject:url]) {
-#if !ForRelease
- NSLog(@"~~~: %@", url);
-#endif
-
- [copy setCachePolicy:NSURLRequestReturnCacheDataDontLoad];
-
- [copy setValue:nil forHTTPHeaderField:@"Cache-Control"];
- [copy setValue:nil forHTTPHeaderField:@"If-Modified-Since"];
- [copy setValue:nil forHTTPHeaderField:@"If-None-Match"];
- }
- }
-
- if ((self = _NSURLConnection$init$(self, _cmd, copy, delegate, usesCache, maxContentLength, startImmediately, connectionProperties)) != nil) {
- } return self;
-}
-
-Class $WAKWindow;
-
-static CGSize $WAKWindow$screenSize(WAKWindow *self, SEL _cmd) {
- CGSize size([[UIScreen mainScreen] bounds].size);
- /*if ([$WAKWindow respondsToSelector:@selector(hasLandscapeOrientation)])
- if ([$WAKWindow hasLandscapeOrientation])
- std::swap(size.width, size.height);*/
- return size;
+static NSMutableDictionary *AutoreleaseDeepMutableCopyOfDictionary(CFTypeRef type) {
+ if (type == NULL)
+ return nil;
+ if (CFGetTypeID(type) != CFDictionaryGetTypeID())
+ return nil;
+ CFTypeRef copy(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, type, kCFPropertyListMutableContainers));
+ CFRelease(type);
+ return [(NSMutableDictionary *) copy autorelease];
}
-Class $NSUserDefaults;
-
-MSHook(id, NSUserDefaults$objectForKey$, NSUserDefaults *self, SEL _cmd, NSString *key) {
- if ([key respondsToSelector:@selector(isEqualToString:)] && [key isEqualToString:@"WebKitLocalStorageDatabasePathPreferenceKey"])
- return Cache("LocalStorage");
- return _NSUserDefaults$objectForKey$(self, _cmd, key);
-}
+int main_store(int, char *argv[]);
int main(int argc, char *argv[]) {
- seteugid(0, 0);
- seteguid(501, 501);
+#ifdef __arm64__
+ const char *argv0(argv[0]);
+ if (const char *slash = strrchr(argv0, '/'))
+ argv0 = slash + 1;
+ if (false);
+ else if (!strcmp(argv0, "store"))
+ return main_store(argc, argv);
+#endif
+
+ int fd(open("/tmp/cydia.log", O_WRONLY | O_APPEND | O_CREAT, 0644));
+ dup2(fd, 2);
+ close(fd);
NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
_trace();
+ CyteInitialize([NSString stringWithFormat:@"Cydia/%@", Cydia_]);
UpdateExternalStatus(0);
- UIScreen *screen([UIScreen mainScreen]);
- if ([screen respondsToSelector:@selector(scale)])
- ScreenScale_ = [screen scale];
- else
- ScreenScale_ = 1;
-
- UIDevice *device([UIDevice currentDevice]);
- if ([device respondsToSelector:@selector(userInterfaceIdiom)]) {
- UIUserInterfaceIdiom idiom([device userInterfaceIdiom]);
- if (idiom == UIUserInterfaceIdiomPad)
- IsWildcat_ = true;
- }
-
- Idiom_ = IsWildcat_ ? @"ipad" : @"iphone";
-
- Pcre pattern("^([0-9]+\\.[0-9]+)");
-
- if (pattern([device systemVersion]))
- Firmware_ = pattern[1];
- if (pattern(Cydia_))
- Major_ = pattern[1];
-
SessionData_ = [NSMutableDictionary dictionaryWithCapacity:4];
+ BridgedHosts_ = [NSMutableSet setWithCapacity:4];
+ InsecureHosts_ = [NSMutableSet setWithCapacity:4];
- HostConfig_ = [[[NSObject alloc] init] autorelease];
- @synchronized (HostConfig_) {
- BridgedHosts_ = [NSMutableSet setWithCapacity:4];
- TokenHosts_ = [NSMutableSet setWithCapacity:4];
- InsecureHosts_ = [NSMutableSet setWithCapacity:4];
- PipelinedHosts_ = [NSMutableSet setWithCapacity:4];
- CachedURLs_ = [NSMutableSet setWithCapacity:32];
- }
-
- NSString *ui(@"ui/ios");
- if (Idiom_ != nil)
- ui = [ui stringByAppendingString:[NSString stringWithFormat:@"~%@", Idiom_]];
- ui = [ui stringByAppendingString:[NSString stringWithFormat:@"/%@", Major_]];
- UI_ = CydiaURL(ui);
-
+ UI_ = CydiaURL([NSString stringWithFormat:@"ui/ios~%@/1.1", IsWildcat_ ? @"ipad" : @"iphone"]);
PackageName = reinterpret_cast<CYString &(*)(Package *, SEL)>(method_getImplementation(class_getInstanceMethod([Package class], @selector(cyname))));
- /* Library Hacks {{{ */
- class_addMethod(objc_getClass("DOMNodeList"), @selector(countByEnumeratingWithState:objects:count:), (IMP) &DOMNodeList$countByEnumeratingWithState$objects$count$, "I20@0:4^{NSFastEnumerationState}8^@12I16");
-
- $WAKWindow = objc_getClass("WAKWindow");
- if ($WAKWindow != NULL)
- if (Method method = class_getInstanceMethod($WAKWindow, @selector(screenSize)))
- method_setImplementation(method, (IMP) &$WAKWindow$screenSize);
-
- $NSURLConnection = objc_getClass("NSURLConnection");
- Method NSURLConnection$init$(class_getInstanceMethod($NSURLConnection, @selector(_initWithRequest:delegate:usesCache:maxContentLength:startImmediately:connectionProperties:)));
- if (NSURLConnection$init$ != NULL) {
- _NSURLConnection$init$ = reinterpret_cast<id (*)(NSURLConnection *, SEL, NSURLRequest *, id, BOOL, int64_t, BOOL, NSDictionary *)>(method_getImplementation(NSURLConnection$init$));
- method_setImplementation(NSURLConnection$init$, reinterpret_cast<IMP>(&$NSURLConnection$init$));
- }
-
- $NSUserDefaults = objc_getClass("NSUserDefaults");
- Method NSUserDefaults$objectForKey$(class_getInstanceMethod($NSUserDefaults, @selector(objectForKey:)));
- if (NSUserDefaults$objectForKey$ != NULL) {
- _NSUserDefaults$objectForKey$ = reinterpret_cast<id (*)(NSUserDefaults *, SEL, NSString *)>(method_getImplementation(NSUserDefaults$objectForKey$));
- method_setImplementation(NSUserDefaults$objectForKey$, reinterpret_cast<IMP>(&$NSUserDefaults$objectForKey$));
- }
- /* }}} */
/* Set Locale {{{ */
Locale_ = CFLocaleCopyCurrent();
Languages_ = [NSLocale preferredLanguages];
- //CFStringRef locale(CFLocaleGetIdentifier(Locale_));
- //NSLog(@"%@", [Languages_ description]);
+ std::string languages;
+ const char *translation(NULL);
- const char *lang;
+ // XXX: this isn't really a language, but this is compatible with older Cydia builds
if (Locale_ != NULL)
- lang = [(NSString *) CFLocaleGetIdentifier(Locale_) UTF8String];
- else if (Languages_ != nil && [Languages_ count] != 0)
- lang = [[Languages_ objectAtIndex:0] UTF8String];
- else
- // XXX: consider just setting to C and then falling through?
- lang = NULL;
-
- if (lang != NULL) {
- Pcre pattern("^([a-z][a-z])(?:-[A-Za-z]*)?(_[A-Z][A-Z])?$");
- lang = !pattern(lang) ? NULL : [pattern->*@"%1$@%2$@" UTF8String];
- }
+ if (const char *language = [(NSString *) CFLocaleGetIdentifier(Locale_) UTF8String]) {
+ RegEx pattern("([a-z][a-z])(?:-[A-Za-z]*)?(_[A-Z][A-Z])?");
+ if (pattern(language)) {
+ translation = strdup([pattern->*@"%1$@%2$@" UTF8String]);
+ languages += translation;
+ languages += ",";
+ }
+ }
- NSLog(@"Setting Language: %s", lang);
+ if (Languages_ != nil)
+ for (NSString *locale : Languages_) {
+ auto components([NSLocale componentsFromLocaleIdentifier:locale]);
+ NSString *language([components objectForKey:(id)kCFLocaleLanguageCode]);
+ if (NSString *script = [components objectForKey:(id)kCFLocaleScriptCode])
+ language = [NSString stringWithFormat:@"%@-%@", language, script];
+ languages += [language UTF8String];
+ languages += ",";
+ }
- if (lang != NULL) {
- setenv("LANG", lang, true);
- std::setlocale(LC_ALL, lang);
- }
+ languages += "en";
+ NSLog(@"Setting Language: [%s] %s", translation, languages.c_str());
/* }}} */
/* Index Collation {{{ */
if (Class $UILocalizedIndexedCollation = objc_getClass("UILocalizedIndexedCollation")) { @try {
}
/* }}} */
- apr_app_initialize(&argc, const_cast<const char * const **>(&argv), NULL);
-
- /* Parse Arguments {{{ */
- bool substrate(false);
-
- if (argc != 0) {
- char **args(argv);
- int arge(1);
-
- for (int argi(1); argi != argc; ++argi)
- if (strcmp(argv[argi], "--") == 0) {
- arge = argi;
- argv[argi] = argv[0];
- argv += argi;
- argc -= argi;
- break;
- }
-
- for (int argi(1); argi != arge; ++argi)
- if (strcmp(args[argi], "--substrate") == 0)
- substrate = true;
- else
- fprintf(stderr, "unknown argument: %s\n", args[argi]);
- }
- /* }}} */
-
App_ = [[NSBundle mainBundle] bundlePath];
Advanced_ = YES;
Cache_ = [[NSString stringWithFormat:@"%@/Library/Caches/com.saurik.Cydia", @"/var/mobile"] retain];
+ mkdir([Cache_ UTF8String], 0755);
/*Method alloc = class_getClassMethod([NSObject class], @selector(alloc));
alloc_ = alloc->method_imp;
void *gestalt(dlopen("/usr/lib/libMobileGestalt.dylib", RTLD_GLOBAL | RTLD_LAZY));
$MGCopyAnswer = reinterpret_cast<CFStringRef (*)(CFStringRef)>(dlsym(gestalt, "MGCopyAnswer"));
+ UniqueID_ = UniqueIdentifier([UIDevice currentDevice]);
/* System Information {{{ */
size_t size;
if (sysctlbyname("kern.maxproc", NULL, NULL, &maxproc, sizeof(maxproc)) == -1)
perror("sysctlbyname(\"kern.maxproc\", #)");
}
-
- sysctlbyname("kern.osversion", NULL, &size, NULL, 0);
- char *osversion = new char[size];
- if (sysctlbyname("kern.osversion", osversion, &size, NULL, 0) == -1)
- perror("sysctlbyname(\"kern.osversion\", ?)");
- else
- System_ = [NSString stringWithUTF8String:osversion];
-
- sysctlbyname("hw.machine", NULL, &size, NULL, 0);
- char *machine = new char[size];
- if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1)
- perror("sysctlbyname(\"hw.machine\", ?)");
- else
- Machine_ = machine;
-
- int64_t usermem(0);
- size = sizeof(usermem);
- if (sysctlbyname("hw.usermem", &usermem, &size, NULL, 0) == -1)
- usermem = 0;
-
- SerialNumber_ = (NSString *) CYIOGetValue("IOService:/", @"IOPlatformSerialNumber");
- ChipID_ = [CYHex((NSData *) CYIOGetValue("IODeviceTree:/chosen", @"unique-chip-id"), true) uppercaseString];
- BBSNum_ = CYHex((NSData *) CYIOGetValue("IOService:/AppleARMPE/baseband", @"snum"), false);
-
- UniqueID_ = UniqueIdentifier(device);
-
- if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:@"/Applications/MobileSafari.app/Info.plist"]) {
- Product_ = [info objectForKey:@"SafariProductVersion"];
- Safari_ = [info objectForKey:@"CFBundleVersion"];
- }
-
- NSString *agent([NSString stringWithFormat:@"Cydia/%@ CyF/%.2f", Cydia_, kCFCoreFoundationVersionNumber]);
-
- if (Pcre match = Pcre("^[0-9]+(\\.[0-9]+)+", Safari_))
- agent = [NSString stringWithFormat:@"Safari/%@ %@", match[0], agent];
- if (Pcre match = Pcre("^[0-9]+[A-Z][0-9]+[a-z]?", System_))
- agent = [NSString stringWithFormat:@"Mobile/%@ %@", match[0], agent];
- if (Pcre match = Pcre("^[0-9]+(\\.[0-9]+)+", Product_))
- agent = [NSString stringWithFormat:@"Version/%@ %@", match[0], agent];
-
- UserAgent_ = agent;
/* }}} */
/* Load Database {{{ */
- _trace();
- Metadata_ = [[[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"] autorelease];
- _trace();
SectionMap_ = [[[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Sections" ofType:@"plist"]] autorelease];
- if (Metadata_ == NULL)
- Metadata_ = [NSMutableDictionary dictionaryWithCapacity:2];
- else {
- Settings_ = [Metadata_ objectForKey:@"Settings"];
-
- Packages_ = [Metadata_ objectForKey:@"Packages"];
-
- Values_ = [Metadata_ objectForKey:@"Values"];
- Sections_ = [Metadata_ objectForKey:@"Sections"];
- Sources_ = [Metadata_ objectForKey:@"Sources"];
+ _trace();
+ mkdir("/var/mobile/Library/Cydia", 0755);
+ MetaFile_.Open("/var/mobile/Library/Cydia/metadata.cb0");
+ _trace();
- Token_ = [Metadata_ objectForKey:@"Token"];
+ Values_ = AutoreleaseDeepMutableCopyOfDictionary(CFPreferencesCopyAppValue(CFSTR("CydiaValues"), CFSTR("com.saurik.Cydia")));
+ Sections_ = AutoreleaseDeepMutableCopyOfDictionary(CFPreferencesCopyAppValue(CFSTR("CydiaSections"), CFSTR("com.saurik.Cydia")));
+ Sources_ = AutoreleaseDeepMutableCopyOfDictionary(CFPreferencesCopyAppValue(CFSTR("CydiaSources"), CFSTR("com.saurik.Cydia")));
+ Version_ = [(NSNumber *) CFPreferencesCopyAppValue(CFSTR("CydiaVersion"), CFSTR("com.saurik.Cydia")) autorelease];
- Version_ = [Metadata_ objectForKey:@"Version"];
- }
+ _trace();
+ NSDictionary *metadata([[[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"] autorelease]);
- if (Values_ == nil) {
+ if (Values_ == nil)
+ Values_ = [metadata objectForKey:@"Values"];
+ if (Values_ == nil)
Values_ = [[[NSMutableDictionary alloc] initWithCapacity:4] autorelease];
- [Metadata_ setObject:Values_ forKey:@"Values"];
- }
- if (Sections_ == nil) {
+ if (Sections_ == nil)
+ Sections_ = [metadata objectForKey:@"Sections"];
+ if (Sections_ == nil)
Sections_ = [[[NSMutableDictionary alloc] initWithCapacity:32] autorelease];
- [Metadata_ setObject:Sections_ forKey:@"Sections"];
- }
- if (Sources_ == nil) {
+ if (Sources_ == nil)
+ Sources_ = [metadata objectForKey:@"Sources"];
+ if (Sources_ == nil)
Sources_ = [[[NSMutableDictionary alloc] initWithCapacity:0] autorelease];
- [Metadata_ setObject:Sources_ forKey:@"Sources"];
- }
- if (Version_ == nil) {
+ // XXX: this wrong, but in a way that doesn't matter :/
+ if (Version_ == nil)
+ Version_ = [metadata objectForKey:@"Version"];
+ if (Version_ == nil)
Version_ = [NSNumber numberWithUnsignedInt:0];
- [Metadata_ setObject:Version_ forKey:@"Version"];
+
+ if (NSDictionary *packages = [metadata objectForKey:@"Packages"]) {
+ bool fail(false);
+ CFDictionaryApplyFunction((CFDictionaryRef) packages, &PackageImport, &fail);
+ _trace();
+ if (fail)
+ NSLog(@"unable to import package preferences... from 2010? oh well :/");
}
if ([Version_ unsignedIntValue] == 0) {
CydiaAddSource(@"http://repo666.ultrasn0w.com/", @"./");
Version_ = [NSNumber numberWithUnsignedInt:1];
- [Metadata_ setObject:Version_ forKey:@"Version"];
-
- [Metadata_ removeObjectForKey:@"LastUpdate"];
- Changed_ = true;
+ if (NSMutableDictionary *cache = [NSMutableDictionary dictionaryWithContentsOfFile:@ CacheState_]) {
+ [cache removeObjectForKey:@"LastUpdate"];
+ [cache writeToFile:@ CacheState_ atomically:YES];
+ }
}
_H<NSMutableArray> broken([NSMutableArray array]);
for (NSString *key in (id) Sources_)
- if ([key rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"# "]].location != NSNotFound)
+ if ([key rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"# "]].location != NSNotFound || ![([[Sources_ objectForKey:key] objectForKey:@"URI"] ?: @"/") hasSuffix:@"/"])
[broken addObject:key];
- if ([broken count] != 0) {
+ if ([broken count] != 0)
for (NSString *key in (id) broken)
[Sources_ removeObjectForKey:key];
- Changed_ = true;
- } broken = nil;
- /* }}} */
-
- _root(CydiaWriteSources());
-
- _trace();
- mkdir("/var/mobile/Library/Cydia", 0755);
- MetaFile_.Open("/var/mobile/Library/Cydia/metadata.cb0");
- _trace();
-
- if (Packages_ != nil) {
- bool fail(false);
- CFDictionaryApplyFunction((CFDictionaryRef) Packages_, &PackageImport, &fail);
- _trace();
+ broken = nil;
- if (!fail) {
- [Metadata_ removeObjectForKey:@"Packages"];
- Packages_ = nil;
- Changed_ = true;
- }
- }
+ SaveConfig(nil);
+ system("/usr/libexec/cydia/cydo /bin/rm -f /var/lib/cydia/metadata.plist");
+ /* }}} */
Finishes_ = [NSArray arrayWithObjects:@"return", @"reopen", @"restart", @"reload", @"reboot", nil];
-#define MobileSubstrate_(name) \
- if (substrate && access("/Library/MobileSubstrate/DynamicLibraries/" #name ".dylib", F_OK) == 0) { \
- void *handle(dlopen("/Library/MobileSubstrate/DynamicLibraries/" #name ".dylib", RTLD_LAZY | RTLD_GLOBAL)); \
- if (handle == NULL) \
- NSLog(@"%s", dlerror()); \
- }
-
- MobileSubstrate_(Activator)
- MobileSubstrate_(libstatusbar)
- MobileSubstrate_(SimulatedKeyEvents)
- MobileSubstrate_(WinterBoard)
-
- /*if (substrate && access("/Library/MobileSubstrate/MobileSubstrate.dylib", F_OK) == 0)
- dlopen("/Library/MobileSubstrate/MobileSubstrate.dylib", RTLD_LAZY | RTLD_GLOBAL);*/
-
if (kCFCoreFoundationVersionNumber > 1000)
- _root(system([[NSString stringWithFormat:@"/usr/libexec/cydia/setnsfpn /var/lib"] UTF8String]));
+ system("/usr/libexec/cydia/cydo /usr/libexec/cydia/setnsfpn /var/lib");
int version([[NSString stringWithContentsOfFile:@"/var/lib/cydia/firmware.ver"] intValue]);
if (access("/User", F_OK) != 0 || version != 6) {
_trace();
- _root(system("/usr/libexec/cydia/firmware.sh"));
+ system("/usr/libexec/cydia/cydo /usr/libexec/cydia/firmware.sh");
_trace();
}
_assert(errno == ENOENT);
}
+ system("/usr/libexec/cydia/cydo /bin/ln -sf /var/mobile/Library/Caches/com.saurik.Cydia/sources.list /etc/apt/sources.list.d/cydia.list");
+
/* APT Initialization {{{ */
_assert(pkgInitConfig(*_config));
_assert(pkgInitSystem(*_config, _system));
- if (lang != NULL)
- _config->Set("APT::Acquire::Translation", lang);
+ _config->Set("Acquire::AllowInsecureRepositories", true);
+ _config->Set("Acquire::Check-Valid-Until", false);
+ _config->Set("Dir::Bin::Methods::store", "/Applications/Cydia.app/store");
+
+ _config->Set("pkgCacheGen::ForceEssential", "");
+
+ if (translation != NULL)
+ _config->Set("APT::Acquire::Translation", translation);
+ _config->Set("Acquire::Languages", languages);
// XXX: this timeout might be important :(
//_config->Set("Acquire::http::Timeout", 15);
+ int64_t usermem(0);
+ size = sizeof(usermem);
+ if (sysctlbyname("hw.usermem", &usermem, &size, NULL, 0) == -1)
+ usermem = 0;
_config->Set("Acquire::http::MaxParallel", usermem >= 384 * 1024 * 1024 ? 16 : 3);
- mkdir([Cache_ UTF8String], 0755);
mkdir([Cache("archives") UTF8String], 0755);
mkdir([Cache("archives/partial") UTF8String], 0755);
_config->Set("Dir::Cache", [Cache_ UTF8String]);
+ symlink("/var/lib/apt/extended_states", [Cache("extended_states") UTF8String]);
+ _config->Set("Dir::State", [Cache_ UTF8String]);
+
mkdir([Cache("lists") UTF8String], 0755);
mkdir([Cache("lists/partial") UTF8String], 0755);
mkdir([Cache("periodic") UTF8String], 0755);
_config->Set("Dir::State::Lists", [Cache("lists") UTF8String]);
+
+ std::string logs("/var/mobile/Library/Logs/Cydia");
+ mkdir(logs.c_str(), 0755);
+ _config->Set("Dir::Log", logs);
+
+ _config->Set("Dir::Bin::dpkg", "/usr/libexec/cydia/cydo");
/* }}} */
/* Color Choices {{{ */
space_ = CGColorSpaceCreateDeviceRGB();
//UIKeyboardDisableAutomaticAppearance();
/* }}} */
- _root({
- chown([Cache("ApplicationCache.db") UTF8String], 501, 501);
- chown([Cache("Cache.db") UTF8String], 501, 501);
- chown([Cache("Cache.db-shm") UTF8String], 501, 501);
- chown([Cache("Cache.db-wal") UTF8String], 501, 501);
- });
-
$SBSSetInterceptsMenuButtonForever = reinterpret_cast<void (*)(bool)>(dlsym(RTLD_DEFAULT, "SBSSetInterceptsMenuButtonForever"));
+ $SBSCopyIconImagePNGDataForDisplayIdentifier = reinterpret_cast<NSData *(*)(NSString *)>(dlsym(RTLD_DEFAULT, "SBSCopyIconImagePNGDataForDisplayIdentifier"));
const char *symbol(kCFCoreFoundationVersionNumber >= 800 ? "MGGetBoolAnswer" : "GSSystemHasCapability");
BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, symbol));