예제 #1
0
 public function test_copy_from_file()
 {
     $attachment = $this->create_object('midcom_db_attachment', array('parentguid' => self::$_topic->guid));
     $stat = $attachment->copy_from_file(self::$_filepath . 'attach.png');
     $this->assertTrue($stat, midcom_connection::get_error_string());
     $blob = new midgard_blob($attachment->__object);
     $this->assertFileEquals(self::$_filepath . 'attach.png', $blob->get_path());
 }
예제 #2
0
파일: pdf.php 프로젝트: nemein/openpsa
 /**
  * @param mixed $handler_id The ID of the handler.
  * @param Array $args The argument list.
  * @param Array &$data The local request data.
  */
 public function _handler_pdf($handler_id, array $args, array &$data)
 {
     $this->_invoice = new org_openpsa_invoices_invoice_dba($args[0]);
     $this->_request_data['invoice_url'] = midcom_core_context::get()->get_key(MIDCOM_CONTEXT_ANCHORPREFIX) . "invoice/" . $this->_invoice->guid . "/";
     //check for manually uploaded pdf-file & if user wants to replace it
     if (array_key_exists('cancel', $_POST)) {
         return new midcom_response_relocate($this->_request_data['invoice_url']);
     } else {
         if (array_key_exists('save', $_POST)) {
             $this->_update_attachment = true;
         } else {
             $data['confirmation_message'] = 'current pdf file was manually uploaded shall it be replaced ?';
             // load schema & datamanager to get attachment
             $schemadb = midcom_helper_datamanager2_schema::load_database($this->_config->get('schemadb'));
             $this->_datamanager = new midcom_helper_datamanager2_datamanager($schemadb);
             if (!$this->_datamanager->autoset_storage($this->_invoice)) {
                 throw new midcom_error("Failed to create a DM2 instance for object {$this->_invoice->guid}.");
             }
             if ($this->_invoice->sent) {
                 $data['confirmation_message'] = 'invoice has already been sent. should it be replaced?';
             } else {
                 if (!empty($this->_datamanager->types['pdf_file']->attachments)) {
                     foreach ($this->_datamanager->types['pdf_file']->attachments as $attachment) {
                         $checksum = $attachment->get_parameter('org.openpsa.invoices', 'auto_generated');
                         // check if auto generated parameter is same as md5 in current-file
                         // if not the file was manually uploaded
                         if ($checksum) {
                             $blob = new midgard_blob($attachment->__object);
                             // check if md5 sum equals the one saved in auto_generated
                             if ($checksum == md5_file($blob->get_path())) {
                                 $this->_update_attachment = true;
                             }
                         }
                     }
                 } else {
                     $this->_update_attachment = true;
                 }
             }
         }
     }
     if ($this->_update_attachment) {
         $this->_request_data['billing_data'] = $this->_invoice->get_billing_data();
         if (self::render_and_attach_pdf($this->_invoice)) {
             midcom::get('uimessages')->add($this->_l10n->get($this->_component), $this->_l10n->get('pdf created'));
         } else {
             midcom::get('uimessages')->add($this->_l10n->get($this->_component), $this->_l10n->get('pdf creation failed') . ': ' . midcom_connection::get_error_string(), 'error');
         }
         return new midcom_response_relocate($this->_request_data["invoice_url"]);
     }
 }
예제 #3
0
 /**
  * Function serves the attachment by provided guid and exits.
  * @todo: Permission handling
  * @todo: Direct filesystem serving
  * @todo: Configuration options
  */
 public function get_serve(array $args)
 {
     $att = new midgard_attachment($args['guid']);
     if (midgardmvc_core::get_instance()->configuration->enable_attachment_cache) {
         midgardmvc_core::get_instance()->dispatcher->header('Location: ' . midgardmvc_core_helpers_attachment::get_url($att));
         midgardmvc_core::get_instance()->dispatcher->end_request();
     }
     $blob = new midgard_blob($att);
     midgardmvc_core::get_instance()->dispatcher->header('Content-type: ' . $att->mimetype);
     /**
      * If X-Sendfile support is enabled just sending correct headers
      */
     if (midgardmvc_core::get_instance()->configuration->enable_xsendfile) {
         midgardmvc_core::get_instance()->dispatcher->header('X-Sendfile: ' . $blob->get_path());
     } else {
         echo $blob->read_content();
     }
     midgardmvc_core::get_instance()->dispatcher->end_request();
 }
