├── Frameworks ├── Growl.framework │ ├── Versions │ │ ├── Current │ │ └── A │ │ │ ├── Growl │ │ │ ├── Headers │ │ │ ├── Growl.h │ │ │ ├── GrowlPluginPreferenceStrings.h │ │ │ └── GrowlDefines.h │ │ │ ├── _CodeSignature │ │ │ └── CodeResources │ │ │ └── Resources │ │ │ └── Info.plist │ ├── Growl │ ├── Headers │ └── Resources └── Sparkle.framework │ ├── Versions │ ├── Current │ └── A │ │ ├── Resources │ │ ├── fr_CA.lproj │ │ ├── fr.lproj │ │ │ ├── fr.lproj │ │ │ ├── Sparkle.strings │ │ │ ├── SUUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ └── SUUpdatePermissionPrompt.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ ├── relaunch │ │ ├── de.lproj │ │ │ ├── Sparkle.strings │ │ │ ├── SUUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ └── SUUpdatePermissionPrompt.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ ├── en.lproj │ │ │ ├── Sparkle.strings │ │ │ ├── SUUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ └── SUUpdatePermissionPrompt.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ ├── es.lproj │ │ │ ├── Sparkle.strings │ │ │ ├── SUUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ └── SUUpdatePermissionPrompt.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ ├── it.lproj │ │ │ ├── Sparkle.strings │ │ │ ├── SUUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ └── SUUpdatePermissionPrompt.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ ├── nl.lproj │ │ │ ├── Sparkle.strings │ │ │ ├── SUUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ └── SUUpdatePermissionPrompt.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ ├── ru.lproj │ │ │ ├── Sparkle.strings │ │ │ ├── SUUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ └── SUUpdatePermissionPrompt.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ ├── sv.lproj │ │ │ ├── Sparkle.strings │ │ │ ├── SUUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ └── SUUpdatePermissionPrompt.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ ├── SUStatus.nib │ │ │ ├── keyedobjects.nib │ │ │ ├── info.nib │ │ │ └── classes.nib │ │ ├── Info.plist │ │ ├── License.txt │ │ └── SUModelTranslation.plist │ │ ├── Sparkle │ │ └── Headers │ │ ├── Sparkle.h │ │ ├── SUAppcast.h │ │ ├── SUVersionComparisonProtocol.h │ │ ├── SUAppcastItem.h │ │ └── SUUpdater.h │ ├── Headers │ ├── Sparkle │ └── Resources ├── .gitmodules ├── Jenkins Menu ├── en.lproj │ ├── InfoPlist.strings │ ├── Localizable.strings │ └── Credits.rtf ├── Resources │ ├── fire.png │ ├── fire@2x.png │ ├── thumb_up.png │ ├── disconnect.png │ ├── thumb_up@2x.png │ ├── disconnect@2x.png │ ├── weather_lightning.png │ ├── weather_lightning@2x.png │ └── Growl Registration Ticket.growlRegDict ├── Jenkins Menu-Prefix.pch ├── main.m ├── NSMenuItem+Q.h ├── JMTrustedHostManager.h ├── JMKeychainManager.h ├── sparkle-pub.pem ├── JMJenkinsJob.h ├── NSMenuItem+Q.m ├── JMJenkinsJob.m ├── JMTrustedHostManager.m ├── Jenkins Menu-Info.plist ├── JMJenkinsDelegate.h ├── JMJenkins.h ├── JMLog.h ├── JMAppDelegate.h ├── JMKeychainManager.m └── JMJenkins.m ├── Jenkins MenuTests ├── en.lproj │ └── InfoPlist.strings ├── JMBaseTestCase.h ├── JMBaseTestCase.m ├── Jenkins MenuTests-Info.plist ├── JMJenkinsJobTest.m ├── Resources │ ├── unknown-xml.xml │ ├── green-xml.xml │ ├── yellow-xml.xml │ └── example-xml.xml ├── JMTrustedHostManagerTest.m ├── JMAppDelegateTest.m └── JMJenkinsTest.m ├── Jenkins Menu.iconset ├── icon_16x16.png ├── icon_32x32.png ├── icon_128x128.png ├── icon_16x16@2x.png ├── icon_256x256.png ├── icon_32x32@2x.png ├── icon_512x512.png ├── icon_128x128@2x.png ├── icon_256x256@2x.png └── icon_512x512@2x.png ├── Jenkins Menu.xcodeproj ├── xcuserdata │ ├── gileadis.xcuserdatad │ │ ├── xcdebugger │ │ │ └── Breakpoints.xcbkptlist │ │ └── xcschemes │ │ │ ├── xcschememanagement.plist │ │ │ └── Jenkins Menu.xcscheme │ └── hat.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── gileadis.xcuserdatad │ │ └── WorkspaceSettings.xcsettings └── xcshareddata │ └── xcschemes │ ├── Tests.xcscheme │ └── Jenkins Menu.xcscheme ├── Podfile ├── Jenkins Menu.xcworkspace └── contents.xcworkspacedata ├── .gitignore ├── Podfile.lock └── README.md /Frameworks/Growl.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /Frameworks/Growl.framework/Growl: -------------------------------------------------------------------------------- 1 | Versions/Current/Growl -------------------------------------------------------------------------------- /Frameworks/Growl.framework/Headers: -------------------------------------------------------------------------------- 1 | Versions/Current/Headers -------------------------------------------------------------------------------- /Frameworks/Growl.framework/Resources: -------------------------------------------------------------------------------- 1 | Versions/Current/Resources -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Headers: -------------------------------------------------------------------------------- 1 | Versions/Current/Headers -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Sparkle: -------------------------------------------------------------------------------- 1 | Versions/Current/Sparkle -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Resources: -------------------------------------------------------------------------------- 1 | Versions/Current/Resources -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "qkit"] 2 | path = qkit 3 | url = git@github.com:qvacua/qkit.git 4 | -------------------------------------------------------------------------------- /Jenkins Menu/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Jenkins MenuTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Jenkins Menu/Resources/fire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu/Resources/fire.png -------------------------------------------------------------------------------- /Jenkins Menu/Resources/fire@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu/Resources/fire@2x.png -------------------------------------------------------------------------------- /Jenkins Menu.iconset/icon_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu.iconset/icon_16x16.png -------------------------------------------------------------------------------- /Jenkins Menu.iconset/icon_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu.iconset/icon_32x32.png -------------------------------------------------------------------------------- /Jenkins Menu/Resources/thumb_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu/Resources/thumb_up.png -------------------------------------------------------------------------------- /Jenkins Menu.iconset/icon_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu.iconset/icon_128x128.png -------------------------------------------------------------------------------- /Jenkins Menu.iconset/icon_16x16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu.iconset/icon_16x16@2x.png -------------------------------------------------------------------------------- /Jenkins Menu.iconset/icon_256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu.iconset/icon_256x256.png -------------------------------------------------------------------------------- /Jenkins Menu.iconset/icon_32x32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu.iconset/icon_32x32@2x.png -------------------------------------------------------------------------------- /Jenkins Menu.iconset/icon_512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu.iconset/icon_512x512.png -------------------------------------------------------------------------------- /Jenkins Menu/Resources/disconnect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu/Resources/disconnect.png -------------------------------------------------------------------------------- /Jenkins Menu/Resources/thumb_up@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu/Resources/thumb_up@2x.png -------------------------------------------------------------------------------- /Jenkins Menu.iconset/icon_128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu.iconset/icon_128x128@2x.png -------------------------------------------------------------------------------- /Jenkins Menu.iconset/icon_256x256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu.iconset/icon_256x256@2x.png -------------------------------------------------------------------------------- /Jenkins Menu.iconset/icon_512x512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu.iconset/icon_512x512@2x.png -------------------------------------------------------------------------------- /Jenkins Menu/Resources/disconnect@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu/Resources/disconnect@2x.png -------------------------------------------------------------------------------- /Frameworks/Growl.framework/Versions/A/Growl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Growl.framework/Versions/A/Growl -------------------------------------------------------------------------------- /Jenkins Menu/Resources/weather_lightning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu/Resources/weather_lightning.png -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/fr_CA.lproj: -------------------------------------------------------------------------------- 1 | /Users/andym/Development/Build Products/Release/Sparkle.framework/Resources/fr.lproj -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/fr.lproj: -------------------------------------------------------------------------------- 1 | /Users/andym/Development/Build Products/Release/Sparkle.framework/Resources/fr.lproj -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Sparkle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Sparkle -------------------------------------------------------------------------------- /Jenkins Menu/Resources/weather_lightning@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Jenkins Menu/Resources/weather_lightning@2x.png -------------------------------------------------------------------------------- /Frameworks/Growl.framework/Versions/A/Headers/Growl.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __OBJC__ 4 | # include 5 | #endif 6 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/relaunch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/relaunch -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/Sparkle.strings -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/Sparkle.strings -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/Sparkle.strings -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/Sparkle.strings -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/Sparkle.strings -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/Sparkle.strings -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/Sparkle.strings -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/Sparkle.strings -------------------------------------------------------------------------------- /Jenkins Menu.xcodeproj/xcuserdata/gileadis.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/SUStatus.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/SUStatus.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :osx, '10.9' 2 | workspace 'Jenkins Menu' 3 | 4 | pod 'AFNetworking' 5 | pod 'Sparkle' 6 | 7 | target :"Jenkins MenuTests" do 8 | pod "OCHamcrest" 9 | pod "OCMockito" 10 | end 11 | -------------------------------------------------------------------------------- /Jenkins Menu.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Jenkins Menu/Jenkins Menu-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Jenkins Menu' target in the 'Jenkins Menu' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Jenkins Menu.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/jenkins-menu/master/Frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Jenkins Menu/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * https://github.com/qvacua/jenkins-menu 4 | * http://qvacua.com 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) { 12 | return NSApplicationMain(argc, (const char **)argv); 13 | } 14 | -------------------------------------------------------------------------------- /Jenkins Menu/NSMenuItem+Q.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * http://qvacua.com 4 | * https://github.com/qvacua 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import 10 | 11 | @interface NSMenuItem (Q) 12 | 13 | - (void)setBlockAction:(void (^)(id sender))block; 14 | - (void (^)(id))blockAction; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap 18 | *.xccheckout 19 | 20 | # CocoaPods 21 | Pods 22 | 23 | # Vim 24 | *.swp 25 | 26 | # Custom 27 | build/* 28 | 29 | # Netbeans 30 | nbproject/* 31 | 32 | -------------------------------------------------------------------------------- /Jenkins Menu.xcodeproj/project.xcworkspace/xcuserdata/gileadis.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Jenkins MenuTests/JMBaseTestCase.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * https://github.com/qvacua/jenkins-menu 4 | * http://qvacua.com 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import 10 | 11 | #define MOCKITO_SHORTHAND 12 | #import 13 | 14 | #define HC_SHORTHAND 15 | #import 16 | 17 | #define hasSize(number) hasCount(equalToInt(number)) 18 | #define isYes is(@(YES)) 19 | #define isNo is(@(NO)) 20 | 21 | @interface JMBaseTestCase : XCTestCase 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Jenkins Menu/JMTrustedHostManager.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * https://github.com/qvacua/jenkins-menu 4 | * http://qvacua.com 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import 10 | 11 | static NSString *const qDefaultTrustedHostsKey = @"trustedURLs"; 12 | 13 | @interface JMTrustedHostManager : NSObject 14 | 15 | @property NSUserDefaults *userDefaults; 16 | 17 | - (BOOL)shouldTrustHost:(NSString *)host; 18 | - (void)permanentlyTrustHost:(NSString *)host; 19 | - (void)onceTrustHost:(NSString *)host; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 629 7 | IBOldestOS 8 | 5 9 | IBOpenObjects 10 | 11 | IBSystem Version 12 | 9E17 13 | targetFramework 14 | IBCocoaFramework 15 | 16 | 17 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 629 7 | IBOldestOS 8 | 5 9 | IBOpenObjects 10 | 11 | IBSystem Version 12 | 9E17 13 | targetFramework 14 | IBCocoaFramework 15 | 16 | 17 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 629 7 | IBOldestOS 8 | 5 9 | IBOpenObjects 10 | 11 | IBSystem Version 12 | 9D34 13 | targetFramework 14 | IBCocoaFramework 15 | 16 | 17 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 629 7 | IBOldestOS 8 | 5 9 | IBOpenObjects 10 | 11 | IBSystem Version 12 | 9E17 13 | targetFramework 14 | IBCocoaFramework 15 | 16 | 17 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 629 7 | IBOldestOS 8 | 5 9 | IBOpenObjects 10 | 11 | IBSystem Version 12 | 9E17 13 | targetFramework 14 | IBCocoaFramework 15 | 16 | 17 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 629 7 | IBOldestOS 8 | 5 9 | IBOpenObjects 10 | 11 | 6 12 | 13 | IBSystem Version 14 | 9D34 15 | targetFramework 16 | IBCocoaFramework 17 | 18 | 19 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AFNetworking (1.3.4) 3 | - OCHamcrest (4.0.1) 4 | - OCMockito (1.3.0): 5 | - OCHamcrest (~> 4.0) 6 | - TPWeakProxy (~> 1.0) 7 | - Sparkle (1.8.0) 8 | - TPWeakProxy (1.0.1) 9 | 10 | DEPENDENCIES: 11 | - AFNetworking 12 | - OCHamcrest 13 | - OCMockito 14 | - Sparkle 15 | 16 | SPEC CHECKSUMS: 17 | AFNetworking: 80c4e0652b08eb34e25b9c0ff3c82556fe5967b4 18 | OCHamcrest: b464725bbb48d0f1cd9c6f4ec3cb35fe0c4f2b94 19 | OCMockito: eca2670b3ce4a457d316b046a36d6f2b980a4da7 20 | Sparkle: 5eb20bb37ca21e471dab8417dee880198d905327 21 | TPWeakProxy: da4177b6ae5eff685642c1cd9698f71ef7060ea5 22 | 23 | COCOAPODS: 0.35.0 24 | -------------------------------------------------------------------------------- /Jenkins Menu/JMKeychainManager.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * http://qvacua.com 4 | * https://github.com/qvacua 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import 10 | 11 | @interface JMCredential : NSObject 12 | 13 | @property NSString *username; 14 | @property NSString *password; 15 | 16 | - (id)initWithUsername:(NSString *)username password:(NSString *)password; 17 | 18 | @end 19 | 20 | @interface JMKeychainManager : NSObject 21 | 22 | @property (readonly) NSString *lastErrorMessage; 23 | 24 | - (JMCredential *)credentialForUrl:(NSURL *)url; 25 | - (BOOL)storeCredential:(JMCredential *)credential forUrl:(NSURL *)url; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Headers/Sparkle.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sparkle.h 3 | // Sparkle 4 | // 5 | // Created by Andy Matuschak on 3/16/06. (Modified by CDHW on 23/12/07) 6 | // Copyright 2006 Andy Matuschak. All rights reserved. 7 | // 8 | 9 | #ifndef SPARKLE_H 10 | #define SPARKLE_H 11 | 12 | // This list should include the shared headers. It doesn't matter if some of them aren't shared (unless 13 | // there are name-space collisions) so we can list all of them to start with: 14 | 15 | #import 16 | 17 | #import 18 | #import 19 | #import 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 670 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | IBSystem Version 14 | 9E17 15 | targetFramework 16 | IBCocoaFramework 17 | 18 | 19 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/SUStatus.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 670 7 | IBLastKnownRelativeProjectPath 8 | Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 10A96 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 670 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9E17 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 670 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 18 14 | 15 | IBSystem Version 16 | 10A96 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBDocumentLocation 6 | 69 14 356 240 0 0 1280 778 7 | IBFramework Version 8 | 489.0 9 | IBLastKnownRelativeProjectPath 10 | ../Sparkle.xcodeproj 11 | IBOldestOS 12 | 5 13 | IBSystem Version 14 | 9D34 15 | targetFramework 16 | IBCocoaFramework 17 | 18 | 19 | -------------------------------------------------------------------------------- /Jenkins Menu/sparkle-pub.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBtzCCASsGByqGSM44BAEwggEeAoGBAOlzzBvZj77sIuH3M0UXswch8coQOl9R 3 | nbyfZDaiU19Treuh0T3xtWCcL3wf8vaCnD9ITTmjYmigJy9w9EHeqa5/z/MN11Vo 4 | sHSjrTQ7yejmSM8P+SQlImPQC3QoQkxtHvocwJTjriDQQspOaoOIvCMTNeYwy8Wh 5 | ESF6ARwfqVJHAhUAlZkcLRR1a148vjIC7DwYQPNZ1bkCgYAZBdblHvHv2xq286La 6 | lV/E6dzpcSOV5cF53KBbPyyhmteqUQwmGBs9vSrH5WfI7xVRMILb3dGLTmFPa9ZJ 7 | VwaN0SGG8TWEcoaI4O2YfHiFwmGN1NfggnOi8J8peldFu2vap6OwdiNNGH5jwVu+ 8 | atFX70UkFzKh39OuvdJVFLkYSQOBhQACgYEAu3DYq91S9AHGWhBMObRNUTisbcVx 9 | czAXiMqiTog3l+jPyaALOe7ocEvWB5OtTAk3o40Rp01JtLytXce+UqecjS6J1bOH 10 | AaUK0XyMSiAfv8f8ghfWHAFsy53HAh9IU8DTVx3lTqpYtymTSVkiEeNEffDr6Nfu 11 | QvtgWdK215ATy3o= 12 | -----END PUBLIC KEY----- 13 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 670 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9E17 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 670 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 10A96 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 658 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9C7010 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 5 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 670 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 10A96 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Jenkins Menu/JMJenkinsJob.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * https://github.com/qvacua/jenkins-menu 4 | * http://qvacua.com 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import 10 | 11 | typedef enum { 12 | JMJenkinsJobStateUnknown = 0, 13 | JMJenkinsJobStateGreen, 14 | JMJenkinsJobStateYellow, 15 | JMJenkinsJobStateRed, 16 | JMJenkinsJobStateAborted, 17 | JMJenkinsJobStateDisabled, 18 | } JMJenkinsJobState; 19 | 20 | @interface JMJenkinsJob : NSObject 21 | 22 | @property NSString *name; 23 | @property NSURL *url; 24 | @property JMJenkinsJobState state; 25 | @property JMJenkinsJobState lastState; 26 | @property (getter=isRunning) BOOL running; 27 | 28 | - (NSString *)description; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 670 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 41 15 | 16 | IBSystem Version 17 | 10A96 18 | targetFramework 19 | IBCocoaFramework 20 | 21 | 22 | -------------------------------------------------------------------------------- /Jenkins MenuTests/JMBaseTestCase.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * https://github.com/qvacua/jenkins-menu 4 | * http://qvacua.com 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import "JMBaseTestCase.h" 10 | #import 11 | 12 | @implementation JMBaseTestCase { 13 | Method _originalMethod; 14 | IMP _originalImpl; 15 | } 16 | 17 | - (void)swapImplOfClass:(Class)clazz selector:(SEL)originalSelector withSelector:(SEL)newSelector { 18 | Method testMethod = class_getInstanceMethod([self class], newSelector); 19 | IMP testImpl = method_getImplementation(testMethod); 20 | 21 | _originalMethod = class_getClassMethod(clazz, originalSelector); 22 | _originalImpl = method_setImplementation(_originalMethod, testImpl); 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Jenkins Menu 2 | ============= 3 | 4 | [Download](https://github.com/qvacua/jenkins-menu/wiki) 5 | 6 | ## About 7 | 8 | A simple menu item for Mac OS X which shows the status of a (also secured) Jenkins CI server. 9 | 10 | Includes Growl support. You can choose which notifications are reported via Growl's preferences or via the Notification Center of OS X 10.8. 11 | 12 | Note that if you have builds that complete within Jenkins Menu's polling period (five minutes by default) then it may not notify you about the build. You can always reduce the polling period in Jenkins Menu's Preferences. 13 | 14 | ## Source Code License 15 | The source code of Qmind is licensed under GNU General Public License version 3 as published by the Free Software Foundation. 16 | -------------------------------------------------------------------------------- /Jenkins Menu.xcodeproj/xcuserdata/gileadis.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Jenkins Menu.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 4B0CE8B0158DC6D0001BA10E 16 | 17 | primary 18 | 19 | 20 | 4B0CE8D1158DC6D1001BA10E 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Jenkins Menu.xcodeproj/xcuserdata/hat.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Jenkins Menu.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 4B0CE8B0158DC6D0001BA10E 16 | 17 | primary 18 | 19 | 20 | 4B0CE8D1158DC6D1001BA10E 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Jenkins MenuTests/Jenkins MenuTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.qvacua.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Jenkins Menu/Resources/Growl Registration Ticket.growlRegDict: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | TicketVersion 6 | 1 7 | AllNotifications 8 | 9 | Error 10 | Began 11 | Broken 12 | StillBroken 13 | Unstable 14 | StillUnstable 15 | Fixed 16 | Succeeded 17 | 18 | DefaultNotifications 19 | 20 | Error 21 | Broken 22 | Unstable 23 | Fixed 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Headers/SUAppcast.h: -------------------------------------------------------------------------------- 1 | // 2 | // SUAppcast.h 3 | // Sparkle 4 | // 5 | // Created by Andy Matuschak on 3/12/06. 6 | // Copyright 2006 Andy Matuschak. All rights reserved. 7 | // 8 | 9 | #ifndef SUAPPCAST_H 10 | #define SUAPPCAST_H 11 | 12 | @class SUAppcastItem; 13 | @interface SUAppcast : NSObject { 14 | NSArray *items; 15 | NSString *userAgentString; 16 | id delegate; 17 | NSMutableData *incrementalData; 18 | } 19 | 20 | - (void)fetchAppcastFromURL:(NSURL *)url; 21 | - (void)setDelegate:delegate; 22 | - (void)setUserAgentString:(NSString *)userAgentString; 23 | 24 | - (NSArray *)items; 25 | 26 | @end 27 | 28 | @interface NSObject (SUAppcastDelegate) 29 | - (void)appcastDidFinishLoading:(SUAppcast *)appcast; 30 | - (void)appcast:(SUAppcast *)appcast failedToLoadWithError:(NSError *)error; 31 | @end 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | Sparkle 9 | CFBundleIdentifier 10 | org.andymatuschak.Sparkle 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | Sparkle 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.5 Beta 6 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 313 23 | 24 | 25 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Headers/SUVersionComparisonProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // SUVersionComparisonProtocol.h 3 | // Sparkle 4 | // 5 | // Created by Andy Matuschak on 12/21/07. 6 | // Copyright 2007 Andy Matuschak. All rights reserved. 7 | // 8 | 9 | #ifndef SUVERSIONCOMPARISONPROTOCOL_H 10 | #define SUVERSIONCOMPARISONPROTOCOL_H 11 | 12 | /*! 13 | @protocol 14 | @abstract Implement this protocol to provide version comparison facilities for Sparkle. 15 | */ 16 | @protocol SUVersionComparison 17 | 18 | /*! 19 | @method 20 | @abstract An abstract method to compare two version strings. 21 | @discussion Should return NSOrderedAscending if b > a, NSOrderedDescending if b < a, and NSOrderedSame if they are equivalent. 22 | */ 23 | - (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB; 24 | 25 | @end 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /Frameworks/Growl.framework/Versions/A/_CodeSignature/CodeResources: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | files 6 | 7 | Resources/Info.plist 8 | 9 | lnx8exuPwE/bsUq32R5DXDQholc= 10 | 11 | 12 | rules 13 | 14 | ^Resources/ 15 | 16 | ^Resources/.*\.lproj/ 17 | 18 | optional 19 | 20 | weight 21 | 1000 22 | 23 | ^Resources/.*\.lproj/locversion.plist$ 24 | 25 | omit 26 | 27 | weight 28 | 1100 29 | 30 | ^version.plist$ 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Jenkins Menu/NSMenuItem+Q.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * http://qvacua.com 4 | * https://github.com/qvacua 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import "NSMenuItem+Q.h" 10 | #import 11 | 12 | static char * const qBlockActionKey = "BlockActionKey"; 13 | 14 | @implementation NSMenuItem (Q) 15 | 16 | - (void)setBlockAction:(void (^)(id))block { 17 | objc_setAssociatedObject(self, qBlockActionKey, nil, OBJC_ASSOCIATION_RETAIN); 18 | 19 | if (block == nil) { 20 | [self setTarget:nil]; 21 | [self setAction:NULL]; 22 | 23 | return; 24 | } 25 | 26 | objc_setAssociatedObject(self, qBlockActionKey, block, OBJC_ASSOCIATION_RETAIN); 27 | [self setTarget:self]; 28 | [self setAction:@selector(blockActionWrapper:)]; 29 | } 30 | 31 | - (void (^)(id))blockAction { 32 | return objc_getAssociatedObject(self, qBlockActionKey); 33 | } 34 | 35 | - (void)blockActionWrapper:(id)sender { 36 | void (^block)(id) = objc_getAssociatedObject(self, qBlockActionKey); 37 | 38 | block(sender); 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Jenkins MenuTests/JMJenkinsJobTest.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * https://github.com/qvacua/jenkins-menu 4 | * http://qvacua.com 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import "JMBaseTestCase.h" 10 | #import "JMJenkinsJob.h" 11 | 12 | @interface JMJenkinsJobTest : JMBaseTestCase 13 | @end 14 | 15 | @implementation JMJenkinsJobTest { 16 | JMJenkinsJob *job; 17 | } 18 | 19 | - (void)setUp { 20 | [super setUp]; 21 | 22 | job = [[JMJenkinsJob alloc] init]; 23 | } 24 | 25 | - (void)testDefaultStates { 26 | assertThat(@(job.state), is(@(JMJenkinsJobStateUnknown))); 27 | assertThat(@(job.lastState), is(@(JMJenkinsJobStateUnknown))); 28 | } 29 | 30 | - (void)testSetState { 31 | job.state = JMJenkinsJobStateGreen; 32 | assertThat(@(job.state), is(@(JMJenkinsJobStateGreen))); 33 | assertThat(@(job.lastState), is(@(JMJenkinsJobStateUnknown))); 34 | 35 | job.state = JMJenkinsJobStateRed; 36 | assertThat(@(job.state), is(@(JMJenkinsJobStateRed))); 37 | assertThat(@(job.lastState), is(@(JMJenkinsJobStateGreen))); 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Jenkins Menu/JMJenkinsJob.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * https://github.com/qvacua/jenkins-menu 4 | * http://qvacua.com 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import "JMJenkinsJob.h" 10 | 11 | @implementation JMJenkinsJob { 12 | JMJenkinsJobState _state; 13 | } 14 | 15 | @dynamic state; 16 | 17 | - (JMJenkinsJobState)state { 18 | return _state; 19 | } 20 | 21 | - (void)setState:(JMJenkinsJobState)newState { 22 | self.lastState = self.state; 23 | _state = newState; 24 | } 25 | 26 | - (NSString *)description { 27 | NSMutableString *description = [NSMutableString stringWithFormat:@"<%@: ", NSStringFromClass([self class])]; 28 | [description appendFormat:@"self.state=%d", self.state]; 29 | [description appendFormat:@", self.name=%@", self.name]; 30 | [description appendFormat:@", self.url=%@", self.url]; 31 | [description appendFormat:@", self.lastState=%d", self.lastState]; 32 | [description appendFormat:@", self.running=%d", self.running]; 33 | [description appendString:@">"]; 34 | return description; 35 | } 36 | 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2006 Andy Matuschak 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | { 2 | IBClasses = ( 3 | { 4 | CLASS = FirstResponder; 5 | LANGUAGE = ObjC; 6 | SUPERCLASS = NSObject; 7 | }, 8 | { 9 | CLASS = NSApplication; 10 | LANGUAGE = ObjC; 11 | SUPERCLASS = NSResponder; 12 | }, 13 | { 14 | CLASS = NSObject; 15 | LANGUAGE = ObjC; 16 | }, 17 | { 18 | ACTIONS = { 19 | installUpdate = id; 20 | remindMeLater = id; 21 | skipThisVersion = id; 22 | }; 23 | CLASS = SUUpdateAlert; 24 | LANGUAGE = ObjC; 25 | OUTLETS = { 26 | delegate = id; 27 | description = NSTextField; 28 | releaseNotesView = WebView; 29 | }; 30 | SUPERCLASS = SUWindowController; 31 | }, 32 | { 33 | CLASS = SUWindowController; 34 | LANGUAGE = ObjC; 35 | SUPERCLASS = NSWindowController; 36 | } 37 | ); 38 | IBVersion = 1; 39 | } -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Headers/SUAppcastItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // SUAppcastItem.h 3 | // Sparkle 4 | // 5 | // Created by Andy Matuschak on 3/12/06. 6 | // Copyright 2006 Andy Matuschak. All rights reserved. 7 | // 8 | 9 | #ifndef SUAPPCASTITEM_H 10 | #define SUAPPCASTITEM_H 11 | 12 | @interface SUAppcastItem : NSObject { 13 | NSString *title; 14 | NSDate *date; 15 | NSString *itemDescription; 16 | 17 | NSURL *releaseNotesURL; 18 | 19 | NSString *DSASignature; 20 | NSString *minimumSystemVersion; 21 | 22 | NSURL *fileURL; 23 | NSString *versionString; 24 | NSString *displayVersionString; 25 | 26 | NSDictionary *propertiesDictionary; 27 | } 28 | 29 | // Initializes with data from a dictionary provided by the RSS class. 30 | - initWithDictionary:(NSDictionary *)dict; 31 | 32 | - (NSString *)title; 33 | - (NSString *)versionString; 34 | - (NSString *)displayVersionString; 35 | - (NSDate *)date; 36 | - (NSString *)itemDescription; 37 | - (NSURL *)releaseNotesURL; 38 | - (NSURL *)fileURL; 39 | - (NSString *)DSASignature; 40 | - (NSString *)minimumSystemVersion; 41 | 42 | // Returns the dictionary provided in initWithDictionary; this might be useful later for extensions. 43 | - (NSDictionary *)propertiesDictionary; 44 | 45 | @end 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /Frameworks/Growl.framework/Versions/A/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 12A269 7 | CFBundleDevelopmentRegion 8 | English 9 | CFBundleExecutable 10 | Growl 11 | CFBundleIdentifier 12 | com.growl.growlframework 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.0 19 | CFBundleSignature 20 | GRRR 21 | CFBundleVersion 22 | 2.0 23 | DTCompiler 24 | com.apple.compilers.llvm.clang.1_0 25 | DTPlatformBuild 26 | 4F250 27 | DTPlatformVersion 28 | GM 29 | DTSDKBuild 30 | 12A264 31 | DTSDKName 32 | macosx10.8 33 | DTXcode 34 | 0440 35 | DTXcodeBuild 36 | 4F250 37 | NSPrincipalClass 38 | GrowlApplicationBridge 39 | 40 | 41 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | doNotInstall 19 | id 20 | installLater 21 | id 22 | installNow 23 | id 24 | 25 | CLASS 26 | SUAutomaticUpdateAlert 27 | LANGUAGE 28 | ObjC 29 | SUPERCLASS 30 | SUWindowController 31 | 32 | 33 | CLASS 34 | FirstResponder 35 | LANGUAGE 36 | ObjC 37 | SUPERCLASS 38 | NSObject 39 | 40 | 41 | CLASS 42 | NSObject 43 | LANGUAGE 44 | ObjC 45 | 46 | 47 | IBVersion 48 | 1 49 | 50 | 51 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | doNotInstall 19 | id 20 | installLater 21 | id 22 | installNow 23 | id 24 | 25 | CLASS 26 | SUAutomaticUpdateAlert 27 | LANGUAGE 28 | ObjC 29 | SUPERCLASS 30 | SUWindowController 31 | 32 | 33 | CLASS 34 | FirstResponder 35 | LANGUAGE 36 | ObjC 37 | SUPERCLASS 38 | NSObject 39 | 40 | 41 | CLASS 42 | NSObject 43 | LANGUAGE 44 | ObjC 45 | 46 | 47 | IBVersion 48 | 1 49 | 50 | 51 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | doNotInstall 19 | id 20 | installLater 21 | id 22 | installNow 23 | id 24 | 25 | CLASS 26 | SUAutomaticUpdateAlert 27 | LANGUAGE 28 | ObjC 29 | SUPERCLASS 30 | SUWindowController 31 | 32 | 33 | CLASS 34 | FirstResponder 35 | LANGUAGE 36 | ObjC 37 | SUPERCLASS 38 | NSObject 39 | 40 | 41 | CLASS 42 | NSObject 43 | LANGUAGE 44 | ObjC 45 | 46 | 47 | IBVersion 48 | 1 49 | 50 | 51 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | doNotInstall 19 | id 20 | installLater 21 | id 22 | installNow 23 | id 24 | 25 | CLASS 26 | SUAutomaticUpdateAlert 27 | LANGUAGE 28 | ObjC 29 | SUPERCLASS 30 | SUWindowController 31 | 32 | 33 | CLASS 34 | FirstResponder 35 | LANGUAGE 36 | ObjC 37 | SUPERCLASS 38 | NSObject 39 | 40 | 41 | CLASS 42 | NSObject 43 | LANGUAGE 44 | ObjC 45 | 46 | 47 | IBVersion 48 | 1 49 | 50 | 51 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | doNotInstall 19 | id 20 | installLater 21 | id 22 | installNow 23 | id 24 | 25 | CLASS 26 | SUAutomaticUpdateAlert 27 | LANGUAGE 28 | ObjC 29 | SUPERCLASS 30 | SUWindowController 31 | 32 | 33 | CLASS 34 | FirstResponder 35 | LANGUAGE 36 | ObjC 37 | SUPERCLASS 38 | NSObject 39 | 40 | 41 | CLASS 42 | NSObject 43 | LANGUAGE 44 | ObjC 45 | 46 | 47 | IBVersion 48 | 1 49 | 50 | 51 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | doNotInstall 19 | id 20 | installLater 21 | id 22 | installNow 23 | id 24 | 25 | CLASS 26 | SUAutomaticUpdateAlert 27 | LANGUAGE 28 | ObjC 29 | SUPERCLASS 30 | SUWindowController 31 | 32 | 33 | CLASS 34 | FirstResponder 35 | LANGUAGE 36 | ObjC 37 | SUPERCLASS 38 | NSObject 39 | 40 | 41 | CLASS 42 | NSObject 43 | LANGUAGE 44 | ObjC 45 | 46 | 47 | IBVersion 48 | 1 49 | 50 | 51 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | doNotInstall 19 | id 20 | installLater 21 | id 22 | installNow 23 | id 24 | 25 | CLASS 26 | SUAutomaticUpdateAlert 27 | LANGUAGE 28 | ObjC 29 | SUPERCLASS 30 | SUWindowController 31 | 32 | 33 | CLASS 34 | FirstResponder 35 | LANGUAGE 36 | ObjC 37 | SUPERCLASS 38 | NSObject 39 | 40 | 41 | CLASS 42 | NSObject 43 | LANGUAGE 44 | ObjC 45 | 46 | 47 | IBVersion 48 | 1 49 | 50 | 51 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | doNotInstall 19 | id 20 | installLater 21 | id 22 | installNow 23 | id 24 | 25 | CLASS 26 | SUAutomaticUpdateAlert 27 | LANGUAGE 28 | ObjC 29 | SUPERCLASS 30 | SUWindowController 31 | 32 | 33 | CLASS 34 | FirstResponder 35 | LANGUAGE 36 | ObjC 37 | SUPERCLASS 38 | NSObject 39 | 40 | 41 | CLASS 42 | NSObject 43 | LANGUAGE 44 | ObjC 45 | 46 | 47 | IBVersion 48 | 1 49 | 50 | 51 | -------------------------------------------------------------------------------- /Jenkins Menu.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 29 | 30 | 31 | 32 | 33 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /Jenkins MenuTests/Resources/unknown-xml.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | NORMAL 4 | the master Jenkins node 5 | 6 | 3 7 | 8 | jruby-test-master 9 | http://ci.jruby.org/job/jruby-test-master/ 10 | aborted 11 | 12 | 13 | jruby-dist-release 14 | http://ci.jruby.org/job/jruby-dist-release/ 15 | disabled 16 | 17 | 18 | 19 | All 20 | http://ci.jruby.org/ 21 | 22 | false 23 | 32323 24 | 25 | false 26 | true 27 | 28 | All 29 | http://ci.jruby.org/ 30 | 31 | 32 | JRuby Core 33 | http://ci.jruby.org/view/JRuby%20Core/ 34 | 35 | 36 | Rails 37 | http://ci.jruby.org/view/Rails/ 38 | 39 | 40 | Ruboto 41 | http://ci.jruby.org/view/Ruboto/ 42 | 43 | 44 | -------------------------------------------------------------------------------- /Jenkins Menu/JMTrustedHostManager.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * https://github.com/qvacua/jenkins-menu 4 | * http://qvacua.com 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import "JMTrustedHostManager.h" 10 | 11 | @interface JMTrustedHostManager () 12 | 13 | @property NSMutableSet *onceTrustHosts; 14 | 15 | @end 16 | 17 | @implementation JMTrustedHostManager { 18 | } 19 | 20 | - (id)init { 21 | self = [super init]; 22 | if (self) { 23 | _userDefaults = [NSUserDefaults standardUserDefaults]; 24 | _onceTrustHosts = [[NSMutableSet alloc] init]; 25 | } 26 | 27 | return self; 28 | } 29 | 30 | - (BOOL)shouldTrustHost:(NSString *)host { 31 | NSArray *trustedHosts = [self.userDefaults arrayForKey:qDefaultTrustedHostsKey]; 32 | if ([trustedHosts containsObject:host]) { 33 | return YES; 34 | } 35 | 36 | if ([self.onceTrustHosts containsObject:host]) { 37 | [self.onceTrustHosts removeObject:host]; 38 | return YES; 39 | } 40 | 41 | return NO; 42 | } 43 | 44 | - (void)permanentlyTrustHost:(NSString *)host { 45 | NSMutableArray *trustedHosts = [NSMutableArray arrayWithArray:[self.userDefaults arrayForKey:qDefaultTrustedHostsKey]]; 46 | 47 | if ([trustedHosts containsObject:host]) { 48 | return; 49 | } 50 | 51 | [trustedHosts addObject:host]; 52 | [self.userDefaults setObject:trustedHosts forKey:qDefaultTrustedHostsKey]; 53 | } 54 | 55 | - (void)onceTrustHost:(NSString *)host { 56 | [self.onceTrustHosts addObject:host]; 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /Jenkins Menu/Jenkins Menu-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | Jenkins Menu 11 | CFBundleIdentifier 12 | com.qvacua.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 0.2.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 9 25 | LSApplicationCategoryType 26 | public.app-category.utilities 27 | LSMinimumSystemVersion 28 | ${MACOSX_DEPLOYMENT_TARGET} 29 | LSUIElement 30 | 1 31 | NSHumanReadableCopyright 32 | Copyright © 2014 Tae Won Ha. All rights reserved. 33 | NSMainNibFile 34 | MainMenu 35 | NSPrincipalClass 36 | NSApplication 37 | SUFeedURL 38 | http://qvacua.com/jenkinsmenu/appcast.xml 39 | SUPublicDSAKeyFile 40 | sparkle-pub.pem 41 | 42 | 43 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/SUStatus.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | CLASS 17 | NSApplication 18 | LANGUAGE 19 | ObjC 20 | SUPERCLASS 21 | NSResponder 22 | 23 | 24 | CLASS 25 | FirstResponder 26 | LANGUAGE 27 | ObjC 28 | SUPERCLASS 29 | NSObject 30 | 31 | 32 | CLASS 33 | NSObject 34 | LANGUAGE 35 | ObjC 36 | 37 | 38 | CLASS 39 | SUStatusController 40 | LANGUAGE 41 | ObjC 42 | OUTLETS 43 | 44 | actionButton 45 | NSButton 46 | progressBar 47 | NSProgressIndicator 48 | 49 | SUPERCLASS 50 | SUWindowController 51 | 52 | 53 | IBVersion 54 | 1 55 | 56 | 57 | -------------------------------------------------------------------------------- /Jenkins Menu/JMJenkinsDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * https://github.com/qvacua/jenkins-menu 4 | * http://qvacua.com 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import 10 | 11 | @class JMJenkins; 12 | 13 | @protocol JMJenkinsDelegate 14 | 15 | @required 16 | /** 17 | * Called when the SSL certificate of the server cannot be trusted. Using this delegate method, you can ask the user 18 | * whether to trust the server. 19 | * 20 | * @param host the host of the server which could not be trusted 21 | */ 22 | - (void)jenkins:(JMJenkins *)jenkins serverTrustFailedwithHost:(NSString *)host; 23 | 24 | /** 25 | * Called when the update failed. 26 | * 27 | * @param userInfo a dictionary containing info about the error occurred. 28 | */ 29 | - (void)jenkins:(JMJenkins *)jenkins updateFailed:(NSDictionary *)userInfo; 30 | 31 | /** 32 | * Only called when both the request and the parsing were successful. 33 | * 34 | * @param userInfo yet always nil 35 | */ 36 | - (void)jenkins:(JMJenkins *)jenkins updateFinished:(NSDictionary *)userInfo; 37 | 38 | /** 39 | * Called directly after the request was created. 40 | * 41 | * @param userInfo yet always nil 42 | */ 43 | - (void)jenkins:(JMJenkins *)jenkins updateStarted:(NSDictionary *)userInfo; 44 | 45 | /** 46 | * Called when the Jenkins instance is secured. 47 | * 48 | * @param userInfo yet always nil 49 | */ 50 | - (void)jenkins:(JMJenkins *)jenkins forbidden:(id)userInfo; 51 | 52 | /** 53 | * Called when the current credential for the secured Jenkins is wrong. 54 | * 55 | * @param userInfo yet always nil 56 | */ 57 | - (void)jenkins:(JMJenkins *)jenkins wrongCredential:(NSDictionary *)userInfo; 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | finishPrompt 19 | id 20 | toggleMoreInfo 21 | id 22 | 23 | CLASS 24 | SUUpdatePermissionPrompt 25 | LANGUAGE 26 | ObjC 27 | OUTLETS 28 | 29 | delegate 30 | id 31 | descriptionTextField 32 | NSTextField 33 | moreInfoButton 34 | NSButton 35 | moreInfoView 36 | NSView 37 | 38 | SUPERCLASS 39 | SUWindowController 40 | 41 | 42 | CLASS 43 | FirstResponder 44 | LANGUAGE 45 | ObjC 46 | SUPERCLASS 47 | NSObject 48 | 49 | 50 | CLASS 51 | NSObject 52 | LANGUAGE 53 | ObjC 54 | 55 | 56 | IBVersion 57 | 1 58 | 59 | 60 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | finishPrompt 19 | id 20 | toggleMoreInfo 21 | id 22 | 23 | CLASS 24 | SUUpdatePermissionPrompt 25 | LANGUAGE 26 | ObjC 27 | OUTLETS 28 | 29 | delegate 30 | id 31 | descriptionTextField 32 | NSTextField 33 | moreInfoButton 34 | NSButton 35 | moreInfoView 36 | NSView 37 | 38 | SUPERCLASS 39 | SUWindowController 40 | 41 | 42 | CLASS 43 | FirstResponder 44 | LANGUAGE 45 | ObjC 46 | SUPERCLASS 47 | NSObject 48 | 49 | 50 | CLASS 51 | NSObject 52 | LANGUAGE 53 | ObjC 54 | 55 | 56 | IBVersion 57 | 1 58 | 59 | 60 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | finishPrompt 19 | id 20 | toggleMoreInfo 21 | id 22 | 23 | CLASS 24 | SUUpdatePermissionPrompt 25 | LANGUAGE 26 | ObjC 27 | OUTLETS 28 | 29 | delegate 30 | id 31 | descriptionTextField 32 | NSTextField 33 | moreInfoButton 34 | NSButton 35 | moreInfoView 36 | NSView 37 | 38 | SUPERCLASS 39 | SUWindowController 40 | 41 | 42 | CLASS 43 | FirstResponder 44 | LANGUAGE 45 | ObjC 46 | SUPERCLASS 47 | NSObject 48 | 49 | 50 | CLASS 51 | NSObject 52 | LANGUAGE 53 | ObjC 54 | 55 | 56 | IBVersion 57 | 1 58 | 59 | 60 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | finishPrompt 19 | id 20 | toggleMoreInfo 21 | id 22 | 23 | CLASS 24 | SUUpdatePermissionPrompt 25 | LANGUAGE 26 | ObjC 27 | OUTLETS 28 | 29 | delegate 30 | id 31 | descriptionTextField 32 | NSTextField 33 | moreInfoButton 34 | NSButton 35 | moreInfoView 36 | NSView 37 | 38 | SUPERCLASS 39 | SUWindowController 40 | 41 | 42 | CLASS 43 | FirstResponder 44 | LANGUAGE 45 | ObjC 46 | SUPERCLASS 47 | NSObject 48 | 49 | 50 | CLASS 51 | NSObject 52 | LANGUAGE 53 | ObjC 54 | 55 | 56 | IBVersion 57 | 1 58 | 59 | 60 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | finishPrompt 19 | id 20 | toggleMoreInfo 21 | id 22 | 23 | CLASS 24 | SUUpdatePermissionPrompt 25 | LANGUAGE 26 | ObjC 27 | OUTLETS 28 | 29 | delegate 30 | id 31 | descriptionTextField 32 | NSTextField 33 | moreInfoButton 34 | NSButton 35 | moreInfoView 36 | NSView 37 | 38 | SUPERCLASS 39 | SUWindowController 40 | 41 | 42 | CLASS 43 | FirstResponder 44 | LANGUAGE 45 | ObjC 46 | SUPERCLASS 47 | NSObject 48 | 49 | 50 | CLASS 51 | NSObject 52 | LANGUAGE 53 | ObjC 54 | 55 | 56 | IBVersion 57 | 1 58 | 59 | 60 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | finishPrompt 19 | id 20 | toggleMoreInfo 21 | id 22 | 23 | CLASS 24 | SUUpdatePermissionPrompt 25 | LANGUAGE 26 | ObjC 27 | OUTLETS 28 | 29 | delegate 30 | id 31 | descriptionTextField 32 | NSTextField 33 | moreInfoButton 34 | NSButton 35 | moreInfoView 36 | NSView 37 | 38 | SUPERCLASS 39 | SUWindowController 40 | 41 | 42 | CLASS 43 | FirstResponder 44 | LANGUAGE 45 | ObjC 46 | SUPERCLASS 47 | NSObject 48 | 49 | 50 | CLASS 51 | NSObject 52 | LANGUAGE 53 | ObjC 54 | 55 | 56 | IBVersion 57 | 1 58 | 59 | 60 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | NSObject 10 | LANGUAGE 11 | ObjC 12 | 13 | 14 | CLASS 15 | SUWindowController 16 | LANGUAGE 17 | ObjC 18 | SUPERCLASS 19 | NSWindowController 20 | 21 | 22 | ACTIONS 23 | 24 | finishPrompt 25 | id 26 | toggleMoreInfo 27 | id 28 | 29 | CLASS 30 | SUUpdatePermissionPrompt 31 | LANGUAGE 32 | ObjC 33 | OUTLETS 34 | 35 | delegate 36 | id 37 | descriptionTextField 38 | NSTextField 39 | moreInfoButton 40 | NSButton 41 | moreInfoView 42 | NSView 43 | 44 | SUPERCLASS 45 | SUWindowController 46 | 47 | 48 | CLASS 49 | FirstResponder 50 | LANGUAGE 51 | ObjC 52 | SUPERCLASS 53 | NSObject 54 | 55 | 56 | IBVersion 57 | 1 58 | 59 | 60 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | finishPrompt 19 | id 20 | toggleMoreInfo 21 | id 22 | 23 | CLASS 24 | SUUpdatePermissionPrompt 25 | LANGUAGE 26 | ObjC 27 | OUTLETS 28 | 29 | delegate 30 | id 31 | descriptionTextField 32 | NSTextField 33 | moreInfoButton 34 | NSButton 35 | moreInfoView 36 | NSView 37 | 38 | SUPERCLASS 39 | SUWindowController 40 | 41 | 42 | CLASS 43 | FirstResponder 44 | LANGUAGE 45 | ObjC 46 | SUPERCLASS 47 | NSObject 48 | 49 | 50 | CLASS 51 | NSObject 52 | LANGUAGE 53 | ObjC 54 | 55 | 56 | IBVersion 57 | 1 58 | 59 | 60 | -------------------------------------------------------------------------------- /Jenkins Menu/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | "ButtonTrust" = "Trust"; 4 | "ButtonCancel" = "Cancel"; 5 | "MessageTrustServer" = "Trust %@?"; 6 | "MessageTrustInformation" = "The server’s credentials can’t be verified."; 7 | "MessageAlwaysTrust" = "Always trust this server in the future."; 8 | 9 | "StatusUpdating" = "Updating Jenkins Status..."; 10 | "StatusSuccess" = "Successfully Updated Jenkins Status"; 11 | "StatusError" = "Error Updating Jenkins Status"; 12 | 13 | "NotifyTitleError" = "Couldn’t Connect"; 14 | "NotifyTitleBegan" = "A Build Started"; 15 | "NotifyTitleBroken" = "Build Broken"; 16 | "NotifyTitleStillBroken" = "Build Still Broken"; 17 | "NotifyTitleUnstable" = "Build Unstable"; 18 | "NotifyTitleStillUnstable" = "Build Still Unstable"; 19 | "NotifyTitleFixed" = "Build Fixed"; 20 | "NotifyTitleSucceeded" = "Build Succeeded"; 21 | 22 | "NotifyMessageError" = "Couldn’t reach %@: %@."; 23 | "NotifyMessageBegan" = "%@ began building."; 24 | "NotifyMessageBroken" = "%@ just broke! Please fix it."; 25 | "NotifyMessageStillBroken" = "%@ is still broken. Please fix it."; 26 | "NotifyMessageUnstable" = "%@ just became unstable!"; 27 | "NotifyMessageStillUnstable" = "%@ is still unstable."; 28 | "NotifyMessageFixed" = "%@ was fixed!"; 29 | "NotifyMessageSucceeded" = "%@ succeeded."; 30 | 31 | "ErrorHttpStatus" = "got HTTP error %ld"; 32 | "ErrorEmptyXML" = "got an empty build status XML document"; 33 | "ErrorCouldNotConnect" = "couldn’t connect"; 34 | 35 | "ErrorKeychainItem" = "There was an error obtaining the keychain item for %@"; 36 | 37 | "JenkinsSecuredStatus" = "The Jenkins CI server is secured"; 38 | 39 | "WarningEnterCredential" = "You have to enter User and Password."; 40 | -------------------------------------------------------------------------------- /Jenkins Menu/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf210 2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \paperw11900\paperh16840\vieww9600\viewh8400\viewkind0 5 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720 6 | 7 | \f0\b\fs24 \cf0 Engineering: 8 | \b0 \ 9 | Tae Won Ha \'97 {\field{\*\fldinst{HYPERLINK "http://www.qvacua.com"}}{\fldrslt http://qvacua.com}}\ 10 | David Gileadi \'97 {\field{\*\fldinst{HYPERLINK "https://github.com/dgileadi"}}{\fldrslt https://github.com/dgileadi}}\ 11 | Kevin Wojniak \'97 {\field{\*\fldinst{HYPERLINK "http://kainjow.com/"}}{\fldrslt http://kainjow.com}}\ 12 | \ 13 | 14 | \b Github:\ 15 | 16 | \b0 {\field{\*\fldinst{HYPERLINK "https://github.com/qvacua/jenkins-menu"}}{\fldrslt https://github.com/qvacua/jenkins-menu}}\ 17 | \ 18 | 19 | \b With special thanks to: 20 | \b0 \ 21 | {\field{\*\fldinst{HYPERLINK "http://jenkins-ci.org/"}}{\fldrslt http://jenkins-ci.org/}}\ 22 | \ 23 | 24 | \b 3rd Party Libraries:\ 25 | 26 | \b0 AFNetworking\ 27 | {\field{\*\fldinst{HYPERLINK "https://github.com/AFNetworking/AFNetworking"}}{\fldrslt https://github.com/AFNetworking/AFNetworking}}\ 28 | Sparkle\ 29 | {\field{\*\fldinst{HYPERLINK "http://sparkle.andymatuschak.org/"}}{\fldrslt http://sparkle.andymatuschak.org/}} 30 | \b \ 31 | \ 32 | Menu icons from: 33 | \b0 \ 34 | {\field{\*\fldinst{HYPERLINK "http://www.fatcow.com/free-icons"}}{\fldrslt http://www.fatcow.com/free-icons}}\ 35 | \ 36 | 37 | \b App icon based on: 38 | \b0 \ 39 | {\field{\*\fldinst{HYPERLINK "https://wiki.jenkins-ci.org/display/JENKINS/Logo"}}{\fldrslt The official Jenkins logo}}\ 40 | License: {\field{\*\fldinst{HYPERLINK "http://creativecommons.org/licenses/by-sa/3.0/"}}{\fldrslt CC BY-SA 3.0}}} -------------------------------------------------------------------------------- /Jenkins MenuTests/Resources/green-xml.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | NORMAL 4 | the master Jenkins node 5 | 6 | 3 7 | 8 | activerecord-jdbc-master 9 | http://ci.jruby.org/job/activerecord-jdbc-master/ 10 | blue 11 | 12 | 13 | jruby-test-all-master 14 | http://ci.jruby.org/job/jruby-test-all-master/ 15 | blue_anime 16 | 17 | 18 | jruby-test-master 19 | http://ci.jruby.org/job/jruby-test-master/ 20 | aborted 21 | 22 | 23 | jruby-dist-release 24 | http://ci.jruby.org/job/jruby-dist-release/ 25 | disabled 26 | 27 | 28 | 29 | All 30 | http://ci.jruby.org/ 31 | 32 | false 33 | 32323 34 | 35 | false 36 | true 37 | 38 | All 39 | http://ci.jruby.org/ 40 | 41 | 42 | JRuby Core 43 | http://ci.jruby.org/view/JRuby%20Core/ 44 | 45 | 46 | Rails 47 | http://ci.jruby.org/view/Rails/ 48 | 49 | 50 | Ruboto 51 | http://ci.jruby.org/view/Ruboto/ 52 | 53 | 54 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | CLASS 17 | NSApplication 18 | LANGUAGE 19 | ObjC 20 | SUPERCLASS 21 | NSResponder 22 | 23 | 24 | ACTIONS 25 | 26 | installUpdate 27 | id 28 | remindMeLater 29 | id 30 | skipThisVersion 31 | id 32 | 33 | CLASS 34 | SUUpdateAlert 35 | LANGUAGE 36 | ObjC 37 | OUTLETS 38 | 39 | delegate 40 | id 41 | description 42 | NSTextField 43 | releaseNotesView 44 | WebView 45 | 46 | SUPERCLASS 47 | SUWindowController 48 | 49 | 50 | CLASS 51 | FirstResponder 52 | LANGUAGE 53 | ObjC 54 | SUPERCLASS 55 | NSObject 56 | 57 | 58 | CLASS 59 | NSObject 60 | LANGUAGE 61 | ObjC 62 | 63 | 64 | IBVersion 65 | 1 66 | 67 | 68 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | CLASS 17 | NSApplication 18 | LANGUAGE 19 | ObjC 20 | SUPERCLASS 21 | NSResponder 22 | 23 | 24 | ACTIONS 25 | 26 | installUpdate 27 | id 28 | remindMeLater 29 | id 30 | skipThisVersion 31 | id 32 | 33 | CLASS 34 | SUUpdateAlert 35 | LANGUAGE 36 | ObjC 37 | OUTLETS 38 | 39 | delegate 40 | id 41 | description 42 | NSTextField 43 | releaseNotesView 44 | WebView 45 | 46 | SUPERCLASS 47 | SUWindowController 48 | 49 | 50 | CLASS 51 | FirstResponder 52 | LANGUAGE 53 | ObjC 54 | SUPERCLASS 55 | NSObject 56 | 57 | 58 | CLASS 59 | NSObject 60 | LANGUAGE 61 | ObjC 62 | 63 | 64 | IBVersion 65 | 1 66 | 67 | 68 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | CLASS 17 | NSApplication 18 | LANGUAGE 19 | ObjC 20 | SUPERCLASS 21 | NSResponder 22 | 23 | 24 | ACTIONS 25 | 26 | installUpdate 27 | id 28 | remindMeLater 29 | id 30 | skipThisVersion 31 | id 32 | 33 | CLASS 34 | SUUpdateAlert 35 | LANGUAGE 36 | ObjC 37 | OUTLETS 38 | 39 | delegate 40 | id 41 | description 42 | NSTextField 43 | releaseNotesView 44 | WebView 45 | 46 | SUPERCLASS 47 | SUWindowController 48 | 49 | 50 | CLASS 51 | FirstResponder 52 | LANGUAGE 53 | ObjC 54 | SUPERCLASS 55 | NSObject 56 | 57 | 58 | CLASS 59 | NSObject 60 | LANGUAGE 61 | ObjC 62 | 63 | 64 | IBVersion 65 | 1 66 | 67 | 68 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | CLASS 17 | NSApplication 18 | LANGUAGE 19 | ObjC 20 | SUPERCLASS 21 | NSResponder 22 | 23 | 24 | ACTIONS 25 | 26 | installUpdate 27 | id 28 | remindMeLater 29 | id 30 | skipThisVersion 31 | id 32 | 33 | CLASS 34 | SUUpdateAlert 35 | LANGUAGE 36 | ObjC 37 | OUTLETS 38 | 39 | delegate 40 | id 41 | description 42 | NSTextField 43 | releaseNotesView 44 | WebView 45 | 46 | SUPERCLASS 47 | SUWindowController 48 | 49 | 50 | CLASS 51 | FirstResponder 52 | LANGUAGE 53 | ObjC 54 | SUPERCLASS 55 | NSObject 56 | 57 | 58 | CLASS 59 | NSObject 60 | LANGUAGE 61 | ObjC 62 | 63 | 64 | IBVersion 65 | 1 66 | 67 | 68 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | CLASS 17 | NSApplication 18 | LANGUAGE 19 | ObjC 20 | SUPERCLASS 21 | NSResponder 22 | 23 | 24 | ACTIONS 25 | 26 | installUpdate 27 | id 28 | remindMeLater 29 | id 30 | skipThisVersion 31 | id 32 | 33 | CLASS 34 | SUUpdateAlert 35 | LANGUAGE 36 | ObjC 37 | OUTLETS 38 | 39 | delegate 40 | id 41 | description 42 | NSTextField 43 | releaseNotesView 44 | WebView 45 | 46 | SUPERCLASS 47 | SUWindowController 48 | 49 | 50 | CLASS 51 | FirstResponder 52 | LANGUAGE 53 | ObjC 54 | SUPERCLASS 55 | NSObject 56 | 57 | 58 | CLASS 59 | NSObject 60 | LANGUAGE 61 | ObjC 62 | 63 | 64 | IBVersion 65 | 1 66 | 67 | 68 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | CLASS 17 | NSApplication 18 | LANGUAGE 19 | ObjC 20 | SUPERCLASS 21 | NSResponder 22 | 23 | 24 | ACTIONS 25 | 26 | installUpdate 27 | id 28 | remindMeLater 29 | id 30 | skipThisVersion 31 | id 32 | 33 | CLASS 34 | SUUpdateAlert 35 | LANGUAGE 36 | ObjC 37 | OUTLETS 38 | 39 | delegate 40 | id 41 | description 42 | NSTextField 43 | releaseNotesView 44 | WebView 45 | 46 | SUPERCLASS 47 | SUWindowController 48 | 49 | 50 | CLASS 51 | FirstResponder 52 | LANGUAGE 53 | ObjC 54 | SUPERCLASS 55 | NSObject 56 | 57 | 58 | CLASS 59 | NSObject 60 | LANGUAGE 61 | ObjC 62 | 63 | 64 | IBVersion 65 | 1 66 | 67 | 68 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | CLASS 17 | NSApplication 18 | LANGUAGE 19 | ObjC 20 | SUPERCLASS 21 | NSResponder 22 | 23 | 24 | ACTIONS 25 | 26 | installUpdate 27 | id 28 | remindMeLater 29 | id 30 | skipThisVersion 31 | id 32 | 33 | CLASS 34 | SUUpdateAlert 35 | LANGUAGE 36 | ObjC 37 | OUTLETS 38 | 39 | delegate 40 | id 41 | description 42 | NSTextField 43 | releaseNotesView 44 | WebView 45 | 46 | SUPERCLASS 47 | SUWindowController 48 | 49 | 50 | CLASS 51 | FirstResponder 52 | LANGUAGE 53 | ObjC 54 | SUPERCLASS 55 | NSObject 56 | 57 | 58 | CLASS 59 | NSObject 60 | LANGUAGE 61 | ObjC 62 | 63 | 64 | IBVersion 65 | 1 66 | 67 | 68 | -------------------------------------------------------------------------------- /Jenkins MenuTests/Resources/yellow-xml.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | NORMAL 4 | the master Jenkins node 5 | 6 | 3 7 | 8 | activerecord-jdbc-master 9 | http://ci.jruby.org/job/activerecord-jdbc-master/ 10 | blue 11 | 12 | 13 | jruby-test-all-master 14 | http://ci.jruby.org/job/jruby-test-all-master/ 15 | blue_anime 16 | 17 | 18 | jruby-rack-dist 19 | http://ci.jruby.org/job/jruby-rack-dist/ 20 | yellow 21 | 22 | 23 | jruby-solaris 24 | http://ci.jruby.org/job/jruby-solaris/ 25 | yellow_anime 26 | 27 | 28 | jruby-test-master 29 | http://ci.jruby.org/job/jruby-test-master/ 30 | aborted 31 | 32 | 33 | jruby-dist-release 34 | http://ci.jruby.org/job/jruby-dist-release/ 35 | disabled 36 | 37 | 38 | 39 | All 40 | http://ci.jruby.org/ 41 | 42 | false 43 | 32323 44 | 45 | false 46 | true 47 | 48 | All 49 | http://ci.jruby.org/ 50 | 51 | 52 | JRuby Core 53 | http://ci.jruby.org/view/JRuby%20Core/ 54 | 55 | 56 | Rails 57 | http://ci.jruby.org/view/Rails/ 58 | 59 | 60 | Ruboto 61 | http://ci.jruby.org/view/Ruboto/ 62 | 63 | 64 | -------------------------------------------------------------------------------- /Jenkins Menu/JMJenkins.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * https://github.com/qvacua/jenkins-menu 4 | * http://qvacua.com 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import 10 | 11 | @protocol JMJenkinsDelegate; 12 | @class JMTrustedHostManager; 13 | @class JMCredential; 14 | 15 | typedef enum { 16 | JMJenkinsConnectionStateUnknown = 0, 17 | JMJenkinsConnectionStateSuccessful, 18 | JMJenkinsConnectionStateConnectionFailure, 19 | JMJenkinsConnectionStateForbidden, 20 | JMJenkinsConnectionStateNoCredential, 21 | JMJenkinsConnectionStateWrongCredential, 22 | JMJenkinsConnectionStateHttpFailure, 23 | JMJenkinsConnectionStateXmlFailure, 24 | JMJenkinsConnectionStateServerTrustFailure, 25 | JMJenkinsConnectionStateFailure, 26 | } JMJenkinsState; 27 | 28 | typedef enum { 29 | JMJenkinsTotalStateUnknown = 0, 30 | JMJenkinsTotalStateGreen, 31 | JMJenkinsTotalStateYellow, 32 | JMJenkinsTotalStateRed, 33 | } JMJenkinsJobsTotalState; 34 | 35 | static const int qHttpStatusUnknown = -1; 36 | static const int qHttpStatusOk = 200; 37 | static const int qHttpStatusBadRequest = 400; 38 | static const int qHttpForbidden = 403; 39 | static const int qHttpUnauthorized = 401; 40 | 41 | static NSString *const qJenkinsConnectionErrorKey = @"ConnectionFailedErrorKey"; 42 | static NSString *const qJenkinsHttpResponseErrorKey = @"HttpResponseFailedErrorKey"; 43 | 44 | @interface JMJenkins : NSObject 45 | 46 | @property NSURL *url; 47 | @property (readonly) NSURL *xmlUrl; 48 | @property (getter=isSecured) BOOL secured; 49 | @property JMCredential *credential; 50 | @property NSTimeInterval interval; 51 | @property (readonly) NSInteger connectionState; 52 | @property (readonly) NSInteger lastHttpStatusCode; 53 | @property (readonly) NSURL *viewUrl; 54 | @property (readonly) NSArray *allJobs; 55 | @property (readonly) NSArray *jobs; 56 | @property (readonly) NSString *potentialHostToTrust; 57 | @property NSArray *blacklistItems; 58 | 59 | @property id delegate; 60 | @property JMTrustedHostManager *trustedHostManager; 61 | 62 | - (void)update; 63 | - (JMJenkinsJobsTotalState)totalState; 64 | 65 | - (NSUInteger)countOfRedJobs; 66 | - (NSUInteger)countOfYellowJobs; 67 | - (NSUInteger)countOfGreenJobs; 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /Jenkins Menu/JMLog.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * http://qvacua.com 4 | * https://github.com/qvacua 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #ifdef DEBUG 10 | 11 | #ifndef log4Debug 12 | #define log4Debug(format, ...) printf("%s", [[NSString stringWithFormat:(@"[DEBUG] %s - %d: " format "\n"), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__] UTF8String]) 13 | #endif 14 | 15 | #ifndef logPoint4Debug 16 | #define logPoint4Debug(prefix, point) printf("%s", [[NSString stringWithFormat:@"[DEBUG] %s - %d: %@: x: %.2f, y: %.2f\n", __PRETTY_FUNCTION__, __LINE__, prefix, point.x, point.y] UTF8String]) 17 | #endif 18 | 19 | #ifndef logSize4Debug 20 | #define logSize4Debug(prefix, size) printf("%s", [[NSString stringWithFormat:@"[DEBUG] %s - %d: %@: w: %.2f, h: %.2f\n", __PRETTY_FUNCTION__, __LINE__, prefix, size.width, size.height] UTF8String]) 21 | #endif 22 | 23 | #ifndef logRect4Debug 24 | #define logRect4Debug(prefix, rect) printf("%s", [[NSString stringWithFormat:@"[DEBUG] %s - %d: %@: x: %.2f, y: %.2f, w: %.2f, h: %.2f\n", __PRETTY_FUNCTION__, __LINE__, prefix, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height] UTF8String]) 25 | #endif 26 | 27 | #ifndef logMarker 28 | #define logMarker printf("%s", [[NSString stringWithFormat:(@"[DEBUG] %s - %d\n"), __PRETTY_FUNCTION__, __LINE__] UTF8String]) 29 | #endif 30 | #else 31 | 32 | #define log4Debug(...) 33 | #define logPoint4Debug(...) 34 | #define logSize4Debug(...) 35 | #define logRect4Debug(...) 36 | 37 | #endif 38 | 39 | #ifndef log4Info 40 | #define log4Info(format, ...) printf("%s", [[NSString stringWithFormat:(@"[INFO] %s - %d: " format "\n"), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__] UTF8String]) 41 | #endif 42 | 43 | #ifndef log4Warn 44 | #define log4Warn(format, ...) printf("%s", [[NSString stringWithFormat:(@"[WARN] %s - %d: " format "\n"), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__] UTF8String]) 45 | #endif 46 | 47 | #ifndef log4Error 48 | #define log4Error(format, ...) printf("%s", [[NSString stringWithFormat:(@"[ERROR] %s - %d: " format "\n"), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__] UTF8String]) 49 | #endif 50 | 51 | #ifndef log4Fatal 52 | #define log4Fatal(format, ...) printf("%s", [[NSString stringWithFormat:(@"[FATAL] %s - %d: " format "\n"), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__] UTF8String]) 53 | #endif 54 | 55 | -------------------------------------------------------------------------------- /Jenkins MenuTests/Resources/example-xml.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | NORMAL 4 | the master Jenkins node 5 | 6 | 3 7 | 8 | activerecord-jdbc-master 9 | http://ci.jruby.org/job/activerecord-jdbc-master/ 10 | blue 11 | 12 | 13 | jruby-test-all-master 14 | http://ci.jruby.org/job/jruby-test-all-master/ 15 | blue_anime 16 | 17 | 18 | jruby-rack-dist 19 | http://ci.jruby.org/job/jruby-rack-dist/ 20 | yellow 21 | 22 | 23 | jruby-solaris 24 | http://ci.jruby.org/job/jruby-solaris/ 25 | yellow_anime 26 | 27 | 28 | jruby-spec-ci-master 29 | http://ci.jruby.org/job/jruby-spec-ci-master/ 30 | red 31 | 32 | 33 | jruby-ossl 34 | http://ci.jruby.org/job/jruby-ossl/ 35 | red_anime 36 | 37 | 38 | jruby-test-master 39 | http://ci.jruby.org/job/jruby-test-master/ 40 | aborted 41 | 42 | 43 | jruby-dist-release 44 | http://ci.jruby.org/job/jruby-dist-release/ 45 | disabled 46 | 47 | 48 | 49 | All 50 | http://ci.jruby.org/ 51 | 52 | false 53 | 32323 54 | 55 | false 56 | true 57 | 58 | All 59 | http://ci.jruby.org/ 60 | 61 | 62 | JRuby Core 63 | http://ci.jruby.org/view/JRuby%20Core/ 64 | 65 | 66 | Rails 67 | http://ci.jruby.org/view/Rails/ 68 | 69 | 70 | Ruboto 71 | http://ci.jruby.org/view/Ruboto/ 72 | 73 | 74 | -------------------------------------------------------------------------------- /Jenkins Menu/JMAppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * https://github.com/qvacua/jenkins-menu 4 | * http://qvacua.com 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import 10 | #import 11 | #import "JMJenkinsDelegate.h" 12 | 13 | @class JMTrustedHostManager; 14 | @class JMKeychainManager; 15 | 16 | static NSString *const qUserDefaultsUrlKey = @"jenkinsUrl"; 17 | static NSString *const qUserDefaultsIntervalKey = @"interval"; 18 | static NSString *const qUserDefaultsSecuredKey = @"fds"; // ups... 19 | static NSString *const qUserDefaultsBlacklistItemsKey = @"blacklistItems"; 20 | static NSString *const qUserDefaultsShowDisabledJobs = @"showDisabledJobs"; 21 | static const NSInteger qBlacklistItemAddSegment = 0; 22 | static const NSInteger qBlacklistItemRemoveSegment = 1; 23 | 24 | @interface JMAppDelegate : NSObject 25 | 26 | @property (weak) IBOutlet NSMenu *menu; 27 | @property (weak) IBOutlet NSMenuItem *jobsMenuItem; 28 | @property (weak) IBOutlet NSMenuItem *statusMenuItem; 29 | 30 | @property (unsafe_unretained) IBOutlet NSWindow *preferencesWindow; 31 | @property (weak) IBOutlet NSTextField *urlTextField; 32 | @property (weak) IBOutlet NSTextField *intervalTextField; 33 | 34 | @property (unsafe_unretained) IBOutlet NSWindow *credentialsWindow; 35 | @property (weak) IBOutlet NSTextField *userTextField; 36 | @property (weak) IBOutlet NSSecureTextField *passwordTextField; 37 | @property (weak) IBOutlet NSButton *storeInKeychanCheckbox; 38 | 39 | @property NSMutableArray *tempBlacklistItems; 40 | @property (unsafe_unretained) IBOutlet NSWindow *blacklistWindow; 41 | @property (weak) IBOutlet NSTableView *blacklistTableView; 42 | @property (weak) IBOutlet NSSegmentedControl *blacklistItemSegmentedControl; 43 | 44 | @property BOOL showDisabledJobs; 45 | 46 | @property NSStatusItem *statusItem; 47 | @property NSTimer *timer; 48 | @property NSUserDefaults *userDefaults; 49 | @property JMKeychainManager *keychainManager; 50 | 51 | @property JMTrustedHostManager *trustedHostManager; 52 | @property JMJenkins *jenkins; 53 | @property NSURL *jenkinsUrl; 54 | @property NSURL *jenkinsXmlUrl; 55 | @property NSTimeInterval interval; 56 | 57 | - (IBAction)updateNowAction:(id)sender; 58 | - (IBAction)openJenkinsUrlAction:(id)sender; 59 | - (IBAction)openPreferencesWindowAction:(id)sender; 60 | - (IBAction)setPreferencesAction:(id)sender; 61 | 62 | - (IBAction)manageBlacklistAction:(id)sender; 63 | - (IBAction)blacklistItemAction:(id)sender; 64 | - (IBAction)blacklistOkAction:(id)sender; 65 | 66 | - (IBAction)credentialsOkAction:(id)sender; 67 | - (IBAction)credentialsCancelAction:(id)sender; 68 | - (IBAction)storeInKeychainToggleAction:(id)sender; 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /Jenkins MenuTests/JMTrustedHostManagerTest.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * https://github.com/qvacua/jenkins-menu 4 | * http://qvacua.com 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import 10 | #import "JMBaseTestCase.h" 11 | #import "JMJenkinsJob.h" 12 | #import "JMTrustedHostManager.h" 13 | 14 | @interface JMTrustedHostManagerTest : JMBaseTestCase 15 | @end 16 | 17 | @implementation JMTrustedHostManagerTest { 18 | JMTrustedHostManager *trustedHostManager; 19 | NSUserDefaults *userDefaults; 20 | 21 | Method originalMethod; 22 | IMP originalImpl; 23 | } 24 | 25 | - (void)setUp { 26 | [super setUp]; 27 | 28 | [self exchangeSystemStatusBarClassMethod]; 29 | 30 | userDefaults = mock([NSUserDefaults class]); 31 | 32 | trustedHostManager = [[JMTrustedHostManager alloc] init]; 33 | trustedHostManager.userDefaults = userDefaults; 34 | } 35 | 36 | - (void)tearDown { 37 | method_setImplementation(originalMethod, originalImpl); 38 | 39 | [super tearDown]; 40 | } 41 | 42 | - (void)testInit { 43 | JMTrustedHostManager *manager = [[JMTrustedHostManager alloc] init]; 44 | assertThat(manager.userDefaults, is([NSUserDefaults standardUserDefaults])); 45 | } 46 | 47 | - (void)testOnceTrustHost { 48 | [trustedHostManager onceTrustHost:@"http://some/host"]; 49 | assertThat(@([trustedHostManager shouldTrustHost:@"http://some/host"]), isYes); 50 | assertThat(@([trustedHostManager shouldTrustHost:@"http://some/host"]), isNo); 51 | 52 | [trustedHostManager onceTrustHost:@"http://some/host"]; 53 | assertThat(@([trustedHostManager shouldTrustHost:@"http://some/host"]), isYes); 54 | assertThat(@([trustedHostManager shouldTrustHost:@"http://some/host"]), isNo); 55 | } 56 | 57 | - (void)testShouldTrustHost { 58 | [given([userDefaults arrayForKey:qDefaultTrustedHostsKey]) willReturn:@[ 59 | @"http://some/host", 60 | @"http://some/other/host", 61 | ]]; 62 | 63 | assertThat(@([trustedHostManager shouldTrustHost:@"http://some/other/host"]), isYes); 64 | assertThat(@([trustedHostManager shouldTrustHost:@"http://yet/another/host"]), isNo); 65 | } 66 | 67 | - (void)testTrustHost { 68 | [given([userDefaults arrayForKey:qDefaultTrustedHostsKey]) willReturn:@[ 69 | @"http://some/host", 70 | @"http://some/other/host", 71 | ]]; 72 | 73 | [trustedHostManager permanentlyTrustHost:@"http://yet/another/host"]; 74 | 75 | [verify(userDefaults) setObject:@[ 76 | @"http://some/host", 77 | @"http://some/other/host", 78 | @"http://yet/another/host" 79 | ] forKey:qDefaultTrustedHostsKey]; 80 | } 81 | 82 | #pragma mark Private 83 | - (void)exchangeSystemStatusBarClassMethod { 84 | Method testMethod = class_getInstanceMethod([self class], @selector(mockSystemStatusBar)); 85 | IMP testImpl = method_getImplementation(testMethod); 86 | 87 | originalMethod = class_getClassMethod([NSStatusBar class], @selector(systemStatusBar)); 88 | originalImpl = method_setImplementation(originalMethod, testImpl); 89 | } 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /Jenkins Menu.xcodeproj/xcshareddata/xcschemes/Jenkins Menu.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Jenkins Menu.xcodeproj/xcuserdata/gileadis.xcuserdatad/xcschemes/Jenkins Menu.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Frameworks/Growl.framework/Versions/A/Headers/GrowlPluginPreferenceStrings.h: -------------------------------------------------------------------------------- 1 | // 2 | // GrowlPluginPreferenceStrings.h 3 | // Growl 4 | // 5 | // Created by Daniel Siemer on 1/30/12. 6 | // Copyright (c) 2012 The Growl Project. All rights reserved. 7 | // 8 | 9 | /* FOR GROWL DEVELOPED COCOA PLUGINS ONLY AT THIS TIME, NOT STABLE */ 10 | 11 | #import 12 | 13 | #define GrowlDisplayOpacity NSLocalizedStringFromTable(@"Opacity:", @"PluginPrefStrings", @"How clear the display is") 14 | #define GrowlDisplayDuration NSLocalizedStringFromTable(@"Duration:", @"PluginPrefStrings", @"How long a notification will stay on screen") 15 | 16 | #define GrowlDisplayPriority NSLocalizedStringFromTable(@"Priority: (low to high)", @"PluginPrefStrings", @"Label for columns of color wells for various priority levels") 17 | #define GrowlDisplayPriorityLow NSLocalizedStringFromTable(@"Very Low", @"PluginPrefStrings", @"Notification Priority Very Low") 18 | #define GrowlDisplayPriorityModerate NSLocalizedStringFromTable(@"Moderate", @"PluginPrefStrings", @"Notification Priority Moderate") 19 | #define GrowlDisplayPriorityNormal NSLocalizedStringFromTable(@"Normal", @"PluginPrefStrings", @"Notification Priority Normal") 20 | #define GrowlDisplayPriorityHigh NSLocalizedStringFromTable(@"High", @"PluginPrefStrings", @"Notification Priority High") 21 | #define GrowlDisplayPriorityEmergency NSLocalizedStringFromTable(@"Emergency", @"PluginPrefStrings", @"Notification Priority Emergency") 22 | 23 | #define GrowlDisplayTextColor NSLocalizedStringFromTable(@"Text", @"PluginPrefStrings", @"Label for row of color wells for the text element of the plugin") 24 | #define GrowlDisplayBackgroundColor NSLocalizedStringFromTable(@"Background", @"PluginPrefStrings", @"Label for row of color wells for the background of the plugin") 25 | 26 | #define GrowlDisplayLimitLines NSLocalizedStringFromTable(@"Limit to 2-5 lines", @"PluginPrefStrings", @"Checkbox to limit the display to 2-5 lines") 27 | #define GrowlDisplayScreen NSLocalizedStringFromTable(@"Screen:", @"PluginPrefStrings", @"Label for box to select screen for display to use") 28 | #define GrowlDisplaySize NSLocalizedStringFromTable(@"Size:", @"PluginPrefStrings", @"Label for pop up box for selecting the size of the display") 29 | #define GrowlDisplaySizeNormal NSLocalizedStringFromTable(@"Normal", @"PluginPrefStrings", @"Normal size for the display") 30 | #define GrowlDisplaySizeLarge NSLocalizedStringFromTable(@"Large", @"PluginPrefStrings", @"Large size for the display") 31 | #define GrowlDisplaySizeSmall NSLocalizedStringFromTable(@"Small", @"PluginPrefStrings", @"Small size for the display") 32 | 33 | #define GrowlDisplayFloatingIcon NSLocalizedStringFromTable(@"Floating Icon", @"PluginPrefStrings", @"Label for checkbox that says to do a floating icon") 34 | 35 | #define GrowlDisplayEffect NSLocalizedStringFromTable(@"Effect:", @"PluginPrefStrings", @"Label for the effect to use") 36 | #define GrowlDisplayEffectSlide NSLocalizedStringFromTable(@"Slide", @"PluginPrefStrings", @"A slide effect") 37 | #define GrowlDisplayEffectFade NSLocalizedStringFromTable(@"Fade", @"PluginPrefStrings", @"A fade effect") 38 | 39 | @interface GrowlPluginPreferenceStrings : NSObject 40 | 41 | @property (nonatomic, retain) NSString *growlDisplayOpacity; 42 | @property (nonatomic, retain) NSString *growlDisplayDuration; 43 | 44 | @property (nonatomic, retain) NSString *growlDisplayPriority; 45 | @property (nonatomic, retain) NSString *growlDisplayPriorityVeryLow; 46 | @property (nonatomic, retain) NSString *growlDisplayPriorityModerate; 47 | @property (nonatomic, retain) NSString *growlDisplayPriorityNormal; 48 | @property (nonatomic, retain) NSString *growlDisplayPriorityHigh; 49 | @property (nonatomic, retain) NSString *growlDisplayPriorityEmergency; 50 | 51 | @property (nonatomic, retain) NSString *growlDisplayTextColor; 52 | @property (nonatomic, retain) NSString *growlDisplayBackgroundColor; 53 | 54 | @property (nonatomic, retain) NSString *growlDisplayLimitLines; 55 | @property (nonatomic, retain) NSString *growlDisplayScreen; 56 | @property (nonatomic, retain) NSString *growlDisplaySize; 57 | @property (nonatomic, retain) NSString *growlDisplaySizeNormal; 58 | @property (nonatomic, retain) NSString *growlDisplaySizeLarge; 59 | @property (nonatomic, retain) NSString *growlDisplaySizeSmall; 60 | 61 | @property (nonatomic, retain) NSString *growlDisplayFloatingIcon; 62 | 63 | @property (nonatomic, retain) NSString *effectLabel; 64 | @property (nonatomic, retain) NSString *slideEffect; 65 | @property (nonatomic, retain) NSString *fadeEffect; 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Headers/SUUpdater.h: -------------------------------------------------------------------------------- 1 | // 2 | // SUUpdater.h 3 | // Sparkle 4 | // 5 | // Created by Andy Matuschak on 1/4/06. 6 | // Copyright 2006 Andy Matuschak. All rights reserved. 7 | // 8 | 9 | #ifndef SUUPDATER_H 10 | #define SUUPDATER_H 11 | 12 | #import 13 | 14 | @class SUUpdateDriver, SUAppcastItem, SUHost, SUAppcast; 15 | @interface SUUpdater : NSObject { 16 | NSTimer *checkTimer; 17 | SUUpdateDriver *driver; 18 | 19 | SUHost *host; 20 | IBOutlet id delegate; 21 | } 22 | 23 | + (SUUpdater *)sharedUpdater; 24 | + (SUUpdater *)updaterForBundle:(NSBundle *)bundle; 25 | - (NSBundle *)hostBundle; 26 | 27 | - (void)setDelegate:(id)delegate; 28 | - delegate; 29 | 30 | - (void)setAutomaticallyChecksForUpdates:(BOOL)automaticallyChecks; 31 | - (BOOL)automaticallyChecksForUpdates; 32 | 33 | - (void)setUpdateCheckInterval:(NSTimeInterval)interval; 34 | - (NSTimeInterval)updateCheckInterval; 35 | 36 | - (void)setFeedURL:(NSURL *)feedURL; 37 | - (NSURL *)feedURL; 38 | 39 | - (void)setSendsSystemProfile:(BOOL)sendsSystemProfile; 40 | - (BOOL)sendsSystemProfile; 41 | 42 | - (void)setAutomaticallyDownloadsUpdates:(BOOL)automaticallyDownloadsUpdates; 43 | - (BOOL)automaticallyDownloadsUpdates; 44 | 45 | // This IBAction is meant for a main menu item. Hook up any menu item to this action, 46 | // and Sparkle will check for updates and report back its findings verbosely. 47 | - (IBAction)checkForUpdates:sender; 48 | 49 | // This kicks off an update meant to be programmatically initiated. That is, it will display no UI unless it actually finds an update, 50 | // in which case it proceeds as usual. If the fully automated updating is turned on, however, this will invoke that behavior, and if an 51 | // update is found, it will be downloaded and prepped for installation. 52 | - (void)checkForUpdatesInBackground; 53 | 54 | // Date of last update check. Returns null if no check has been performed. 55 | - (NSDate*)lastUpdateCheckDate; 56 | 57 | // This begins a "probing" check for updates which will not actually offer to update to that version. The delegate methods, though, 58 | // (up to updater:didFindValidUpdate: and updaterDidNotFindUpdate:), are called, so you can use that information in your UI. 59 | - (void)checkForUpdateInformation; 60 | 61 | // Call this to appropriately schedule or cancel the update checking timer according to the preferences for time interval and automatic checks. This call does not change the date of the next check, but only the internal NSTimer. 62 | - (void)resetUpdateCycle; 63 | 64 | - (BOOL)updateInProgress; 65 | @end 66 | 67 | @interface NSObject (SUUpdaterDelegateInformalProtocol) 68 | // This method allows you to add extra parameters to the appcast URL, potentially based on whether or not Sparkle will also be sending along the system profile. This method should return an array of dictionaries with keys: "key", "value", "displayKey", "displayValue", the latter two being specifically for display to the user. 69 | - (NSArray *)feedParametersForUpdater:(SUUpdater *)updater sendingSystemProfile:(BOOL)sendingProfile; 70 | 71 | // Use this to override the default behavior for Sparkle prompting the user about automatic update checks. 72 | - (BOOL)updaterShouldPromptForPermissionToCheckForUpdates:(SUUpdater *)bundle; 73 | 74 | // Implement this if you want to do some special handling with the appcast once it finishes loading. 75 | - (void)updater:(SUUpdater *)updater didFinishLoadingAppcast:(SUAppcast *)appcast; 76 | 77 | // If you're using special logic or extensions in your appcast, implement this to use your own logic for finding 78 | // a valid update, if any, in the given appcast. 79 | - (SUAppcastItem *)bestValidUpdateInAppcast:(SUAppcast *)appcast forUpdater:(SUUpdater *)bundle; 80 | 81 | // Sent when a valid update is found by the update driver. 82 | - (void)updater:(SUUpdater *)updater didFindValidUpdate:(SUAppcastItem *)update; 83 | 84 | // Sent when a valid update is not found. 85 | - (void)updaterDidNotFindUpdate:(SUUpdater *)update; 86 | 87 | // Sent immediately before installing the specified update. 88 | - (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)update; 89 | 90 | // Return YES to delay the relaunch until you do some processing; invoke the given NSInvocation to continue. 91 | - (BOOL)updater:(SUUpdater *)updater shouldPostponeRelaunchForUpdate:(SUAppcastItem *)update untilInvoking:(NSInvocation *)invocation; 92 | 93 | // Called immediately before relaunching. 94 | - (void)updaterWillRelaunchApplication:(SUUpdater *)updater; 95 | 96 | // This method allows you to provide a custom version comparator. 97 | // If you don't implement this method or return nil, the standard version comparator will be used. 98 | - (id )versionComparatorForUpdater:(SUUpdater *)updater; 99 | 100 | // Returns the path which is used to relaunch the client after the update is installed. By default, the path of the host bundle. 101 | - (NSString *)pathToRelaunchForUpdater:(SUUpdater *)updater; 102 | 103 | @end 104 | 105 | // Define some minimum intervals to avoid DOS-like checking attacks. These are in seconds. 106 | #ifdef DEBUG 107 | #define SU_MIN_CHECK_INTERVAL 60 108 | #else 109 | #define SU_MIN_CHECK_INTERVAL 60*60 110 | #endif 111 | 112 | #ifdef DEBUG 113 | #define SU_DEFAULT_CHECK_INTERVAL 60 114 | #else 115 | #define SU_DEFAULT_CHECK_INTERVAL 60*60*24 116 | #endif 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /Frameworks/Sparkle.framework/Versions/A/Resources/SUModelTranslation.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ADP2,1 6 | Developer Transition Kit 7 | MacBook1,1 8 | MacBook (Core Duo) 9 | MacBook2,1 10 | MacBook (Core 2 Duo) 11 | MacBook4,1 12 | MacBook (Core 2 Duo Feb 2008) 13 | MacBookAir1,1 14 | MacBook Air (January 2008) 15 | MacBookPro1,1 16 | MacBook Pro Core Duo (15-inch) 17 | MacBookPro1,2 18 | MacBook Pro Core Duo (17-inch) 19 | MacBookPro2,1 20 | MacBook Pro Core 2 Duo (17-inch) 21 | MacBookPro2,2 22 | MacBook Pro Core 2 Duo (15-inch) 23 | MacBookPro3,1 24 | MacBook Pro Core 2 Duo (15-inch LED, Core 2 Duo) 25 | MacBookPro3,2 26 | MacBook Pro Core 2 Duo (17-inch HD, Core 2 Duo) 27 | MacBookPro4,1 28 | MacBook Pro (Core 2 Duo Feb 2008) 29 | MacPro1,1 30 | Mac Pro (four-core) 31 | MacPro2,1 32 | Mac Pro (eight-core) 33 | MacPro3,1 34 | Mac Pro (January 2008 4- or 8- core "Harpertown") 35 | Macmini1,1 36 | Mac Mini (Core Solo/Duo) 37 | PowerBook1,1 38 | PowerBook G3 39 | PowerBook2,1 40 | iBook G3 41 | PowerBook2,2 42 | iBook G3 (FireWire) 43 | PowerBook2,3 44 | iBook G3 45 | PowerBook2,4 46 | iBook G3 47 | PowerBook3,1 48 | PowerBook G3 (FireWire) 49 | PowerBook3,2 50 | PowerBook G4 51 | PowerBook3,3 52 | PowerBook G4 (Gigabit Ethernet) 53 | PowerBook3,4 54 | PowerBook G4 (DVI) 55 | PowerBook3,5 56 | PowerBook G4 (1GHz / 867MHz) 57 | PowerBook4,1 58 | iBook G3 (Dual USB, Late 2001) 59 | PowerBook4,2 60 | iBook G3 (16MB VRAM) 61 | PowerBook4,3 62 | iBook G3 Opaque 16MB VRAM, 32MB VRAM, Early 2003) 63 | PowerBook5,1 64 | PowerBook G4 (17 inch) 65 | PowerBook5,2 66 | PowerBook G4 (15 inch FW 800) 67 | PowerBook5,3 68 | PowerBook G4 (17-inch 1.33GHz) 69 | PowerBook5,4 70 | PowerBook G4 (15 inch 1.5/1.33GHz) 71 | PowerBook5,5 72 | PowerBook G4 (17-inch 1.5GHz) 73 | PowerBook5,6 74 | PowerBook G4 (15 inch 1.67GHz/1.5GHz) 75 | PowerBook5,7 76 | PowerBook G4 (17-inch 1.67GHz) 77 | PowerBook5,8 78 | PowerBook G4 (Double layer SD, 15 inch) 79 | PowerBook5,9 80 | PowerBook G4 (Double layer SD, 17 inch) 81 | PowerBook6,1 82 | PowerBook G4 (12 inch) 83 | PowerBook6,2 84 | PowerBook G4 (12 inch, DVI) 85 | PowerBook6,3 86 | iBook G4 87 | PowerBook6,4 88 | PowerBook G4 (12 inch 1.33GHz) 89 | PowerBook6,5 90 | iBook G4 (Early-Late 2004) 91 | PowerBook6,7 92 | iBook G4 (Mid 2005) 93 | PowerBook6,8 94 | PowerBook G4 (12 inch 1.5GHz) 95 | PowerMac1,1 96 | Power Macintosh G3 (Blue & White) 97 | PowerMac1,2 98 | Power Macintosh G4 (PCI Graphics) 99 | PowerMac10,1 100 | Mac Mini G4 101 | PowerMac10,2 102 | Mac Mini (Late 2005) 103 | PowerMac11,2 104 | Power Macintosh G5 (Late 2005) 105 | PowerMac12,1 106 | iMac G5 (iSight) 107 | PowerMac2,1 108 | iMac G3 (Slot-loading CD-ROM) 109 | PowerMac2,2 110 | iMac G3 (Summer 2000) 111 | PowerMac3,1 112 | Power Macintosh G4 (AGP Graphics) 113 | PowerMac3,2 114 | Power Macintosh G4 (AGP Graphics) 115 | PowerMac3,3 116 | Power Macintosh G4 (Gigabit Ethernet) 117 | PowerMac3,4 118 | Power Macintosh G4 (Digital Audio) 119 | PowerMac3,5 120 | Power Macintosh G4 (Quick Silver) 121 | PowerMac3,6 122 | Power Macintosh G4 (Mirrored Drive Door) 123 | PowerMac4,1 124 | iMac G3 (Early/Summer 2001) 125 | PowerMac4,2 126 | iMac G4 (Flat Panel) 127 | PowerMac4,4 128 | eMac 129 | PowerMac4,5 130 | iMac G4 (17-inch Flat Panel) 131 | PowerMac5,1 132 | Power Macintosh G4 Cube 133 | PowerMac6,1 134 | iMac G4 (USB 2.0) 135 | PowerMac6,3 136 | iMac G4 (20-inch Flat Panel) 137 | PowerMac6,4 138 | eMac (USB 2.0, 2005) 139 | PowerMac7,2 140 | Power Macintosh G5 141 | PowerMac7,3 142 | Power Macintosh G5 143 | PowerMac8,1 144 | iMac G5 145 | PowerMac8,2 146 | iMac G5 (Ambient Light Sensor) 147 | PowerMac9,1 148 | Power Macintosh G5 (Late 2005) 149 | RackMac1,1 150 | Xserve G4 151 | RackMac1,2 152 | Xserve G4 (slot-loading, cluster node) 153 | RackMac3,1 154 | Xserve G5 155 | Xserve1,1 156 | Xserve (Intel Xeon) 157 | Xserve2,1 158 | Xserve (January 2008 quad-core) 159 | iMac1,1 160 | iMac G3 (Rev A-D) 161 | iMac4,1 162 | iMac (Core Duo) 163 | iMac4,2 164 | iMac for Education (17-inch, Core Duo) 165 | iMac5,1 166 | iMac (Core 2 Duo, 17 or 20 inch, SuperDrive) 167 | iMac5,2 168 | iMac (Core 2 Duo, 17 inch, Combo Drive) 169 | iMac6,1 170 | iMac (Core 2 Duo, 24 inch, SuperDrive) 171 | iMac8,1 172 | iMac (April 2008) 173 | 174 | 175 | -------------------------------------------------------------------------------- /Jenkins Menu/JMKeychainManager.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * http://qvacua.com 4 | * https://github.com/qvacua 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import "JMKeychainManager.h" 10 | 11 | @implementation JMCredential 12 | 13 | @synthesize username = _username; 14 | @synthesize password = _password; 15 | 16 | - (id)initWithUsername:(NSString *)username password:(NSString *)password { 17 | self = [super init]; 18 | if (self) { 19 | _username = username; 20 | _password = password; 21 | } 22 | 23 | return self; 24 | } 25 | 26 | @end 27 | 28 | @interface JMKeychainManager () 29 | 30 | @property (readwrite) NSString *lastErrorMessage; 31 | 32 | @end 33 | 34 | @implementation JMKeychainManager { 35 | } 36 | 37 | @synthesize lastErrorMessage = _lastErrorMessage; 38 | 39 | - (JMCredential *)credentialForUrl:(NSURL *)url { 40 | NSString *host = url.host; 41 | NSString *path = url.path; 42 | 43 | UInt32 passwordLength = 0; 44 | void *passwordBuffer = NULL; 45 | SecKeychainItemRef keychainItem = NULL; 46 | OSStatus err = SecKeychainFindInternetPassword( 47 | NULL, // keychain, NULL == default one 48 | (UInt32) host.length, host.UTF8String, // serverName 49 | 0, NULL, // securityDomain 50 | 0, NULL, // no accountName 51 | (UInt32) path.length, path.UTF8String, // path 52 | (UInt16) url.port.intValue, // port 53 | kSecProtocolTypeHTTP, // protocol 54 | kSecAuthenticationTypeHTTPBasic, // authType 55 | &passwordLength, &passwordBuffer, // no password 56 | &keychainItem // keychain item 57 | ); 58 | 59 | if (err) { 60 | self.lastErrorMessage = [self errorMessageFromOsStatus:err]; 61 | return nil; 62 | } 63 | 64 | NSString *password = [self passwordFromKeychainBuffer:passwordBuffer length:passwordLength]; 65 | NSString *username = [self usernameFromKeychainItem:keychainItem]; 66 | 67 | SecKeychainItemFreeContent(NULL, passwordBuffer); 68 | CFRelease(keychainItem); 69 | 70 | if (username == nil) { 71 | return nil; 72 | } 73 | 74 | if (password == nil) { 75 | self.lastErrorMessage = [NSString stringWithFormat:NSLocalizedString(@"ErrorKeychainItem", @"There was an error obtaining the keychain item for %@"), url]; 76 | return nil; 77 | } 78 | 79 | return [[JMCredential alloc] initWithUsername:username password:password]; 80 | } 81 | 82 | - (BOOL)storeCredential:(JMCredential *)credential forUrl:(NSURL *)url { 83 | [self deleteExistingKeychainItemForUrl:url credential:credential]; 84 | 85 | NSString *host = url.host; 86 | NSString *path = url.path; 87 | 88 | OSStatus err = SecKeychainAddInternetPassword( 89 | NULL, // keychain 90 | (UInt32) host.length, host.UTF8String, // serverName 91 | 0, NULL, // securityDomain 92 | (UInt32) credential.username.length, credential.username.UTF8String, // accountName 93 | (UInt32) path.length, path.UTF8String, // path 94 | (UInt16) url.port.intValue, // port 95 | kSecProtocolTypeHTTP, // protocol 96 | kSecAuthenticationTypeHTTPBasic, // authenticationType 97 | (UInt32) credential.password.length, credential.password.UTF8String, // password 98 | NULL // keychain item 99 | ); 100 | 101 | if (err) { 102 | self.lastErrorMessage = [self errorMessageFromOsStatus:err]; 103 | return NO; 104 | } 105 | 106 | return YES; 107 | } 108 | 109 | - (void)deleteExistingKeychainItemForUrl:(NSURL *)url credential:(JMCredential *)credential { 110 | NSString *host = url.host; 111 | NSString *path = url.path; 112 | NSString *username = credential.username; 113 | 114 | SecKeychainItemRef keychainItem = NULL; 115 | SecKeychainFindInternetPassword( 116 | NULL, // keychain, NULL == default one 117 | (UInt32) host.length, host.UTF8String, // serverName 118 | 0, NULL, // securityDomain 119 | (UInt32) username.length, username.UTF8String, // no accountName 120 | (UInt32) path.length, path.UTF8String, // path 121 | (UInt16) url.port.intValue, // port 122 | kSecProtocolTypeHTTP, // protocol 123 | kSecAuthenticationTypeHTTPBasic, // authType 124 | NULL, NULL, // no password 125 | &keychainItem // keychain item 126 | ); 127 | 128 | if (keychainItem == NULL) { 129 | return; 130 | } 131 | 132 | SecKeychainItemDelete(keychainItem); 133 | CFRelease(keychainItem); 134 | } 135 | 136 | #pragma mark Private 137 | - (NSString *)errorMessageFromOsStatus:(OSStatus)err { 138 | CFStringRef errorStr = SecCopyErrorMessageString(err, NULL); 139 | NSString *errorMsg = [NSString stringWithString:(__bridge NSString *) errorStr]; 140 | CFRelease(errorStr); 141 | 142 | return errorMsg; 143 | } 144 | 145 | - (NSString *)usernameFromKeychainItem:(SecKeychainItemRef)keychainItem { 146 | UInt32 attributeTags[1] = {kSecAccountItemAttr}; 147 | UInt32 formatConstants[1] = {CSSM_DB_ATTRIBUTE_FORMAT_STRING}; 148 | 149 | SecKeychainAttributeInfo attributeInfo; 150 | attributeInfo.count = 1; 151 | attributeInfo.tag = attributeTags; 152 | attributeInfo.format = formatConstants; 153 | 154 | SecKeychainAttributeList *attributeList = nil; 155 | OSStatus err = SecKeychainItemCopyAttributesAndData(keychainItem, &attributeInfo, NULL, &attributeList, 0, NULL); 156 | 157 | if (err) { 158 | self.lastErrorMessage = [self errorMessageFromOsStatus:err]; 159 | return nil; 160 | } 161 | 162 | SecKeychainAttribute accountNameAttribute = attributeList->attr[0]; 163 | NSString *username = [[NSString alloc] initWithBytes:accountNameAttribute.data length:accountNameAttribute.length encoding:NSUTF8StringEncoding]; 164 | return username; 165 | } 166 | 167 | - (NSString *)passwordFromKeychainBuffer:(void *)passwordBuffer length:(UInt32)passwordLength { 168 | NSString *password = [[NSString alloc] initWithBytes:passwordBuffer length:passwordLength encoding:NSUTF8StringEncoding]; 169 | return password; 170 | } 171 | 172 | @end 173 | -------------------------------------------------------------------------------- /Jenkins MenuTests/JMAppDelegateTest.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * https://github.com/qvacua/jenkins-menu 4 | * http://qvacua.com 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import "JMBaseTestCase.h" 10 | #import "JMJenkinsJob.h" 11 | #import "JMAppDelegate.h" 12 | #import "JMJenkins.h" 13 | #import "JMKeychainManager.h" 14 | #import 15 | 16 | @interface JMAppDelegateTest : JMBaseTestCase 17 | @end 18 | 19 | @implementation JMAppDelegateTest { 20 | JMAppDelegate *appDelegate; 21 | 22 | NSUserDefaults *userDefaults; 23 | JMKeychainManager *keychainManager; 24 | JMJenkins *mockJenkins; 25 | 26 | Method originalMethod; 27 | IMP originalImpl; 28 | 29 | NSTableView *tableView; 30 | } 31 | 32 | - (void)setUp { 33 | [super setUp]; 34 | 35 | [self exchangeSystemStatusBarClassMethod]; 36 | 37 | userDefaults = mock([NSUserDefaults class]); 38 | keychainManager = mock([JMKeychainManager class]); 39 | mockJenkins = mock([JMJenkins class]); 40 | 41 | tableView = mock([NSTableView class]); 42 | 43 | appDelegate = [[JMAppDelegate alloc] init]; 44 | appDelegate.userDefaults = userDefaults; 45 | appDelegate.keychainManager = keychainManager; 46 | 47 | appDelegate.blacklistTableView = tableView; 48 | } 49 | 50 | - (void)tearDown { 51 | method_setImplementation(originalMethod, originalImpl); 52 | 53 | [super tearDown]; 54 | } 55 | 56 | - (void)testInit { 57 | appDelegate = [[JMAppDelegate alloc] init]; 58 | 59 | assertThat(appDelegate.userDefaults, is([NSUserDefaults standardUserDefaults])); 60 | assertThat(appDelegate.keychainManager, isNot(nilValue())); 61 | assertThat(appDelegate.jenkins, isNot(nilValue())); 62 | assertThat(appDelegate.trustedHostManager, isNot(nilValue())); 63 | assertThat(appDelegate.jenkins.trustedHostManager, is(appDelegate.trustedHostManager)); 64 | } 65 | 66 | - (void)testJenkinsForbiddenCredentialExistsInKeychain { 67 | NSURL *url = [NSURL URLWithString:@"http://localhost:8080"]; 68 | JMCredential *credential = [[JMCredential alloc] initWithUsername:@"user" password:@"pw"]; 69 | 70 | appDelegate.jenkins = mockJenkins; 71 | appDelegate.jenkinsUrl = url; 72 | 73 | [given([mockJenkins isSecured]) willReturnBool:YES]; 74 | [given([keychainManager credentialForUrl:appDelegate.jenkinsXmlUrl]) willReturn:credential]; 75 | 76 | [appDelegate jenkins:mockJenkins forbidden:nil]; 77 | [verify(mockJenkins) setCredential:credential]; 78 | [verify(mockJenkins) update]; 79 | } 80 | 81 | - (void)testBlacklistItemAddAction { 82 | NSUInteger oldCount = appDelegate.tempBlacklistItems.count; 83 | 84 | NSSegmentedControl *segControl = mock([NSSegmentedControl class]); 85 | [given([segControl selectedSegment]) willReturnInteger:qBlacklistItemAddSegment]; 86 | [appDelegate blacklistItemAction:segControl]; 87 | 88 | assertThat(appDelegate.tempBlacklistItems, hasSize(oldCount + 1)); 89 | assertThat(appDelegate.tempBlacklistItems.lastObject, is(@"")); 90 | [verify(tableView) reloadData]; 91 | [verify(tableView) selectRowIndexes:[NSIndexSet indexSetWithIndex:oldCount] byExtendingSelection:NO]; 92 | [verify(tableView) editColumn:0 row:oldCount withEvent:nil select:YES]; 93 | } 94 | 95 | - (void)testBlacklistItemRemoveAction { 96 | [appDelegate.tempBlacklistItems addObject:@"oldItem"]; 97 | NSUInteger oldCount = appDelegate.tempBlacklistItems.count; 98 | 99 | NSSegmentedControl *segControl = mock([NSSegmentedControl class]); 100 | [given([segControl selectedSegment]) willReturnInteger:qBlacklistItemRemoveSegment]; 101 | [appDelegate blacklistItemAction:segControl]; 102 | 103 | assertThat(appDelegate.tempBlacklistItems, hasSize(oldCount - 1)); 104 | [verify(tableView) reloadData]; 105 | } 106 | 107 | - (void)testAppDidFinishLaunching { 108 | JMJenkins *jenkins = appDelegate.jenkins; 109 | [given([userDefaults objectForKey:qUserDefaultsUrlKey]) willReturn:@"http://some/host"]; 110 | [given([userDefaults objectForKey:qUserDefaultsIntervalKey]) willReturn:@18]; 111 | [given([userDefaults boolForKey:qUserDefaultsSecuredKey]) willReturn:@(YES)]; 112 | 113 | [appDelegate applicationDidFinishLaunching:nil]; 114 | 115 | assertThat(jenkins.delegate, is(appDelegate)); 116 | assertThat(@(jenkins.interval), is(@18)); 117 | assertThat(jenkins.url, is([NSURL URLWithString:@"http://some/host"])); 118 | assertThat(@(jenkins.secured), isYes); 119 | } 120 | 121 | - (void)testAppDidFinishLaunchingOldXmlUrlInDefaults { 122 | JMJenkins *jenkins = appDelegate.jenkins; 123 | [given([userDefaults objectForKey:qUserDefaultsUrlKey]) willReturn:@"http://some/host/api/xml"]; 124 | [given([userDefaults objectForKey:qUserDefaultsIntervalKey]) willReturn:@18]; 125 | 126 | [appDelegate applicationDidFinishLaunching:nil]; 127 | 128 | assertThat(jenkins.url, is([NSURL URLWithString:@"http://some/host"])); 129 | } 130 | 131 | - (void)testAppDidFinishLaunchingOldXmlUrlInDefaultsWithSlash { 132 | JMJenkins *jenkins = appDelegate.jenkins; 133 | [given([userDefaults objectForKey:qUserDefaultsUrlKey]) willReturn:@"http://some/host/api/xml/"]; 134 | [given([userDefaults objectForKey:qUserDefaultsIntervalKey]) willReturn:@18]; 135 | 136 | [appDelegate applicationDidFinishLaunching:nil]; 137 | 138 | assertThat(jenkins.url, is([NSURL URLWithString:@"http://some/host"])); 139 | } 140 | 141 | - (void)testSetJenkinsUrl { 142 | [given([userDefaults objectForKey:qUserDefaultsUrlKey]) willReturn:@"http://some/host/"]; 143 | [given([userDefaults objectForKey:qUserDefaultsIntervalKey]) willReturn:@18]; 144 | [appDelegate applicationDidFinishLaunching:nil]; 145 | 146 | appDelegate.jenkinsUrl = [[NSURL alloc] initWithString:@"http://other/host"]; 147 | 148 | NSURL *url = [NSURL URLWithString:@"http://other/host"]; 149 | NSURL *xmlUrl = [url URLByAppendingPathComponent:@"api/xml"]; 150 | 151 | assertThat(appDelegate.jenkinsXmlUrl, is(xmlUrl)); 152 | assertThat(appDelegate.jenkins.url, is(url)); 153 | assertThat(appDelegate.jenkins.xmlUrl, is(xmlUrl)); 154 | [verify(userDefaults) setObject:[url absoluteString] forKey:qUserDefaultsUrlKey]; 155 | } 156 | 157 | - (void)testSetInterval { 158 | [given([userDefaults objectForKey:qUserDefaultsUrlKey]) willReturn:@"http://some/host/"]; 159 | [given([userDefaults objectForKey:qUserDefaultsIntervalKey]) willReturn:@18]; 160 | [appDelegate applicationDidFinishLaunching:nil]; 161 | 162 | appDelegate.interval = 37; 163 | 164 | assertThat(@(appDelegate.interval), is(@37)); 165 | assertThat(@(appDelegate.jenkins.interval), is(@37)); 166 | [verify(userDefaults) setObject:@37 forKey:qUserDefaultsIntervalKey]; 167 | } 168 | 169 | #pragma mark Private 170 | - (void)exchangeSystemStatusBarClassMethod { 171 | Method testMethod = class_getInstanceMethod([self class], @selector(mockSystemStatusBar)); 172 | IMP testImpl = method_getImplementation(testMethod); 173 | 174 | originalMethod = class_getClassMethod([NSStatusBar class], @selector(systemStatusBar)); 175 | originalImpl = method_setImplementation(originalMethod, testImpl); 176 | } 177 | 178 | - (NSStatusBar *)mockSystemStatusBar { 179 | return nil; 180 | } 181 | 182 | @end 183 | -------------------------------------------------------------------------------- /Jenkins Menu/JMJenkins.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * https://github.com/qvacua/jenkins-menu 4 | * http://qvacua.com 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import "JMJenkins.h" 10 | #import "JMJenkinsJob.h" 11 | #import "JMJenkinsDelegate.h" 12 | #import "JMTrustedHostManager.h" 13 | #import "JMLog.h" 14 | #import "JMKeychainManager.h" 15 | #import "AFHTTPClient.h" 16 | 17 | static NSTimeInterval const qDefaultInterval = 5 * 60; 18 | static const NSTimeInterval qTimeoutInterval = 15; 19 | static NSString *const qJenkinsXmlApiPath = @"/api/xml"; 20 | 21 | @interface JMJenkins () 22 | 23 | @property NSURLConnection *connection; 24 | @property(readwrite) NSInteger lastHttpStatusCode; 25 | @property(readwrite) NSInteger connectionState; 26 | @property(readwrite) NSURL *viewUrl; 27 | @property(readonly) NSMutableArray *mutableJobs; 28 | @property(readonly) NSMutableArray *filteredJobs; 29 | @property(readwrite) NSString *potentialHostToTrust; 30 | 31 | @end 32 | 33 | @implementation JMJenkins { 34 | NSURL *_url; 35 | } 36 | 37 | @dynamic allJobs; 38 | @dynamic jobs; 39 | @dynamic url; 40 | 41 | #pragma mark Properties 42 | - (NSArray *)allJobs { 43 | return self.mutableJobs; 44 | } 45 | 46 | - (NSArray *)jobs { 47 | return self.filteredJobs; 48 | } 49 | 50 | - (NSURL *)url { 51 | return _url; 52 | } 53 | 54 | - (void)setUrl:(NSURL *)newUrl { 55 | _url = newUrl; 56 | _xmlUrl = [newUrl URLByAppendingPathComponent:qJenkinsXmlApiPath]; 57 | } 58 | 59 | #pragma mark Public 60 | - (void)update { 61 | [self.connection cancel]; 62 | 63 | if (self.secured && self.credential == nil) { 64 | self.connectionState = JMJenkinsConnectionStateNoCredential; 65 | [self.delegate jenkins:self wrongCredential:nil]; 66 | 67 | return; 68 | } 69 | 70 | NSURLRequest *request = [self urlRequest]; 71 | self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 72 | log4Info(@"Connecting to %@", self.xmlUrl); 73 | 74 | [self.delegate jenkins:self updateStarted:nil]; 75 | 76 | if (self.connection == nil) { 77 | log4Warn(@"Connection to %@ failed!", self.xmlUrl); 78 | 79 | self.connectionState = JMJenkinsConnectionStateConnectionFailure; 80 | [self.delegate jenkins:self updateFailed:nil]; 81 | } 82 | } 83 | 84 | - (NSUInteger)countOfRedJobs { 85 | return [self countState:JMJenkinsJobStateRed]; 86 | } 87 | 88 | - (NSUInteger)countOfYellowJobs { 89 | return [self countState:JMJenkinsJobStateYellow]; 90 | } 91 | 92 | - (NSUInteger)countOfGreenJobs { 93 | return [self countState:JMJenkinsJobStateGreen]; 94 | } 95 | 96 | - (JMJenkinsJobsTotalState)totalState { 97 | if ([self countOfRedJobs] > 0) { 98 | return JMJenkinsTotalStateRed; 99 | } 100 | 101 | if ([self countOfYellowJobs] > 0) { 102 | return JMJenkinsTotalStateYellow; 103 | } 104 | 105 | if ([self countOfGreenJobs] > 0) { 106 | return JMJenkinsTotalStateGreen; 107 | } 108 | 109 | return JMJenkinsTotalStateUnknown; 110 | } 111 | 112 | #pragma mark NSObject 113 | - (id)init { 114 | self = [super init]; 115 | if (self) { 116 | _interval = qDefaultInterval; 117 | _connectionState = JMJenkinsConnectionStateUnknown; 118 | _lastHttpStatusCode = qHttpStatusUnknown; 119 | _mutableJobs = [[NSMutableArray alloc] init]; 120 | _filteredJobs = [[NSMutableArray alloc] init]; 121 | _blacklistItems = [[NSArray alloc] init]; 122 | } 123 | 124 | return self; 125 | } 126 | 127 | #pragma mark NSURLConnectionDataDelegate 128 | - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 129 | log4Debug(@"response"); 130 | NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response; 131 | 132 | NSInteger responseStatusCode = [httpResponse statusCode]; 133 | self.lastHttpStatusCode = responseStatusCode; 134 | 135 | /** 136 | * Forbidden occurs when the Jenkins is secured. Jenkins does not send a authentication challenge, 137 | * instead it responses with Forbidden and a login form. This means the -connection:didReceiveData: gets invoked. 138 | */ 139 | if (responseStatusCode == qHttpForbidden) { 140 | self.connectionState = JMJenkinsConnectionStateForbidden; 141 | 142 | return; 143 | } 144 | 145 | /** 146 | * Unauthorized occurs when the credential is wrong. 147 | */ 148 | if (responseStatusCode == qHttpUnauthorized) { 149 | self.connectionState = JMJenkinsConnectionStateWrongCredential; 150 | 151 | return; 152 | } 153 | 154 | if (responseStatusCode < qHttpStatusOk || responseStatusCode >= qHttpStatusBadRequest) { 155 | log4Warn(@"Connection to %@ was not successful. The Http status code was: %ld", self.xmlUrl, responseStatusCode); 156 | 157 | self.connectionState = JMJenkinsConnectionStateHttpFailure; 158 | [self.delegate jenkins:self updateFailed:@{ 159 | qJenkinsHttpResponseErrorKey : @(responseStatusCode) 160 | }]; 161 | 162 | return; 163 | } 164 | 165 | self.connectionState = JMJenkinsConnectionStateSuccessful; 166 | } 167 | 168 | - (BOOL)isJobBlacklisted:(JMJenkinsJob *)job 169 | { 170 | for (NSString *blacklistedName in self.blacklistItems) { 171 | if ([blacklistedName isEqualTo:job.name]) { 172 | return YES; 173 | } 174 | NSError *regexerr = nil; 175 | NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:blacklistedName options:NSRegularExpressionCaseInsensitive error:®exerr]; 176 | if (!regex) { 177 | continue; 178 | } 179 | NSArray *matches = [regex matchesInString:job.name options:0 range:NSMakeRange(0, [job.name length])]; 180 | if ([matches count] > 0) { 181 | return YES; 182 | } 183 | } 184 | return NO; 185 | } 186 | 187 | - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 188 | log4Debug(@"data"); 189 | 190 | if (self.connectionState == JMJenkinsConnectionStateForbidden) { 191 | log4Debug(@"forbidden"); 192 | self.secured = YES; 193 | [self.delegate jenkins:self forbidden:nil]; 194 | return; 195 | } 196 | 197 | if (self.connectionState == JMJenkinsConnectionStateWrongCredential) { 198 | log4Debug(@"wrong credential"); 199 | [self.delegate jenkins:self wrongCredential:nil]; 200 | return; 201 | } 202 | 203 | if (self.connectionState != JMJenkinsConnectionStateSuccessful) { 204 | return; 205 | } 206 | 207 | NSXMLDocument *xmlDoc = [self xmlDocumentFromData:data]; 208 | if (xmlDoc == nil) { 209 | self.connectionState = JMJenkinsConnectionStateXmlFailure; 210 | return; 211 | } 212 | 213 | NSArray *children = [[xmlDoc rootElement] children]; 214 | if ([children count] == 0) { 215 | log4Warn(@"XML of %@ is empty.", self.xmlUrl); 216 | 217 | self.connectionState = JMJenkinsConnectionStateXmlFailure; 218 | return; 219 | } 220 | 221 | [self.mutableJobs removeAllObjects]; 222 | [self.filteredJobs removeAllObjects]; 223 | 224 | [children enumerateObjectsUsingBlock:^(NSXMLNode *childNode, NSUInteger index, BOOL *stop) { 225 | if ([[childNode name] isEqualToString:@"primaryView"]) { 226 | self.viewUrl = [self viewUrlFromXmlNode:childNode]; 227 | return; 228 | } 229 | 230 | if ([[childNode name] isEqualToString:@"job"]) { 231 | JMJenkinsJob *job = [self jobsFromXmlNode:childNode]; 232 | [self.mutableJobs addObject:job]; 233 | if (![self isJobBlacklisted:job]) { 234 | [self.filteredJobs addObject:job]; 235 | } 236 | return; 237 | } 238 | }]; 239 | 240 | [self.delegate jenkins:self updateFinished:nil]; 241 | } 242 | 243 | - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { 244 | /** 245 | * When we get an authentication challenge from the server, this delegate method is called before 246 | * - connecion:didReceiveResponse: 247 | * - connecion:didReceiveData: 248 | */ 249 | 250 | log4Debug(@"challenge"); 251 | if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { 252 | if ([self.trustedHostManager shouldTrustHost:challenge.protectionSpace.host]) { 253 | NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; 254 | [challenge.sender useCredential:credential forAuthenticationChallenge:challenge]; 255 | 256 | self.potentialHostToTrust = nil; 257 | 258 | return; 259 | } 260 | } 261 | 262 | self.potentialHostToTrust = challenge.protectionSpace.host; 263 | 264 | if ([challenge.sender respondsToSelector:@selector(performDefaultHandlingForAuthenticationChallenge:)]) { 265 | [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge]; 266 | return; 267 | } 268 | 269 | [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge]; 270 | } 271 | 272 | - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 273 | if ([error code] == NSURLErrorServerCertificateUntrusted) { 274 | log4Warn(@"Certification issue with %@", self.xmlUrl); 275 | self.connectionState = JMJenkinsConnectionStateServerTrustFailure; 276 | [self.delegate jenkins:self serverTrustFailedwithHost:_potentialHostToTrust]; 277 | 278 | return; 279 | } 280 | 281 | log4Warn(@"Connection to %@ failed: %@", self.xmlUrl, connection); 282 | self.connectionState = JMJenkinsConnectionStateFailure; 283 | [self.delegate jenkins:self updateFailed:@{ 284 | qJenkinsConnectionErrorKey : error 285 | }]; 286 | } 287 | 288 | #pragma mark Private 289 | - (JMJenkinsJob *)jobsFromXmlNode:(NSXMLNode *)node { 290 | JMJenkinsJob *job = [[JMJenkinsJob alloc] init]; 291 | 292 | [[node children] enumerateObjectsUsingBlock:^(id childNode, NSUInteger index, BOOL *stop) { 293 | NSString *nodeName = [childNode name]; 294 | NSString *nodeStringValue = [childNode stringValue]; 295 | 296 | if ([nodeName isEqualToString:@"name"]) { 297 | job.name = nodeStringValue; 298 | return; 299 | } 300 | 301 | if ([nodeName isEqualToString:@"url"]) { 302 | job.url = [NSURL URLWithString:nodeStringValue]; 303 | return; 304 | } 305 | 306 | if ([nodeName isEqualToString:@"color"]) { 307 | job.state = [self jobStateFromColor:nodeStringValue]; 308 | job.running = [self runningStateFromColor:nodeStringValue]; 309 | return; 310 | } 311 | }]; 312 | 313 | return job; 314 | } 315 | 316 | - (NSXMLDocument *)xmlDocumentFromData:(NSData *)xmlData { 317 | NSError *xmlError = nil; 318 | NSXMLDocument *xmlDoc = [[NSXMLDocument alloc] initWithData:xmlData options:0 error:&xmlError]; 319 | 320 | if (xmlError) { 321 | log4Warn(@"XML parsing of %@ failed: %@", self.xmlUrl, xmlError); 322 | return nil; 323 | } 324 | 325 | return xmlDoc; 326 | } 327 | 328 | - (NSURL *)viewUrlFromXmlNode:(NSXMLNode *)node { 329 | __block NSURL *viewUrl; 330 | [[node children] enumerateObjectsUsingBlock:^(id childNode, NSUInteger index, BOOL *stop) { 331 | if (![[childNode name] isEqualToString:@"url"]) { 332 | return; 333 | } 334 | 335 | viewUrl = [NSURL URLWithString:[childNode stringValue]]; 336 | *stop = YES; 337 | }]; 338 | 339 | return viewUrl; 340 | } 341 | 342 | - (JMJenkinsJobState)jobStateFromColor:(NSString *)color { 343 | if ([color hasPrefix:@"blue"]) { 344 | return JMJenkinsJobStateGreen; 345 | } 346 | 347 | if ([color hasPrefix:@"yellow"]) { 348 | return JMJenkinsJobStateYellow; 349 | } 350 | 351 | if ([color hasPrefix:@"red"]) { 352 | return JMJenkinsJobStateRed; 353 | } 354 | 355 | if ([color hasPrefix:@"aborted"]) { 356 | return JMJenkinsJobStateAborted; 357 | } 358 | 359 | if ([color hasPrefix:@"disabled"]) { 360 | return JMJenkinsJobStateDisabled; 361 | } 362 | 363 | return JMJenkinsJobStateUnknown; 364 | } 365 | 366 | - (BOOL)runningStateFromColor:(NSString *)color { 367 | if ([color hasSuffix:@"_anime"]) { 368 | return YES; 369 | } 370 | 371 | return NO; 372 | } 373 | 374 | - (NSUInteger)countState:(JMJenkinsJobState)jobState { 375 | NSUInteger count = 0; 376 | for (JMJenkinsJob *job in self.jobs) { 377 | if ([self.blacklistItems containsObject:job.name]) { 378 | continue; 379 | } 380 | 381 | if (job.state == jobState) { 382 | count++; 383 | } 384 | } 385 | 386 | return count; 387 | } 388 | 389 | - (NSURLRequest *)urlRequest { 390 | NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:self.xmlUrl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:qTimeoutInterval]; 391 | 392 | if (self.credential == nil) { 393 | return urlRequest; 394 | } 395 | 396 | NSString *username = self.credential.username; 397 | NSString *password = self.credential.password; 398 | 399 | /** 400 | * For one https server I could try out the HTTP basic auth method did not work. Thus, we are now using the POST 401 | * method to get through. We're using AFNetworking for that. 402 | * 403 | * It could well be that we have to modify the following code when Jenkins changes the internal login mechanism. 404 | */ 405 | AFHTTPClient *client = [AFHTTPClient clientWithBaseURL:self.url]; 406 | urlRequest = [client requestWithMethod:@"POST" path:@"j_acegi_security_check" parameters:@{ 407 | @"from" : qJenkinsXmlApiPath, 408 | @"j_username" : username, 409 | @"j_password" : password 410 | }]; 411 | 412 | return urlRequest; 413 | } 414 | 415 | @end 416 | -------------------------------------------------------------------------------- /Jenkins MenuTests/JMJenkinsTest.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Jenkins Menu 3 | * https://github.com/qvacua/jenkins-menu 4 | * http://qvacua.com 5 | * 6 | * See LICENSE 7 | */ 8 | 9 | #import "JMBaseTestCase.h" 10 | #import "JMJenkins.h" 11 | #import "JMJenkinsJob.h" 12 | #import "JMTrustedHostManager.h" 13 | #import "JMJenkinsDelegate.h" 14 | 15 | 16 | @interface JMJenkinsTest : JMBaseTestCase 17 | @end 18 | 19 | @implementation JMJenkinsTest { 20 | JMJenkins *jenkins; 21 | NSHTTPURLResponse *response; 22 | JMTrustedHostManager *trustedHostManager; 23 | NSURLAuthenticationChallenge *challenge; 24 | NSURLProtectionSpace *protectionSpace; 25 | id sender; 26 | id delegate; 27 | } 28 | 29 | - (void)setUp { 30 | [super setUp]; 31 | 32 | trustedHostManager = mock([JMTrustedHostManager class]); 33 | delegate = mockProtocol(@protocol(JMJenkinsDelegate)); 34 | 35 | jenkins = [[JMJenkins alloc] init]; 36 | jenkins.trustedHostManager = trustedHostManager; 37 | jenkins.delegate = delegate; 38 | 39 | 40 | response = mock([NSHTTPURLResponse class]); 41 | challenge = mock([NSURLAuthenticationChallenge class]); 42 | protectionSpace = mock([NSURLProtectionSpace class]); 43 | sender = mockProtocol(@protocol(NSURLAuthenticationChallengeSender)); 44 | 45 | [given([challenge protectionSpace]) willReturn:protectionSpace]; 46 | [given([challenge sender]) willReturn:sender]; 47 | [given([protectionSpace host]) willReturn:@"http://some.host"]; 48 | } 49 | 50 | - (void)testTotalStateRedAndCount { 51 | [self makeResponseReturnHttpOk]; 52 | NSData *xmlData = [self xmlDataFromFileName:@"example-xml"]; 53 | 54 | [jenkins connection:nil didReceiveData:xmlData]; 55 | assertThat(@(jenkins.totalState), is(@(JMJenkinsTotalStateRed))); 56 | assertThat(@([jenkins countOfRedJobs]), is(@2)); 57 | } 58 | 59 | - (void)testTotalStateYellowAndCount { 60 | [self makeResponseReturnHttpOk]; 61 | NSData *xmlData = [self xmlDataFromFileName:@"yellow-xml"]; 62 | 63 | [jenkins connection:nil didReceiveData:xmlData]; 64 | assertThat(@(jenkins.totalState), is(@(JMJenkinsTotalStateYellow))); 65 | assertThat(@([jenkins countOfYellowJobs]), is(@2)); 66 | } 67 | 68 | - (void)testTotalStateGreenAndCount { 69 | [self makeResponseReturnHttpOk]; 70 | NSData *xmlData = [self xmlDataFromFileName:@"green-xml"]; 71 | 72 | [jenkins connection:nil didReceiveData:xmlData]; 73 | assertThat(@(jenkins.totalState), is(@(JMJenkinsTotalStateGreen))); 74 | assertThat(@([jenkins countOfGreenJobs]), is(@2)); 75 | } 76 | 77 | - (void)testTotalStateUnknown { 78 | [self makeResponseReturnHttpOk]; 79 | NSData *xmlData = [self xmlDataFromFileName:@"unknown-xml"]; 80 | 81 | [jenkins connection:nil didReceiveData:xmlData]; 82 | assertThat(@(jenkins.totalState), is(@(JMJenkinsTotalStateUnknown))); 83 | } 84 | 85 | - (void)testUpdateSecuredButNoCredential { 86 | jenkins.url = [NSURL URLWithString:@"pro://some/crazy/"]; 87 | jenkins.secured = YES; 88 | jenkins.credential = nil; 89 | 90 | [jenkins update]; 91 | 92 | assertThat(@(jenkins.connectionState), is(@(JMJenkinsConnectionStateNoCredential))); 93 | [verify(delegate) jenkins:jenkins wrongCredential:nil]; 94 | } 95 | 96 | - (void)testDefaultProperties { 97 | assertThat(@(jenkins.connectionState), is(@(JMJenkinsConnectionStateUnknown))); 98 | assertThat(@(jenkins.lastHttpStatusCode), is(@(qHttpStatusUnknown))); 99 | assertThat(@(jenkins.interval), is(@300)); 100 | assertThat(jenkins.jobs, isNot(nilValue())); 101 | } 102 | 103 | - (void)testKvoJenkinsUrl { 104 | jenkins.url = [NSURL URLWithString:@"http://some/url/to/jenkins"]; 105 | 106 | assertThat(jenkins.xmlUrl, is([NSURL URLWithString:@"http://some/url/to/jenkins/api/xml"])); 107 | } 108 | 109 | - (void)testConnectionDidReceiveResponseForbidden { 110 | [given([response statusCode]) willReturnInteger:qHttpForbidden]; 111 | [jenkins connection:nil didReceiveResponse:response]; 112 | assertThat(@(jenkins.connectionState), is(@(JMJenkinsConnectionStateForbidden))); 113 | assertThat(@(jenkins.lastHttpStatusCode), is(@(qHttpForbidden))); 114 | 115 | [jenkins connection:nil didReceiveData:nil]; 116 | [verify(delegate) jenkins:jenkins forbidden:nil]; 117 | assertThat(@(jenkins.secured), isYes); 118 | } 119 | 120 | - (void)testConnectionDidReceiveResponseUnauthorized { 121 | [given([response statusCode]) willReturnInteger:qHttpUnauthorized]; 122 | [jenkins connection:nil didReceiveResponse:response]; 123 | assertThat(@(jenkins.connectionState), is(@(JMJenkinsConnectionStateWrongCredential))); 124 | assertThat(@(jenkins.lastHttpStatusCode), is(@(qHttpUnauthorized))); 125 | 126 | [jenkins connection:nil didReceiveData:nil]; 127 | [verify(delegate) jenkins:jenkins wrongCredential:nil]; 128 | } 129 | 130 | - (void)testConnectionDidReceiveResponseFailure1 { 131 | [given([response statusCode]) willReturnInteger:404]; 132 | [jenkins connection:nil didReceiveResponse:response]; 133 | assertThat(@(jenkins.connectionState), is(@(JMJenkinsConnectionStateHttpFailure))); 134 | assertThat(@(jenkins.lastHttpStatusCode), is(@404)); 135 | 136 | MKTArgumentCaptor *captor = [[MKTArgumentCaptor alloc] init]; 137 | [verify(delegate) jenkins:jenkins updateFailed:captor.capture]; 138 | NSDictionary *userInfo = captor.value; 139 | 140 | assertThat(userInfo, hasKey(qJenkinsHttpResponseErrorKey)); 141 | assertThat(userInfo, hasValue(@404)); 142 | } 143 | 144 | - (void)testConnectionDidReceiveResponseFailure2 { 145 | [given([response statusCode]) willReturnInteger:199]; 146 | [jenkins connection:nil didReceiveResponse:response]; 147 | assertThat(@(jenkins.connectionState), is(@(JMJenkinsConnectionStateHttpFailure))); 148 | assertThat(@(jenkins.lastHttpStatusCode), is(@199)); 149 | 150 | MKTArgumentCaptor *captor = [[MKTArgumentCaptor alloc] init]; 151 | [verify(delegate) jenkins:jenkins updateFailed:captor.capture]; 152 | NSDictionary *userInfo = captor.value; 153 | 154 | assertThat(userInfo, hasKey(qJenkinsHttpResponseErrorKey)); 155 | assertThat(userInfo, hasValue(@199)); 156 | } 157 | 158 | - (void)testConnectionDidReceiveResponse { 159 | [given([response statusCode]) willReturnInteger:qHttpStatusOk]; 160 | [jenkins connection:nil didReceiveResponse:response]; 161 | assertThat(@(jenkins.connectionState), is(@(JMJenkinsConnectionStateSuccessful))); 162 | assertThat(@(jenkins.lastHttpStatusCode), is(@(qHttpStatusOk))); 163 | } 164 | 165 | - (void)testConnectionDidReceiveDataXmlError { 166 | [self makeResponseReturnHttpOk]; 167 | NSData *malformedXmlData = [@"" dataUsingEncoding:NSUTF8StringEncoding]; 178 | 179 | [jenkins connection:nil didReceiveData:emptyXmlData]; 180 | assertThat(jenkins.jobs, isEmpty()); 181 | assertThat(@(jenkins.lastHttpStatusCode), is(@(qHttpStatusOk))); 182 | assertThat(@(jenkins.connectionState), is(@(JMJenkinsConnectionStateXmlFailure))); 183 | } 184 | 185 | - (void)testConnectionDidReceiveData { 186 | [self makeResponseReturnHttpOk]; 187 | NSData *xmlData = [self xmlDataFromFileName:@"example-xml"]; 188 | 189 | [jenkins connection:nil didReceiveData:xmlData]; 190 | assertThat(jenkins.jobs, hasSize(8)); 191 | assertThat(jenkins.viewUrl, is([NSURL URLWithString:@"http://ci.jruby.org/"])); 192 | 193 | [self assertJob:jenkins.jobs[0] name:@"activerecord-jdbc-master" urlString:@"http://ci.jruby.org/job/activerecord-jdbc-master/" state:JMJenkinsJobStateGreen running:NO]; 194 | [self assertJob:jenkins.jobs[1] name:@"jruby-test-all-master" urlString:@"http://ci.jruby.org/job/jruby-test-all-master/" state:JMJenkinsJobStateGreen running:YES]; 195 | [self assertJob:jenkins.jobs[2] name:@"jruby-rack-dist" urlString:@"http://ci.jruby.org/job/jruby-rack-dist/" state:JMJenkinsJobStateYellow running:NO]; 196 | [self assertJob:jenkins.jobs[3] name:@"jruby-solaris" urlString:@"http://ci.jruby.org/job/jruby-solaris/" state:JMJenkinsJobStateYellow running:YES]; 197 | [self assertJob:jenkins.jobs[4] name:@"jruby-spec-ci-master" urlString:@"http://ci.jruby.org/job/jruby-spec-ci-master/" state:JMJenkinsJobStateRed running:NO]; 198 | [self assertJob:jenkins.jobs[5] name:@"jruby-ossl" urlString:@"http://ci.jruby.org/job/jruby-ossl/" state:JMJenkinsJobStateRed running:YES]; 199 | [self assertJob:jenkins.jobs[6] name:@"jruby-test-master" urlString:@"http://ci.jruby.org/job/jruby-test-master/" state:JMJenkinsJobStateAborted running:NO]; 200 | [self assertJob:jenkins.jobs[7] name:@"jruby-dist-release" urlString:@"http://ci.jruby.org/job/jruby-dist-release/" state:JMJenkinsJobStateDisabled running:NO]; 201 | 202 | [verify(delegate) jenkins:jenkins updateFinished:nil]; 203 | } 204 | 205 | - (void)testBlacklistItemsOnlyGreenExcluded { 206 | jenkins.blacklistItems = @[ 207 | @"activerecord-jdbc-master", 208 | @"jruby-test-all-master" 209 | ]; 210 | 211 | [self makeResponseReturnHttpOk]; 212 | NSData *xmlData = [self xmlDataFromFileName:@"example-xml"]; 213 | 214 | [jenkins connection:nil didReceiveData:xmlData]; 215 | assertThat(jenkins.jobs, hasSize(6)); 216 | assertThat(@(jenkins.totalState), is(@(JMJenkinsTotalStateRed))); 217 | assertThat(@(jenkins.countOfGreenJobs), is(@0)); 218 | } 219 | 220 | - (void)testBlacklistItemsOnlyRedExcluded { 221 | jenkins.blacklistItems = @[ 222 | @"jruby-spec-ci-master", 223 | @"jruby-ossl" 224 | ]; 225 | 226 | [self makeResponseReturnHttpOk]; 227 | NSData *xmlData = [self xmlDataFromFileName:@"example-xml"]; 228 | 229 | [jenkins connection:nil didReceiveData:xmlData]; 230 | assertThat(jenkins.jobs, hasSize(6)); 231 | assertThat(@(jenkins.totalState), is(@(JMJenkinsTotalStateYellow))); 232 | assertThat(@(jenkins.countOfRedJobs), is(@0)); 233 | } 234 | 235 | - (void)testBlacklistItemsYellowRedExcluded { 236 | jenkins.blacklistItems = @[ 237 | @"jruby-solaris", 238 | @"jruby-rack-dist", 239 | @"jruby-spec-ci-master", 240 | @"jruby-ossl" 241 | ]; 242 | 243 | [self makeResponseReturnHttpOk]; 244 | NSData *xmlData = [self xmlDataFromFileName:@"example-xml"]; 245 | 246 | [jenkins connection:nil didReceiveData:xmlData]; 247 | assertThat(jenkins.jobs, hasSize(4)); 248 | assertThat(@(jenkins.totalState), is(@(JMJenkinsTotalStateGreen))); 249 | assertThat(@(jenkins.countOfYellowJobs), is(@0)); 250 | assertThat(@(jenkins.countOfRedJobs), is(@0)); 251 | } 252 | 253 | /** 254 | * @bug 255 | */ 256 | - (void)testConnectionDidReceiveDataMultipleTimes { 257 | [self makeResponseReturnHttpOk]; 258 | NSData *xmlData = [self xmlDataFromFileName:@"example-xml"]; 259 | 260 | [jenkins connection:nil didReceiveData:xmlData]; 261 | assertThat(jenkins.jobs, hasSize(8)); 262 | 263 | [jenkins connection:nil didReceiveData:xmlData]; 264 | assertThat(jenkins.jobs, hasSize(8)); 265 | } 266 | 267 | - (void)testConnectionAuthenticationFirstContact { 268 | [given([protectionSpace authenticationMethod]) willReturn:NSURLAuthenticationMethodServerTrust]; 269 | [given([trustedHostManager shouldTrustHost:@"http://some.host"]) willReturnBool:NO]; 270 | 271 | [jenkins connection:nil willSendRequestForAuthenticationChallenge:challenge]; 272 | 273 | assertThat(jenkins.potentialHostToTrust, is(@"http://some.host")); 274 | [verify(sender) performDefaultHandlingForAuthenticationChallenge:challenge]; 275 | } 276 | 277 | - (void)testConnectionAuthenticationWillTrust { 278 | [given([protectionSpace authenticationMethod]) willReturn:NSURLAuthenticationMethodServerTrust]; 279 | [given([trustedHostManager shouldTrustHost:@"http://some.host"]) willReturnBool:YES]; 280 | 281 | [jenkins connection:nil willSendRequestForAuthenticationChallenge:challenge]; 282 | 283 | assertThat(jenkins.potentialHostToTrust, is(nilValue())); 284 | [verify(sender) useCredential:instanceOf([NSURLCredential class]) forAuthenticationChallenge:challenge]; 285 | } 286 | 287 | - (void)testConnectionAuthenticationSomeOtherAuthMethod { 288 | [given([protectionSpace authenticationMethod]) willReturn:NSURLAuthenticationMethodNTLM]; 289 | 290 | [jenkins connection:nil willSendRequestForAuthenticationChallenge:challenge]; 291 | 292 | assertThat(jenkins.potentialHostToTrust, is(@"http://some.host")); 293 | [verify(sender) performDefaultHandlingForAuthenticationChallenge:challenge]; 294 | } 295 | 296 | - (void)testConnectionDidFailWithTrustIssue { 297 | [given([protectionSpace authenticationMethod]) willReturn:NSURLAuthenticationMethodServerTrust]; 298 | [given([trustedHostManager shouldTrustHost:@"http://some.host"]) willReturnBool:NO]; 299 | 300 | NSError *error = mock([NSError class]); 301 | [given([error code]) willReturnUnsignedInteger:NSURLErrorServerCertificateUntrusted]; 302 | 303 | // this will set the _potentialHostToTrust 304 | [jenkins connection:nil willSendRequestForAuthenticationChallenge:challenge]; 305 | 306 | [jenkins connection:nil didFailWithError:error]; 307 | assertThat(@(jenkins.connectionState), is(@(JMJenkinsConnectionStateServerTrustFailure))); 308 | [verify(delegate) jenkins:jenkins serverTrustFailedwithHost:@"http://some.host"]; 309 | 310 | [verifyCount(delegate, never()) jenkins:jenkins updateFailed:nil]; 311 | } 312 | 313 | - (void)testConnectionDidFailForUnknownReason { 314 | NSError *error = mock([NSError class]); 315 | [given([error code]) willReturnUnsignedInteger:NSURLErrorServerCertificateUntrusted + 1]; 316 | 317 | [jenkins connection:nil didFailWithError:error]; 318 | 319 | assertThat(@(jenkins.connectionState), is(@(JMJenkinsConnectionStateFailure))); 320 | [verify(delegate) jenkins:jenkins updateFailed:@{ 321 | qJenkinsConnectionErrorKey: error 322 | }]; 323 | } 324 | 325 | #pragma mark Private 326 | - (void)assertJob:(JMJenkinsJob *)job name:(NSString *)name urlString:(NSString *)urlString state:(JMJenkinsJobState)state running:(BOOL)running { 327 | assertThat(job.name, is(name)); 328 | assertThat(job.url, is([NSURL URLWithString:urlString])); 329 | assertThat(@(job.state), is(@(state))); 330 | assertThat(@(job.running), is(@(running))); 331 | } 332 | 333 | - (void)makeResponseReturnHttpOk { 334 | [given([response statusCode]) willReturnInteger:qHttpStatusOk]; 335 | [jenkins connection:nil didReceiveResponse:response]; 336 | } 337 | 338 | - (NSData *)xmlDataFromFileName:(NSString *)fileName { 339 | NSURL *xmlUrl = [[NSBundle bundleForClass:[self class]] URLForResource:fileName withExtension:@"xml"]; 340 | return [NSData dataWithContentsOfURL:xmlUrl]; 341 | } 342 | 343 | @end 344 | -------------------------------------------------------------------------------- /Frameworks/Growl.framework/Versions/A/Headers/GrowlDefines.h: -------------------------------------------------------------------------------- 1 | // 2 | // GrowlDefines.h 3 | // 4 | 5 | #ifndef _GROWLDEFINES_H 6 | #define _GROWLDEFINES_H 7 | 8 | #ifdef __OBJC__ 9 | #define XSTR(x) (@x) 10 | #else 11 | #define XSTR CFSTR 12 | #endif 13 | 14 | /*! @header GrowlDefines.h 15 | * @abstract Defines all the notification keys. 16 | * @discussion Defines all the keys used for registration with Growl and for 17 | * Growl notifications. 18 | * 19 | * Most applications should use the functions or methods of Growl.framework 20 | * instead of posting notifications such as those described here. 21 | * @updated 2004-01-25 22 | */ 23 | 24 | // UserInfo Keys for Registration 25 | #pragma mark UserInfo Keys for Registration 26 | 27 | /*! @group Registration userInfo keys */ 28 | /* @abstract Keys for the userInfo dictionary of a GROWL_APP_REGISTRATION distributed notification. 29 | * @discussion The values of these keys describe the application and the 30 | * notifications it may post. 31 | * 32 | * Your application must register with Growl before it can post Growl 33 | * notifications (and have them not be ignored). However, as of Growl 0.6, 34 | * posting GROWL_APP_REGISTRATION notifications directly is no longer the 35 | * preferred way to register your application. Your application should instead 36 | * use Growl.framework's delegate system. 37 | * See +[GrowlApplicationBridge setGrowlDelegate:] or Growl_SetDelegate for 38 | * more information. 39 | */ 40 | 41 | /*! @defined GROWL_APP_NAME 42 | * @abstract The name of your application. 43 | * @discussion The name of your application. This should remain stable between 44 | * different versions and incarnations of your application. 45 | * For example, "SurfWriter" is a good app name, whereas "SurfWriter 2.0" and 46 | * "SurfWriter Lite" are not. 47 | */ 48 | #define GROWL_APP_NAME XSTR("ApplicationName") 49 | /*! @defined GROWL_APP_ID 50 | * @abstract The bundle identifier of your application. 51 | * @discussion The bundle identifier of your application. This key should 52 | * be unique for your application while there may be several applications 53 | * with the same GROWL_APP_NAME. 54 | * This key is optional. 55 | */ 56 | #define GROWL_APP_ID XSTR("ApplicationId") 57 | /*! @defined GROWL_APP_ICON_DATA 58 | * @abstract The image data for your application's icon. 59 | * @discussion Image data representing your application's icon. This may be 60 | * superimposed on a notification icon as a badge, used as the notification 61 | * icon when a notification-specific icon is not supplied, or ignored 62 | * altogether, depending on the display. Must be in a format supported by 63 | * NSImage, such as TIFF, PNG, GIF, JPEG, BMP, PICT, or PDF. 64 | * 65 | * Optional. Not supported by all display plugins. 66 | */ 67 | #define GROWL_APP_ICON_DATA XSTR("ApplicationIcon") 68 | /*! @defined GROWL_NOTIFICATIONS_DEFAULT 69 | * @abstract The array of notifications to turn on by default. 70 | * @discussion These are the names of the notifications that should be enabled 71 | * by default when your application registers for the first time. If your 72 | * application reregisters, Growl will look here for any new notification 73 | * names found in GROWL_NOTIFICATIONS_ALL, but ignore any others. 74 | */ 75 | #define GROWL_NOTIFICATIONS_DEFAULT XSTR("DefaultNotifications") 76 | /*! @defined GROWL_NOTIFICATIONS_ALL 77 | * @abstract The array of all notifications your application can send. 78 | * @discussion These are the names of all of the notifications that your 79 | * application may post. See GROWL_NOTIFICATION_NAME for a discussion of good 80 | * notification names. 81 | */ 82 | #define GROWL_NOTIFICATIONS_ALL XSTR("AllNotifications") 83 | /*! @defined GROWL_NOTIFICATIONS_HUMAN_READABLE_DESCRIPTIONS 84 | * @abstract A dictionary of human-readable names for your notifications. 85 | * @discussion By default, the Growl UI will display notifications by the names given in GROWL_NOTIFICATIONS_ALL 86 | * which correspond to the GROWL_NOTIFICATION_NAME. This dictionary specifies the human-readable name to display. 87 | * The keys of the dictionary are GROWL_NOTIFICATION_NAME strings; the objects are the human-readable versions. 88 | * For any GROWL_NOTIFICATION_NAME not specific in this dictionary, the GROWL_NOTIFICATION_NAME will be displayed. 89 | * 90 | * This key is optional. 91 | */ 92 | #define GROWL_NOTIFICATIONS_HUMAN_READABLE_NAMES XSTR("HumanReadableNames") 93 | /*! @defined GROWL_NOTIFICATIONS_DESCRIPTIONS 94 | * @abstract A dictionary of descriptions of _when_ each notification occurs 95 | * @discussion This is an NSDictionary whose keys are GROWL_NOTIFICATION_NAME strings and whose objects are 96 | * descriptions of _when_ each notification occurs, such as "You received a new mail message" or 97 | * "A file finished downloading". 98 | * 99 | * This key is optional. 100 | */ 101 | #define GROWL_NOTIFICATIONS_DESCRIPTIONS XSTR("NotificationDescriptions") 102 | /*! @defined GROWL_NOTIFICATIONS_ICONS 103 | * @abstract A dictionary of icons for each notification 104 | * @discussion This is an NSDictionary whose keys are GROWL_NOTIFICATION_NAME strings and whose objects are 105 | * icons for each notification, for GNTP spec 106 | * 107 | * This key is optional. 108 | */ 109 | #define GROWL_NOTIFICATIONS_ICONS XSTR("NotificationIcons") 110 | 111 | /*! @defined GROWL_TICKET_VERSION 112 | * @abstract The version of your registration ticket. 113 | * @discussion Include this key in a ticket plist file that you put in your 114 | * application bundle for auto-discovery. The current ticket version is 1. 115 | */ 116 | #define GROWL_TICKET_VERSION XSTR("TicketVersion") 117 | // UserInfo Keys for Notifications 118 | #pragma mark UserInfo Keys for Notifications 119 | 120 | /*! @group Notification userInfo keys */ 121 | /* @abstract Keys for the userInfo dictionary of a GROWL_NOTIFICATION distributed notification. 122 | * @discussion The values of these keys describe the content of a Growl 123 | * notification. 124 | * 125 | * Not all of these keys are supported by all displays. Only the name, title, 126 | * and description of a notification are universal. Most of the built-in 127 | * displays do support all of these keys, and most other visual displays 128 | * probably will also. But, as of 0.6, the Log, MailMe, and Speech displays 129 | * support only textual data. 130 | */ 131 | 132 | /*! @defined GROWL_NOTIFICATION_NAME 133 | * @abstract The name of the notification. 134 | * @discussion The name of the notification. Note that if you do not define 135 | * GROWL_NOTIFICATIONS_HUMAN_READABLE_NAMES when registering your ticket originally this name 136 | * will the one displayed within the Growl preference pane and should be human-readable. 137 | */ 138 | #define GROWL_NOTIFICATION_NAME XSTR("NotificationName") 139 | /*! @defined GROWL_NOTIFICATION_TITLE 140 | * @abstract The title to display in the notification. 141 | * @discussion The title of the notification. Should be very brief. 142 | * The title usually says what happened, e.g. "Download complete". 143 | */ 144 | #define GROWL_NOTIFICATION_TITLE XSTR("NotificationTitle") 145 | /*! @defined GROWL_NOTIFICATION_DESCRIPTION 146 | * @abstract The description to display in the notification. 147 | * @discussion The description should be longer and more verbose than the title. 148 | * The description usually tells the subject of the action, 149 | * e.g. "Growl-0.6.dmg downloaded in 5.02 minutes". 150 | */ 151 | #define GROWL_NOTIFICATION_DESCRIPTION XSTR("NotificationDescription") 152 | /*! @defined GROWL_NOTIFICATION_ICON 153 | * @discussion Image data for the notification icon. Image data must be in a format 154 | * supported by NSImage, such as TIFF, PNG, GIF, JPEG, BMP, PICT, or PDF. 155 | * 156 | * Optional. Not supported by all display plugins. 157 | */ 158 | #define GROWL_NOTIFICATION_ICON_DATA XSTR("NotificationIcon") 159 | /*! @defined GROWL_NOTIFICATION_APP_ICON 160 | * @discussion Image data for the application icon, in case GROWL_APP_ICON does 161 | * not apply for some reason. Image data be in a format supported by NSImage, such 162 | * as TIFF, PNG, GIF, JPEG, BMP, PICT, or PDF. 163 | * 164 | * Optional. Not supported by all display plugins. 165 | */ 166 | #define GROWL_NOTIFICATION_APP_ICON_DATA XSTR("NotificationAppIcon") 167 | /*! @defined GROWL_NOTIFICATION_PRIORITY 168 | * @discussion The priority of the notification as an integer number from 169 | * -2 to +2 (+2 being highest). 170 | * 171 | * Optional. Not supported by all display plugins. 172 | */ 173 | #define GROWL_NOTIFICATION_PRIORITY XSTR("NotificationPriority") 174 | /*! @defined GROWL_NOTIFICATION_STICKY 175 | * @discussion A Boolean number controlling whether the notification is sticky. 176 | * 177 | * Optional. Not supported by all display plugins. 178 | */ 179 | #define GROWL_NOTIFICATION_STICKY XSTR("NotificationSticky") 180 | /*! @defined GROWL_NOTIFICATION_CLICK_CONTEXT 181 | * @abstract Identifies which notification was clicked. 182 | * @discussion An identifier for the notification for clicking purposes. 183 | * 184 | * This will be passed back to the application when the notification is 185 | * clicked. It must be plist-encodable (a data, dictionary, array, number, or 186 | * string object), and it should be unique for each notification you post. 187 | * A good click context would be a UUID string returned by NSProcessInfo or 188 | * CFUUID. 189 | * 190 | * Optional. Not supported by all display plugins. 191 | */ 192 | #define GROWL_NOTIFICATION_CLICK_CONTEXT XSTR("NotificationClickContext") 193 | 194 | /*! @defined GROWL_NOTIFICATION_IDENTIFIER 195 | * @abstract An identifier for the notification for coalescing purposes. 196 | * Notifications with the same identifier fall into the same class; only 197 | * the last notification of a class is displayed on the screen. If a 198 | * notification of the same class is currently being displayed, it is 199 | * replaced by this notification. 200 | * 201 | * Optional. Not supported by all display plugins. 202 | */ 203 | #define GROWL_NOTIFICATION_IDENTIFIER XSTR("GrowlNotificationIdentifier") 204 | 205 | /*! @defined GROWL_APP_PID 206 | * @abstract The process identifier of the process which sends this 207 | * notification. If this field is set, the application will only receive 208 | * clicked and timed out notifications which originate from this process. 209 | * 210 | * Optional. 211 | */ 212 | #define GROWL_APP_PID XSTR("ApplicationPID") 213 | 214 | /*! @defined GROWL_NOTIFICATION_PROGRESS 215 | * @abstract If this key is set, it should contain a double value wrapped 216 | * in a NSNumber which describes some sort of progress (from 0.0 to 100.0). 217 | * If this is key is not set, no progress bar is shown. 218 | * 219 | * Optional. Not supported by all display plugins. 220 | */ 221 | #define GROWL_NOTIFICATION_PROGRESS XSTR("NotificationProgress") 222 | 223 | /*! @defined GROWL_NOTIFICATION_ALREADY_SHOWN 224 | * @abstract If this key is set, it should contain a bool value wrapped 225 | * in a NSNumber which describes whether the notification has 226 | * already been displayed, for instance by built in Notification 227 | * Center support. This value can be used to allow display 228 | * plugins to skip a notification, while still allowing Growl 229 | * actions to run on them. 230 | * 231 | * Optional. Not supported by all display plugins. 232 | */ 233 | #define GROWL_NOTIFICATION_ALREADY_SHOWN XSTR("AlreadyShown") 234 | 235 | 236 | // Notifications 237 | #pragma mark Notifications 238 | 239 | /*! @group Notification names */ 240 | /* @abstract Names of distributed notifications used by Growl. 241 | * @discussion These are notifications used by applications (directly or 242 | * indirectly) to interact with Growl, and by Growl for interaction between 243 | * its components. 244 | * 245 | * Most of these should no longer be used in Growl 0.6 and later, in favor of 246 | * Growl.framework's GrowlApplicationBridge APIs. 247 | */ 248 | 249 | /*! @defined GROWL_APP_REGISTRATION 250 | * @abstract The distributed notification for registering your application. 251 | * @discussion This is the name of the distributed notification that can be 252 | * used to register applications with Growl. 253 | * 254 | * The userInfo dictionary for this notification can contain these keys: 255 | *
    256 | *
  • GROWL_APP_NAME
  • 257 | *
  • GROWL_APP_ICON_DATA
  • 258 | *
  • GROWL_NOTIFICATIONS_ALL
  • 259 | *
  • GROWL_NOTIFICATIONS_DEFAULT
  • 260 | *
