1 // =================================================================================================
2 // ADOBE SYSTEMS INCORPORATED
3 // Copyright 2011 Adobe Systems Incorporated
4 // All Rights Reserved
5 //
6 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
7 // of the Adobe license agreement accompanying it.
8 // =================================================================================================
9 
10 #include "FileHandlerInstance.h"
11 
12 namespace XMP_PLUGIN
13 {
14 
FileHandlerInstance(SessionRef object,FileHandlerSharedPtr handler,XMPFiles * _parent)15 FileHandlerInstance::FileHandlerInstance ( SessionRef object, FileHandlerSharedPtr handler, XMPFiles * _parent ):
16 XMPFileHandler( _parent ), mObject( object ), mHandler( handler )
17 {
18 	this->handlerFlags = mHandler->getHandlerFlags();
19 	this->stdCharForm  = kXMP_Char8Bit;
20 	PluginManager::addHandlerInstance( this->mObject, this );
21 }
22 
~FileHandlerInstance()23 FileHandlerInstance::~FileHandlerInstance()
24 {
25 	WXMP_Error error;
26 	mHandler->getModule()->getPluginAPIs()->mTerminateSessionProc( this->mObject, &error );
27 	PluginManager::removeHandlerInstance( this->mObject );
28 	CheckError( error );
29 }
30 
GetFileModDate(XMP_DateTime * modDate)31 bool FileHandlerInstance::GetFileModDate ( XMP_DateTime * modDate )
32 {
33 	XMP_Bool ok;
34 	WXMP_Error error;
35 	GetSessionFileModDateProc wGetFileModDate = mHandler->getModule()->getPluginAPIs()->mGetFileModDateProc;
36 	wGetFileModDate ( this->mObject, &ok, modDate, &error );
37 	CheckError ( error );
38 	return ConvertXMP_BoolToBool( ok );
39 }
40 
CacheFileData()41 void FileHandlerInstance::CacheFileData()
42 {
43 	if( this->containsXMP ) return;
44 
45 	WXMP_Error error;
46 	XMP_StringPtr xmpStr = NULL;
47 	mHandler->getModule()->getPluginAPIs()->mCacheFileDataProc( this->mObject, this->parent->ioRef, &xmpStr, &error );
48 
49 	if( error.mErrorID != kXMPErr_NoError )
50 	{
51 		if ( xmpStr != 0 ) free( (void*) xmpStr );
52 		if ( error.mErrorID == kXMPErr_FilePermission )
53 			throw XMP_Error( kXMPErr_FilePermission, error.mErrorMsg );
54 		else
55 			throw XMP_Error( kXMPErr_InternalFailure, error.mErrorMsg );
56 	}
57 
58 	if( xmpStr != NULL )
59 	{
60 		this->xmpPacket.assign( xmpStr );
61 		free( (void*) xmpStr ); // It should be freed as documentation of mCacheFileDataProc says so.
62 		this->containsXMP = true;
63 	}
64 	else
65 		this->containsXMP = false;
66 }
67 
ProcessXMP()68 void FileHandlerInstance::ProcessXMP()
69 {
70 	if( this->processedXMP ) return;
71 	this->processedXMP = true;
72 
73 	SXMPUtils::RemoveProperties ( &this->xmpObj, 0, 0, kXMPUtil_DoAllProperties );
74 	if ( this->xmpPacket.size() != 0 )
75 		this->xmpObj.ParseFromBuffer ( this->xmpPacket.c_str(), (XMP_StringLen)this->xmpPacket.size() );
76 
77 	WXMP_Error error;
78 	if ( mHandler->getModule()->getPluginAPIs()->mVersion >= 4 && mHandler->getModule()->getPluginAPIs()->mImportToXMPStringWithPacketProc )
79 	{
80 		XMP_StringPtr xmpStr = this->xmpPacket.c_str();
81 		XMP_StringPtr oldPacketPtr = NULL;
82 		XMP_PacketInfo packetInfo;
83 		mHandler->getModule()->getPluginAPIs()->mImportToXMPStringWithPacketProc( this->mObject, &xmpStr, &error, &oldPacketPtr, &packetInfo );
84 
85 		if( xmpStr != NULL && xmpStr != this->xmpPacket.c_str() )
86 		{
87 			XMP_StringLen newLen = static_cast<XMP_StringLen>(strlen( xmpStr ));
88 			this->xmpObj.Erase();
89 			this->xmpObj.ParseFromBuffer( xmpStr, newLen, 0 );
90 
91 			// Note: Freeing memory would not create any problem as plugin would have allocated memory using Host library function
92 			free( ( void * ) xmpStr );
93 			this->containsXMP = true;
94 		}
95 
96 		if( oldPacketPtr != NULL )
97 		{
98 			this->xmpPacket.resize( strlen( oldPacketPtr ) );
99 			this->xmpPacket.assign( oldPacketPtr );
100 			this->packetInfo = packetInfo;
101 
102 			// Note: Freeing memory would not create any problem as plugin would have allocated memory using Host library function
103 			free( ( void * ) oldPacketPtr );
104 			this->containsXMP = true;
105 		}
106 	}
107 	else if( mHandler->getModule()->getPluginAPIs()->mVersion >= 2 && mHandler->getModule()->getPluginAPIs()->mImportToXMPStringProc )
108 	{
109 		XMP_StringPtr xmpStr = this->xmpPacket.c_str();
110 		mHandler->getModule()->getPluginAPIs()->mImportToXMPStringProc( this->mObject, &xmpStr, &error );
111 
112 		if( xmpStr != NULL && xmpStr != this->xmpPacket.c_str() )
113 		{
114 			XMP_StringLen newLen = static_cast<XMP_StringLen>(strlen( xmpStr ));
115 			this->xmpObj.Erase();
116 			this->xmpObj.ParseFromBuffer( xmpStr, newLen, 0 );
117 
118 			// Note: Freeing memory would not create any problem as plugin would have allocated memory using Host library function
119 			free( ( void * ) xmpStr );
120 			this->containsXMP = true;
121 		}
122 	}
123 	else
124 	{
125 		if( mHandler->getModule()->getPluginAPIs()->mImportToXMPProc )
126 			mHandler->getModule()->getPluginAPIs()->mImportToXMPProc( this->mObject, this->xmpObj.GetInternalRef(), &error );
127 		this->containsXMP = true;
128 	}
129 	CheckError( error );
130 }
131 
UpdateFile(bool doSafeUpdate)132 void FileHandlerInstance::UpdateFile ( bool doSafeUpdate )
133 {
134 	bool optimizeFileLayout = XMP_OptionIsSet ( this->parent->openFlags, kXMPFiles_OptimizeFileLayout );
135 	this->needsUpdate |= optimizeFileLayout;
136 	if( !this->needsUpdate ) return;
137 	WXMP_Error error;
138 
139 	if ( xmpPacket.size() != 0 )
140 	{
141 		if( mHandler->getModule()->getPluginAPIs()->mExportFromXMPStringProc )
142 		{
143 			std::string xmp;
144 			this->xmpObj.SerializeToBuffer( &xmp, kXMP_NoOptions, 0 );
145 			XMP_StringPtr xmpStr = xmp.c_str();
146 			mHandler->getModule()->getPluginAPIs()->mExportFromXMPStringProc( this->mObject, xmpStr, &error );
147 			if ( xmpStr != xmp.c_str() )
148 				this->xmpObj.SerializeToBuffer ( &this->xmpPacket, mHandler->getSerializeOption() );
149 		}
150 		else
151 		{
152 			if( mHandler->getModule()->getPluginAPIs()->mExportFromXMPProc )
153 			{
154 				mHandler->getModule()->getPluginAPIs()->mExportFromXMPProc( this->mObject, this->xmpObj.GetInternalRef(), &error );
155 				this->xmpObj.SerializeToBuffer ( &this->xmpPacket, mHandler->getSerializeOption() );
156 			}
157 		}
158 		CheckError( error );
159 
160 
161 	}
162 	mHandler->getModule()->getPluginAPIs()->mUpdateFileProc( this->mObject, this->parent->ioRef, doSafeUpdate, this->xmpPacket.c_str(), &error );
163 	CheckError( error );
164 	this->needsUpdate = false;
165 }
166 
WriteTempFile(XMP_IO * tempRef)167 void FileHandlerInstance::WriteTempFile( XMP_IO* tempRef )
168 {
169 	WXMP_Error error;
170 	if( mHandler->getModule()->getPluginAPIs()->mExportFromXMPProc )
171 		mHandler->getModule()->getPluginAPIs()->mExportFromXMPProc( this->mObject, this->xmpObj.GetInternalRef(), &error );
172 	CheckError( error );
173 
174 	this->xmpObj.SerializeToBuffer ( &this->xmpPacket, mHandler->getSerializeOption() );
175 
176 	mHandler->getModule()->getPluginAPIs()->mWriteTempFileProc( this->mObject, this->parent->ioRef, tempRef, this->xmpPacket.c_str(), &error );
177 	CheckError( error );
178 }
179 
SetStringVector(StringVectorRef clientPtr,XMP_StringPtr * arrayPtr,XMP_Uns32 stringCount)180 static void SetStringVector ( StringVectorRef clientPtr, XMP_StringPtr * arrayPtr, XMP_Uns32 stringCount )
181 {
182 	std::vector<std::string>* clientVec = (std::vector<std::string>*) clientPtr;
183 	clientVec->clear();
184 	for ( XMP_Uns32 i = 0; i < stringCount; ++i ) {
185 		std::string nextValue ( arrayPtr[i] );
186 		clientVec->push_back ( nextValue );
187 	}
188 }
189 
FillMetadataFiles(std::vector<std::string> * metadataFiles)190 void FileHandlerInstance::FillMetadataFiles( std::vector<std::string> * metadataFiles )
191 {
192 	WXMP_Error error;
193 	FillMetadataFilesProc wFillMetadataFilesProc = mHandler->getModule()->getPluginAPIs()->mFillMetadataFilesProc;
194 	if ( wFillMetadataFilesProc ) {
195 		wFillMetadataFilesProc( this->mObject, metadataFiles, SetStringVector, &error);
196 		CheckError( error );
197 	} else {
198 		XMP_Throw ( "This version of plugin does not support FillMetadataFiles API", kXMPErr_Unimplemented );
199 	}
200 }
201 
FillAssociatedResources(std::vector<std::string> * resourceList)202 void FileHandlerInstance::FillAssociatedResources( std::vector<std::string> * resourceList )
203 {
204 	WXMP_Error error;
205 	FillAssociatedResourcesProc wFillAssociatedResourcesProc = mHandler->getModule()->getPluginAPIs()->mFillAssociatedResourcesProc;
206 	if ( wFillAssociatedResourcesProc ) {
207 		wFillAssociatedResourcesProc( this->mObject, resourceList, SetStringVector, &error);
208 		CheckError( error );
209 	} else {
210 		XMP_Throw ( "This version of plugin does not support FillAssociatedResources API", kXMPErr_Unimplemented );
211 	}
212 }
213 
IsMetadataWritable()214 bool FileHandlerInstance::IsMetadataWritable( )
215 {
216 	WXMP_Error error;
217 	XMP_Bool result = kXMP_Bool_False;
218 	IsMetadataWritableProc wIsMetadataWritableProc = mHandler->getModule()->getPluginAPIs()->mIsMetadataWritableProc;
219 	if ( wIsMetadataWritableProc ) {
220 		wIsMetadataWritableProc( this->mObject, &result, &error);
221 		CheckError( error );
222 	} else {
223 		XMP_Throw ( "This version of plugin does not support IsMetadataWritable API", kXMPErr_Unimplemented );
224 	}
225 	return ConvertXMP_BoolToBool( result );
226 }
227 
SetErrorCallback(ErrorCallbackBox errorCallbackBox)228 void FileHandlerInstance::SetErrorCallback ( ErrorCallbackBox errorCallbackBox )
229 {
230 	WXMP_Error error;
231 	SetErrorCallbackproc wSetErrorCallbackproc = mHandler->getModule()->getPluginAPIs()->mSetErrorCallbackproc ;
232 	if( wSetErrorCallbackproc )	{
233 		wSetErrorCallbackproc( this->mObject, errorCallbackBox, &error );
234 		CheckError( error );
235 	} else {
236 		XMP_Throw ( "This version of plugin does not support IsMetadataWritable API", kXMPErr_Unimplemented );
237 	}
238 }
239 
SetProgressCallback(XMP_ProgressTracker::CallbackInfo * progCBInfoPtr)240 void FileHandlerInstance::SetProgressCallback ( XMP_ProgressTracker::CallbackInfo * progCBInfoPtr )
241 {
242 	WXMP_Error error;
243 	SetProgressCallbackproc wSetProgressCallbackproc = mHandler->getModule()->getPluginAPIs()->mSetProgressCallbackproc ;
244 	if( wSetProgressCallbackproc )	{
245 		wSetProgressCallbackproc( this->mObject, progCBInfoPtr, &error );
246 		CheckError( error );
247 	} else {
248 		XMP_Throw ( "This version of plugin does not support IsMetadataWritable API", kXMPErr_Unimplemented );
249 	}
250 }
251 
252 } //namespace XMP_PLUGIN
253