예제 #4
0
 /**
  * Links file to public web folder.
  * 
  * @param midgard_attachment attachment An attachment object
  * @return true of false 
  */
 public static function add_to_cache(midgard_attachment &$attachment)
 {
     $blob = new midgard_blob($attachment);
     // FIXME: Attachment directory creating should be done more elegantly
     $attachment_dir = explode('/', $attachment->location);
     $attachment_dir = midgardmvc_core::get_instance()->configuration->attachment_cache_directory . "{$attachment_dir[0]}/{$attachment_dir[1]}/";
     if (is_file(midgardmvc_core::get_instance()->configuration->attachment_cache_directory . $attachment->location)) {
         return false;
     }
     if (!is_dir($attachment_dir)) {
         mkdir($attachment_dir, 0700, true);
     }
     return symlink($blob->get_path(), midgardmvc_core::get_instance()->configuration->attachment_cache_directory . $attachment->location);
 }
예제 #5
0
 /**
  * Simple wrapper for stat() on the blob object.
  *
  * @return mixed Either a stat array as for stat() or false on failure.
  */
 function stat()
 {
     if (!$this->id) {
         debug_add('Cannot open a non-persistent attachment..', MIDCOM_LOG_WARN);
         debug_print_r('Object state:', $this);
         return false;
     }
     $blob = new midgard_blob($this->__object);
     $path = $blob->get_path();
     if (!file_exists($path)) {
         debug_add("File {$path} that blob {$this->guid} points to cannot be found", MIDCOM_LOG_WARN);
         return false;
     }
     return stat($path);
 }
