public static function update()
 {
     $file_id = (int) $_REQUEST['file_id'];
     $file = MediaFile::find_by_id($file_id);
     if (isset($_REQUEST['slug'])) {
         self::simulate_temporary_episode_slug($_REQUEST['slug']);
     }
     $info = $file->determine_file_size();
     $file->save();
     $result = array();
     $result['file_url'] = $file->get_file_url();
     $result['file_id'] = $file_id;
     $result['reachable'] = podlove_is_resolved_and_reachable_http_status($info['http_code']);
     $result['file_size'] = $file->size;
     if (!$result['reachable']) {
         $info['certinfo'] = print_r($info['certinfo'], true);
         $info['php_open_basedir'] = ini_get('open_basedir');
         $info['php_safe_mode'] = ini_get('safe_mode');
         $info['php_curl'] = in_array('curl', get_loaded_extensions());
         $info['curl_exec'] = function_exists('curl_exec');
         $errorLog = "--- # Can't reach {$file->get_file_url()}\n";
         $errorLog .= "--- # Please include this output when you report a bug\n";
         foreach ($info as $key => $value) {
             $errorLog .= "{$key}: {$value}\n";
         }
         \Podlove\Log::get()->addError($errorLog);
     }
     Ajax::respond_with_json($result);
 }
示例#2
0
 /**
  * Register Event for Auphonic Webhook
  */
 public function auphonic_webhook()
 {
     if (!isset($_REQUEST['podlove-auphonic-production']) || empty($_REQUEST['podlove-auphonic-production']) || empty($_POST)) {
         return;
     }
     if ($_POST['status_string'] !== 'Done') {
         return;
     }
     $post_id = (int) $_REQUEST['podlove-auphonic-production'];
     $episodes_to_be_remote_published = get_option('podlove_episodes_to_be_remote_published');
     if (!is_array($episodes_to_be_remote_published) || !isset($episodes_to_be_remote_published[$post_id])) {
         return;
     }
     $episode = $episodes_to_be_remote_published[$post_id];
     $auth_key = $episode['auth_key'];
     $action = $episode['action'];
     if ($_REQUEST['authkey'] !== $auth_key) {
         \Podlove\Log::get()->addWarning('Auphonic webhook failed. AuthKey mismatch.', ['post_id' => $post_id]);
         return;
     }
     // Update episode with production results
     $this->update_production_data($post_id);
     if ($action == 'publish') {
         wp_publish_post($post_id);
     }
     unset($episodes_to_be_remote_published[$post_id]);
     update_option('podlove_episodes_to_be_remote_published', $episodes_to_be_remote_published);
 }
 public function register_database_logger()
 {
     global $wpdb;
     $log = Log::get();
     // write logs to database
     $log->pushHandler(new WPDBHandler($wpdb, $log->get_log_level()));
     // send critical logs via email
     // $log->pushHandler( new WPMailHandler( get_option( 'admin_email' ), "Podlove | Critical notice for " . get_option( 'blogname' ), Logger::CRITICAL ) );
 }
 private function validate_post(\WP_Post $post)
 {
     $episode = Model\Episode::find_or_create_by_post_id($post->ID);
     if ($episode && $episode->is_valid()) {
         Log::get()->addInfo('Validate episode', array('episode_id' => $episode->id));
         $episode->refetch_files();
         update_post_meta($post->ID, '_podlove_last_validated_at', time());
     }
 }
 /**
  * Apply Twig to given template
  * 
  * @param  string $html File path or HTML string.
  * @param  array  $vars optional variables for Twig context
  * @return string       rendered template string
  */
 public static function apply_to_html($html, $vars = array())
 {
     // file loader for internal use
     $file_loader = new \Twig_Loader_Filesystem();
     $file_loader->addPath(implode(DIRECTORY_SEPARATOR, array(\Podlove\PLUGIN_DIR, 'templates')), 'core');
     // other modules can register their own template directories/namespaces
     $file_loader = apply_filters('podlove_twig_file_loader', $file_loader);
     // database loader for user templates
     $db_loader = new TwigLoaderPodloveDatabase();
     $loaders = array($file_loader, $db_loader);
     $loaders = apply_filters('podlove_twig_loaders', $loaders);
     $loader = new \Twig_Loader_Chain($loaders);
     $twig = new \Twig_Environment($loader, array('autoescape' => false));
     $twig->addExtension(new \Twig_Extensions_Extension_I18n());
     $twig->addExtension(new \Twig_Extensions_Extension_Date());
     $formatBytesFilter = new \Twig_SimpleFilter('formatBytes', function ($string) {
         return \Podlove\format_bytes($string, 0);
     });
     $padLeftFilter = new \Twig_SimpleFilter('padLeft', function ($string, $padChar, $length) {
         while (strlen($string) < $length) {
             $string = $padChar . $string;
         }
         return $string;
     });
     $twig->addFilter($formatBytesFilter);
     $twig->addFilter($padLeftFilter);
     // add functions
     foreach (self::$template_tags as $tag) {
         $func = new \Twig_SimpleFunction($tag, function () use($tag) {
             return $tag();
         });
         $twig->addFunction($func);
     }
     $context = ['option' => $vars];
     // add podcast to global context
     $context = array_merge($context, ['podcast' => new Podcast(Model\Podcast::get())]);
     // Apply filters to twig templates
     $context = apply_filters('podlove_templates_global_context', $context);
     // add podcast to global context if we are in an episode
     if ($episode = Model\Episode::find_one_by_property('post_id', get_the_ID())) {
         $context = array_merge($context, array('episode' => new Episode($episode)));
     }
     try {
         return $twig->render($html, $context);
     } catch (\Twig_Error $e) {
         $message = $e->getRawMessage();
         $line = $e->getTemplateLine();
         $template = $e->getTemplateFile();
         \Podlove\Log::get()->addError($message, ['type' => 'twig', 'line' => $line, 'template' => $template]);
     }
     return "";
 }
