#endif
/* }}} */
+typedef enum {
+ kUIControlEventMouseDown = 1 << 0,
+ kUIControlEventMouseMovedInside = 1 << 2, // mouse moved inside control target
+ kUIControlEventMouseMovedOutside = 1 << 3, // mouse moved outside control target
+ kUIControlEventMouseUpInside = 1 << 6, // mouse up inside control target
+ kUIControlEventMouseUpOutside = 1 << 7, // mouse up outside control target
+ kUIControlAllEvents = (kUIControlEventMouseDown | kUIControlEventMouseMovedInside | kUIControlEventMouseMovedOutside | kUIControlEventMouseUpInside | kUIControlEventMouseUpOutside)
+} UIControlEventMasks;
+
@interface NSString (UIKit)
- (NSString *) stringByAddingPercentEscapes;
- (NSString *) stringByReplacingCharacter:(unsigned short)arg0 withCharacter:(unsigned short)arg1;
static const int PulseInterval_ = 50000;
static const int ButtonBarHeight_ = 48;
static const float KeyboardTime_ = 0.4f;
+static const char * const SpringBoard_ = "/System/Library/LaunchDaemons/com.apple.SpringBoard.plist";
#ifndef Cydia_
#define Cydia_ ""
return [NSString stringWithFormat:@"%.1f%s", size, powers_[power]];
}
+NSString *StripVersion(NSString *version) {
+ NSRange colon = [version rangeOfString:@":"];
+ if (colon.location != NSNotFound)
+ version = [version substringFromIndex:(colon.location + 1)];
+ return version;
+}
+
static const float TextViewOffset_ = 22;
UITextView *GetTextView(NSString *value, float left, bool html) {
@class Package;
@class Source;
+@interface NSObject (ProgressDelegate)
+@end
+
+@implementation NSObject(ProgressDelegate)
+
+- (void) _setProgressError:(NSArray *)args {
+ [self performSelector:@selector(setProgressError:forPackage:)
+ withObject:[args objectAtIndex:0]
+ withObject:([args count] == 1 ? nil : [args objectAtIndex:1])
+ ];
+}
+
+@end
+
@protocol ProgressDelegate
-- (void) setProgressError:(NSString *)error;
+- (void) setProgressError:(NSString *)error forPackage:(NSString *)id;
- (void) setProgressTitle:(NSString *)title;
- (void) setProgressPercent:(float)percent;
- (void) addProgressOutput:(NSString *)output;
public pkgAcquireStatus
{
private:
- _transient id<ProgressDelegate> delegate_;
+ _transient NSObject<ProgressDelegate> *delegate_;
public:
Status() :
)
return;
- [delegate_ setProgressError:[NSString stringWithUTF8String:item.Owner->ErrorText.c_str()]];
+ [delegate_ performSelectorOnMainThread:@selector(_setProgressError:)
+ withObject:[NSArray arrayWithObjects:[NSString stringWithUTF8String:item.Owner->ErrorText.c_str()], nil]
+ waitUntilDone:YES
+ ];
}
virtual bool Pulse(pkgAcquire *Owner) {
NSMutableDictionary *sources_;
NSMutableArray *packages_;
- _transient id<ConfigurationDelegate, ProgressDelegate> delegate_;
+ _transient NSObject<ConfigurationDelegate, ProgressDelegate> *delegate_;
Status status_;
Progress progress_;
- (NSString *) installed;
- (BOOL) valid;
-- (BOOL) upgradable;
+- (BOOL) upgradableAndEssential:(BOOL)essential;
- (BOOL) essential;
- (BOOL) broken;
database_ = database;
version_ = [database_ policy]->GetCandidateVer(iterator_);
- latest_ = version_.end() ? nil : [[NSString stringWithUTF8String:version_.VerStr()] retain];
+ latest_ = version_.end() ? nil : [StripVersion([NSString stringWithUTF8String:version_.VerStr()]) retain];
if (!version_.end())
file_ = version_.FileList();
}
pkgCache::VerIterator current = iterator_.CurrentVer();
- installed_ = current.end() ? nil : [[NSString stringWithUTF8String:current.VerStr()] retain];
+ installed_ = current.end() ? nil : [StripVersion([NSString stringWithUTF8String:current.VerStr()]) retain];
id_ = [[[NSString stringWithUTF8String:iterator_.Name()] lowercaseString] retain];
return !version_.end();
}
-- (BOOL) upgradable {
+- (BOOL) upgradableAndEssential:(BOOL)essential {
pkgCache::VerIterator current = iterator_.CurrentVer();
if (current.end())
- return [self essential];
+ return essential && [self essential];
else {
pkgCache::VerIterator candidate = [database_ policy]->GetCandidateVer(iterator_);
return !candidate.end() && candidate != current;
}
- (NSComparisonResult) compareForChanges:(Package *)package {
- BOOL lhs = [self upgradable];
- BOOL rhs = [package upgradable];
+ BOOL lhs = [self upgradableAndEssential:YES];
+ BOOL rhs = [package upgradableAndEssential:YES];
if (lhs != rhs)
return lhs ? NSOrderedAscending : NSOrderedDescending;
NSString *string = [NSString stringWithUTF8String:(data + 8)];
[delegate_ setProgressTitle:string];
} else if (pmstatus_r(data, size)) {
+ std::string type([pmstatus_r[1] UTF8String]);
+ NSString *id = pmstatus_r[2];
+
float percent([pmstatus_r[3] floatValue]);
[delegate_ setProgressPercent:(percent / 100)];
NSString *string = pmstatus_r[4];
- std::string type([pmstatus_r[1] UTF8String]);
if (type == "pmerror")
- [delegate_ setProgressError:string];
+ [delegate_ performSelectorOnMainThread:@selector(_setProgressError:)
+ withObject:[NSArray arrayWithObjects:string, id, nil]
+ waitUntilDone:YES
+ ];
else if (type == "pmstatus")
[delegate_ setProgressTitle:string];
else if (type == "pmconffile")
if ([context isEqualToString:@"remove"])
switch (button) {
case 1:
- [delegate_ confirm];
+ [self cancel];
break;
case 2:
- [self cancel];
+ [delegate_ confirm];
break;
default:
_assert(false);
essential_ = nil;
else if (Advanced_ || true) {
essential_ = [[UIAlertSheet alloc]
- initWithTitle:@"Remove Essential?"
+ initWithTitle:@"Removing Essentials"
buttons:[NSArray arrayWithObjects:
- @"Yes (Force Removal)",
- @"No (Safe, Recommended)",
+ @"Cancel Operation (Safe)",
+ @"Force Removal (Unsafe)",
nil]
- defaultButtonIndex:1
+ defaultButtonIndex:0
delegate:self
context:@"remove"
];
[essential_ setDestructiveButton:[[essential_ buttons] objectAtIndex:0]];
- [essential_ setBodyText:@"This operation requires the removal of one or more packages that are required for the continued operation of either Cydia or the iPhoneOS. If you continue you will almost certainly break something past Cydia's ability to fix it. Are you absolutely certain you wish to continue?"];
+ [essential_ setBodyText:@"This operation involves the removal of one or more packages that are required for the continued operation of either Cydia or iPhoneOS. If you continue, you may not be able to use Cydia to repair any damage."];
} else {
essential_ = [[UIAlertSheet alloc]
initWithTitle:@"Unable to Comply"
context:@"unable"
];
- [essential_ setBodyText:@"This operation requires the removal of one or more packages that are required for the continued operation of either Cydia or the iPhoneOS. In order to continue and force this operation you will need to be activate the Advanced mode undder to continue and force this operation you will need to be activate the Advanced mode under Settings."];
+ [essential_ setBodyText:@"This operation requires the removal of one or more packages that are required for the continued operation of either Cydia or iPhoneOS. In order to continue and force this operation you will need to be activate the Advanced mode under to continue and force this operation you will need to be activate the Advanced mode under Settings."];
}
AddTextView(fields_, installing, @"Installing");
UIProgressBar *progress_;
UITextView *output_;
UITextLabel *status_;
+ UIPushButton *close_;
id delegate_;
}
[progress_ release];
[output_ release];
[status_ release];
+ [close_ release];
[super dealloc];
}
}, prgsize};
progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
- [overlay_ addSubview:progress_];
+ [progress_ setStyle:0];
status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(
10,
[output_ setAllowsRubberBanding:YES];
[overlay_ addSubview:output_];
- [overlay_ addSubview:status_];
- [progress_ setStyle:0];
+ close_ = [[UIPushButton alloc] initWithFrame:CGRectMake(
+ 10,
+ bounds.size.height - prgsize.height - 50,
+ bounds.size.width - 20,
+ 26 + prgsize.height
+ )];
+
+ [close_ setAutosizesToFit:NO];
+ [close_ setDrawsShadow:YES];
+ [close_ setStretchBackground:YES];
+ [close_ setTitle:@"Close Window"];
+ [close_ setEnabled:YES];
+
+ GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
+ [close_ setTitleFont:bold];
+ CFRelease(bold);
+
+ [close_ addTarget:self action:@selector(closeButtonPushed) forEvents:kUIControlEventMouseUpInside];
+ [close_ setBackground:[UIImage applicationImageNamed:@"green-up.png"] forState:0];
+ [close_ setBackground:[UIImage applicationImageNamed:@"green-dn.png"] forState:1];
} return self;
}
[sheet dismiss];
}
-- (void) _retachThread {
+- (void) closeButtonPushed {
[delegate_ progressViewIsComplete:self];
[self resetView];
}
+- (void) _retachThread {
+ [overlay_ addSubview:close_];
+ [progress_ removeFromSuperview];
+ [status_ removeFromSuperview];
+}
+
- (void) _detachNewThreadData:(ProgressData *)data {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[output_ setText:@""];
[progress_ setProgress:0];
+ [close_ removeFromSuperview];
+ [overlay_ addSubview:progress_];
+ [overlay_ addSubview:status_];
+
[transition_ transition:6 toView:overlay_];
[NSThread
];
}
-- (void) setProgressError:(NSString *)error {
- [self
- performSelectorOnMainThread:@selector(_setProgressError:)
- withObject:error
- waitUntilDone:YES
- ];
+- (void) setProgressError:(NSString *)error forPackage:(NSString *)id {
+ Package *package = id == nil ? nil : [database_ packageWithName:id];
+
+ UIAlertSheet *sheet = [[[UIAlertSheet alloc]
+ initWithTitle:(package == nil ? @"Source Error" : [package name])
+ buttons:[NSArray arrayWithObjects:@"Okay", nil]
+ defaultButtonIndex:0
+ delegate:self
+ context:@"error"
+ ] autorelease];
+
+ [sheet setBodyText:error];
+ [sheet popupAlertAnimated:YES];
}
- (void) setProgressTitle:(NSString *)title {
[sheet popupAlertAnimated:YES];
}
-- (void) _setProgressError:(NSString *)error {
- UIAlertSheet *sheet = [[[UIAlertSheet alloc]
- initWithTitle:@"Package Error"
- buttons:[NSArray arrayWithObjects:@"Okay", nil]
- defaultButtonIndex:0
- delegate:self
- context:@"error"
- ] autorelease];
-
- [sheet setBodyText:error];
- [sheet popupAlertAnimated:YES];
-}
-
- (void) _setProgressTitle:(NSString *)title {
[status_ setText:[title stringByAppendingString:@"..."]];
}
UITextLabel *description_;
UITextLabel *source_;
//UIImageView *trusted_;
+#ifdef USE_BADGES
UIImageView *badge_;
UITextLabel *status_;
+#endif
+ BOOL setup_;
}
- (PackageCell *) init;
[name_ release];
[description_ release];
[source_ release];
+#ifdef USE_BADGES
[badge_ release];
[status_ release];
+#endif
//[trusted_ release];
[super dealloc];
}
/*trusted_ = [[UIImageView alloc] initWithFrame:CGRectMake(30, 30, 16, 16)];
[trusted_ setImage:[UIImage applicationImageNamed:@"trusted.png"]];*/
+#ifdef USE_BADGES
badge_ = [[UIImageView alloc] initWithFrame:CGRectMake(17, 70, 16, 16)];
status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(48, 68, 280, 20)];
[status_ setBackgroundColor:Clear_];
[status_ setFont:small];
+#endif
+
+ /*[icon_ setImage:[UIImage applicationImageNamed:@"unknown.png"]];
+ [icon_ zoomToScale:0.5];
+ [icon_ setFrame:CGRectMake(10, 10, 30, 30)];*/
[self addSubview:icon_];
[self addSubview:name_];
[self addSubview:description_];
[self addSubview:source_];
- [self addSubview:badge_];
- [self addSubview:status_];
CFRelease(small);
CFRelease(large);
}
- (void) setPackage:(Package *)package {
+ /*if (setup_)
+ return;
+ else
+ setup_ = YES;*/
+
Source *source = [package source];
UIImage *image = nil;
image = [UIImage applicationImageNamed:@"unknown.png"];
[icon_ setImage:image];
- if (image != nil) {
+ /*if (image != nil) {
CGSize size = [image size];
float scale = 30 / std::max(size.width, size.height);
[icon_ zoomToScale:scale];
- }
+ }*/
[icon_ setFrame:CGRectMake(10, 10, 30, 30)];
[source_ setText:from];
+#ifdef USE_BADGES
+ [badge_ removeFromSuperview];
+ [status_ removeFromSuperview];
+
if (NSString *mode = [package mode]) {
[badge_ setImage:[UIImage applicationImageNamed:
[mode isEqualToString:@"Remove"] || [mode isEqualToString:@"Purge"] ? @"removing.png" : @"installing.png"
} else {
[badge_ setImage:nil];
[status_ setText:nil];
+ goto done;
}
+
+ [self addSubview:badge_];
+ [self addSubview:status_];
+ done:;
+#endif
}
- (void) _setSelected:(float)fraction {
}
+ (int) heightForPackage:(Package *)package {
+#ifdef USE_BADGES
if ([package hasMode] || [package half])
return 96;
else
+#endif
return 73;
}
++number;
if ([package_ website] != nil)
++number;
- if ([[package_ source] trusted])
- ++number;
return number;
} else if ([package_ installed] != nil && group-- == 0)
return 2;
++number;
if ([package_ relationships] != nil)
++number;
+ if ([[package_ source] trusted])
+ ++number;
return number;
} else if ([package_ source] != nil && group-- == 0) {
Source *source = [package_ source];
[cell setShowSelection:NO];
if (group-- == 0) {
- if (row-- == 0) {
+ if (false) {
+ } else if (row-- == 0) {
[cell setTitle:[package_ name]];
[cell setValue:[package_ latest]];
} else if ([package_ author] != nil && row-- == 0) {
[cell setTitle:@"More Information"];
[cell setShowDisclosure:YES];
[cell setShowSelection:YES];
- } else if ([[package_ source] trusted] && row-- == 0) {
- [cell setIcon:[UIImage applicationImageNamed:@"trusted.png"]];
- [cell setValue:@"This package has been signed."];
} else _assert(false);
} else if ([package_ installed] != nil && group-- == 0) {
- if (row-- == 0) {
+ if (false) {
+ } else if (row-- == 0) {
[cell setTitle:@"Version"];
NSString *installed([package_ installed]);
[cell setValue:(installed == nil ? @"n/a" : installed)];
[cell setShowSelection:YES];
} else _assert(false);
} else if (group-- == 0) {
- if (row-- == 0) {
+ if (false) {
+ } else if (row-- == 0) {
[cell setTitle:@"Identifier"];
[cell setValue:[package_ id]];
} else if (row-- == 0) {
[cell setTitle:@"Package Relationships"];
[cell setShowDisclosure:YES];
[cell setShowSelection:YES];
+ } else if ([[package_ source] trusted] && row-- == 0) {
+ [cell setIcon:[UIImage applicationImageNamed:@"trusted.png"]];
+ [cell setValue:@"This package has been signed."];
} else _assert(false);
} else if ([package_ source] != nil && group-- == 0) {
Source *source = [package_ source];
NSString *description = [source description];
- if (row-- == 0) {
+ if (false) {
+ } else if (row-- == 0) {
NSString *label = [source label];
if (label == nil)
label = [source uri];
return YES;
}
-// XXX: this is now unmaintainable
- (void) tableRowSelected:(NSNotification *)notification {
int row = [table_ selectedRow];
- NSString *website = [package_ website];
- Address *author = [package_ author];
- BOOL trusted = [[package_ source] trusted];
- NSString *installed = [package_ installed];
- Address *maintainer = [package_ maintainer];
-
- if (maintainer != nil && row == 7
- + (author == nil ? 0 : 1)
- + (website == nil ? 0 : 1)
- + (trusted ? 1 : 0)
- + (installed == nil ? 0 : 3)
- ) {
- [delegate_ openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@",
- [maintainer email],
- [[NSString stringWithFormat:@"regarding apt package \"%@\"", [package_ name]] stringByAddingPercentEscapes]
- ]]];
- } else if (installed && row == 5
- + (author == nil ? 0 : 1)
- + (website == nil ? 0 : 1)
- + (trusted ? 1 : 0)
- ) {
- FileTable *files = [[[FileTable alloc] initWithBook:book_ database:database_] autorelease];
- [files setDelegate:delegate_];
- [files setPackage:package_];
- [book_ pushPage:files];
- } else if (author != nil && row == 2) {
- [delegate_ openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@",
- [author email],
- [[NSString stringWithFormat:@"regarding apt package \"%@\"", [package_ name]] stringByAddingPercentEscapes]
- ]]];
- } else if (website != nil && row == (author == nil ? 3 : 4)) {
- NSURL *url = [NSURL URLWithString:website];
- BrowserView *browser = [[[BrowserView alloc] initWithBook:book_ database:database_] autorelease];
- [browser setDelegate:delegate_];
- [book_ pushPage:browser];
- [browser loadURL:url];
- }
+ if (row == INT_MAX)
+ return;
+
+ #define _else else goto _label; return; } _label:
+
+ if (true) {
+ if (row-- == 0) {
+ } else if (row-- == 0) {
+ } else if ([package_ author] != nil && row-- == 0) {
+ [delegate_ openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@",
+ [[package_ author] email],
+ [[NSString stringWithFormat:@"regarding apt package \"%@\"",
+ [package_ name]
+ ] stringByAddingPercentEscapes]
+ ]]];
+ } else if (description_ != nil && row-- == 0) {
+ } else if ([package_ website] != nil && row-- == 0) {
+ NSURL *url = [NSURL URLWithString:[package_ website]];
+ BrowserView *browser = [[[BrowserView alloc] initWithBook:book_ database:database_] autorelease];
+ [browser setDelegate:delegate_];
+ [book_ pushPage:browser];
+ [browser loadURL:url];
+ } _else if ([package_ installed] != nil) {
+ if (row-- == 0) {
+ } else if (row-- == 0) {
+ } else if (row-- == 0) {
+ FileTable *files = [[[FileTable alloc] initWithBook:book_ database:database_] autorelease];
+ [files setDelegate:delegate_];
+ [files setPackage:package_];
+ [book_ pushPage:files];
+ } _else if (true) {
+ if (row-- == 0) {
+ } else if (row-- == 0) {
+ } else if (row-- == 0) {
+ } else if ([package_ size] != 0 && row-- == 0) {
+ } else if ([package_ maintainer] != nil && row-- == 0) {
+ [delegate_ openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@",
+ [[package_ maintainer] email],
+ [[NSString stringWithFormat:@"regarding apt package \"%@\"",
+ [package_ name]
+ ] stringByAddingPercentEscapes]
+ ]]];
+ } else if ([package_ relationships] != nil && row-- == 0) {
+ } else if ([[package_ source] trusted] && row-- == 0) {
+ } _else if ([package_ source] != nil) {
+ Source *source = [package_ source];
+ NSString *description = [source description];
+
+ if (row-- == 0) {
+ } else if (row-- == 0) {
+ } else if (description != nil && ![description isEqualToString:[source label]] && row-- == 0) {
+ } else if ([source origin] != nil && row-- == 0) {
+ } _else _assert(false);
}
- (void) _clickButtonWithName:(NSString *)name {
[table_ reloadData];
if ([package_ source] == nil);
+ else if ([package_ upgradableAndEssential:NO])
+ [buttons_ addObject:@"Upgrade"];
else if ([package_ installed] == nil)
[buttons_ addObject:@"Install"];
- else if ([package_ upgradable])
- [buttons_ addObject:@"Upgrade"];
else
[buttons_ addObject:@"Reinstall"];
if ([package_ installed] != nil)
for (size_t i(0); i != [packages count]; ++i) {
Package *package([packages objectAtIndex:i]);
- if ([package installed] == nil && [package valid] || [package upgradable])
+ if ([package installed] == nil && [package valid] || [package upgradableAndEssential:NO])
[packages_ addObject:package];
}
for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
Package *package = [packages_ objectAtIndex:offset];
- if ([package upgradable]) {
+ if ([package upgradableAndEssential:YES]) {
++upgrades_;
[upgradable addToCount];
} else {
[pool release];
}
-- (void) setProgressError:(NSString *)error {
- [self
- performSelectorOnMainThread:@selector(_setProgressError:)
- withObject:error
- waitUntilDone:YES
- ];
+- (void) setProgressError:(NSString *)error forPackage:(NSString *)id {
+ [prompt_ setText:[NSString stringWithFormat:@"Error: %@", error]];
}
- (void) setProgressTitle:(NSString *)title {
[sheet dismiss];
}
-- (void) _setProgressError:(NSString *)error {
- [prompt_ setText:[NSString stringWithFormat:@"Error: %@", error]];
-}
-
- (void) _setProgressTitle:(NSString *)title {
[prompt_ setText:[title stringByAppendingString:@"..."]];
}
context:@"fixhalf"
] autorelease];
- [sheet setBodyText:@"When the shell scripts associated with packages fail, they are left in a state known as either half-configured or half-installed. These errors don't go away and instead continue to cause issues. These scripts can be deleted and the packages forcibly removed."];
+ [sheet setBodyText:@"When the shell scripts associated with packages fail, they are left in a bad state known as either half-configured or half-installed. These errors don't go away and instead continue to cause issues. These scripts can be deleted and the packages forcibly removed."];
[sheet popupAlertAnimated:YES];
} else if (!Ignored_ && [essential_ count] != 0) {
int count = [essential_ count];
context:@"upgrade"
] autorelease];
- [sheet setBodyText:@"One or more essential packages are currently out of date. If these packages are not upgraded you are likely to encounter errors."];
+ [sheet setBodyText:@"One or more essential packages are currently out of date. If these upgrades are not performed you are likely to encounter errors."];
[sheet popupAlertAnimated:YES];
}
}
Package *package = [packages objectAtIndex:i];
if ([package half])
[broken_ addObject:package];
- if ([package upgradable]) {
+ if ([package upgradableAndEssential:NO]) {
if ([package essential])
[essential_ addObject:package];
++changes;
pid_t pid = ExecFork();
if (pid == 0) {
sleep(1);
- execlp("launchctl", "launchctl", "stop", "com.apple.SpringBoard", NULL);
+ if (pid_t child = fork())
+ waitpid(child, NULL, 0);
+ else {
+ execlp("launchctl", "launchctl", "unload", SpringBoard_, NULL);
+ exit(0);
+ }
+ execlp("launchctl", "launchctl", "load", SpringBoard_, NULL);
exit(0);
}
}