QuickLook plugin to preview .strings files

Posted: March 25th, 2014 | Author: | Filed under: Debugging, MacOSX, Programming | Tags: | 2 Comments »



OS X and iOS use .strings files for localized text strings as described in the String Resources Documentation:

Resource files that contain localizable strings are referred to as strings files because of their filename extension, which is .strings.



It is yet annoying that OS X and Xcode don’t provide a built-in QuickLook plugin for previewing .strings files. When you preview such a file in QuickLook you see this window:


Without 'StringsFile' QuickLook plugin

To solve this issue, here is a simple QuickLook plugin called ‘StringsFile’ that lets you preview .strings files (plain text .strings and binary property plist .strings).
This QuickLook plugin is really useful to quickly check the content of a .strings file. When you preview such a file, you will now see:


With 'StringsFile' QuickLook plugin


A precompiled version can be downloaded here: StringsFile.qlgenerator.zip



You can download the source code here : Download ‘StringsFile’ Source Code



Installation:

  • Download the precompiled version
  • Unzip
  • Copy the file into /Library/QuickLook/ or ~/Library/QuickLook/
  • Execute the command “qlmanage -r” in the Terminal – or restart the machine



Update (02.04.2014): The plugin has been updated to also generate a thumbnail for .strings files.


Thumbnail


Detecting the iOS device hardware architecture (32-bit/64-bit)

Posted: October 9th, 2013 | Author: | Filed under: iOS, Programming | Tags: , , , , , | 2 Comments »


In a previous post I explained how to detect if an app runs in a 32-bit or 64-bit iOS Simulator. It was not explaining how to detect if an iOS app runs on a 32-bit or 64-bit iOS device. This post aims at giving a generic method that can detect all cases:

  • 32-bit application running in a 32-bit iOS Simulator
  • 32-bit application running in a 64-bit iOS Simulator
  • 64-bit application running in a 64-bit iOS Simulator
  • 32-bit application running in a 32-bit iOS device
  • 32-bit application running in a 64-bit iOS device
  • 64-bit application running in a 64-bit iOS device


Below is the method is64bitHardware. It returns YES if the hardware is a 64-bit hardware and works on a real iOS device and in an iOS Simulator.
When running in an iOS Simulator, it uses the function is64bitSimulator() from my previous post http://blog.timac.org/?p=886.
When running on a real iOS device, it asks the kernel for the host info.



#include <mach/mach.h>

+ (BOOL) is64bitHardware
{
#if __LP64__
	// The app has been compiled for 64-bit intel and runs as 64-bit intel
	return YES;
#endif
	
	// Use some static variables to avoid performing the tasks several times.
	static BOOL sHardwareChecked = NO;
	static BOOL sIs64bitHardware = NO;
	
	if(!sHardwareChecked)
	{
		sHardwareChecked = YES;
	
#if TARGET_IPHONE_SIMULATOR
		// The app was compiled as 32-bit for the iOS Simulator.
		// We check if the Simulator is a 32-bit or 64-bit simulator using the function is64bitSimulator()
		// See http://blog.timac.org/?p=886
		sIs64bitHardware = is64bitSimulator();
#else
		// The app runs on a real iOS device: ask the kernel for the host info.
		struct host_basic_info host_basic_info;
		unsigned int count;
		kern_return_t returnValue = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)(&host_basic_info), &count);
		if(returnValue != KERN_SUCCESS)
		{
			sIs64bitHardware = NO;
		}
		
		sIs64bitHardware = (host_basic_info.cpu_type == CPU_TYPE_ARM64);

#endif // TARGET_IPHONE_SIMULATOR
	}

	return sIs64bitHardware;
}





Detecting if an app runs in a 32-bit or 64-bit iOS Simulator

Posted: October 1st, 2013 | Author: | Filed under: iOS, Programming | Tags: , , , , | No Comments »


With Xcode 5, it is now possible to compile an application for armv7 and/or arm64.
You can compile an application as 32-bit and/or as 64-bit and you can run this application in a 32-bit or 64-bit iOS Simulator:



In fact there are 3 different cases:

  • 32-bit application running in a 32-bit iOS Simulator
  • 32-bit application running in a 64-bit iOS Simulator
  • 64-bit application running in a 64-bit iOS Simulator

It is possible to distinguish these 3 different cases but this is not as easy as I would expected.


The case of a 64-bit application running in a 64-bit iOS Simulator is simple to solve by just using the define __LP64__: A 64-bit application can only run in a 64-bit iOS Simulator.


