Imported Upstream version 17.10.1
[platform/upstream/libzypp.git] / zypp / repo / ServiceRepos.cc
index 59c846c..f82f51e 100644 (file)
 #include <sstream>
 #include "zypp/base/Logger.h"
 #include "zypp/repo/ServiceRepos.h"
+#include "zypp/repo/RepoException.h"
+#include "zypp/media/MediaException.h"
 #include "zypp/parser/RepoFileReader.h"
 #include "zypp/media/MediaManager.h"
 #include "zypp/parser/RepoindexFileReader.h"
 #include "zypp/ExternalProgram.h"
 
 using std::stringstream;
+using std::endl;
 
+///////////////////////////////////////////////////////////////////
 namespace zypp
 {
-namespace repo
-{
+  ///////////////////////////////////////////////////////////////////
+  namespace repo
+  {
+    struct ServiceRepos::Impl
+    { virtual ~Impl() {} };
 
-class ServiceRepos::Impl
-{
-public:
-    Impl()
-    {
-    }
-    
-    virtual ~Impl()
-    {
-    }
-};
+    ///////////////////////////////////////////////////////////////////
 
-class RIMServiceRepos : public ServiceRepos::Impl
-{
-public:
-    ServiceRepos::ProcessRepo _callback;
-    
-    RIMServiceRepos(const ServiceInfo &service,
-                    const ServiceRepos::ProcessRepo & callback,
-                    const ProgressData::ReceiverFnc &progress = ProgressData::ReceiverFnc() )
-        : _callback(callback)
-    {
-      // repoindex.xml must be fetched always without using cookies (bnc #573897)
-      Url serviceUrl( service.url() );
-      serviceUrl.setQueryParam( "cookies", "0" );
-      
-      // download the repo index file
-      media::MediaManager mediamanager;
-      media::MediaAccessId mid = mediamanager.open( serviceUrl );
-      mediamanager.attach( mid );
-      mediamanager.provideFile( mid, "repo/repoindex.xml" );
-      Pathname path = mediamanager.localPath(mid, "repo/repoindex.xml" );
-      parser::RepoindexFileReader reader(path, _callback);
-      mediamanager.release( mid );
-      mediamanager.close( mid );
-    }
-    
-    ~RIMServiceRepos()
+    struct RIMServiceRepos : public ServiceRepos::Impl
     {
+      RIMServiceRepos( const Pathname & /*root_r*/,
+                      const ServiceInfo & service,
+                      const ServiceRepos::ProcessRepo & callback,
+                      const ProgressData::ReceiverFnc & progress = ProgressData::ReceiverFnc() )
+      {
+       // repoindex.xml must be fetched always without using cookies (bnc #573897)
+       Url serviceUrl( service.url() );
+       serviceUrl.setQueryParam( "cookies", "0" );
 
-    }
-};
+       // download the repo index file
+       media::MediaManager mediamanager;
+       media::MediaAccessId mid = mediamanager.open( serviceUrl );
+       mediamanager.attach( mid );
+       mediamanager.provideFile( mid, "repo/repoindex.xml" );
+       Pathname path = mediamanager.localPath(mid, "repo/repoindex.xml" );
+       try {
+         parser::RepoindexFileReader reader(path, callback);
+         service.setProbedTtl( reader.ttl() ); // hack! Modifying the const Service to set parsed TTL
+         mediamanager.release( mid );
+         mediamanager.close( mid );
+       } catch ( const Exception &e ) {
+         //Reader throws a bare exception, we need to translate it into something our calling
+         //code expects and handles (bnc#1116840)
+         ZYPP_CAUGHT ( e );
+         ServicePluginInformalException ex ( e.msg() );
+         ex.remember( e );
+         ZYPP_THROW( ex );
+       }
+      }
+    };
 
-class LocalServiceRepos : public ServiceRepos::Impl
-{
-public:
-    ServiceRepos::ProcessRepo _callback;
-    
-    LocalServiceRepos(const ServiceInfo &service,
-                      const ServiceRepos::ProcessRepo & callback,
-                      const ProgressData::ReceiverFnc &progress = ProgressData::ReceiverFnc() )
-        : _callback(callback)
-    {
-      Url serviceUrl( service.url() );
-      stringstream buffer;
-     
-      ExternalProgram prog(serviceUrl.getPathName(), ExternalProgram::Discard_Stderr, false, -1, true);
-      std::string line;
-      for(line = prog.receiveLine(); !line.empty(); line = prog.receiveLine() )
-          buffer << line;
-      prog.close();
-      parser::RepoFileReader parser(buffer, _callback);
-    }
-    
-    ~LocalServiceRepos()
+    ///////////////////////////////////////////////////////////////////
+
+    struct PluginServiceRepos : public ServiceRepos::Impl
     {
+      PluginServiceRepos( const Pathname & root_r,
+                         const ServiceInfo & service,
+                         const ServiceRepos::ProcessRepo & callback,
+                         const ProgressData::ReceiverFnc & progress = ProgressData::ReceiverFnc() )
+      {
+       // bsc#1080693: Service script needs to be executed chrooted to the RepoManagers rootDir.
+       // The service is not aware of the rootDir, so it's explicitly passed and needs to be
+       // stripped from the URLs path.
+       stringstream buffer;
 
-    }
-};
+       ExternalProgram::Arguments args;
+       args.reserve( 3 );
+       args.push_back( "/bin/sh" );
+       args.push_back( "-c" );
+       args.push_back( Pathname::stripprefix( root_r, service.url().getPathName() ).asString() );
+       ExternalProgramWithStderr prog( args, root_r );
+       prog >> buffer;
 
-    
-ServiceRepos::ServiceRepos(const ServiceInfo &service,
-                           const ServiceRepos::ProcessRepo & callback,
-                           const ProgressData::ReceiverFnc &progress)
-    : _impl( (service.type() == ServiceType::LOCAL) ? (ServiceRepos::Impl *)(new LocalServiceRepos(service, callback, progress)) : (ServiceRepos::Impl *)(new RIMServiceRepos(service, callback, progress)))
-{
-}
-    
-ServiceRepos::~ServiceRepos()
-{
-}
-    
+       if ( prog.close() != 0 )
+       {
+         // ServicePluginInformalException:
+         // Ignore this error but we'd like to report it somehow...
+         std::string errbuffer;
+         prog.stderrGetUpTo( errbuffer, '\0' );
+         ERR << "Capture plugin error:[" << endl << errbuffer << endl << ']' << endl;
+         ZYPP_THROW( repo::ServicePluginInformalException( service, errbuffer ) );
+       }
+       parser::RepoFileReader parser( buffer, callback );
+      }
+    };
+
+    ///////////////////////////////////////////////////////////////////
+
+    ServiceRepos::ServiceRepos( const Pathname & root_r,
+                               const ServiceInfo & service,
+                               const ServiceRepos::ProcessRepo & callback,
+                               const ProgressData::ReceiverFnc &progress )
+    : _impl( ( service.type() == ServiceType::PLUGIN )
+    ? static_cast<ServiceRepos::Impl*>( new PluginServiceRepos( root_r, service, callback, progress ) )
+    : static_cast<ServiceRepos::Impl*>( new RIMServiceRepos( root_r, service, callback, progress ) ) )
+    {}
+
+    ServiceRepos::~ServiceRepos()
+    {}
 
-}
-}
+  } // namespace repo
+  ///////////////////////////////////////////////////////////////////
+} //namespace zypp
+///////////////////////////////////////////////////////////////////