Common/Source/GrowlDefinesInternal.h
author Peter Hosey <hg@boredzo.org>
Tue Jul 14 06:30:22 2009 -0700 (2009-07-14)
changeset 4240 c85bf1983721
parent 4041 49b99685af70
child 4246 4f52d1d98978
child 4735 2093d9c003d4
permissions -rw-r--r--
Fix GrowlSafari for Safari 4.0.x on Tiger.

We now correctly test the build number and use the correct stage constants for the Tiger version of Safari 4.
     1 //
     2 //  GrowlDefinesInternal.h
     3 //  Growl
     4 //
     5 //  Created by Karl Adam on Mon May 17 2004.
     6 //  Copyright (c) 2004 the Growl Project. All rights reserved.
     7 //
     8 
     9 #ifndef _GROWL_GROWLDEFINESINTERNAL_H
    10 #define _GROWL_GROWLDEFINESINTERNAL_H
    11 
    12 #include <CoreFoundation/CoreFoundation.h>
    13 #include <sys/types.h>
    14 #include <unistd.h>
    15 
    16 #ifdef __OBJC__
    17 #define XSTR(x) (@x)
    18 #else /* !__OBJC__ */
    19 #define XSTR CFSTR
    20 #endif /* __OBJC__ */
    21 
    22 /*!	@header	GrowlDefinesInternal.h
    23  *	@abstract	Defines internal Growl macros and types.
    24  *  @ignore ATTRIBUTE_PACKED
    25  *	@discussion	These constants are used both by GrowlHelperApp and by plug-ins.
    26  *
    27  *	 Notification keys (used in GrowlHelperApp, in GrowlApplicationBridge, and
    28  *	 by applications that don't use GrowlApplicationBridge) are defined in
    29  *	 GrowlDefines.h.
    30  */
    31 
    32 /*!	@defined	GROWL_TCP_PORT
    33  *	@abstract	The TCP listen port for Growl notification servers.
    34  */
    35 #define GROWL_TCP_PORT	23052
    36 
    37 /*!	@defined	GROWL_UDP_PORT
    38  *	@abstract	The UDP listen port for Growl notification servers.
    39  */
    40 #define GROWL_UDP_PORT	9887
    41 
    42 /*!	@defined	GROWL_PROTOCOL_VERSION
    43  *	@abstract	The current version of the Growl network-notifications protocol (without encryption).
    44  */
    45 #define GROWL_PROTOCOL_VERSION	1
    46 
    47 /*!	@defined	GROWL_PROTOCOL_VERSION_AES128
    48 *	@abstract	The current version of the Growl network-notifications protocol (with AES-128 encryption).
    49 */
    50 #define GROWL_PROTOCOL_VERSION_AES128	2
    51 
    52 /*!	@defined	GROWL_TYPE_REGISTRATION
    53  *	@abstract	The packet type of registration packets with MD5 authentication.
    54  */
    55 #define GROWL_TYPE_REGISTRATION			0
    56 /*!	@defined	GROWL_TYPE_NOTIFICATION
    57  *	@abstract	The packet type of notification packets with MD5 authentication.
    58  */
    59 #define GROWL_TYPE_NOTIFICATION			1
    60 /*!	@defined	GROWL_TYPE_REGISTRATION_SHA256
    61  *	@abstract	The packet type of registration packets with SHA-256 authentication.
    62  */
    63 #define GROWL_TYPE_REGISTRATION_SHA256	2
    64 /*!	@defined	GROWL_TYPE_NOTIFICATION_SHA256
    65  *	@abstract	The packet type of notification packets with SHA-256 authentication.
    66  */
    67 #define GROWL_TYPE_NOTIFICATION_SHA256	3
    68 /*!	@defined	GROWL_TYPE_REGISTRATION_NOAUTH
    69 *	@abstract	The packet type of registration packets without authentication.
    70 */
    71 #define GROWL_TYPE_REGISTRATION_NOAUTH	4
    72 /*!	@defined	GROWL_TYPE_NOTIFICATION_NOAUTH
    73 *	@abstract	The packet type of notification packets without authentication.
    74 */
    75 #define GROWL_TYPE_NOTIFICATION_NOAUTH	5
    76 
    77 #define ATTRIBUTE_PACKED __attribute((packed))
    78 
    79 /*!	@struct	GrowlNetworkPacket
    80  *	@abstract	This struct is a header common to all incoming Growl network
    81  *	 packets which identifies the type and version of the packet.
    82  */
    83 struct GrowlNetworkPacket {
    84 	unsigned char version;
    85 	unsigned char type;
    86 } ATTRIBUTE_PACKED;
    87 
    88 /*!
    89  * @struct GrowlNetworkRegistration
    90  * @abstract The format of a registration packet.
    91  * @discussion A Growl client that wants to register with a Growl server sends
    92  * a packet in this format.
    93  * @field common The Growl packet header.
    94  * @field appNameLen The name of the application that is registering.
    95  * @field numAllNotifications The number of notifications in the list.
    96  * @field numDefaultNotifications The number of notifications in the list that are enabled by default.
    97  * @field data Variable-sized data.
    98  */
    99 struct GrowlNetworkRegistration {
   100 	struct GrowlNetworkPacket common;
   101 	/*	This name is used both internally and in the Growl
   102 	 *	 preferences.
   103 	 *
   104 	 *	 The application name should remain stable between different versions
   105 	 *	 and incarnations of your application.
   106 	 *	 For example, "SurfWriter" is a good app name, whereas "SurfWriter 2.0"
   107 	 *	 and "SurfWriter Lite" are not.
   108 	 *
   109 	 *	 In addition to being unsigned, the application name length is in
   110 	 *	 network byte order.
   111 	 */
   112 	unsigned short appNameLen;
   113 	/*	These names are used both internally and in the Growl
   114 	 *	 preferences. For this reason, they should be human-readable.
   115 	 */
   116 	unsigned char numAllNotifications;
   117 
   118 	unsigned char numDefaultNotifications;
   119 	/*	The variable-sized data of a registration is:
   120 	 *	 - The application name, in UTF-8 encoding, for appNameLen bytes.
   121 	 *	 - The list of all notification names.
   122 	 *	 - The list of default notifications, as 8-bit unsigned indices into the list of all notifications.
   123 	 *	 - The MD5/SHA256 checksum of all the data preceding the checksum.
   124 	 *
   125 	 *	 Each notification name is encoded as:
   126 	 *	 - Length: two bytes, unsigned, network byte order.
   127 	 *	 - Name: As many bytes of UTF-8-encoded text as the length says.
   128 	 *	 And there are numAllNotifications of these.
   129 	 */
   130 	unsigned char data[];
   131 } ATTRIBUTE_PACKED;
   132 
   133 /*!
   134  * @struct GrowlNetworkNotification
   135  * @abstract The format of a notification packet.
   136  * @discussion	A Growl client that wants to post a notification to a Growl
   137  * server sends a packet in this format.
   138  * @field common The Growl packet header.
   139  * @field flags The priority number and the sticky bit.
   140  * @field nameLen The length of the notification name.
   141  * @field titleLen The length of the notification title.
   142  * @field descriptionLen The length of the notification description.
   143  * @field appNameLen The length of the application name.
   144  * @field data Variable-sized data.
   145  */
   146 struct GrowlNetworkNotification {
   147 	struct GrowlNetworkPacket common;
   148 	/*!
   149 	 * @struct GrowlNetworkNotificationFlags
   150 	 * @abstract Various flags.
   151 	 * @discussion This 16-bit packed structure contains the priority as a
   152 	 *  signed 3-bit integer from -2 to +2, and the sticky flag as a single bit.
   153 	 *  The high 12 bits of the structure are reserved for future use.
   154 	 * @field reserved reserved for future use.
   155 	 * @field priority the priority as a signed 3-bit integer from -2 to +2.
   156 	 * @field sticky the sticky flag.
   157 	 */
   158 	struct GrowlNetworkNotificationFlags {
   159 #ifdef __BIG_ENDIAN__
   160 		unsigned reserved: 12;
   161 		signed   priority: 3;
   162 		unsigned sticky:   1;
   163 #else
   164 		unsigned sticky:   1;
   165 		signed   priority: 3;
   166 		unsigned reserved: 12;
   167 #endif
   168 	} ATTRIBUTE_PACKED flags; //size = 16 (12 + 3 + 1)
   169 
   170 	/*	In addition to being unsigned, the notification name length
   171 	 *	 is in network byte order.
   172 	 */
   173 	unsigned short nameLen;
   174 	/*	@discussion	In addition to being unsigned, the title length is in
   175 	 *	 network byte order.
   176 	 */
   177 	unsigned short titleLen;
   178 	/*	In addition to being unsigned, the description length is in
   179 	 *	 network byte order.
   180 	 */
   181 	unsigned short descriptionLen;
   182 	/*	In addition to being unsigned, the application name length
   183 	 *	 is in network byte order.
   184 	 */
   185 	unsigned short appNameLen;
   186 	/*	The variable-sized data of a notification is:
   187 	 *	 - Notification name, in UTF-8 encoding, for nameLen bytes.
   188 	 *	 - Title, in UTF-8 encoding, for titleLen bytes.
   189 	 *	 - Description, in UTF-8 encoding, for descriptionLen bytes.
   190 	 *	 - Application name, in UTF-8 encoding, for appNameLen bytes.
   191 	 *	 - The MD5/SHA256 checksum of all the data preceding the checksum.
   192 	 */
   193 	unsigned char data[];
   194 } ATTRIBUTE_PACKED;
   195 
   196 /*!	@defined	GrowlEnabledKey
   197  *	@abstract	Preference key controlling whether Growl is enabled.
   198  *	@discussion	If this is false, then when GrowlHelperApp is launched to open
   199  *	 a Growl registration dictionary file, GrowlHelperApp will quit when it has
   200  *	 finished processing the file instead of listening for notifications.
   201  */
   202 #define GrowlEnabledKey					XSTR("GrowlEnabled")
   203 
   204 /*!	@defined	GROWL_SCREENSHOT_MODE
   205  *	@abstract	Preference and notification key controlling whether to save a screenshot of the notification.
   206  *	@discussion	This is for GHA's private usage. If your application puts this
   207  *	 key into a notification dictionary, GHA will clobber it. This key is only
   208  *	 allowed in the notification dictionaries GHA passes to displays.
   209  *
   210  *	 If this key contains an object whose boolValue is not NO, the display is
   211  *	 asked to save a screenshot of the notification to
   212  *	 ~/Library/Application\ Support/Growl/Screenshots.
   213  */
   214 #define GROWL_SCREENSHOT_MODE			XSTR("ScreenshotMode")
   215 
   216 /*!	@defined	GROWL_APP_LOCATION
   217  *	@abstract	The location of this application.
   218  *	@discussion	Contains either the POSIX path to the application, or a file-data dictionary (as used by the Dock).
   219  *	 contains the file's alias record and its pathname.
   220  */
   221 #define GROWL_APP_LOCATION				XSTR("AppLocation")
   222 
   223 /*!	@defined	GROWL_REMOTE_ADDRESS
   224  *	@abstract	The address of the host who sent this notification/registration.
   225  *	@discussion	Contains an NSData with the address of the remote host who
   226  *    sent this notification/registration.
   227  */
   228 #define GROWL_REMOTE_ADDRESS			XSTR("RemoteAddress")
   229 
   230 /*!
   231  *	@defined    GROWL_PREFPANE_BUNDLE_IDENTIFIER
   232  *	@discussion The bundle identifier for the Growl preference pane.
   233  */
   234 #define GROWL_PREFPANE_BUNDLE_IDENTIFIER		XSTR("com.growl.prefpanel")
   235 /*!
   236  *	@defined    GROWL_HELPERAPP_BUNDLE_IDENTIFIER
   237  *	@discussion The bundle identifier for the Growl background application (GrowlHelperApp).
   238  */
   239 #define GROWL_HELPERAPP_BUNDLE_IDENTIFIER	XSTR("com.Growl.GrowlHelperApp")
   240 
   241 /*!
   242  *	@defined    GROWL_PREFPANE_NAME
   243  *	@discussion The file name of the Growl preference pane.
   244  */
   245 #define GROWL_PREFPANE_NAME						XSTR("Growl.prefPane")
   246 #define PREFERENCE_PANES_SUBFOLDER_OF_LIBRARY	XSTR("PreferencePanes")
   247 #define PREFERENCE_PANE_EXTENSION				XSTR("prefPane")
   248 
   249 //plug-in bundle filename extensions
   250 #define GROWL_PLUGIN_EXTENSION                  XSTR("growlPlugin")
   251 #define GROWL_PATHWAY_EXTENSION                 XSTR("growlPathway")
   252 #define GROWL_VIEW_EXTENSION					XSTR("growlView")
   253 #define GROWL_STYLE_EXTENSION					XSTR("growlStyle")
   254 
   255 /* --- These following macros are intended for plug-ins --- */
   256 
   257 /*!	@function    SYNCHRONIZE_GROWL_PREFS
   258  *	@abstract    Synchronizes Growl prefs so they're up-to-date.
   259  *	@discussion  This macro is intended for use by GrowlHelperApp and by
   260  *	 plug-ins (when the prefpane is selected).
   261  */
   262 #define SYNCHRONIZE_GROWL_PREFS() CFPreferencesAppSynchronize(CFSTR("com.Growl.GrowlHelperApp"))
   263 
   264 /*!	@function    UPDATE_GROWL_PREFS
   265  *	@abstract    Tells GrowlHelperApp to update its prefs.
   266  *	@discussion  This macro is intended for use by plug-ins.
   267  *	 It sends a notification to tell GrowlHelperApp to update its preferences.
   268  */
   269 #define UPDATE_GROWL_PREFS() do { \
   270 	SYNCHRONIZE_GROWL_PREFS(); \
   271 	CFStringRef _key = CFSTR("pid"); \
   272 	int pid = getpid(); \
   273 	CFNumberRef _value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &pid); \
   274 	CFDictionaryRef userInfo = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&_key, (const void **)&_value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); \
   275 	CFRelease(_value); \
   276 	CFNotificationCenterPostNotification(CFNotificationCenterGetDistributedCenter(), \
   277 										 CFSTR("GrowlPreferencesChanged"), \
   278 										 CFSTR("GrowlUserDefaults"), \
   279 										 userInfo, false); \
   280 	CFRelease(userInfo); \
   281 	} while(0)
   282 
   283 /*!	@function    READ_GROWL_PREF_VALUE
   284  *	@abstract    Reads the given pref value from the plug-in's preferences.
   285  *	@discussion  This macro is intended for use by plug-ins. It reads the value for the
   286  *	 given key from the plug-in's preferences (which are stored in a dictionary inside of
   287  *	 GrowlHelperApp's prefs).
   288  *	@param	key	The preference key to read the value of.
   289  *	@param	domain	The bundle ID of the plug-in.
   290  *	@param	type	The type of the result expected.
   291  *	@param	result	A pointer to an id. Set to the value if exists, left unchanged if not.
   292  *
   293  *	 If the value is set, you are responsible for releasing it.
   294  */
   295 #define READ_GROWL_PREF_VALUE(key, domain, type, result) do {\
   296 	CFDictionaryRef prefs = (CFDictionaryRef)CFPreferencesCopyAppValue((CFStringRef)domain, \
   297 																		CFSTR("com.Growl.GrowlHelperApp")); \
   298 	if (prefs) {\
   299 		if (CFDictionaryContainsKey(prefs, key)) {\
   300 			*result = (type)CFDictionaryGetValue(prefs, key); \
   301 			CFRetain(*result); \
   302 		} \
   303 		CFRelease(prefs); } \
   304 	} while(0)
   305 
   306 /*!	@function    WRITE_GROWL_PREF_VALUE
   307  *	@abstract    Writes the given pref value to the plug-in's preferences.
   308  *	@discussion  This macro is intended for use by plug-ins. It writes the given
   309  *	 value to the plug-in's preferences.
   310  *	@param	key	The preference key to write the value of.
   311  *	@param	value	The value to write to the preferences. It should be either a
   312  *	 CoreFoundation type or toll-free bridged with one.
   313  *	@param	domain	The bundle ID of the plug-in.
   314  */
   315 #define WRITE_GROWL_PREF_VALUE(key, value, domain) do {\
   316 	CFDictionaryRef staticPrefs = (CFDictionaryRef)CFPreferencesCopyAppValue((CFStringRef)domain, \
   317 																			 CFSTR("com.Growl.GrowlHelperApp")); \
   318 	CFMutableDictionaryRef prefs; \
   319 	if (staticPrefs == NULL) {\
   320 		prefs = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); \
   321 	} else {\
   322 		prefs = CFDictionaryCreateMutableCopy(NULL, 0, staticPrefs); \
   323 		CFRelease(staticPrefs); \
   324 	}\
   325 	CFDictionarySetValue(prefs, key, value); \
   326 	CFPreferencesSetAppValue((CFStringRef)domain, prefs, CFSTR("com.Growl.GrowlHelperApp")); \
   327 	CFRelease(prefs); } while(0)
   328 
   329 /*!	@function    READ_GROWL_PREF_BOOL
   330  *	@abstract    Reads the given Boolean from the plug-in's preferences.
   331  *	@discussion  This is a wrapper around READ_GROWL_PREF_VALUE() intended for
   332  *	 use with Booleans.
   333  *	@param	key	The preference key to read the Boolean from.
   334  *	@param	domain	The bundle ID of the plug-in.
   335  *	@param	result	A pointer to a Boolean type. Left unchanged if the value doesn't exist.
   336  */
   337 #define READ_GROWL_PREF_BOOL(key, domain, result) do {\
   338 	CFBooleanRef boolValue = NULL; \
   339 	READ_GROWL_PREF_VALUE(key, domain, CFBooleanRef, &boolValue); \
   340 	if (boolValue) {\
   341 		*result = CFBooleanGetValue(boolValue); \
   342 		CFRelease(boolValue); \
   343 	} } while(0)
   344 
   345 /*!	@function    WRITE_GROWL_PREF_BOOL
   346  *	@abstract    Writes the given Boolean to the plug-in's preferences.
   347  *	@discussion  This is a wrapper around WRITE_GROWL_PREF_VALUE() intended for
   348  *	 use with Booleans.
   349  *	@param	key	The preference key to write the Boolean for.
   350  *	@param	value	The Boolean value to write to the preferences.
   351  *	@param	domain	The bundle ID of the plug-in.
   352  */
   353 #define WRITE_GROWL_PREF_BOOL(key, value, domain) do {\
   354 	WRITE_GROWL_PREF_VALUE(key, value ? kCFBooleanTrue : kCFBooleanFalse, domain); } while(0)
   355 
   356 /*!	@function    READ_GROWL_PREF_INT
   357  *	@abstract    Reads the given integer from the plug-in's preferences.
   358  *	@discussion  This is a wrapper around READ_GROWL_PREF_VALUE() intended for
   359  *	 use with integers.
   360  *	@param	key	The preference key to read the integer from.
   361  *	@param	domain	The bundle ID of the plug-in.
   362  *	@param	result	A pointer to an integer. Leaves unchanged if the value doesn't exist.
   363  */
   364 #define READ_GROWL_PREF_INT(key, domain, result) do {\
   365 	CFNumberRef intValue = NULL; \
   366 	READ_GROWL_PREF_VALUE(key, domain, CFNumberRef, &intValue); \
   367 	if (intValue) {\
   368 		CFNumberGetValue(intValue, kCFNumberIntType, result); \
   369 		CFRelease(intValue); \
   370 	} } while(0)
   371 
   372 /*!	@function    WRITE_GROWL_PREF_INT
   373  *	@abstract    Writes the given integer to the plug-in's preferences.
   374  *	@discussion  This is a wrapper around WRITE_GROWL_PREF_VALUE() intended for
   375  *	 use with integers.
   376  *	@param	key	The preference key to write the integer for.
   377  *	@param	value	The integer value to write to the preferences.
   378  *	@param	domain	The bundle ID of the plug-in.
   379  */
   380 #define WRITE_GROWL_PREF_INT(key, value, domain) do {\
   381 	CFNumberRef intValue = CFNumberCreate(NULL, kCFNumberIntType, &value); \
   382 	WRITE_GROWL_PREF_VALUE(key, intValue, domain); \
   383 	CFRelease(intValue); } while(0)
   384 
   385 /*!	@function    READ_GROWL_PREF_FLOAT
   386  *	@abstract    Reads the given float from the plug-in's preferences.
   387  *	@discussion  This is a wrapper around READ_GROWL_PREF_VALUE() intended for
   388  *	 use with floats.
   389  *	@param	key	The preference key to read the float from.
   390  *	@param	domain	The bundle ID of the plug-in.
   391  *	@param	result	A pointer to a float. Leaves unchanged if the value doesn't exist.
   392  */
   393 #define READ_GROWL_PREF_FLOAT(key, domain, result) do {\
   394 	CFNumberRef floatValue = NULL; \
   395 	READ_GROWL_PREF_VALUE(key, domain, CFNumberRef, &floatValue); \
   396 	if (floatValue) {\
   397 		CFNumberGetValue(floatValue, kCFNumberFloatType, result); \
   398 		CFRelease(floatValue); \
   399 	} } while(0)
   400 
   401 /*!	@function    WRITE_GROWL_PREF_FLOAT
   402  *	@abstract    Writes the given float to the plug-in's preferences.
   403  *	@discussion  This is a wrapper around WRITE_GROWL_PREF_VALUE() intended for
   404  *	 use with floats.
   405  *	@param	key	The preference key to write the float for.
   406  *	@param	value	The float value to write to the preferences.
   407  *	@param	domain	The bundle ID of the plug-in.
   408  */
   409 #define WRITE_GROWL_PREF_FLOAT(key, value, domain) do {\
   410 	CFNumberRef floatValue = CFNumberCreate(NULL, kCFNumberFloatType, &value); \
   411 	WRITE_GROWL_PREF_VALUE(key, floatValue, domain); \
   412 	CFRelease(floatValue); } while(0)
   413 
   414 
   415 /*!	@defined	GROWL_CLOSE_ALL_NOTIFICATIONS
   416  *	@abstract	Notification to close all Growl notifications
   417  *	@discussion	Should be posted to the default notification center when a close widget is option+clicked.
   418  *    All notifications should close in response. 
   419  */
   420 #define GROWL_CLOSE_ALL_NOTIFICATIONS XSTR("GrowlCloseAllNotifications")
   421 
   422 #pragma mark Small utilities
   423 
   424 /*!
   425  * @defined FLOAT_EQ(x,y)
   426  * @abstract Compares two floats.
   427  */
   428 #define FLOAT_EQ(x,y) (((y - FLT_EPSILON) < x) && (x < (y + FLT_EPSILON)))
   429 
   430 #endif //ndef _GROWL_GROWLDEFINESINTERNAL_H