Distinguishing the 2 other cases is more difficult and a runtime check is needed. Something to note is that the ‘iOS Simulator’ process is running as 64-bit even in the case of a 32-bit iOS Simulator.

I noticed however that a process called ‘SimulatorBridge’ is used:

  • When launching an 64-bit iOS Simulator, the process ‘SimulatorBridge’ runs as 64-bit
  • When launching an 32-bit iOS Simulator, the process ‘SimulatorBridge’ runs as 32-bit

Running a 32-bit iOS Simulator



Below is a function to know if the iOS Simulator is a 32-bit Simulator or a 64-bit Simulator. The function “is64bitSimulator()” returns true if the iOS Simulator is a 64-bit iOS Simulator:

#include <sys/sysctl.h>

#if TARGET_IPHONE_SIMULATOR

bool is64bitSimulator()
{
	bool is64bitSimulator = false;
	
	/* Setting up the mib (Management Information Base) which is an array of integers where each
	 * integer specifies how the data will be gathered.  Here we are setting the MIB
	 * block to lookup the information on all the BSD processes on the system.  Also note that
	 * every regular application has a recognized BSD process accociated with it.  We pass
	 * CTL_KERN, KERN_PROC, KERN_PROC_ALL to sysctl as the MIB to get back a BSD structure with
	 * all BSD process information for all processes in it (including BSD process names)
	 */
	int mib[6] = {0,0,0,0,0,0};
	mib[0] = CTL_KERN;
    mib[1] = KERN_PROC;
    mib[2] = KERN_PROC_ALL;
	
	long numberOfRunningProcesses = 0;
	struct kinfo_proc* BSDProcessInformationStructure = NULL;
	size_t sizeOfBufferRequired = 0;
	
	/* Here we have a loop set up where we keep calling sysctl until we finally get an unrecoverable error
	 * (and we return) or we finally get a succesful result.  Note with how dynamic the process list can
	 * be you can expect to have a failure here and there since the process list can change between
	 * getting the size of buffer required and the actually filling that buffer.
	 */
	BOOL successfullyGotProcessInformation = NO;
	int error = 0;
	
	while (successfullyGotProcessInformation == NO)
	{
		/* Now that we have the MIB for looking up process information we will pass it to sysctl to get the 
		 * information we want on BSD processes.  However, before we do this we must know the size of the buffer to 
		 * allocate to accomidate the return value.  We can get the size of the data to allocate also using the 
		 * sysctl command.  In this case we call sysctl with the proper arguments but specify no return buffer 
		 * specified (null buffer).  This is a special case which causes sysctl to return the size of buffer required.
		 *
		 * First Argument: The MIB which is really just an array of integers.  Each integer is a constant
		 *     representing what information to gather from the system.  Check out the man page to know what
		 *     constants sysctl will work with.  Here of course we pass our MIB block which was passed to us.
		 * Second Argument: The number of constants in the MIB (array of integers).  In this case there are three.
		 * Third Argument: The output buffer where the return value from sysctl will be stored.  In this case
		 *     we don't want anything return yet since we don't yet know the size of buffer needed.  Thus we will
		 *     pass null for the buffer to begin with.
		 * Forth Argument: The size of the output buffer required.  Since the buffer itself is null we can just
		 *     get the buffer size needed back from this call.
		 * Fifth Argument: The new value we want the system data to have.  Here we don't want to set any system
		 *     information we only want to gather it.  Thus, we pass null as the buffer so sysctl knows that 
		 *     we have no desire to set the value.
		 * Sixth Argument: The length of the buffer containing new information (argument five).  In this case
		 *     argument five was null since we didn't want to set the system value.  Thus, the size of the buffer
		 *     is zero or NULL.
		 * Return Value: a return value indicating success or failure.  Actually, sysctl will either return
		 *     zero on no error and -1 on error.  The errno UNIX variable will be set on error.
		 */ 
		error = sysctl(mib, 3, NULL, &sizeOfBufferRequired, NULL, 0);
		if (error) 
			return NULL;
		
		/* Now we successful obtained the size of the buffer required for the sysctl call.  This is stored in the 
		 * SizeOfBufferRequired variable.  We will malloc a buffer of that size to hold the sysctl result.
		 */
		BSDProcessInformationStructure = (struct kinfo_proc*) malloc(sizeOfBufferRequired);
		if (BSDProcessInformationStructure == NULL)
			return NULL;
		
		/* Now we have the buffer of the correct size to hold the result we can now call sysctl
		 * and get the process information.  
		 *
		 * First Argument: The MIB for gathering information on running BSD processes.  The MIB is really 
		 *     just an array of integers.  Each integer is a constant representing what information to 
		 *     gather from the system.  Check out the man page to know what constants sysctl will work with.  
		 * Second Argument: The number of constants in the MIB (array of integers).  In this case there are three.
		 * Third Argument: The output buffer where the return value from sysctl will be stored.  This is the buffer
		 *     which we allocated specifically for this purpose.  
		 * Forth Argument: The size of the output buffer (argument three).  In this case its the size of the 
		 *     buffer we already allocated.  
		 * Fifth Argument: The buffer containing the value to set the system value to.  In this case we don't
		 *     want to set any system information we only want to gather it.  Thus, we pass null as the buffer
		 *     so sysctl knows that we have no desire to set the value.
		 * Sixth Argument: The length of the buffer containing new information (argument five).  In this case
		 *     argument five was null since we didn't want to set the system value.  Thus, the size of the buffer
		 *     is zero or NULL.
		 * Return Value: a return value indicating success or failure.  Actually, sysctl will either return 
		 *     zero on no error and -1 on error.  The errno UNIX variable will be set on error.
		 */
		error = sysctl(mib, 3, BSDProcessInformationStructure, &sizeOfBufferRequired, NULL, 0);
		if (error == 0)
        {
			//Here we successfully got the process information.  Thus set the variable to end this sysctl calling loop
            successfullyGotProcessInformation = YES;
        }
        else 
        {
			/* failed getting process information we will try again next time around the loop.  Note this is caused
			 * by the fact the process list changed between getting the size of the buffer and actually filling
			 * the buffer (something which will happen from time to time since the process list is dynamic).
			 * Anyways, the attempted sysctl call failed.  We will now begin again by freeing up the allocated 
			 * buffer and starting again at the beginning of the loop.
			 */
            free(BSDProcessInformationStructure); 
        }
	} //end while loop
	
	
	/* Now that we have the BSD structure describing the running processes we will parse it for the desired
     * process name.  First we will the number of running processes.  We can determine
     * the number of processes running because there is a kinfo_proc structure for each process.
     */
	numberOfRunningProcesses = sizeOfBufferRequired / sizeof(struct kinfo_proc);
	for (int i = 0; i < numberOfRunningProcesses; i++)
    {
		//Getting name of process we are examining
        const char *name = BSDProcessInformationStructure[i].kp_proc.p_comm;
		
		if(strcmp(name, "SimulatorBridge") == 0)
		{
			int p_flag = BSDProcessInformationStructure[i].kp_proc.p_flag;
			is64bitSimulator = (p_flag & P_LP64) == P_LP64;
			break;
		}
    }
	
	free(BSDProcessInformationStructure);
	return is64bitSimulator;
}