예제 #6
0
파일: resolver.php 프로젝트: nemein/openpsa
 /**
  * Deliver a blob to the client.
  *
  * This is a replacement for mgd_serve_attachment that should work around most of
  * its bugs: It is missing all important HTTP Headers concerning file size,
  * modification date and expiration. It will not call _midcom_stop_request() when it is finished,
  * you still have to do that yourself. It will add the following HTTP Headers:
  *
  * - Cache-Control: public max-age=$expires
  * - Expires: GMT Date $now+$expires
  * - Last-Modified: GMT Date of the last modified timestamp of the Attachment
  * - Content-Length: The Length of the Attachment in Bytes
  * - Accept-Ranges: none
  *
  * This should enable caching of browsers for Navigation images and so on. You can
  * influence the expiration of the served attachment with the parameter $expires.
  * It is the time in seconds till the client should refetch the file. The default
  * for this is 24 hours. If you set it to "0" caching will be prohibited by
  * changing the sent headers like this:
  *
  * - Pragma: no-cache
  * - Cache-Control: no-cache
  * - Expires: Current GMT Date
  *
  * If expires is set to -1, no expires header gets sent.
  *
  * @param MidgardAttachment &$attachment    A reference to the attachment to be delivered.
  * @param int $expires HTTP-Expires timeout in seconds, set this to 0 for uncacheable pages, or to -1 for no Expire header.
  */
 public function serve_attachment(&$attachment, $expires = -1)
 {
     if ($GLOBALS['midcom_config']['attachment_cache_enabled']) {
         $path = '/' . substr($attachment->guid, 0, 1) . "/{$attachment->guid}_{$attachment->name}";
         if (file_exists($GLOBALS['midcom_config']['attachment_cache_root'] . $path)) {
             $response = new midcom_response_relocate($GLOBALS['midcom_config']['attachment_cache_url'] . $path, 301);
             $response->send();
         }
     }
     // Sanity check expires
     if (!is_int($expires) || $expires < -1) {
         throw new midcom_error("\$expires has to be a positive integer or zero or -1, is now {$expires}.");
     }
     // Doublecheck that this is registered
     $cache = midcom::get('cache');
     $cache->content->register($attachment->guid);
     $stats = $attachment->stat();
     $last_modified =& $stats[9];
     $app = midcom::get();
     $etag = md5("{$last_modified}{$attachment->name}{$attachment->mimetype}{$attachment->guid}");
     // Check etag and return 304 if necessary
     if ($expires != 0 && $cache->content->_check_not_modified($last_modified, $etag)) {
         if (!_midcom_headers_sent()) {
             $cache->content->cache_control_headers();
             // Doublemakesure these are present
             $app->header('HTTP/1.0 304 Not Modified', 304);
             $app->header("ETag: {$etag}");
         }
         while (@ob_end_flush()) {
         }
         debug_add("End of MidCOM run: {$_SERVER['REQUEST_URI']}");
         _midcom_stop_request();
     }
     $f = $attachment->open('r');
     if (!$f) {
         throw new midcom_error('Failed to open attachment for reading: ' . midcom_connection::get_error_string());
     }
     $app->header("ETag: {$etag}");
     $cache->content->content_type($attachment->mimetype);
     $cache->content->register_sent_header("Content-Type: {$attachment->mimetype}");
     $app->header("Last-Modified: " . gmdate("D, d M Y H:i:s", $last_modified) . ' GMT');
     $app->header("Content-Length: " . $stats[7]);
     $app->header("Content-Description: {$attachment->title}");
     // PONDER: Support ranges ("continue download") somehow ?
     $app->header("Accept-Ranges: none");
     if ($expires > 0) {
         // If custom expiry now+expires is set use that
         $cache->content->expires(time() + $expires);
     } else {
         if ($expires == 0) {
             // expires set to 0 means disable cache, so we shall
             $cache->content->no_cache();
         }
     }
     // TODO: Check metadata service for the real expiry timestamp ?
     $cache->content->cache_control_headers();
     $send_att_body = true;
     if ($GLOBALS['midcom_config']['attachment_xsendfile_enable']) {
         $blob = new midgard_blob($attachment->__object);
         $att_local_path = $blob->get_path();
         debug_add("Checking is_readable({$att_local_path})");
         if (is_readable($att_local_path)) {
             $app->header("X-Sendfile: {$att_local_path}");
             $send_att_body = false;
         }
     }
     // Store metadata in cache so _check_hit() can help us
     if (!$cache->content->_uncached && !$cache->content->_no_cache) {
         $cache->content->write_meta_cache('A-' . $etag, $etag);
     }
     while (@ob_end_flush()) {
     }
     if (!$send_att_body) {
         debug_add('NOT sending file (X-Sendfile will take care of that, _midcom_stop_request()ing so nothing has a chance the mess things up anymore');
         _midcom_stop_request();
     }
     fpassthru($f);
     $attachment->close();
     debug_add("End of MidCOM run: {$_SERVER['REQUEST_URI']}");
     _midcom_stop_request();
 }
