Bug Summary

File:libcmis/unxlngi6.pro/misc/build/libcmis-0.2.3/src/libcmis/atom-object.cxx
Location:line 436, column 22
Description:Called C++ object pointer is null

Annotated Source Code

1/* libcmis
2 * Version: MPL 1.1 / GPLv2+ / LGPLv2+
3 *
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License or as specified alternatively below. You may obtain a copy of
7 * the License at http://www.mozilla.org/MPL/
8 *
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
13 *
14 * Major Contributor(s):
15 * Copyright (C) 2011 SUSE <cbosdonnat@suse.com>
16 *
17 *
18 * All Rights Reserved.
19 *
20 * For minor contributions see the git repository.
21 *
22 * Alternatively, the contents of this file may be used under the terms of
23 * either the GNU General Public License Version 2 or later (the "GPLv2+"), or
24 * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
25 * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
26 * instead of those above.
27 */
28
29#include <algorithm>
30#include <sstream>
31
32#include <boost/date_time/posix_time/posix_time.hpp>
33
34#include "atom-object.hxx"
35#include "atom-object-type.hxx"
36#include "atom-session.hxx"
37#include "atom-utils.hxx"
38#include "xml-utils.hxx"
39
40using namespace std;
41
42namespace
43{
44 class MatchLink
45 {
46 private:
47 string m_rel;
48 string m_type;
49
50 public:
51 MatchLink( string rel, string type ) : m_rel( rel ), m_type( type ) { }
52 bool operator() ( AtomLink link )
53 {
54 bool matchesRel = link.getRel( ) == m_rel;
55
56 // Some implementation (SharePoint) are omitting the type attribute
57 bool matchesType = m_type.empty( ) || link.getType().empty() || ( link.getType( ) == m_type );
58 return matchesRel && matchesType;
59 }
60 };
61}
62
63AtomObject::AtomObject( AtomPubSession* session ) throw ( libcmis::Exception ) :
64 m_session( session ),
65 m_refreshTimestamp( 0 ),
66 m_infosUrl( ),
67 m_typeId( ),
68 m_typeDescription( ),
69 m_properties( ),
70 m_allowableActions( ),
71 m_links( )
72{
73}
74
75AtomObject::AtomObject( const AtomObject& copy ) :
76 m_session( copy.m_session ),
77 m_refreshTimestamp( copy.m_refreshTimestamp ),
78 m_infosUrl( copy.m_infosUrl ),
79 m_typeId( copy.m_typeId ),
80 m_typeDescription( copy.m_typeDescription ),
81 m_properties( copy.m_properties ),
82 m_allowableActions( copy.m_allowableActions ),
83 m_links( copy.m_links )
84{
85}
86
87AtomObject& AtomObject::operator=( const AtomObject& copy )
88{
89 m_session = copy.m_session;
90 m_refreshTimestamp = copy.m_refreshTimestamp;
91 m_infosUrl = copy.m_infosUrl;
92 m_typeId = copy.m_typeId;
93 m_typeDescription = copy.m_typeDescription;
94 m_properties = copy.m_properties;
95 m_allowableActions = copy.m_allowableActions;
96 m_links = copy.m_links;
97
98 return *this;
99}
100
101AtomObject::~AtomObject( )
102{
103}
104
105string AtomObject::getId( )
106{
107 string name;
108 map< string, libcmis::PropertyPtr >::iterator it = getProperties( ).find( string( "cmis:objectId" ) );
109 if ( it != getProperties( ).end( ) && !it->second->getStrings( ).empty( ) )
110 name = it->second->getStrings( ).front( );
111 return name;
112}
113
114string AtomObject::getName( )
115{
116 string name;
117 map< string, libcmis::PropertyPtr >::iterator it = getProperties( ).find( string( "cmis:name" ) );
118 if ( it != getProperties( ).end( ) && !it->second->getStrings( ).empty( ) )
119 name = it->second->getStrings( ).front( );
120 return name;
121}
122
123vector< string > AtomObject::getPaths( )
124{
125 return vector< string > ( );
126}
127
128string AtomObject::getBaseType( )
129{
130 string value;
131 map< string, libcmis::PropertyPtr >::iterator it = getProperties( ).find( string( "cmis:baseTypeId" ) );
132 if ( it != getProperties( ).end( ) && !it->second->getStrings( ).empty( ) )
133 value = it->second->getStrings( ).front( );
134 return value;
135}
136
137string AtomObject::getType( )
138{
139 string value;
140 map< string, libcmis::PropertyPtr >::iterator it = getProperties( ).find( string( "cmis:objectTypeId" ) );
141 if ( it != getProperties( ).end( ) && !it->second->getStrings( ).empty( ) )
142 value = it->second->getStrings( ).front( );
143 return value;
144}
145
146string AtomObject::getCreatedBy( )
147{
148 string value;
149 map< string, libcmis::PropertyPtr >::iterator it = getProperties( ).find( string( "cmis:createdBy" ) );
150 if ( it != getProperties( ).end( ) && !it->second->getStrings( ).empty( ) )
151 value = it->second->getStrings( ).front( );
152 return value;
153}
154
155boost::posix_time::ptime AtomObject::getCreationDate( )
156{
157 boost::posix_time::ptime value;
158 map< string, libcmis::PropertyPtr >::iterator it = getProperties( ).find( string( "cmis:creationDate" ) );
159 if ( it != getProperties( ).end( ) && !it->second->getDateTimes( ).empty( ) )
160 value = it->second->getDateTimes( ).front( );
161 return value;
162}
163
164string AtomObject::getLastModifiedBy( )
165{
166 string value;
167 map< string, libcmis::PropertyPtr >::iterator it = getProperties( ).find( string( "cmis:lastModifiedBy" ) );
168 if ( it != getProperties( ).end( ) && !it->second->getStrings( ).empty( ) )
169 value = it->second->getStrings( ).front( );
170 return value;
171}
172
173boost::posix_time::ptime AtomObject::getLastModificationDate( )
174{
175 boost::posix_time::ptime value;
176 map< string, libcmis::PropertyPtr >::iterator it = getProperties( ).find( string( "cmis:lastModificationDate" ) );
177 if ( it != getProperties( ).end( ) && !it->second->getDateTimes( ).empty( ) )
178 value = it->second->getDateTimes( ).front( );
179 return value;
180}
181
182bool AtomObject::isImmutable( )
183{
184 bool value = false;
185 map< string, libcmis::PropertyPtr >::iterator it = getProperties( ).find( string( "cmis:isImmutable" ) );
186 if ( it != getProperties( ).end( ) && !it->second->getBools( ).empty( ) )
187 value = it->second->getBools( ).front( );
188 return value;
189}
190
191string AtomObject::getChangeToken( )
192{
193 string value;
194 map< string, libcmis::PropertyPtr >::iterator it = getProperties( ).find( string( "cmis:changeToken" ) );
195 if ( it != getProperties( ).end( ) && !it->second->getStrings( ).empty( ) )
196 value = it->second->getStrings( ).front( );
197 return value;
198}
199
200std::map< std::string, libcmis::PropertyPtr >& AtomObject::getProperties( )
201{
202 return m_properties;
203}
204
205void AtomObject::updateProperties( ) throw ( libcmis::Exception )
206{
207 if ( getAllowableActions().get() && !getAllowableActions()->isAllowed( libcmis::ObjectAction::UpdateProperties ) )
208 throw libcmis::Exception( string( "UpdateProperties is not allowed on object " ) + getId() );
209
210 xmlBufferPtr buf = xmlBufferCreate( );
211 xmlTextWriterPtr writer = xmlNewTextWriterMemory( buf, 0 );
212
213 xmlTextWriterStartDocument( writer, NULL__null, NULL__null, NULL__null );
214
215 // Copy and remove the readonly properties before serializing
216 AtomObject copy( *this );
217 map< string, libcmis::PropertyPtr >& props = copy.getProperties( );
218 for ( map< string, libcmis::PropertyPtr >::iterator it = props.begin( ); it != props.end( ); )
219 {
220 if ( !it->second->getPropertyType( )->isUpdatable( ) )
221 props.erase( it++ );
222 else
223 ++it;
224 }
225 copy.toXml( writer );
226
227 xmlTextWriterEndDocument( writer );
228 string str( ( const char * )xmlBufferContent( buf ) );
229 istringstream is( str );
230
231 xmlFreeTextWriter( writer );
232 xmlBufferFree( buf );
233
234 string respBuf;
235 try
236 {
237 respBuf = getSession( )->httpPutRequest( getInfosUrl( ), is, "application/atom+xml;type=entry" );
238 }
239 catch ( const atom::CurlException& e )
240 {
241 throw e.getCmisException( );
242 }
243
244 xmlDocPtr doc = xmlReadMemory( respBuf.c_str(), respBuf.size(), getInfosUrl().c_str(), NULL__null, 0 );
245 if ( NULL__null == doc )
246 throw libcmis::Exception( "Failed to parse object infos" );
247
248 refreshImpl( doc );
249 xmlFreeDoc( doc );
250}
251
252libcmis::ObjectTypePtr AtomObject::getTypeDescription( )
253{
254 // Don't use the type from the properties as it may not be read yet.
255 if ( !m_typeDescription.get( ) )
256 m_typeDescription.reset( new AtomObjectType( m_session, m_typeId ) );
257
258 return m_typeDescription;
259}
260
261boost::shared_ptr< libcmis::AllowableActions > AtomObject::getAllowableActions( )
262{
263 return m_allowableActions;
264}
265
266void AtomObject::refreshImpl( xmlDocPtr doc ) throw ( libcmis::Exception )
267{
268 bool createdDoc = ( NULL__null == doc );
269 if ( createdDoc )
270 {
271 string buf;
272 try
273 {
274 buf = getSession()->httpGetRequest( getInfosUrl() )->str( );
275 }
276 catch ( const atom::CurlException& e )
277 {
278 throw e.getCmisException( );
279 }
280
281 doc = xmlReadMemory( buf.c_str(), buf.size(), getInfosUrl().c_str(), NULL__null, 0 );
282
283 if ( NULL__null == doc )
284 throw libcmis::Exception( "Failed to parse object infos" );
285
286 }
287
288 extractInfos( doc );
289 m_refreshTimestamp = time( NULL__null );
290
291 if ( createdDoc )
292 xmlFreeDoc( doc );
293}
294
295void AtomObject::remove( bool allVersions ) throw ( libcmis::Exception )
296{
297 if ( getAllowableActions( ).get() && !getAllowableActions()->isAllowed( libcmis::ObjectAction::DeleteObject ) )
298 throw libcmis::Exception( string( "DeleteObject not allowed on object " ) + getId() );
299
300 try
301 {
302 string deleteUrl = getInfosUrl( );
303 if ( deleteUrl.find( '?' ) != string::npos )
304 deleteUrl += "&";
305 else
306 deleteUrl += "?";
307
308 string allVersionsStr = "TRUE";
309 if ( !allVersions )
310 allVersionsStr = "FALSE";
311 deleteUrl += "allVersions=" + allVersionsStr;
312
313 m_session->httpDeleteRequest( deleteUrl );
314 }
315 catch ( const atom::CurlException& e )
316 {
317 throw e.getCmisException( );
318 }
319}
320
321string AtomObject::toString( )
322{
323 stringstream buf;
324
325 buf << "Id: " << getId() << endl;
326 buf << "Name: " << getName() << endl;
327 buf << "Type: " << getType() << endl;
328 buf << "Base type: " << getBaseType() << endl;
329 buf << "Created on " << boost::posix_time::to_simple_string( getCreationDate() )
330 << " by " << getCreatedBy() << endl;
331 buf << "Last modified on " << boost::posix_time::to_simple_string( getLastModificationDate() )
332 << " by " << getLastModifiedBy() << endl;
333 buf << "Change token: " << getChangeToken() << endl;
334
335 // Write remaining properties
336 static const char* skippedProps[] = {
337 "cmis:name", "cmis:baseTypeId", "cmis:objectTypeId", "cmis:createdBy",
338 "cmis:creationDate", "cmis:lastModifiedBy", "cmis:lastModificationDate",
339 "cmis::changeToken"
340 };
341 int skippedCount = sizeof( skippedProps ) / sizeof( char* );
342
343 for ( map< string, libcmis::PropertyPtr >::iterator it = getProperties( ).begin();
344 it != getProperties( ).end( ); ++it )
345 {
346 string propId = it->first;
347 bool toSkip = false;
348 for ( int i = 0; i < skippedCount && !toSkip; ++i )
349 {
350 toSkip = propId == skippedProps[i];
351 }
352
353 if ( !toSkip )
354 {
355 libcmis::PropertyPtr prop = it->second;
356 buf << prop->getPropertyType( )->getDisplayName( ) << "( " << prop->getPropertyType()->getId( ) << " ): " << endl;
357 vector< string > strValues = prop->getStrings( );
358 for ( vector< string >::iterator valueIt = strValues.begin( );
359 valueIt != strValues.end( ); ++valueIt )
360 {
361 buf << "\t" << *valueIt << endl;
362 }
363 }
364 }
365
366 return buf.str();
367}
368
369void AtomObject::toXml( xmlTextWriterPtr writer )
370{
371 xmlTextWriterStartElement( writer, BAD_CAST(xmlChar *)( "atom:entry" ) );
372 xmlTextWriterWriteAttribute( writer, BAD_CAST(xmlChar *)( "xmlns:atom" ), NS_ATOM_URL(xmlChar *)( "http://www.w3.org/2005/Atom" ) );
373 xmlTextWriterWriteAttribute( writer, BAD_CAST(xmlChar *)( "xmlns:cmis" ), NS_CMIS_URL(xmlChar *)( "http://docs.oasis-open.org/ns/cmis/core/200908/"
)
);
374 xmlTextWriterWriteAttribute( writer, BAD_CAST(xmlChar *)( "xmlns:cmisra" ), NS_CMISRA_URL(xmlChar *)( "http://docs.oasis-open.org/ns/cmis/restatom/200908/"
)
);
375
376 if ( !getCreatedBy( ).empty( ) )
377 {
378 xmlTextWriterStartElement( writer, BAD_CAST(xmlChar *)( "atom:author" ) );
379 xmlTextWriterWriteElement( writer, BAD_CAST(xmlChar *)( "atom:name" ), BAD_CAST(xmlChar *)( getCreatedBy( ).c_str( ) ) );
380 xmlTextWriterEndElement( writer );
381 }
382
383 xmlTextWriterWriteElement( writer, BAD_CAST(xmlChar *)( "atom:title" ), BAD_CAST(xmlChar *)( getName( ).c_str( ) ) );
384
385 boost::posix_time::ptime now( boost::posix_time::second_clock::universal_time( ) );
386 xmlTextWriterWriteElement( writer, BAD_CAST(xmlChar *)( "atom:updated" ), BAD_CAST(xmlChar *)( libcmis::writeDateTime( now ).c_str( ) ) );
387
388 contentToXml( writer );
389
390 xmlTextWriterStartElement( writer, BAD_CAST(xmlChar *)( "cmisra:object" ) );
391
392 // Output the properties
393 xmlTextWriterStartElement( writer, BAD_CAST(xmlChar *)( "cmis:properties" ) );
394 for ( map< string, libcmis::PropertyPtr >::iterator it = getProperties( ).begin( );
395 it != getProperties( ).end( ); ++it )
396 {
397 it->second->toXml( writer );
398 }
399 xmlTextWriterEndElement( writer ); // cmis:properties
400 xmlTextWriterEndElement( writer ); // cmisra:object
401
402 xmlTextWriterEndElement( writer ); // atom:entry
403}
404
405void AtomObject::extractInfos( xmlDocPtr doc )
406{
407 xmlXPathContextPtr xpathCtx = xmlXPathNewContext( doc );
408
409 atom::registerNamespaces( xpathCtx );
410
411 if ( NULL__null != xpathCtx )
1
Taking true branch
412 {
413 // Get all the atom links
414 string linksReq( "//atom:link" );
415 xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression( BAD_CAST(xmlChar *)( linksReq.c_str() ), xpathCtx );
416 if ( NULL__null != xpathObj && NULL__null != xpathObj->nodesetval )
417 {
418 int size = xpathObj->nodesetval->nodeNr;
419 for ( int i = 0; i < size; i++ )
420 {
421 xmlNodePtr node = xpathObj->nodesetval->nodeTab[i];
422 try
423 {
424 AtomLink link( node );
425 m_links.push_back( node );
426 }
427 catch ( const libcmis::Exception& )
428 {
429 // Broken or incomplete link... don't add it
430 }
431 }
432 }
433 xmlXPathFreeObject( xpathObj );
434
435 // Get the infos URL as we may not have it
436 m_infosUrl = getLink( "self", "application/atom+xml;type=entry" )->getHref( );
2
Called C++ object pointer is null
437
438 // Get the allowableActions
439 xpathObj = xmlXPathEvalExpression( BAD_CAST(xmlChar *)( "//cmis:allowableActions" ), xpathCtx );
440 if ( xpathObj && xpathObj->nodesetval && xpathObj->nodesetval->nodeNr > 0 )
441 {
442 xmlNodePtr node = xpathObj->nodesetval->nodeTab[0];
443 m_allowableActions.reset( new libcmis::AllowableActions( node ) );
444 }
445 xmlXPathFreeObject( xpathObj );
446
447 // First get the type id as it will give us the property definitions
448 string typeIdReq( "//cmis:propertyId[@propertyDefinitionId='cmis:objectTypeId']/cmis:value/text()" );
449 m_typeId = atom::getXPathValue( xpathCtx, typeIdReq );
450
451 string propertiesReq( "//cmis:properties/*" );
452 xpathObj = xmlXPathEvalExpression( BAD_CAST(xmlChar *)( propertiesReq.c_str() ), xpathCtx );
453 if ( NULL__null != xpathObj && NULL__null != xpathObj->nodesetval )
454 {
455 int size = xpathObj->nodesetval->nodeNr;
456 for ( int i = 0; i < size; i++ )
457 {
458 xmlNodePtr node = xpathObj->nodesetval->nodeTab[i];
459 libcmis::PropertyPtr property = libcmis::parseProperty( node, getTypeDescription( ) );
460 if ( property.get( ) )
461 m_properties.insert(
462 std::pair< string, libcmis::PropertyPtr >(
463 property->getPropertyType( )->getId(),
464 property ) );
465 }
466 }
467 xmlXPathFreeObject( xpathObj );
468 }
469
470 xmlXPathFreeContext( xpathCtx );
471}
472
473void AtomObject::contentToXml( xmlTextWriterPtr )
474{
475}
476
477AtomLink* AtomObject::getLink( std::string rel, std::string type )
478{
479 AtomLink* link = NULL__null;
480 vector< AtomLink >::iterator it = find_if( m_links.begin(), m_links.end(), MatchLink( rel, type ) );
481 if ( it != m_links.end() )
482 link = &( *it );
483 return link;
484}
485
486AtomLink::AtomLink( xmlNodePtr node ) throw ( libcmis::Exception ):
487 m_rel( ),
488 m_type( ),
489 m_id( ),
490 m_href( )
491{
492 m_rel = libcmis::getXmlNodeAttributeValue( node, "rel" );
493 m_href = libcmis::getXmlNodeAttributeValue( node, "href" );
494
495 try
496 {
497 m_type = libcmis::getXmlNodeAttributeValue( node, "type" );
498 m_id = libcmis::getXmlNodeAttributeValue( node, "id" );
499 }
500 catch ( const libcmis::Exception & )
501 {
502 // id attribute can be missing
503 // type attribute is missing in some implementations (SharePoint)
504 }
505}