261 | * 262 | * No longer recommended as of Growl 0.6. An alternate method of registering 263 | * is to use Growl.framework's delegate system. 264 | * See +[GrowlApplicationBridge setGrowlDelegate:] or Growl_SetDelegate for 265 | * more information. 266 | */ 267 | #define GROWL_APP_REGISTRATION XSTR("GrowlApplicationRegistrationNotification") 268 | /*! @defined GROWL_APP_REGISTRATION_CONF 269 | * @abstract The distributed notification for confirming registration. 270 | * @discussion The name of the distributed notification sent to confirm the 271 | * registration. Used by the Growl preference pane. Your application probably 272 | * does not need to use this notification. 273 | */ 274 | #define GROWL_APP_REGISTRATION_CONF XSTR("GrowlApplicationRegistrationConfirmationNotification") 275 | /*! @defined GROWL_NOTIFICATION 276 | * @abstract The distributed notification for Growl notifications. 277 | * @discussion This is what it all comes down to. This is the name of the 278 | * distributed notification that your application posts to actually send a 279 | * Growl notification. 280 | * 281 | * The userInfo dictionary for this notification can contain these keys: 282 | *
    283 | *
  • GROWL_NOTIFICATION_NAME (required)
  • 284 | *
  • GROWL_NOTIFICATION_TITLE (required)
  • 285 | *
  • GROWL_NOTIFICATION_DESCRIPTION (required)
  • 286 | *
  • GROWL_NOTIFICATION_ICON
  • 287 | *
  • GROWL_NOTIFICATION_APP_ICON
  • 288 | *
  • GROWL_NOTIFICATION_PRIORITY
  • 289 | *
  • GROWL_NOTIFICATION_STICKY
  • 290 | *
  • GROWL_NOTIFICATION_CLICK_CONTEXT
  • 291 | *
  • GROWL_APP_NAME (required)
  • 292 | *