예제 #7
0
 /**
  * Creates or updates a package in the database
  *
  * @return object package object
  */
 public function createPackage($project_name = null, $repo_id = null, $repo_name = null, $arch_name = null, $package_name = null, $file_name = null, $repo_arch_name = null)
 {
     if ($project_name && $repo_name && $arch_name && $package_name && $file_name) {
         // get fill package info via OBS API
         try {
             $extinfo = $this->api->getPackageWithFullInformation($project_name, $repo_name, $arch_name, $package_name, $file_name);
         } catch (RuntimeException $e) {
             $this->log('         [EXCEPTION] ' . $e->getMessage());
         }
     } else {
         throw new RuntimeException('Not enough parameters to gather full package information');
         return;
     }
     // get a com_meego_package instance
     $package = $this->getPackageByFileName($file_name, $repo_id);
     if ($package && $repo_id && $extinfo) {
         if (!$package->guid) {
             $package->repository = $repo_id;
             $package->filename = $extinfo->filename;
         }
         // deb or rpm
         $package->type = substr($package->filename, strrpos($package->filename, '.') + 1);
         $package->size = $extinfo->size;
         $package->name = $extinfo->name;
         $package->title = $extinfo->title;
         $package->parent = $package_name;
         $package->version = $extinfo->version;
         $summary_max_length = 100;
         if (array_key_exists('summary_max_length', $this->config)) {
             $summary_max_length = $this->config['summary_max_length'];
         }
         if (strlen($extinfo->summary)) {
             $package->summary = $this->generateAbstract($extinfo->summary, $summary_max_length);
         } else {
             $package->summary = $this->generateAbstract($extinfo->description, $summary_max_length);
         }
         $package->description = $extinfo->description;
         // if the package is a source package then the downloadurl is slightly different
         // also change the title a bit
         if ($repo_arch_name == 'src') {
             $package->title = $package->title . '-src';
         }
         if ($repo_arch_name == 'armv7el') {
             // fix the inconsistency between the published repo and the API
             $repo_arch_name = 'armv7l';
             if ($package->type == 'deb') {
                 $repo_arch_name = $extinfo->arch;
             }
         }
         // direct download url
         $_uri = str_replace(':', ':/', $project_name) . '/' . str_replace(':', ':/', $repo_name) . '/' . $repo_arch_name . '/' . $file_name;
         $package->downloadurl = $this->download_repo_protocol . '://' . $this->download_repo_host . '/' . $_uri;
         // @todo
         $package->bugtracker = '* TODO *';
         // for some info we need a special xray
         try {
             switch ($package->type) {
                 case 'rpm':
                     $xray = new RpmXray($this->download_repo_protocol, $this->download_repo_host, $_uri);
                     break;
                 case 'deb':
                     $xray = new DebXray($this->download_repo_protocol, $this->download_repo_host, $_uri, $this->config['wget'], $this->config['wget_options'], $this->debug);
                     break;
                 default:
                     throw new RuntimeException("Unknown file extension: " . $package->type . "(should be rpm or deb).");
             }
         } catch (RuntimeException $e) {
             $this->log('         [EXCEPTION] ' . $e->getMessage());
             // if there was a problem during xray (with code 999)
             // then it almost certainly means that the package no longer exists in the repository
             // so if the package exists in our database then remove it
             if ($package->guid && $e->getCode() == 999) {
                 // if package deletion is OK then return immediately
                 $result = $this->deletePackage($package, $project_name);
             }
         }
         if (is_object($xray)) {
             $package->license = $this->getLicense($xray->license, '');
             $package->homepageurl = $xray->url;
             $package->category = $this->getCategory($xray->group);
             if (isset($xray->title) && strlen($xray->title)) {
                 $package->title = $xray->title;
             }
         }
         // call the parent
         if ($package->guid) {
             $this->log('           update: ' . $package->filename . ' (title: ' . $package->title . ', guid: ' . $package->guid . ')');
             $package->metadata->hidden = false;
             $package->update();
         } else {
             if ($package->create()) {
                 $this->log('           create: ' . $package->filename . ' (title: ' . $package->title . ', guid: ' . $package->guid . ')');
             } else {
                 $this->log('           failed to create: ' . $package->filename . ' (title: ' . $package->title . ')');
             }
         }
         try {
             // if attachment creation failed then use the original OBS link
             $package->installfileurl = $this->api->getInstallFileURL($project_name, $repo_name, $arch_name, $package_name, $file_name);
             // get the file and store it locally
             // $fp might be a stream, or string if wget is in use
             $fp = $this->api->http->get_as_stream($this->api->getRelativeInstallPath($project_name, $repo_name, $arch_name, $package_name, $file_name));
             if ($fp) {
                 $attachment = $package->create_attachment($package_name . "_install.ymp", $package_name . "_install.ymp", "text/x-suse-ymp");
                 if ($attachment) {
                     $blob = new midgard_blob($attachment);
                     $handler = $blob->get_handler('wb');
                     if ($handler) {
                         if (!$this->config['wget']) {
                             $ymp = stream_get_contents($fp);
                         } else {
                             $ymp = $fp;
                         }
                         $origymp = $ymp;
                         // replace name with the package name
                         $ymp = self::replace_name_with_packagename($ymp, $package->name);
                         if (!strlen($ymp)) {
                             $this->log('           attempt to update package name in: ' . $attachment->name . ' would result in 0 byte long file; rollback, location: blobs/' . $attachment->location);
                             $ymp = $origymp;
                         }
                         // write the attachment to the file system
                         fwrite($handler, $ymp);
                         if (!$this->config['wget']) {
                             fclose($fp);
                         }
                         // close the attachment's handler
                         fclose($handler);
                         $attachment->update();
                         $this->log('           attachment created: ' . $attachment->name . ' (location: blobs/' . $attachment->location . ')');
                     } else {
                         $this->log('Could not create attachment');
                     }
                 } else {
                     // could not create attachment, maybe we have it already
                     $attachments = $package->list_attachments();
                     foreach ($attachments as $attachment) {
                         if ($attachment->name == $package_name . "_install.ymp") {
                             $blob = new midgard_blob($attachment);
                             $handler = $blob->get_handler('rb+');
                             if ($handler) {
                                 $content = $blob->read_content();
                                 $ymp = $content;
                                 if (strlen($content)) {
                                     $ymp = self::replace_name_with_packagename($content, $package->name);
                                 }
                                 if (!strlen($ymp)) {
                                     $this->log('           attempt to update package name in: ' . $attachment->name . ' would result in 0 byte long file; rollback, location: blobs/' . $attachment->location);
                                     $ymp = $content;
                                 }
                                 fwrite($handler, $ymp);
                                 fclose($handler);
                             } else {
                                 $this->log('           failed to update attachment: ' . $attachment->name . ', location: blobs/' . $attachment->location);
                             }
                             break;
                         }
                     }
                 }
                 // set the install url field to the local attachment
                 if (is_object($attachment)) {
                     // write a local relative URL for the install file
                     $package->installfileurl = '/mgd:attachment/' . $attachment->guid . '/' . $attachment->name;
                 }
                 // update because of the installfileurl stuff
                 $package->update();
             }
         } catch (RuntimeException $e) {
             $this->log('         [EXCEPTION] ' . $e->getMessage());
         }
         // get the roles and create the necessary role objects
         $roles = $this->api->getPackageMeta($project_name, $package_name);
         foreach ($roles as $role => $userids) {
             foreach ($userids as $userid) {
                 $this->log('           create role: ' . $userid . ' = ' . $role . ' (' . $package->guid . ')');
                 $this->createRole($package->guid, $userid, $role);
             }
         }
         // add relations by calling the parent class
         $this->addRelations($extinfo, $package);
     }
     return $package;
 }
 /**
  * Goes through a release specified by a URL that points to a Release file
  *
  * @param string OBS project name, e.g. home:feri
  * @param string optional; specify a concrete package to be imported
  * @param boolean optional; if true then only cleanup will be performed on the local database
  *                otherwise full import happens
  *
  */
 public function go($release_file_url = null, $specific_package_name = null, $cleanonly = false)
 {
     // get release information from the relase file
     switch ($this->protocol) {
         case 'http':
         case 'https':
             $content = $this->http->get($release_file_url);
             break;
         case 'file':
             # todo
             break;
     }
     $release = $this->parseReleaseFile($content);
     if (!array_key_exists('Suite', $release)) {
         throw new RuntimeException('The Release files does not specify a suite.' . $packages_file_url);
         return null;
     }
     // generate name and tile from release information
     $project_name = strtolower($release['Origin'] . '-' . $release['Suite'] . '-' . $release['Label']);
     $project_title = ucwords($release['Origin'] . ' ' . $release['Suite'] . ' ' . $release['Label']);
     // check if the project is already recorded in our database
     // this returns a com_meego_project object
     $project = $this->getProject($project_name);
     // set properties
     $project->name = $project_name;
     $project->title = $project_title;
     $project->description = "Debian repository from " . ucfirst($release['Origin']);
     if (!$cleanonly) {
         if ($project->guid) {
             $log = 'Update project record: ' . $project->name;
             $project->update();
         } else {
             $log = 'Create project record: ' . $project->name;
             $project->create();
         }
         $this->log($log . ' (' . $project->title . ', ' . $project->description . ')');
     }
     if ($project->id) {
         $this->log("\nComponents in {$project->name}:");
         // get all components (ie repositories in the database) this Suite contains
         $repositories = explode(' ', $release['Components']);
         // iterate through each and every published repository
         // and dig out the packages
         foreach ($repositories as $repo_name) {
             $this->log("\n -> " . $repo_name);
             $architectures = explode(' ', $release['Architectures']);
             // get all available architectures within this repository
             foreach ($architectures as $arch_name) {
                 $this->log("\n  -> " . $arch_name);
                 // get a com_meego_repository object
                 $repo = $this->getRepository($repo_name, $arch_name, $project->id);
                 $repo_title = ucfirst($release['Suite']) . ' ' . ucfirst($release['Label']) . ' ' . ucfirst($repo_name) . ' (for ' . $arch_name . ')';
                 // fill in properties of the repo object
                 $repo->name = strtolower($release['Suite'] . '_' . $release['Label'] . '_' . $repo_name);
                 $repo->title = $repo_title;
                 $repo->arch = $arch_name;
                 $repo->project = $project->id;
                 $repo->os = $release['Origin'];
                 $repo->osversion = $release['Suite'];
                 $repo->osgroup = $release['Label'];
                 $repo->osux = $release['ux'];
                 if (!$cleanonly) {
                     if ($repo->guid) {
                         $log = '     update: ';
                         $repo->update();
                     } else {
                         $log = '     create: ';
                         $repo->create();
                     }
                     $this->log($log . $repo->name . ' (id: ' . $repo->id . '; ' . $repo->os . ' ' . $repo->osversion . ', ' . $repo->osgroup . ', ' . $repo->osux . ')');
                 }
                 $fulllist = array();
                 // determine the url of the binary Packages file
                 $packages_file_url = preg_replace('|Release$|', '', $release_file_url) . '/' . $repo_name . '/binary-' . $arch_name . '/Packages';
                 // get an array of all available packages
                 // this array is a special one, so study the method for details
                 $packages = $this->parsePackagesFile($packages_file_url);
                 if (!count($packages)) {
                     continue;
                 }
                 foreach ($packages as $package_name => $versions) {
                     // iterate through each versions
                     foreach ($versions as $package_version => $details) {
                         $this->log("\n     -> package #" . ++$this->package_counter . ': ' . $package_name . ' ' . $package_version);
                         if ($cleanonly) {
                             // only cleanup is requested so we can go to the next package
                             continue;
                         }
                         // creates or updates a package in the database
                         $package = $this->createPackage($project->name, $repo->id, $repo_name, $arch_name, $details);
                         if (!$package) {
                             // we got no package object, usually because we had to delete
                             // an existing one from database, so go to next binary package
                             continue;
                         }
                         $fulllist[] = $package->filename;
                         try {
                             $image_names = array_filter($this->api->getPackageSourceFiles($project->name, $package_name), function ($name) {
                                 $retval = false;
                                 $_icon_marker = 'icon.png';
                                 $_screenshot_marker = 'screenshot.png';
                                 if (strpos($name, $_icon_marker) === strlen($name) - strlen($_icon_marker) || strpos($name, $_screenshot_marker) === strlen($name) - strlen($_screenshot_marker)) {
                                     $retval = true;
                                 }
                                 return $retval;
                             });
                         } catch (RuntimeException $e) {
                             $this->log('         [EXCEPTION] ' . $e->getMessage());
                         }
                         foreach ($image_names as $name) {
                             try {
                                 $fp = $this->api->getPackageSourceFile($project->name, $package_name, $name);
                             } catch (RuntimeException $e) {
                                 $this->log('         [EXCEPTION] ' . $e->getMessage());
                             }
                             if ($fp) {
                                 $attachment = $package->create_attachment($name, $name, "image/png");
                                 if ($attachment) {
                                     $blob = new midgard_blob($attachment);
                                     $handler = $blob->get_handler('wb');
                                     fwrite($handler, stream_get_contents($fp));
                                     fclose($fp);
                                     fclose($handler);
                                     $attachment->update();
                                 }
                             }
                         }
                     }
                 }
                 // now cleanup all the packages from our database
                 // that are not part of this OBS repository
                 $this->cleanPackages($repo, $fulllist);
             }
         }
     }
     // if $project->id
 }