#endif // TARGET_IPHONE_SIMULATOR




Using AddressSanitizer with Xcode 4.6.1

Posted: April 10th, 2013 | Author: | Filed under: Debugging, MacOSX, Programming | Tags: , , , , , | 2 Comments »

Clang 3.3 now supports AddressSanitizer. Here is the description from the Clang 3.3 documentation:

AddressSanitizer is a fast memory error detector. It consists of a compiler instrumentation module and a run-time library. The tool can detect the following types of bugs:

  • Out-of-bounds accesses to heap, stack and globals
  • Use-after-free
  • Use-after-return (to some extent)
  • Double-free, invalid free

Typical slowdown introduced by AddressSanitizer is 2x.


Using AddressSanitizer by manually compiling a file is well documented. On the other hand using Xcode 4.6.1 to build a complex project with AddressSanitizer enabled is not so easy. Following are the steps to build an Xcode project with AddressSanitizer.


Note that I used Xcode 4.6.1 when writing this article. Xcode 4.6.1 contains a Clang build based on LLVM 3.2. Most likely a future Xcode build will contain a Clang build based on LLVM 3.3 which would simplify the use of AddressSanitizer in Xcode.

1- Building Clang 3.3

Since Xcode 4.6.1 contains an old build of Clang, we need to get and build Clang trunk. This is fairly easy. Here is what I did:

- svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
- cd llvm/tools
- svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
- cd ../..
- cd llvm/projects
- svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk compiler-rt
- cd ../..
- mkdir build
- cd build
- ../llvm/configure –enable-optimizations
- make -j `sysctl -n hw.logicalcpu`



2- Tell Xcode 4.6.1 to use Clang 3.3 we just compiled

The simplest solution I found is to add the following user define in the Xcode target:
CC = “PATH_TO/llvm/build/Debug+Asserts/bin/clang”;
You need to set PATH_TO to the folder where you compiled llvm.



3- Make sure the deployment target is set to 10.7 or higher.