293 | * 294 | * No longer recommended as of Growl 0.6. Three alternate methods of posting 295 | * notifications are +[GrowlApplicationBridge notifyWithTitle:description:notificationName:iconData:priority:isSticky:clickContext:], 296 | * Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext, and 297 | * Growl_PostNotification. 298 | */ 299 | #define GROWL_NOTIFICATION XSTR("GrowlNotification") 300 | /*! @defined GROWL_PING 301 | * @abstract A distributed notification to check whether Growl is running. 302 | * @discussion This is used by the Growl preference pane. If it receives a 303 | * GROWL_PONG, the preference pane takes this to mean that Growl is running. 304 | */ 305 | #define GROWL_PING XSTR("Honey, Mind Taking Out The Trash") 306 | /*! @defined GROWL_PONG 307 | * @abstract The distributed notification sent in reply to GROWL_PING. 308 | * @discussion GrowlHelperApp posts this in reply to GROWL_PING. 309 | */ 310 | #define GROWL_PONG XSTR("What Do You Want From Me, Woman") 311 | /*! @defined GROWL_IS_READY 312 | * @abstract The distributed notification sent when Growl starts up. 313 | * @discussion GrowlHelperApp posts this when it has begin listening on all of 314 | * its sources for new notifications. GrowlApplicationBridge (in 315 | * Growl.framework), upon receiving this notification, reregisters using the 316 | * registration dictionary supplied by its delegate. 317 | */ 318 | #define GROWL_IS_READY XSTR("Lend Me Some Sugar; I Am Your Neighbor!") 319 | 320 | 321 | /*! @defined GROWL_DISTRIBUTED_NOTIFICATION_CLICKED_SUFFIX 322 | * @abstract Part of the name of the distributed notification sent when a supported notification is clicked. 323 | * @discussion When a Growl notification with a click context is clicked on by 324 | * the user, Growl posts a distributed notification whose name is in the format: 325 | * [NSString stringWithFormat:@"%@-%d-%@", appName, pid, GROWL_DISTRIBUTED_NOTIFICATION_CLICKED_SUFFIX] 326 | * The GrowlApplicationBridge responds to this notification by calling a callback in its delegate. 327 | */ 328 | #define GROWL_DISTRIBUTED_NOTIFICATION_CLICKED_SUFFIX XSTR("GrowlClicked!") 329 | 330 | /*! @defined GROWL_DISTRIBUTED_NOTIFICATION_TIMED_OUT_SUFFIX 331 | * @abstract Part of the name of the distributed notification sent when a supported notification times out without being clicked. 332 | * @discussion When a Growl notification with a click context times out, Growl posts a distributed notification 333 | * whose name is in the format: 334 | * [NSString stringWithFormat:@"%@-%d-%@", appName, pid, GROWL_DISTRIBUTED_NOTIFICATION_TIMED_OUT_SUFFIX] 335 | * The GrowlApplicationBridge responds to this notification by calling a callback in its delegate. 336 | * NOTE: The user may have actually clicked the 'close' button; this triggers an *immediate* time-out of the notification. 337 | */ 338 | #define GROWL_DISTRIBUTED_NOTIFICATION_TIMED_OUT_SUFFIX XSTR("GrowlTimedOut!") 339 | 340 | /*! @defined GROWL_DISTRIBUTED_NOTIFICATION_NOTIFICATIONCENTER_ON 341 | * @abstract The distributed notification sent when the Notification Center support is toggled on in Growl 2.0 342 | * @discussion When the user enables Notification Center support in Growl 2.0, this notification is sent 343 | * to inform all running apps that they should now speak to Notification Center directly. 344 | */ 345 | #define GROWL_DISTRIBUTED_NOTIFICATION_NOTIFICATIONCENTER_ON XSTR("GrowlNotificationCenterOn!") 346 | 347 | /*! @defined GROWL_DISTRIBUTED_NOTIFICATION_NOTIFICATIONCENTER_OFF 348 | * @abstract The distributed notification sent when the Notification Center support is toggled off in Growl 2.0 349 | * @discussion When the user enables Notification Center support in Growl 2.0, this notification is sent 350 | * to inform all running apps that they should no longer speak to Notification Center directly. 351 | */ 352 | #define GROWL_DISTRIBUTED_NOTIFICATION_NOTIFICATIONCENTER_OFF XSTR("GrowlNotificationCenterOff!") 353 | 354 | /*! @defined GROWL_DISTRIBUTED_NOTIFICATION_NOTIFICATIONCENTER_QUERY 355 | * @abstract The distributed notification sent by an application to query Growl 2.0's notification center support. 356 | * @discussion When an app starts up, it will send this query to get Growl 2.0 to spit out whether notification 357 | * center support is on or off. 358 | */ 359 | #define GROWL_DISTRIBUTED_NOTIFICATION_NOTIFICATIONCENTER_QUERY XSTR("GrowlNotificationCenterYN?") 360 | 361 | 362 | /*! @group Other symbols */ 363 | /* Symbols which don't fit into any of the other categories. */ 364 | 365 | /*! @defined GROWL_KEY_CLICKED_CONTEXT 366 | * @abstract Used internally as the key for the clickedContext passed over DNC. 367 | * @discussion This key is used in GROWL_NOTIFICATION_CLICKED, and contains the 368 | * click context that was supplied in the original notification. 369 | */ 370 | #define GROWL_KEY_CLICKED_CONTEXT XSTR("ClickedContext") 371 | /*! @defined GROWL_REG_DICT_EXTENSION 372 | * @abstract The filename extension for registration dictionaries. 373 | * @discussion The GrowlApplicationBridge in Growl.framework registers with 374 | * Growl by creating a file with the extension of .(GROWL_REG_DICT_EXTENSION) 375 | * and opening it in the GrowlHelperApp. This happens whether or not Growl is 376 | * running; if it was stopped, it quits immediately without listening for 377 | * notifications. 378 | */ 379 | #define GROWL_REG_DICT_EXTENSION XSTR("growlRegDict") 380 | 381 | 382 | #define GROWL_POSITION_PREFERENCE_KEY @"GrowlSelectedPosition" 383 | 384 | #define GROWL_PLUGIN_CONFIG_ID XSTR("GrowlPluginConfigurationID") 385 | 386 | #endif //ndef _GROWLDEFINES_H 387 | --------------------------------------------------------------------------------