function podlove_handle_media_file_tracking(\Podlove\Model\MediaFile $media_file)
{
    if (\Podlove\get_setting('tracking', 'mode') !== "ptm_analytics") {
        return;
    }
    if (strtoupper($_SERVER['REQUEST_METHOD']) === 'HEAD') {
        return;
    }
    $intent = new Model\DownloadIntent();
    $intent->media_file_id = $media_file->id;
    $intent->accessed_at = date('Y-m-d H:i:s');
    $ptm_source = trim(podlove_get_query_var('ptm_source'));
    $ptm_context = trim(podlove_get_query_var('ptm_context'));
    if ($ptm_source) {
        $intent->source = $ptm_source;
    }
    if ($ptm_context) {
        $intent->context = $ptm_context;
    }
    // set user agent
    $ua_string = trim($_SERVER['HTTP_USER_AGENT']);
    if ($agent = Model\UserAgent::find_or_create_by_uastring($ua_string)) {
        $intent->user_agent_id = $agent->id;
    }
    // save HTTP range header
    // @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35 for spec
    if (isset($_SERVER['HTTP_RANGE'])) {
        $intent->httprange = $_SERVER['HTTP_RANGE'];
    }
    // get ip, but don't store it
    $ip_string = $_SERVER['REMOTE_ADDR'];
    try {
        $ip = IP\Address::factory($_SERVER['REMOTE_ADDR']);
        if (method_exists($ip, 'as_IPv6_address')) {
            $ip = $ip->as_IPv6_address();
        }
        $ip_string = $ip->format(IP\Address::FORMAT_COMPACT);
    } catch (\InvalidArgumentException $e) {
        \Podlove\Log::get()->addWarning('Could not use IP "' . $_SERVER['REMOTE_ADDR'] . '"' . $e->getMessage());
    }
    // Generate a hash from IP address and UserAgent so we can identify
    // identical requests without storing an IP address.
    if (function_exists('openssl_digest')) {
        $intent->request_id = openssl_digest($ip_string . $ua_string, 'sha256');
    } else {
        $intent->request_id = sha1($ip_string . $ua_string);
    }
    $intent = $intent->add_geo_data($ip_string);
    $intent->save();
}
function podlove_validate_image_cache()
{
    set_time_limit(5 * MINUTE_IN_SECONDS);
    PHP_Timer::start();
    $cache_files = glob(trailingslashit(Image::cache_dir()) . "*" . DIRECTORY_SEPARATOR . "*" . DIRECTORY_SEPARATOR . "cache.yml");
    foreach ($cache_files as $cache_file) {
        $cache = Yaml::parse(file_get_contents($cache_file));
        $validator = new HttpHeaderValidator($cache['source'], $cache['etag'], $cache['last-modified']);
        $validator->validate();
        if ($validator->hasChanged()) {
            wp_schedule_single_event(time(), 'podlove_refetch_cached_image', [$cache['source'], $cache['filename']]);
        }
    }
    $time = PHP_Timer::stop();
    \Podlove\Log::get()->addInfo(sprintf('Finished validating %d images in %s', count($cache_files), PHP_Timer::secondsToTimeString($time)));
}
 public function request($url, $params = array())
 {
     $defaults = array('user-agent' => self::user_agent(), 'stream' => false, 'decompress' => false, 'filename' => null, 'sslcertificates' => ABSPATH . WPINC . '/certificates/ca-bundle.crt');
     $params = wp_parse_args($params, $defaults);
     if (!isset($params['_redirection']) || $params['_redirection']) {
         if (!self::curl_can_follow_redirects()) {
             $url = self::resolve_redirects($url, 5);
         }
     }
     $this->response = $this->curl->request($url, $params);
     if (is_wp_error($this->response)) {
         Log::get()->addError('Curl error', array('url' => $url, 'error' => $this->response->get_error_message()));
     } elseif (substr($this->response['response']['code'], 0, 1) >= 4) {
         Log::get()->addError('Curl error', array('url' => $url, 'response code' => $this->response['response']['code']));
         Log::get()->addDebug(print_r($this->response, true));
     }
 }
 public function refetch_files()
 {
     $valid_files = array();
     foreach (EpisodeAsset::all() as $asset) {
         if ($file = MediaFile::find_by_episode_id_and_episode_asset_id($this->id, $asset->id)) {
             $file->determine_file_size();
             $file->save();
             if ($file->is_valid()) {
                 $valid_files[] = $file->id;
             }
         }
     }
     if (empty($valid_files) && get_post_status($this->post_id) == 'publish') {
         Log::get()->addAlert('All assets for this episode are invalid!', array('episode_id' => $this->id));
     }
 }
