15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* ***** BEGIN LICENSE BLOCK *****
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Version: MPL 1.1/GPL 2.0/LGPL 2.1
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The contents of this file are subject to the Mozilla Public License Version
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1.1 (the "License"); you may not use this file except in compliance with
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the License. You may obtain a copy of the License at
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * http://www.mozilla.org/MPL/
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Software distributed under the License is distributed on an "AS IS" basis,
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * for the specific language governing rights and limitations under the
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * License.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The Original Code is Chimera code.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The Initial Developer of the Original Code is
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Netscape Communications Corporation.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Portions created by the Initial Developer are Copyright (C) 2002
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the Initial Developer. All Rights Reserved.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Contributor(s):
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   Simon Fraser <sfraser@netscape.com>
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   Bruce Davidson <Bruce.Davidson@ipl.com>
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Alternatively, the contents of this file may be used under the terms of
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * either the GNU General Public License Version 2 or later (the "GPL"), or
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in which case the provisions of the GPL or the LGPL are applicable instead
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of those above. If you wish to allow use of your version of this file only
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * under the terms of either the GPL or the LGPL, and not to allow others to
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * use your version of this file under the terms of the MPL, indicate your
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * decision by deleting the provisions above and replace them with the notice
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and other provisions required by the GPL or the LGPL. If you do not delete
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the provisions above, a recipient may use your version of this file under
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the terms of any one of the MPL, the GPL or the LGPL.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ***** END LICENSE BLOCK ***** */
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "NSPasteboard+Utils.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "NSURL+Utils.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "NSString+Utils.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSString* const kCorePasteboardFlavorType_url  = @"CorePasteboardFlavorType 0x75726C20"; // 'url '  url
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSString* const kCorePasteboardFlavorType_urln = @"CorePasteboardFlavorType 0x75726C6E"; // 'urln'  title
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSString* const kCorePasteboardFlavorType_urld = @"CorePasteboardFlavorType 0x75726C64"; // 'urld' URL description
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSString* const kCaminoBookmarkListPBoardType = @"MozBookmarkType"; // list of Camino bookmark UIDs
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NSString* const kWebURLsWithTitlesPboardType  = @"WebURLsWithTitlesPboardType"; // Safari-compatible URL + title arrays
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@interface NSPasteboard(ChimeraPasteboardURLUtilsPrivate)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (NSString*)cleanedStringWithPasteboardString:(NSString*)aString;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@end
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@implementation NSPasteboard(ChimeraPasteboardURLUtilsPrivate)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Utility method to ensure strings we're using in |containsURLData|
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and |getURLs:andTitles| are free of internal control characters
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and leading/trailing whitespace
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (NSString*)cleanedStringWithPasteboardString:(NSString*)aString
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSString* cleanString = [aString stringByRemovingCharactersInSet:[NSCharacterSet controlCharacterSet]];
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return [cleanString stringByTrimmingWhitespace];
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@end
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@implementation NSPasteboard(ChimeraPasteboardURLUtils)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (int)declareURLPasteboardWithAdditionalTypes:(NSArray*)additionalTypes owner:(id)newOwner
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSArray* allTypes = [additionalTypes arrayByAddingObjectsFromArray:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            [NSArray arrayWithObjects:
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        kWebURLsWithTitlesPboardType,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        NSURLPboardType,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        NSStringPboardType,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        kCorePasteboardFlavorType_url,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        kCorePasteboardFlavorType_urln,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        nil]];
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return [self declareTypes:allTypes owner:newOwner];
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copy a single URL (with an optional title) to the clipboard in all relevant
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// formats. Convenience method for clients that can only ever deal with one
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// URL and shouldn't have to build up the arrays for setURLs:withTitles:.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)setDataForURL:(NSString*)url title:(NSString*)title
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSArray* urlList = [NSArray arrayWithObject:url];
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSArray* titleList = nil;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (title)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    titleList = [NSArray arrayWithObject:title];
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [self setURLs:urlList withTitles:titleList];
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copy a set of URLs, each of which may have a title, to the pasteboard
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// using all the available formats.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The title array should be nil, or must have the same length as the URL array.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)setURLs:(NSArray*)inUrls withTitles:(NSArray*)inTitles
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int urlCount = [inUrls count];
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Best format that we know about is Safari's URL + title arrays - build these up
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!inTitles) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NSMutableArray* tmpTitleArray = [NSMutableArray arrayWithCapacity:urlCount];
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < urlCount; ++i)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [tmpTitleArray addObject:[inUrls objectAtIndex:i]];
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inTitles = tmpTitleArray;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSMutableArray* filePaths = [NSMutableArray array];
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 0; i < urlCount; ++i) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NSURL* url = [NSURL URLWithString:[inUrls objectAtIndex:i]];
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ([url isFileURL] && [[NSFileManager defaultManager] fileExistsAtPath:[url path]])
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [filePaths addObject:[url path]];
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ([filePaths count] > 0) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [self addTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:nil];
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [self setPropertyList:filePaths forType:NSFilenamesPboardType];
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSMutableArray* clipboardData = [NSMutableArray array];
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [clipboardData addObject:[NSArray arrayWithArray:inUrls]];
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [clipboardData addObject:inTitles];
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [self setPropertyList:clipboardData forType:kWebURLsWithTitlesPboardType];
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (urlCount == 1) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NSString* url = [inUrls objectAtIndex:0];
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NSString* title = [inTitles objectAtIndex:0];
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[NSURL URLWithString:url] writeToPasteboard:self];
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [self setString:url forType:NSStringPboardType];
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* tempCString = [url UTF8String];
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [self setData:[NSData dataWithBytes:tempCString length:strlen(tempCString)] forType:kCorePasteboardFlavorType_url];
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (inTitles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tempCString = [title UTF8String];
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [self setData:[NSData dataWithBytes:tempCString length:strlen(tempCString)] forType:kCorePasteboardFlavorType_urln];
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (urlCount > 1)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // With multiple URLs there aren't many other formats we can use
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Just write a string of each URL (ignoring titles) on a separate line
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [self setString:[inUrls componentsJoinedByString:@"\n"] forType:NSStringPboardType];
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // but we have to put something in the carbon style flavors, otherwise apps will think
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // there is data there, but get nothing
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NSString* firstURL   = [inUrls objectAtIndex:0];
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NSString* firstTitle = [inTitles objectAtIndex:0];
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* tempCString = [firstURL UTF8String];
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [self setData:[NSData dataWithBytes:tempCString length:strlen(tempCString)] forType:kCorePasteboardFlavorType_url];
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tempCString = [firstTitle UTF8String];    // not i18n friendly
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [self setData:[NSData dataWithBytes:tempCString length:strlen(tempCString)] forType:kCorePasteboardFlavorType_urln];
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Get the set of URLs and their corresponding titles from the pasteboard.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If there are no URLs in a format we understand on the pasteboard empty
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// arrays will be returned. The two arrays will always be the same size.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The arrays returned are on the auto release pool. If |convertFilenames|
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is YES, then the function will attempt to convert filenames in the drag
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to file URLs.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void) getURLs:(NSArray**)outUrls
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    andTitles:(NSArray**)outTitles
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    convertingFilenames:(BOOL)convertFilenames
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSArray* types = [self types];
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSURL* urlFromNSURL = nil;  // Used below in getting an URL from the NSURLPboardType.
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ([types containsObject:kWebURLsWithTitlesPboardType]) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NSArray* urlAndTitleContainer = [self propertyListForType:kWebURLsWithTitlesPboardType];
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *outUrls = [urlAndTitleContainer objectAtIndex:0];
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *outTitles = [urlAndTitleContainer objectAtIndex:1];
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if ([types containsObject:NSFilenamesPboardType]) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NSArray *files = [self propertyListForType:NSFilenamesPboardType];
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *outUrls = [NSMutableArray arrayWithCapacity:[files count]];
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *outTitles = [NSMutableArray arrayWithCapacity:[files count]];
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for ( unsigned int i = 0; i < [files count]; ++i ) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NSString *file = [files objectAtIndex:i];
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NSString *ext = [[file pathExtension] lowercaseString];
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NSString *urlString = nil;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NSString *title = @"";
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSType fileType = NSHFSTypeCodeFromFileType(NSHFSTypeOfFile(file));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Check whether the file is a .webloc, a .ftploc, a .url, or some other kind of file.
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ([ext isEqualToString:@"webloc"] || [ext isEqualToString:@"ftploc"] || fileType == 'ilht' || fileType == 'ilft') {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NSURL* urlFromInetloc = [NSURL URLFromInetloc:file];
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (urlFromInetloc) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          urlString = [urlFromInetloc absoluteString];
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          title     = [[file lastPathComponent] stringByDeletingPathExtension];
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if ([ext isEqualToString:@"url"] || fileType == 'LINK') {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NSURL* urlFromIEURLFile = [NSURL URLFromIEURLFile:file];
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (urlFromIEURLFile) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          urlString = [urlFromIEURLFile absoluteString];
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          title     = [[file lastPathComponent] stringByDeletingPathExtension];
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!urlString) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!convertFilenames) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          continue;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Use the filename if not a .webloc or .url file, or if either of the
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // functions returns nil.
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        urlString = [[NSURL fileURLWithPath:file] absoluteString];
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        title     = [file lastPathComponent];
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [(NSMutableArray*) *outUrls addObject:urlString];
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [(NSMutableArray*) *outTitles addObject:title];
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if ([types containsObject:NSURLPboardType] && (urlFromNSURL = [NSURL URLFromPasteboard:self])) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *outUrls = [NSArray arrayWithObject:[urlFromNSURL absoluteString]];
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NSString* title = nil;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ([types containsObject:kCorePasteboardFlavorType_urld])
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      title = [self stringForType:kCorePasteboardFlavorType_urld];
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!title && [types containsObject:kCorePasteboardFlavorType_urln])
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      title = [self stringForType:kCorePasteboardFlavorType_urln];
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!title && [types containsObject:NSStringPboardType])
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      title = [self stringForType:NSStringPboardType];
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *outTitles = [NSArray arrayWithObject:(title ? title : @"")];
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if ([types containsObject:NSStringPboardType]) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NSString* potentialURLString = [self cleanedStringWithPasteboardString:[self stringForType:NSStringPboardType]];
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ([potentialURLString isValidURI]) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *outUrls = [NSArray arrayWithObject:potentialURLString];
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NSString* title = nil;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ([types containsObject:kCorePasteboardFlavorType_urld])
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        title = [self stringForType:kCorePasteboardFlavorType_urld];
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!title && [types containsObject:kCorePasteboardFlavorType_urln])
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        title = [self stringForType:kCorePasteboardFlavorType_urln];
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *outTitles = [NSArray arrayWithObject:(title ? title : @"")];
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The string doesn't look like a URL - return empty arrays
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *outUrls = [NSArray array];
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *outTitles = [NSArray array];
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We don't recognise any of these formats - return empty arrays
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *outUrls = [NSArray array];
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *outTitles = [NSArray array];
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Indicates if this pasteboard contains URL data that we understand
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Deals with all our URL formats. Only strings that are valid URLs count.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If this returns YES it is safe to use getURLs:andTitles: to retrieve the data.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NB: Does not consider our internal bookmark list format, because callers
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// usually need to deal with this separately because it can include folders etc.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (BOOL) containsURLData
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSArray* types = [self types];
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (    [types containsObject:kWebURLsWithTitlesPboardType]
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || [types containsObject:NSURLPboardType]
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || [types containsObject:NSFilenamesPboardType] )
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return YES;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ([types containsObject:NSStringPboardType]) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Trim whitespace off the ends and newlines out of the middle so we don't reject otherwise-valid URLs;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we'll do another cleaning when we set the URLs and titles later, so this is safe.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NSString* potentialURLString = [self cleanedStringWithPasteboardString:[self stringForType:NSStringPboardType]];
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return [potentialURLString isValidURI];
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NO;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@end
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@implementation NSPasteboard(ChromiumHTMLUtils)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convert the RTF to HTML via an NSAttributedString.
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (NSString*)htmlFromRtf {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (![[self types] containsObject:NSRTFPboardType])
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return @"";
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSAttributedString* attributed =
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [[[NSAttributedString alloc]
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             initWithRTF:[self dataForType:NSRTFPboardType]
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      documentAttributes:nil] autorelease];
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSDictionary* attributeDict =
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [NSDictionary dictionaryWithObject:NSHTMLTextDocumentType
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  forKey:NSDocumentTypeDocumentAttribute];
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSData* htmlData =
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [attributed dataFromRange:NSMakeRange(0, [attributed length])
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             documentAttributes:attributeDict
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          error:nil];
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // According to the docs, NSHTMLTextDocumentType is UTF8.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return [[[NSString alloc]
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      initWithData:htmlData encoding:NSUTF8StringEncoding] autorelease];
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@end
307