/* Cydia - iPhone UIKit Front-End for Debian APT
- * Copyright (C) 2008 Jay Freeman (saurik)
+ * Copyright (C) 2008-2009 Jay Freeman (saurik)
*/
/*
}
public:
+ _finline _H(const This_ &rhs) :
+ value_(rhs.value_ == nil ? nil : [rhs.value_ retain])
+ {
+ }
+
_finline _H(Type_ *value = NULL, bool mended = false) :
value_(value)
{
#define lprintf(args...) fprintf(stderr, args)
-#define ForRelease 0
+#define ForRelease 1
#define TraceLogging (1 && !ForRelease)
#define HistogramInsertionSort (0 && !ForRelease)
#define ProfileTimes (0 && !ForRelease)
CFStringRef cache_;
_finline void clear_() {
- if (cache_ != nil)
+ if (cache_ != NULL) {
CFRelease(cache_);
+ cache_ = NULL;
+ }
}
public:
_finline CYString() :
data_(0),
size_(0),
- cache_(nil)
+ cache_(NULL)
{
}
static const float KeyboardTime_ = 0.3f;
#define SpringBoard_ "/System/Library/LaunchDaemons/com.apple.SpringBoard.plist"
-#define SandboxTemplate_ "/usr/share/sandbox/SandboxTemplate.sb"
#define NotifyConfig_ "/etc/notify.conf"
static bool Queuing_;
return CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const uint8_t *>(value), strlen(value), kCFStringEncodingUTF8, NO, kCFAllocatorNull);
}
+const char *StripVersion_(const char *version) {
+ const char *colon(strchr(version, ':'));
+ if (colon != NULL)
+ version = colon + 1;
+ return version;
+}
+
CFStringRef StripVersion(const char *version) {
const char *colon(strchr(version, ':'));
if (colon != NULL)
version = colon + 1;
+ return CFStringCreateWithBytes(kCFAllocatorDefault, reinterpret_cast<const uint8_t *>(version), strlen(version), kCFStringEncodingUTF8, NO);
+ // XXX: performance
return CFCString(version);
}
- (void) upgrade;
- (void) update;
-- (void) updateWithStatus:(Status &)status;
+- (NSString *) updateWithStatus:(Status &)status;
- (void) setDelegate:(id)delegate;
- (Source *) getSource:(pkgCache::PkgFileIterator)file;
/* Source Class {{{ */
@interface Source : NSObject {
+ CYString depiction_;
CYString description_;
CYString label_;
CYString origin_;
- (NSComparisonResult) compareByNameAndType:(Source *)source;
+- (NSString *) depictionForPackage:(NSString *)package;
- (NSString *) supportForPackage:(NSString *)package;
- (NSDictionary *) record;
description_.clear();
label_.clear();
origin_.clear();
+ depiction_.clear();
support_.clear();
version_.clear();
defaultIcon_.clear();
debReleaseIndex *dindex(dynamic_cast<debReleaseIndex *>(index));
if (dindex != NULL) {
- FileFd fd(dindex->MetaIndexFile("Release"), FileFd::ReadOnly);
- pkgTagFile tags(&fd);
+ FileFd fd;
+ if (!fd.Open(dindex->MetaIndexFile("Release"), FileFd::ReadOnly))
+ _error->Discard();
+ else {
+ pkgTagFile tags(&fd);
- pkgTagSection section;
- tags.Step(section);
+ pkgTagSection section;
+ tags.Step(section);
- struct {
- const char *name_;
- CYString *value_;
- } names[] = {
- {"default-icon", &defaultIcon_},
- {"description", &description_},
- {"label", &label_},
- {"origin", &origin_},
- {"support", &support_},
- {"version", &version_},
- };
-
- for (size_t i(0); i != sizeof(names) / sizeof(names[0]); ++i) {
- const char *start, *end;
+ struct {
+ const char *name_;
+ CYString *value_;
+ } names[] = {
+ {"default-icon", &defaultIcon_},
+ {"depiction", &depiction_},
+ {"description", &description_},
+ {"label", &label_},
+ {"origin", &origin_},
+ {"support", &support_},
+ {"version", &version_},
+ };
+
+ for (size_t i(0); i != sizeof(names) / sizeof(names[0]); ++i) {
+ const char *start, *end;
- if (section.Find(names[i].name_, start, end)) {
- CYString &value(*names[i].value_);
- value.set(pool, start, end - start);
+ if (section.Find(names[i].name_, start, end)) {
+ CYString &value(*names[i].value_);
+ value.set(pool, start, end - start);
+ }
}
}
}
return [lhs compare:rhs options:LaxCompareOptions_];
}
+- (NSString *) depictionForPackage:(NSString *)package {
+ return depiction_.empty() ? nil : [depiction_ stringByReplacingOccurrencesOfString:@"*" withString:package];
+}
+
- (NSString *) supportForPackage:(NSString *)package {
return support_.empty() ? nil : [support_ stringByReplacingOccurrencesOfString:@"*" withString:package];
}
bool visible_;
NSString *latest_;
- NSString *installed_;
+ CYString installed_;
CYString id_;
CYString name_;
- (NSString *) latest;
- (NSString *) installed;
+- (BOOL) uninstalled;
- (BOOL) valid;
- (BOOL) upgradableAndEssential:(BOOL)essential;
if (latest_ != nil)
[latest_ release];
- if (installed_ != nil)
- [installed_ release];
if (sponsor$_ != nil)
[sponsor$_ release];
_profile(Package$initWithVersion$Versions)
current = iterator_.CurrentVer();
if (!current.end())
- installed_ = (NSString *) StripVersion(current.VerStr());
+ installed_.set(pool_, StripVersion_(current.VerStr()));
if (!version_.end())
file_ = version_.FileList();
_end
}
+ visible_ = true;
+
_profile(Package$initWithVersion$Tags)
pkgCache::TagIterator tag(iterator_.TagList());
if (!tag.end()) {
do {
const char *name(tag.Name());
[tags_ addObject:(NSString *)CFCString(name)];
- if (role_ == nil && strncmp(name, "role::", 6) == 0)
+ if (role_ == nil && strncmp(name, "role::", 6) == 0 /*&& strcmp(name, "role::leaper") != 0*/)
role_ = (NSString *) CFCString(name + 6);
+ if (visible_ && strncmp(name, "require::", 9) == 0 && (
+ true
+ ))
+ visible_ = false;
++tag;
} while (!tag.end());
}
if (version == nil) {
[metadata_ setObject:latest_ forKey:@"LastVersion"];
changed = true;
- } else if (![version isEqualToString:latest_]) {
+ } else {
+ if (![version isEqualToString:latest_]) {
[metadata_ setObject:latest_ forKey:@"LastVersion"];
lastSeen_ = now_;
[metadata_ setObject:lastSeen_ forKey:@"LastSeen"];
changed = true;
- }
+ } }
}
metadata_ = [metadata_ retain];
_end
essential_ = ((iterator_->Flags & pkgCache::Flag::Essential) == 0 ? NO : YES) || [self hasTag:@"cydia::essential"];
- visible_ = [self hasSupportingRole] && [self unfiltered];
+ visible_ = visible_ && [self hasSupportingRole] && [self unfiltered];
} _end } return self;
}
}
- (NSString *) longSection {
- return LocalizeSection(section_);
+ return LocalizeSection([self section]);
}
- (NSString *) shortSection {
return installed_;
}
+- (BOOL) uninstalled {
+ return installed_.empty();
+}
+
- (BOOL) valid {
return !version_.end();
}
}
- (NSString *) depiction {
- return depiction_;
+ return !depiction_.empty() ? depiction_ : [[self source] depictionForPackage:id_];
}
- (Address *) sponsor {
}
- (bool) isInstalledAndVisible:(NSNumber *)number {
- return (![number boolValue] || [self visible]) && [self installed] != nil;
+ return (![number boolValue] || [self visible]) && ![self uninstalled];
}
- (bool) isVisiblyUninstalledInSection:(NSString *)name {
return
[self visible] &&
- [self installed] == nil && (
+ [self uninstalled] && (
name == nil ||
section == nil && [name length] == 0 ||
[name isEqualToString:section]
for (pkgAcquire::ItemIterator item = fetcher_->ItemsBegin(); item != fetcher_->ItemsEnd(); item++) {
if ((*item)->Status == pkgAcquire::Item::StatDone && (*item)->Complete)
continue;
+ if ((*item)->Status == pkgAcquire::Item::StatIdle)
+ continue;
std::string uri = (*item)->DescURI();
std::string error = (*item)->ErrorText;
[self updateWithStatus:status_];
}
-- (void) updateWithStatus:(Status &)status {
+- (NSString *) updateWithStatus:(Status &)status {
pkgSourceList list;
_assert(list.ReadMainList());
FileFd lock;
lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
- _assert(!_error->PendingError());
+
+ if (_error->PendingError()) {
+ std::string error;
+ if (!_error->PopMessage(error))
+ _assert(false);
+ _error->Discard();
+ return [NSString stringWithUTF8String:error.c_str()];
+ }
pkgAcquire fetcher(&status);
_assert(list.GetIndexes(&fetcher));
[Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"];
Changed_ = true;
}
+
+ return nil;
}
- (void) setDelegate:(id)delegate {
}
- (Source *) getSource:(pkgCache::PkgFileIterator)file {
- return sources_[file->ID];
+ SourceMap::const_iterator i(sources_.find(file->ID));
+ return i == sources_.end() ? nil : i->second;
}
@end
[transition_ transition:6 toView:view_];
}
-- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
- NSString *context([sheet context]);
-
- if ([context isEqualToString:@"error"])
- [sheet dismiss];
- else if ([context isEqualToString:@"conffile"]) {
- FILE *input = [database_ input];
-
- switch (button) {
- case 1:
- fprintf(input, "N\n");
- fflush(input);
- break;
- case 2:
- fprintf(input, "Y\n");
- fflush(input);
- break;
- default:
- _assert(false);
- }
-
- [sheet dismiss];
- }
-}
-
-- (void) closeButtonPushed {
- running_ = NO;
-
- switch (Finish_) {
- case 0:
- [self resetView];
- break;
-
- case 1:
- [delegate_ suspendWithAnimation:YES];
- break;
+- (void) _checkError {
+ if (_error->PendingError()) {
+ std::string error;
+ if (!_error->PopMessage(error))
+ _assert(false);
- case 2:
- system("launchctl stop com.apple.SpringBoard");
- break;
+ UIActionSheet *sheet = [[[UIActionSheet alloc]
+ initWithTitle:CYLocalize("ERROR")
+ buttons:[NSArray arrayWithObjects:CYLocalize("OKAY"), nil]
+ defaultButtonIndex:0
+ delegate:self
+ context:@"_error"
+ ] autorelease];
- case 3:
- system("launchctl unload "SpringBoard_"; launchctl load "SpringBoard_);
- break;
+ [sheet setBodyText:[NSString stringWithUTF8String:error.c_str()]];
+ [sheet popupAlertAnimated:YES];
- case 4:
- system("reboot");
- break;
+ return;
}
-}
-
-- (void) _retachThread {
- UINavigationItem *item = [navbar_ topItem];
- [item setTitle:CYLocalize("COMPLETE")];
-
- [overlay_ addSubview:close_];
- [progress_ removeFromSuperview];
- [status_ removeFromSuperview];
[delegate_ progressViewIsComplete:self];
if (Finish_ < 4) {
- FileFd file(SandboxTemplate_, FileFd::ReadOnly);
- MMap mmap(file, MMap::ReadOnly);
- SHA1Summation sha1;
- sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
- if (!(sandplate_ == sha1.Result()))
- Finish_ = 4;
- }
-
- if (Finish_ < 4) {
- FileFd file(NotifyConfig_, FileFd::ReadOnly);
- MMap mmap(file, MMap::ReadOnly);
- SHA1Summation sha1;
- sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
- if (!(notifyconf_ == sha1.Result()))
- Finish_ = 4;
+ FileFd file;
+ if (!file.Open(NotifyConfig_, FileFd::ReadOnly))
+ _error->Discard();
+ else {
+ MMap mmap(file, MMap::ReadOnly);
+ SHA1Summation sha1;
+ sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
+ if (!(notifyconf_ == sha1.Result()))
+ Finish_ = 4;
+ }
}
if (Finish_ < 3) {
- FileFd file(SpringBoard_, FileFd::ReadOnly);
- MMap mmap(file, MMap::ReadOnly);
- SHA1Summation sha1;
- sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
- if (!(springlist_ == sha1.Result()))
- Finish_ = 3;
+ FileFd file;
+ if (!file.Open(SpringBoard_, FileFd::ReadOnly))
+ _error->Discard();
+ else {
+ MMap mmap(file, MMap::ReadOnly);
+ SHA1Summation sha1;
+ sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
+ if (!(springlist_ == sha1.Result()))
+ Finish_ = 3;
+ }
}
switch (Finish_) {
[delegate_ setStatusBarShowsProgress:NO];
}
+- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
+ NSString *context([sheet context]);
+
+ if ([context isEqualToString:@"error"])
+ [sheet dismiss];
+ else if ([context isEqualToString:@"_error"]) {
+ [sheet dismiss];
+ [self _checkError];
+ } else if ([context isEqualToString:@"conffile"]) {
+ FILE *input = [database_ input];
+
+ switch (button) {
+ case 1:
+ fprintf(input, "N\n");
+ fflush(input);
+ break;
+ case 2:
+ fprintf(input, "Y\n");
+ fflush(input);
+ break;
+ default:
+ _assert(false);
+ }
+
+ [sheet dismiss];
+ }
+}
+
+- (void) closeButtonPushed {
+ running_ = NO;
+
+ switch (Finish_) {
+ case 0:
+ [self resetView];
+ break;
+
+ case 1:
+ [delegate_ suspendWithAnimation:YES];
+ break;
+
+ case 2:
+ system("launchctl stop com.apple.SpringBoard");
+ break;
+
+ case 3:
+ system("launchctl unload "SpringBoard_"; launchctl load "SpringBoard_);
+ break;
+
+ case 4:
+ system("reboot");
+ break;
+ }
+}
+
+- (void) _retachThread {
+ UINavigationItem *item = [navbar_ topItem];
+ [item setTitle:CYLocalize("COMPLETE")];
+
+ [overlay_ addSubview:close_];
+ [progress_ removeFromSuperview];
+ [status_ removeFromSuperview];
+
+ [self _checkError];
+}
+
- (void) _detachNewThreadData:(ProgressData *)data { _pooled
[[data target] performSelector:[data selector] withObject:[data object]];
[data release];
running_ = YES;
{
- FileFd file(SandboxTemplate_, FileFd::ReadOnly);
- MMap mmap(file, MMap::ReadOnly);
- SHA1Summation sha1;
- sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
- sandplate_ = sha1.Result();
- }
-
- {
- FileFd file(NotifyConfig_, FileFd::ReadOnly);
- MMap mmap(file, MMap::ReadOnly);
- SHA1Summation sha1;
- sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
- notifyconf_ = sha1.Result();
+ FileFd file;
+ if (!file.Open(NotifyConfig_, FileFd::ReadOnly))
+ _error->Discard();
+ else {
+ MMap mmap(file, MMap::ReadOnly);
+ SHA1Summation sha1;
+ sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
+ notifyconf_ = sha1.Result();
+ }
}
{
- FileFd file(SpringBoard_, FileFd::ReadOnly);
- MMap mmap(file, MMap::ReadOnly);
- SHA1Summation sha1;
- sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
- springlist_ = sha1.Result();
+ FileFd file;
+ if (!file.Open(SpringBoard_, FileFd::ReadOnly))
+ _error->Discard();
+ else {
+ MMap mmap(file, MMap::ReadOnly);
+ SHA1Summation sha1;
+ sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
+ springlist_ = sha1.Result();
+ }
}
[transition_ transition:6 toView:overlay_];
section_ = [section localized];
if (section_ != nil)
section_ = [section_ retain];
- name_ = [(section_ == nil ? CYLocalize("NO_SECTION") : section_) retain];
+ name_ = [(section_ == nil || [section_ length] == 0 ? CYLocalize("NO_SECTION") : section_) retain];
count_ = [[NSString stringWithFormat:@"%d", [section count]] retain];
if (editing_)
if ([package_ source] == nil);
else if ([package_ upgradableAndEssential:NO])
[buttons_ addObject:CYLocalize("UPGRADE")];
- else if ([package_ installed] == nil)
+ else if ([package_ uninstalled])
[buttons_ addObject:CYLocalize("INSTALL")];
else
[buttons_ addObject:CYLocalize("REINSTALL")];
- if ([package_ installed] != nil)
+ if (![package_ uninstalled])
[buttons_ addObject:CYLocalize("REMOVE")];
if (special_ != NULL) {
];
}
-- (void) _update_ {
+- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
+ NSString *context([sheet context]);
+
+ if ([context isEqualToString:@"refresh"])
+ [sheet dismiss];
+}
+
+- (void) _update_:(NSString *)error {
updating_ = false;
[indicator_ stopAnimation];
[UIView commitAnimations];
- [delegate_ performSelector:@selector(reloadData) withObject:nil afterDelay:0];
+ if (error == nil)
+ [delegate_ performSelector:@selector(reloadData) withObject:nil afterDelay:0];
+ else {
+ UIActionSheet *sheet = [[[UIActionSheet alloc]
+ initWithTitle:[NSString stringWithFormat:CYLocalize("COLON_DELIMITED"), CYLocalize("ERROR"), CYLocalize("REFRESH")]
+ buttons:[NSArray arrayWithObjects:
+ CYLocalize("OK"),
+ nil]
+ defaultButtonIndex:0
+ delegate:self
+ context:@"refresh"
+ ] autorelease];
+
+ [sheet setBodyText:error];
+ [sheet popupAlertAnimated:YES];
+
+ [self reloadButtons];
+ }
}
- (id) initWithFrame:(CGRect)frame database:(Database *)database {
Status status;
status.setDelegate(self);
- [database_ updateWithStatus:status];
+ NSString *error([database_ updateWithStatus:status]);
[self
- performSelectorOnMainThread:@selector(_update_)
- withObject:nil
+ performSelectorOnMainThread:@selector(_update_:)
+ withObject:error
waitUntilDone:NO
];
}
return !updating_;
}
-- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
- [sheet dismiss];
-}
-
- (void) _setProgressTitle:(NSString *)title {
[prompt_ setText:title];
}
[*section addToCount];
_profile(SectionsView$reloadData$Filter)
- if (![package valid] || [package installed] != nil || ![package visible])
+ if (![package valid] || ![package uninstalled] || ![package visible])
continue;
_end
[section addToCount];
_profile(SectionsView$reloadData$Filter)
- if (![package valid] || [package installed] != nil || ![package visible])
+ if (![package valid] || ![package uninstalled] || ![package visible])
continue;
_end
_trace();
for (Package *package in packages)
if (
- [package installed] == nil && [package valid] && [package visible] ||
+ [package uninstalled] && [package valid] && [package visible] ||
[package upgradableAndEssential:YES]
)
[packages_ addObject:package];
Changed_ = true;
+ [sheet dismiss];
+
if (reset)
[self updateData];
else
[self finish];
-
- [sheet dismiss];
} else if ([context isEqualToString:@"upgrade"]) {
switch (button) {
case 1:
if (
readlink("/Applications", NULL, 0) == -1 && errno == EINVAL ||
readlink("/Library/Ringtones", NULL, 0) == -1 && errno == EINVAL ||
- readlink("/Library/Wallpaper", NULL, 0) == -1 && errno == EINVAL ||
+ readlink("/Library/Wallpaper", NULL, 0) == -1 && errno == EINVAL /*||
+ readlink("/usr/bin", NULL, 0) == -1 && errno == EINVAL*/ ||
readlink("/usr/include", NULL, 0) == -1 && errno == EINVAL ||
+ readlink("/usr/lib/pam", NULL, 0) == -1 && errno == EINVAL ||
readlink("/usr/libexec", NULL, 0) == -1 && errno == EINVAL ||
readlink("/usr/share", NULL, 0) == -1 && errno == EINVAL /*||
readlink("/var/lib", NULL, 0) == -1 && errno == EINVAL*/