示例#10
0
 public function download_source()
 {
     // for download_url()
     require_once ABSPATH . 'wp-admin/includes/file.php';
     $result = $this->download_url($this->source_url);
     if (is_wp_error($result)) {
         \Podlove\Log::get()->addWarning(sprintf(__('Unable to download image. %s.'), $result->get_error_message()), ['url' => $this->source_url]);
         return;
     }
     list($temp_file, $response) = $result;
     if (is_wp_error($temp_file)) {
         \Podlove\Log::get()->addWarning(sprintf(__('Unable to download image. %s.'), $temp_file->get_error_message()), ['url' => $this->source_url]);
     }
     if (!wp_mkdir_p($this->upload_basedir)) {
         \Podlove\Log::get()->addWarning(sprintf(__('Unable to create directory %s. Is its parent directory writable by the server?'), $this->upload_basedir));
     }
     $this->save_cache_data($response);
     $move_new_file = @rename($temp_file, $this->original_file());
     if (false === $move_new_file) {
         \Podlove\Log::get()->addWarning(sprintf(__('The downloaded image could not be moved to %s.'), $this->original_file()));
     }
     @unlink($temp_file);
     $this->add_donotbackup_dotfile();
 }
 /**
  * POST $data to the given $url
  * 
  * @param  string $url  ADN API URL
  * @param  array  $data
  */
 public function post($url, $data)
 {
     $data_string = json_encode($data);
     $curl = new Http\Curl();
     $curl->request($url, array('method' => 'POST', 'timeout' => '5000', 'body' => $data_string, 'headers' => array('Content-type' => 'application/json', 'Content-Length' => \Podlove\PHP\strlen($data_string))));
     $response = $curl->get_response();
     $body = json_decode($response['body']);
     if ($body->meta->code !== 200) {
         \Podlove\Log::get()->addWarning(sprintf('Error: App.net Module failed to Post: %s (Code %s)', str_replace("'", "''", $body->meta->error_message), $body->meta->code));
     }
 }
 /**
  * Main Cron function call.
  */
 public function do_validations()
 {
     set_time_limit(1800);
     // set max_execution_time to half an hour
     Log::get()->addInfo('Begin scheduled feed validation.');
     $this->renewFeedTransients();
     Log::get()->addInfo('End scheduled feed validation.');
 }
 public static function logValidation($feedid, $errors_and_warnings, $redirected = FALSE)
 {
     $feed = \Podlove\Model\Feed::find_by_id($feedid);
     $feed_subscribe_url = $redirected === FALSE ? $feed->get_subscribe_url() : $feed->redirect_url;
     if ($redirected === TRUE) {
         $redirected = ' (Redirected)';
     }
     foreach ($errors_and_warnings['warnings'] as $warning_key => $warning) {
         \Podlove\Log::get()->addInfo('Warning: ' . $warning['text'] . ', line ' . $warning['line'] . ' in Feed <a href="' . $feed_subscribe_url . '">' . $feed->name . $redirected . '</a>.');
     }
     foreach ($errors_and_warnings['errors'] as $error_key => $error) {
         \Podlove\Log::get()->addError('Error: ' . $error['text'] . ', line ' . $error['line'] . ' in Feed <a href="' . $feed_subscribe_url . '">' . $feed->name . $redirected . '</a>.');
     }
 }
    // bring in form
    $core_modules = [];
    foreach (Modules\Base::get_core_module_names() as $module) {
        $core_modules[$module] = "on";
    }
    return array_merge($new_val, $core_modules);
}, 10, 2);
// fire activation and deactivation hooks for modules
add_action('update_option_podlove_active_modules', function ($old_val, $new_val) {
    $deactivated_modules = array_keys(array_diff_assoc($old_val, $new_val));
    $activated_modules = array_keys(array_diff_assoc($new_val, $old_val));
    if ($deactivated_modules) {
        foreach ($deactivated_modules as $deactivated_module) {
            Log::get()->addInfo('Deactivate module "' . $deactivated_module . '"');
            do_action('podlove_module_was_deactivated', $deactivated_module);
            do_action('podlove_module_was_deactivated_' . $deactivated_module);
        }
    }
    if ($activated_modules) {
        foreach ($activated_modules as $activated_module) {
            Log::get()->addInfo('Activate module "' . $activated_module . '"');
            // init module before firing hooks
            $class = Modules\Base::get_class_by_module_name($activated_module);
            if (class_exists($class)) {
                $class::instance()->load();
            }
            do_action('podlove_module_was_activated', $activated_module);
            do_action('podlove_module_was_activated_' . $activated_module);
        }
    }
}, 10, 2);
 /**
  * Validate media file headers.
  *
  * @todo  $this->id not available for first validation before media_file has been saved
  * @param  array $response curl response
  */
 private function validate_request($response)
 {
     // skip unsaved media files
     if (!$this->id) {
         return;
     }
     $header = $response['header'];
     if ($response['error']) {
         Log::get()->addError('Curl Error: ' . $response['error'], array('media_file_id' => $this->id));
     }
     // skip validation if ETag did not change
     if ((int) $header["http_code"] === 304) {
         return;
     }
     // look for ETag and safe for later
     if (podlove_is_resolved_and_reachable_http_status($header["http_code"]) && preg_match('/ETag:\\s*"([^"]+)"/i', $response['response'], $matches)) {
         $this->etag = $matches[1];
     } else {
         $this->etag = NULL;
     }
     do_action('podlove_media_file_content_has_changed', $this->id);
     // verify HTTP header
     if (!preg_match("/^[23]\\d\\d\$/", $header["http_code"])) {
         Log::get()->addError('Unexpected http response when trying to access remote media file.', array('media_file_id' => $this->id, 'http_code' => $header["http_code"]));
         return;
     }
     // check that content length exists and hasn't changed
     if (!isset($header['download_content_length']) || $header['download_content_length'] <= 0) {
         Log::get()->addWarning('Unable to read "Content-Length" header. Impossible to determine file size.', array('media_file_id' => $this->id, 'mime_type' => $header['content_type'], 'expected_mime_type' => $mime_type));
     } elseif ($header['download_content_length'] != $this->size) {
         Log::get()->addInfo('Change of media file content length detected.', array('media_file_id' => $this->id, 'old_size' => $this->size, 'new_size' => $header['download_content_length']));
     }
     // check if mime type matches asset mime type
     $mime_type = $this->episode_asset()->file_type()->mime_type;
     if ($header['content_type'] != $mime_type) {
         Log::get()->addWarning('Media file mime type does not match expected asset mime type.', array('media_file_id' => $this->id, 'mime_type' => $header['content_type'], 'expected_mime_type' => $mime_type));
     }
 }