I used the deployment target set to 10.7.



4- Add the C flag and linker flag -fsanitize=address

Add the C flag -fsanitize=address
Add the linker flag -fsanitize=address



5- Compile your project

Congratulations! You now have a build of your project with AddressSanitizer enabled.



6- Running the application

Xcode 4.6.1 fails to run this executable but you can run it from the Terminal and AddressSanitizer will detect possible memory errors.
If your application has a memory error, you will see an error message like:


Memory Error with AddressSanitizer



7- Symbolize the symbols

Currently AddressSanitizer does not symbolize its output.
You will need to manually symbolize the addresses. This can easily be done with atos (see man atos) and the dSYM file produced during the compilation (you might need to turn on “DWARF with dSYM File” in the Xcode target).

For example to symbolize the symbol 0x100001d86 in the AddressSanitizer message:

Alex:MyApplication alex$ atos -o build/Debug/MyApplication.app.dSYM/Contents/Resources/DWARF/MyApplication 0x100001d86
-[AppDelegate applicationDidFinishLaunching:] (in MyApplication) (AppDelegate.mm:23)



Useful references

Clang 3.3 documentation for AddressSanitizer: http://clang.llvm.org/docs/AddressSanitizer.html

AddressSanitizer HomePage: http://code.google.com/p/address-sanitizer/


Simple code injection using DYLD_INSERT_LIBRARIES

Posted: December 18th, 2012 | Author: | Filed under: code injection, Debugging, DYLD_INSERT_LIBRARIES, MacOSX, Programming | 1 Comment »



In the following article I will describe a simple method to inject code into executables on Mac OS X 10.8 using the DYLD_INSERT_LIBRARIES environment variable.
I also wrote a simple launcher that starts Calculator.app and injects code to modify the About Box of Calculator.app. When bringing the About Box window of Calculator.app, a custom alert will be displayed:

Modifying Calculator.app AboutBox to display a custom alert



Note: Code injection should be used with care. You should probably not ship applications using code injection and the discussed environment variable DYLD_INSERT_LIBRARIES.



On Mac OS X 10.8, there are several ways to inject code into an arbitrary 64-bit process:

  • writing a plugin if the targeted application supports plugins. Such a solution is possible for applications like Safari, Mail, Xcode… but not for the Calculator.app.
  • Injecting code through Scripting Additions: you create a daemon to watch the launch of the targeted application and this daemon sends a custom Apple event to trigger the code injection. This solution is apparently used by 1Password 3.
  • you can inject code using Mach ports by using mach_override and mach_inject but it has some downsides (you need to be in the procmod group or root).
  • Injecting code through a kernel extension: This is really powerful but the code runs in the kernel.
  • Modifying the binary of the application but this can’t be reused and you need to reapply the changes for each new version of the application.
  • Injecting code using the DYLD_INSERT_LIBRARIES environment variable: this is a really simple solution to implement but you can only inject code in the application you launch.

Now that we know the different ways for injecting code, let’s look more in details at the DYLD_INSERT_LIBRARIES environment variable.


Using DYLD_INSERT_LIBRARIES has several advantages:

  • It is simple to implement.
  • All the code runs in userland and you don’t need to be root or run with the procmod group.
  • You don’t rely on complex third party code.
  • It can be used to inject code in any application you start.
  • You only inject code in a specific application.

It has some downsides:

  • You can only inject code in the applications you start.


On Mac OS X, the dynamic linker (dyld) can be used to load a dynamic library specified in the DYLD_INSERT_LIBRARIES environment variable into an executable. I created a simple dynamic library that replaces the -[CalculatorController showAbout:] method of Calculator.app with a custom implementation. Following is the code of the dynamic library (ACCalculatorOverrides.m). Here is what it does:

  • I created an object called ACCalculatorOverrides with a +(void)load class method. This code is invoked really early by the runtime. It exchanges the implementation of the method -[CalculatorController showAbout:] by the implementation of -[ACCalculatorOverrides patchedShowAbout:].
  • The method -[ACCalculatorOverrides patchedShowAbout:] will call the original method to display the original About Box and then display a custom alert.

#import "ACCalculatorOverrides.h"

#include <stdio.h>
#include <objc/runtime.h>
#include <Foundation/Foundation.h>
#include <AppKit/AppKit.h>

static IMP sOriginalImp = NULL;

@implementation ACCalculatorOverrides

