1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 #include <sal/types.h>
27
28 #ifndef _TRANSFERABLE_HXX_
29 #include "OSXTransferable.hxx"
30 #endif
31
32 #include "DataFlavorMapping.hxx"
33
34 using namespace rtl;
35 using namespace std;
36 using namespace osl;
37 using namespace cppu;
38 using namespace com::sun::star::uno;
39 using namespace com::sun::star::datatransfer;
40 using namespace com::sun::star::io;
41 using namespace com::sun::star::lang;
42 using namespace com::sun::star::container;
43
44 const Type CPPUTYPE_SEQINT8 = getCppuType((Sequence<sal_Int8>*)0);
45 const Type CPPUTYPE_OUSTRING = getCppuType((OUString*)0);
46
47 namespace // private
48 {
isValidFlavor(const DataFlavor & aFlavor)49 bool isValidFlavor( const DataFlavor& aFlavor )
50 {
51 size_t len = aFlavor.MimeType.getLength();
52 Type dtype = aFlavor.DataType;
53 return ((len > 0) && ((dtype == CPPUTYPE_SEQINT8) || (dtype == CPPUTYPE_OUSTRING)));
54 }
55
56 } // namespace private
57
58
OSXTransferable(const Reference<XMimeContentTypeFactory> rXMimeCntFactory,DataFlavorMapperPtr_t pDataFlavorMapper,NSPasteboard * pasteboard)59 OSXTransferable::OSXTransferable(const Reference<XMimeContentTypeFactory> rXMimeCntFactory,
60 DataFlavorMapperPtr_t pDataFlavorMapper,
61 NSPasteboard* pasteboard) :
62 mrXMimeCntFactory(rXMimeCntFactory),
63 mDataFlavorMapper(pDataFlavorMapper),
64 mPasteboard(pasteboard)
65 {
66 [mPasteboard retain];
67
68 initClipboardItemList();
69 }
70
71
~OSXTransferable()72 OSXTransferable::~OSXTransferable()
73 {
74 [mPasteboard release];
75 }
76
77
getTransferData(const DataFlavor & aFlavor)78 Any SAL_CALL OSXTransferable::getTransferData( const DataFlavor& aFlavor )
79 throw( UnsupportedFlavorException, IOException, RuntimeException )
80 {
81 if (!isValidFlavor(aFlavor) || !isDataFlavorSupported(aFlavor))
82 {
83 throw UnsupportedFlavorException(OUString(RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Unsupported data flavor")),
84 static_cast<XTransferable*>(this));
85 }
86
87 bool bInternal(false);
88 const NSString* sysFormat =
89 (aFlavor.MimeType.compareToAscii( "image/png", 9 ) == 0)
90 ? mDataFlavorMapper->openOfficeImageToSystemFlavor( mPasteboard )
91 : mDataFlavorMapper->openOfficeToSystemFlavor(aFlavor, bInternal);
92 DataProviderPtr_t dp;
93
94 if ([sysFormat caseInsensitiveCompare: NSFilenamesPboardType] == NSOrderedSame)
95 {
96 NSArray* sysData = [mPasteboard propertyListForType: (NSString*)sysFormat];
97 dp = mDataFlavorMapper->getDataProvider(sysFormat, sysData);
98 }
99 else
100 {
101 NSData* sysData = [mPasteboard dataForType: (NSString*)sysFormat];
102 dp = mDataFlavorMapper->getDataProvider(sysFormat, sysData);
103 }
104
105 if (dp.get() == NULL)
106 {
107 throw UnsupportedFlavorException(OUString(RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Unsupported data flavor")),
108 static_cast<XTransferable*>(this));
109 }
110
111 return dp->getOOoData();
112 }
113
114
isUnicodeText(const DataFlavor & flavor)115 bool OSXTransferable::isUnicodeText(const DataFlavor& flavor)
116 {
117 return (flavor.DataType == CPPUTYPE_OUSTRING);
118 }
119
120
getTransferDataFlavors()121 Sequence< DataFlavor > SAL_CALL OSXTransferable::getTransferDataFlavors( )
122 throw( RuntimeException )
123 {
124 return mFlavorList;
125 }
126
127
isDataFlavorSupported(const DataFlavor & aFlavor)128 sal_Bool SAL_CALL OSXTransferable::isDataFlavorSupported(const DataFlavor& aFlavor)
129 throw( RuntimeException )
130 {
131 for (sal_Int32 i = 0; i < mFlavorList.getLength(); i++)
132 if (compareDataFlavors(aFlavor, mFlavorList[i]))
133 return sal_True;
134
135 return sal_False;
136 }
137
138
initClipboardItemList()139 void OSXTransferable::initClipboardItemList()
140 {
141 NSArray* pboardFormats = [mPasteboard types];
142
143 if (pboardFormats == NULL)
144 {
145 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Cannot get clipboard data")),
146 static_cast<XTransferable*>(this));
147 }
148
149 mFlavorList = mDataFlavorMapper->typesArrayToFlavorSequence(pboardFormats);
150 }
151
152
153 /* Compares two DataFlavors. Returns true if both DataFlavor have the same media type
154 and the number of parameter and all parameter values do match otherwise false
155 is returned.
156 */
compareDataFlavors(const DataFlavor & lhs,const DataFlavor & rhs)157 bool OSXTransferable::compareDataFlavors(const DataFlavor& lhs, const DataFlavor& rhs )
158 {
159 try
160 {
161 Reference<XMimeContentType> xLhs(mrXMimeCntFactory->createMimeContentType(lhs.MimeType));
162 Reference<XMimeContentType> xRhs(mrXMimeCntFactory->createMimeContentType(rhs.MimeType));
163
164 if (!xLhs->getFullMediaType().equalsIgnoreAsciiCase(xRhs->getFullMediaType()) ||
165 !cmpAllContentTypeParameter(xLhs, xRhs))
166 {
167 return false;
168 }
169 }
170 catch( IllegalArgumentException& )
171 {
172 OSL_ENSURE( sal_False, "Invalid content type detected" );
173 return false;
174 }
175
176 return true;
177 }
178
179
cmpAllContentTypeParameter(const Reference<XMimeContentType> xLhs,const Reference<XMimeContentType> xRhs) const180 bool OSXTransferable::cmpAllContentTypeParameter(const Reference<XMimeContentType> xLhs,
181 const Reference<XMimeContentType> xRhs) const
182 {
183 Sequence<OUString> xLhsFlavors = xLhs->getParameters();
184 Sequence<OUString> xRhsFlavors = xRhs->getParameters();
185
186 // Stop here if the number of parameters is different already
187 if (xLhsFlavors.getLength() != xRhsFlavors.getLength())
188 return false;
189
190 try
191 {
192 OUString pLhs;
193 OUString pRhs;
194
195 for (sal_Int32 i = 0; i < xLhsFlavors.getLength(); i++)
196 {
197 pLhs = xLhs->getParameterValue(xLhsFlavors[i]);
198 pRhs = xRhs->getParameterValue(xLhsFlavors[i]);
199
200 if (!pLhs.equalsIgnoreAsciiCase(pRhs))
201 {
202 return false;
203 }
204 }
205 }
206 catch(IllegalArgumentException&)
207 {
208 return false;
209 }
210
211 return true;
212 }
213