+(void)load
{
	// We replace the method -[CalculatorController showAbout:] with the method -[ACCalculatorOverrides patchedShowAbout:]
	Class originalClass = NSClassFromString(@"CalculatorController");
	Method originalMeth = class_getInstanceMethod(originalClass, @selector(showAbout:));
	sOriginalImp = method_getImplementation(originalMeth);
	
	Method replacementMeth = class_getInstanceMethod(NSClassFromString(@"ACCalculatorOverrides"), @selector(patchedShowAbout:));
	method_exchangeImplementations(originalMeth, replacementMeth);
}

-(void)patchedShowAbout:(id)sender
{
	// We first call the original method to display the original About Box
	sOriginalImp(self, @selector(showAbout:), self);
	
	// Run our custom code which simply display an alert
	NSAlert *alert = [NSAlert alertWithMessageText:@"Code has been injected!" defaultButton:@"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:@"The code has been injected using DYLD_INSERT_LIBRARIES into Calculator.app"];
	[alert runModal];
}

@end



It is possible to manually build this dynamic library by running in the Terminal:

gcc -framework AppKit -framework Foundation -o CalculatorOverrides.dylib -dynamiclib ACCalculatorOverrides.m

and manually injecting it into Calculator.app by running in the Terminal:

DYLD_INSERT_LIBRARIES=/PATH_TO/CalculatorOverrides.dylib /Applications/Calculator.app/Contents/MacOS/Calculator &



But to make it simpler to use, let’s write a launcher. The launcher will be a background-only application (LSUIElement set to YES) that will execute the previously mentioned command line and then quit itself. Here is the code of the launcher:


#import "AppDelegate.h"

@implementation AppDelegate

- (void)dealloc
{
    [super dealloc];
}

-(void)bringToFrontApplicationWithBundleIdentifier:(NSString*)inBundleIdentifier
{
	// Try to bring the application to front
	NSArray* appsArray = [NSRunningApplication runningApplicationsWithBundleIdentifier:inBundleIdentifier];
	if([appsArray count] > 0)
	{
		[[appsArray objectAtIndex:0] activateWithOptions:NSApplicationActivateIgnoringOtherApps];
	}
	
	// Quit ourself
	[[NSApplication sharedApplication] terminate:self];
}

-(void)launchApplicationWithPath:(NSString*)inPath andBundleIdentifier:(NSString*)inBundleIdentifier
{
	if(inPath != nil)
	{
		// Run Calculator.app and inject our dynamic library
		NSString *dyldLibrary = [[NSBundle bundleForClass:[self class]] pathForResource:@"CalculatorOverrides" ofType:@"dylib"];
		NSString *launcherString = [NSString stringWithFormat:@"DYLD_INSERT_LIBRARIES=\"%@\" \"%@\" &", dyldLibrary, inPath];
		system([launcherString UTF8String]);
		
		// Bring it to front after a delay
		[self performSelector:@selector(bringToFrontApplicationWithBundleIdentifier:) withObject:inBundleIdentifier afterDelay:1.0];
	}
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
	NSString *calculatorPath = @"/Applications/Calculator.app/Contents/MacOS/Calculator";
	if([[NSFileManager defaultManager] fileExistsAtPath:calculatorPath])
		[self launchApplicationWithPath:calculatorPath andBundleIdentifier:@"com.apple.calculator"];
}

@end



Download: You can download here the compiled Calculator Launcher. If you launch it, it will launch the Calculator.app and inject the code to display an alert when you display the About Box of Calculator.app. If you are interested by the source code, the full sources are available here.


Marre d’être inscrit aux newsletters car sur les listes électorales consulaires ?

Posted: March 30th, 2012 | Author: | Filed under: Politique | No Comments »

Vous aussi vous êtes inscrit sur les listes électorales consulaires et vous en avez marre d’être inscrit, sans votre accord, aux newsletters de tous les candidats et partis ?
Voici un exemple de lettre que vous pouvez envoyer à votre consulat.

Pour les français vivant à Munich, vous pouvez contacter votre consulat ici :
http://www.botschaft-frankreich.de/konsulate/spip.php?article77&empfanger=162

Vous pouvez contacter la section consulaire de l’ambassade ici :
http://www.botschaft-frankreich.de/konsulate/spip.php?article31&empfanger=150



——————————————————————

Madame, Monsieur,

En tant que français vivant à l’étranger, je suis inscrit sur les listes électorales consulaires et au Registre des Français établis hors de France. Je souhaite bien évidemment recevoir les informations envoyées par mon consulat.

Cependant je ne souhaite pas que l’on m’inscrive sans mon avis aux newsletters de tous les candidats, partis, groupements politiques, … !

En un an, j’ai été abonné aux newsletters de :
- PS – Primaires citoyennes, francaisaletranger@lesprimairescitoyennes.fr
- François Hollande, fhollande@francoishollande.fr
- Nicolas Jeanneté, nicolas.jeannete@ymail.com
- Nicolas Sarkozy, nicolassarkozy@communication.lafranceforte.fr
- François Bayrou, lettreinfo@bayrou.cccampaigns.com
- UMP

Cette manière de communiquer mes coordonnées personnelles est tout à fait inadmissible !

Au lieu de communiquer mes coordonnées personnelles sans mon accord, et de m’inscrire à toutes les newsletters de tous les candidats et partis, il aurait été plus intelligent que mon consulat ne m’envoie qu’UN SEUL email contenant une liste de liens pour que je puisse m’abonner, si je le souhaite, aux newsletters des différents candidats et partis.

Cordialement



——————————————————————

[MAJ] : Voilà la réponse du consulat :


Je fais suite à votre message de réclamation et vous prie de bien vouloir trouver ci-après les renseignements suivants :

1/Aux termes de la loi organique n° 76-97 du 31 janvier 1976 modifiée (notamment son article 8), de ses décrets d’application et de l’arrêt n°296013 du Conseil d’Etat du 10 aout 2007, il est prévu l’inscription obligatoire des adresses électroniques sur les listes électorales consulaires. Ces dispositions visent à faciliter, dans le contexte particulier de l’expatriation, la communication avec les compatriotes. Toujours en application de la loi, ces listes électorales peuvent être communiquées, dans les conditions prévues par le code électoral, aux électeurs, aux candidats et aux partis et groupements politiques. Ce dispositif est une adaptation de la législation applicable en métropole.


2/ La loi n’interdit pas aux électeurs d’indiquer à leur consulat une seconde adresse électronique. Celle-ci sera alors réservée à la communication avec le consulat. Elle ne sera pas mentionnée sur la Liste électorale consulaire et ne pourra pas être communiquée aux tiers.


3/ Le Ministère des Affaires étrangères communique les listes électorales consulaires et les adresses électroniques en se conformant aux avis de la Commission nationale de l’informatique et des libertés, notamment sa récente recommandation du 26 janvier 2012 concernant l’utilisation des adresses électroniques par les partis politiques.


4/ Toute personne qui obtient communication d’une liste électorale devient dépositaire de données à caractère personnel, ce qui engage sa responsabilité. Il lui appartient de veiller au respect de ses obligations à l’égard des électeurs et notamment de prendre toutes les mesures nécessaires pour garantir la protection de leur vie privée.



——————————————————————

[MAJ] : Dépôt de plainte auprès de la CNIL :

Si vous en avez marre, vous pouvez témoigner auprès de la CNIL par internet. C’est très rapide et ça se passe ici :
http://www.cnil.fr/en/elections/temoigner/

Vous pouvez également déposer une plainte auprès de la CNIL :
http://www.cnil.fr

Enfin il y a quelques liens intéressants :
LISTES ELECTORALES – Souriez, vous êtes spammés !

CAMPAGNE – Signalez les abus à la CNIL


StuffIt ContextualMenu for MacOSX 10.6

Posted: September 21st, 2010 | Author: | Filed under: MacOSX, Programming | Tags: , , , , , , , , | 3 Comments »



Smith Micro Software released StuffIt Deluxe® 2011 this week. If you don’t know StuffIt Deluxe®, it is described like this:

The StuffIt Deluxe® package gives you all the features you need to backup, share, archive, encrypt and shrink your photos, music, and other documents without compromising quality. StuffIt’s advanced technology specializes in the compression of MP3, PDF and graphics files with no quality loss. Shrink documents up to 98% of their original size. Use StuffIt to free-up space on your computer and to fit more compressed files onto CD/DVDs or other drives.


With MacOS X 10.5 (and older), it was possible to access some features of StuffIt directly from the Finder using a Contextual Menu. Here is the description in the StuffIt User Guide of The StuffIt Contextual Menu:

StuffItCM is an alternative to MagicMenu. Except for keyboard shortcuts, all the commands available in MagicMenu are also available in the StuffIt Contextual Menu. Rather than appearing in the Finder menubar, the Contextual Menu appears when you hold down the Control (Ctrl) key or right-click while selecting a file in the Finder.

Mac OS 10.4 (Tiger) users will find the “StuffIt” option at the top-level of the Finder’s contextual menu.

Mac OS 10.5 (Leopard) users will find non-Apple contextual menus under “More”.

In Mac OS 10.6 (Snow Leopard), Apple has removed support for third party contextual menu plugins. As a result, the StuffIt Contextual Menu is not available.


This is yet partially true. Apple indeed removed the old contextual menu API in MacOSX 10.6. But Apple added a new API. You may have heared about it in my previous post “Implementing a Service on 10.6″.



To reenable this missing feature for 10.6 users, I built a Service that adds 2 menu items in the Contextual Menu of the Finder: ‘UnStuff with StuffIt’ and ‘Stuff with StuffIt’. The ‘UnStuff with StuffIt’ menu item is only visible when you select a file compressed by StuffIt in the Finder. The ‘Stuff with StuffIt’ menu item will appear for any file.

Figure 1: ‘UnStuff with StuffIt’ in the Finder contextual menu


UnStuff with StuffIt

Figure 2: These 2 menu items are also available in the ‘Services’ menu


Stuff with StuffIt

The implementation of this Service is really simple: It uses the 2 command line tools ‘stuff’ and ‘unstuff’ installed by StuffIt Deluxe® 2011 and StuffIt Deluxe® 2010 (I don’t know if previous versions of StuffIt Deluxe® install these 2 command line tools).


Download: You can download here the compiled StuffIt Service. To install it, unzip it, then move the ‘StuffItService.service’ in your ~/Library/Services folder and log out. If you are interested by the source code, the full sources are available here.


Implementing a Service on 10.6

Posted: July 27th, 2010 | Author: | Filed under: MacOSX, Programming | Tags: , , , , , , | 1 Comment »



In this post I talk on how to write a Service for MacOS X 10.6. If you don’t know what is a Service, Apple describes it here http://www.apple.com/macosx/refinements/:

The Services menu in Mac OS X lets you use features of one application while working in another. In Snow Leopard, services are more simplified, streamlined, and helpful. The Services menu is contextual, so it shows just the services appropriate for the application you’re using or content you’re viewing rather than all available services. You can access services with a right click of your mouse or Control-click of your trackpad. You can configure the menu to show only the services you want, and you can even create your own services using Automator.

The technical documentation from Apple on how to write your own Service is available here: Services Implementation Guide. Writing a Service for MacOS X 10.6 is not complicated in itself. Some useful documentation (on how to correctly write the Info.plist of the service) is available but it is hard to find a working sample. So the aim at this post is to provide a sample Service with the source code. The Service is really simple and can do 2 tasks:

  • implement a functionality similar to the ‘Paste and Match Style’ feature available in most applications under the Edit menu.
  • implement a functionality to copy the selection from the front application as plain text in the Clipboard.


Download: You can download here the compiled Service. To install it, unzip it, then move the ‘Citrouille.service’ in your ~/Library/Services folder and log out. If you are interested by the source code, the full sources are available here.



‘Paste and Match Style’: A simple implementation of the ‘Paste and Match Style’ functionality. When you copy text (with whatever fonts, sizes and colours it had), you can select ‘Paste and Match Style’ from the Services menu in any application to paste the text with the current style. This feature doesn’t have advantages over the built-in ‘Paste and Match Style’ from many MacOSX applications.

Figure 1: ‘Paste and Match Style’ in the Services menu


WithoutTextSelection

The implementation for ‘Paste and Match Style’ is really simple:

- (void)doPasteAsPlainText:(NSPasteboard *)pboard userData:(NSString *)userData error:(NSString **)error
{
	NSString *outString = @"";
	BOOL hasError = NO;
	
	if(!hasError)
	{
		// Test for strings on the pasteboard.
		NSArray *classes = [NSArray arrayWithObject:[NSString class]];
		NSDictionary *options = [NSDictionary dictionary];
		
		if (![[NSPasteboard generalPasteboard] canReadObjectForClasses:classes options:options])
		{
			outString = @"";
			hasError = YES;
			*error = NSLocalizedString(@"Error: There is no string in the pasteboard.", @"outputing nothing");
		}
	}
	
	if(!hasError)
	{
		outString = [[NSPasteboard generalPasteboard] stringForType:NSPasteboardTypeString];
		if(outString == nil)
		{
			outString = @"";
			hasError = YES;
			*error = NSLocalizedString(@"Error: There is no valid string in the pasteboard.", @"outputing nothing");
		}
	}
	
	
	// Write the string onto the pasteboard.
	[pboard clearContents];
	[pboard writeObjects:[NSArray arrayWithObject:outString]];
}
 



‘Copy as Plain Text’: you can select a text in any application and select ‘Copy as Plain Text’ from the Services menu in any application. This will copy the selected text as plain text (no style) in the clipboard.

Figure 2: ‘Copy as Plain Text’ in the Services menu


WithTextSelection

- (void)doCopyAsPlainText:(NSPasteboard *)pboard userData:(NSString *)userData error:(NSString **)error
{
	// Test for strings on the pasteboard.
	NSArray *classes = [NSArray arrayWithObject:[NSString class]];
	NSDictionary *options = [NSDictionary dictionary];
	
	if (![pboard canReadObjectForClasses:classes options:options])
	{
		*error = NSLocalizedString(@"Error: couldn't get text.", @"pboard couldn't give string.");
		return;
	}
	
	NSString *pboardString = [pboard stringForType:NSPasteboardTypeString];
	[[NSPasteboard generalPasteboard] clearContents];
	[[NSPasteboard generalPasteboard]  writeObjects:[NSArray arrayWithObject:pboardString]];
}
 

Cornichon

Posted: March 17th, 2010 | Author: | Filed under: Cornichon, MacOSX | Tags: , , , , , , , , | No Comments »


Cornichon is a powerful tool you can use to dynamically profile Mac OS X applications on the system and track the process’ performance over time.


Figure 1: Profiling Safari with Cornichon

screenshot-small

The Cornichon application includes the ability to:

  • Profile Mac OS X applications
  • Profile iPhone applications running in the iPhone simulator
  • Examine the behavior of one or more processes
  • See the different collected data of a process in real time in a graph
  • Export the data as TAB files that you can later easily import in Apple Numbers or Microsoft Excel


With the Cornichon application, you can inspect different aspects of a process’ behavior:

  • CPU usage
  • Resident memory size (RSIZE)
  • Resident private address space size (RPRVT)
  • Total memory size (VSIZE)
  • Number of threads


Why using Cornichon?

Apple provides several tools that allow you to profile Mac OS X applications: Activity Monitor, Instruments, and some command line tools like ‘top’ or ‘ps’.
But none of these tools provide a real-time graph to profile a specific application:

  • Activity Monitor has no graph view which makes it difficult to see how the process’ performance evolves over time.
  • The ‘Activity Monitor’ template of Instruments only monitors the system workload but not the workload of a specific application.


Cornichon System Requirements

  • Mac OS X 10.5.8 or later.
  • Universal application (for both Intel and PowerPC-based Macs).


FAQ


Determining the running kernel mode on 10.6

Posted: March 6th, 2010 | Author: | Filed under: MacOSX, Programming | Tags: , , , , , , , | 1 Comment »

It might be useful in some cases to know if the MacOS kernel is running in the 32-bit or 64-bit (K64) mode. This is useful for example if you write an application like ‘System Profiler’ that displays the details of the currently running system:

'System Software Overview' in the 'System Profiler' app

Obviously this post only applies to intel machines running on Snow Leopard (see my previous post ‘Intel 64-bit summary’). To simplify the code, I assume that you compiled your application with the 10.6 SDK.

In the IOKit framework on 10.6 the function OSKextGetRunningKernelArchitecture is defined as followed in the OSKext.h header:


/*!
 * @function OSKextGetRunningKernelArchitecture
 * @abstract Returns the architecture of the running kernel.
 *
 * @result
 * The architecture of the running kernel.
 * The caller does not own the returned pointer and should not free it.
 *
 * @discussion
 * This function consults the kernel task and returns a pointer to the
 * NXArchInfo struct representing its architecture.
 * The running kernel's architecture does not necessarily match that
 * of user space tasks (for example, a 32-bit user space task could be
 * running with a 64-bit kernel, or vice-versa).
 */
CF_EXPORT const NXArchInfo *
OSKextGetRunningKernelArchitecture(void)
                AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;

This function is the one I use to determine the current running kernel mode:

#import <Foundation/Foundation.h>
#import <mach-o/arch.h>

// OSKextGetRunningKernelArchitecture is not available in
// the 10.6 SDK headers, but exported since 10.6.
extern const NXArchInfo *OSKextGetRunningKernelArchitecture(void);

static BOOL Is64BitKernel()
{
	BOOL isK64 = NO;
	
	const NXArchInfo *archInfo = OSKextGetRunningKernelArchitecture();
	if (archInfo != NULL)
	{
		isK64 = ((archInfo->cputype & CPU_ARCH_ABI64) != 0);
	}
	
    return isK64;
}

int main (int argc, const char * argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	
	fprintf(stderr, "Is 64-bit kernel: %d\n", Is64BitKernel());
   
    [pool drain];
    return 0;
}

And don’t forget to link against the IOKit framework.

Also note that it is quite easy to make the previous code compiling with the 10.5 (or earlier) SDK by dynamically getting the address of the OSKextGetRunningKernelArchitecture function and checking if the address is not NULL.