Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LaTeX Pixel Density #819

Merged
merged 6 commits into from Jun 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 17 additions & 10 deletions inc/modules/export/prince/class-pdf.php
Expand Up @@ -67,8 +67,6 @@ class Pdf extends Export {
*/
function __construct( array $args ) {

// Some defaults

if ( ! defined( 'PB_PRINCE_COMMAND' ) ) {
define( 'PB_PRINCE_COMMAND', '/usr/bin/prince' );
}
Expand All @@ -84,6 +82,7 @@ function __construct( array $args ) {
$this->url = home_url() . "/format/xhtml?timestamp={$timestamp}&hashkey={$md5}";

$this->themeOptionsOverrides();
$this->fixLatexDpi();
}


Expand All @@ -95,18 +94,16 @@ function __construct( array $args ) {
function convert() {

// Sanity check

if ( empty( $this->exportStylePath ) || ! is_file( $this->exportStylePath ) ) {
$this->logError( '$this->exportStylePath must be set before calling convert().' );

return false;
}

// Set logfile
$this->logfile = $this->createTmpFile();

// Set filename
$filename = $this->timestampedFileName( '.pdf' );
$filename = $this->generateFileName();
$this->outputPath = $filename;

// Fonts
Expand All @@ -117,7 +114,9 @@ function convert() {
$css_file = $this->createTmpFile();
file_put_contents( $css_file, $css );

// --------------------------------------------------------------------
// Save PDF as file in exports folder

$prince = new \PrinceXMLPhp\PrinceWrapper( PB_PRINCE_COMMAND );
$prince->setHTML( true );
$prince->setCompress( true );
Expand Down Expand Up @@ -149,15 +148,11 @@ function convert() {
* @return bool
*/
function validate() {

// Is this a PDF?
if ( ! $this->isPdf( $this->outputPath ) ) {

$this->logError( file_get_contents( $this->logfile ) );

return false;
}

return true;
}

Expand All @@ -177,6 +172,12 @@ function logError( $message, array $more_info = [] ) {
parent::logError( $message, $more_info );
}

/**
* @return string
*/
protected function generateFileName() {
return $this->timestampedFileName( '.pdf' );
}

/**
* Verify if body is actual PDF
Expand Down Expand Up @@ -282,6 +283,13 @@ protected function themeOptionsOverrides() {

}

/**
* Increase PB-LaTeX resolution to ~300 dpi
*/
protected function fixLatexDpi() {
$this->url .= '&pb-latex-zoom=3';
$this->cssOverrides .= "\n" . 'img.latex { prince-image-resolution: 300dpi; }' . "\n";
}

/**
* Dependency check.
Expand All @@ -292,7 +300,6 @@ static function hasDependencies() {
if ( false !== \Pressbooks\Utility\check_prince_install() && false !== \Pressbooks\Utility\check_xmllint_install() ) {
return true;
}

return false;
}
}
73 changes: 18 additions & 55 deletions inc/modules/export/prince/class-printpdf.php
Expand Up @@ -6,75 +6,38 @@

namespace Pressbooks\Modules\Export\Prince;

use Pressbooks\Container;

class PrintPdf extends Pdf {

/**
* @param array $args
*/
function __construct( array $args ) {

parent::__construct( $args );

// Override
$this->pdfProfile = 'PDF/X-1a';
$this->pdfOutputIntent = '/usr/lib/prince/icc/USWebCoatedSWOP.icc';
}

/**
* @return string
*/
protected function generateFileName() {
return $this->timestampedFileName( '._print.pdf' );
}

/**
* Create $this->outputPath
* Return the desired PDF profile.
*
* @return bool
* @return string
*/
function convert() {

// Sanity check

if ( empty( $this->exportStylePath ) || ! is_file( $this->exportStylePath ) ) {
$this->logError( '$this->exportStylePath must be set before calling convert().' );

return false;
}

// Set logfile
$this->logfile = $this->createTmpFile();

// Set filename
$filename = $this->timestampedFileName( '._print.pdf' );
$this->outputPath = $filename;

// Fonts
Container::get( 'GlobalTypography' )->getFonts();

// CSS File
$css = $this->kneadCss();
$css_file = $this->createTmpFile();
file_put_contents( $css_file, $css );

// Save PDF as file in exports folder
$prince = new \PrinceXMLPhp\PrinceWrapper( PB_PRINCE_COMMAND );
$prince->setHTML( true );
$prince->setCompress( true );
if ( defined( 'WP_ENV' ) && WP_ENV === 'development' || WP_ENV === 'staging' ) {
$prince->setInsecure( true );
}
$prince->setOptions( '--pdf-profile=' . $this->pdfProfile . ' --pdf-output-intent=' . $this->pdfOutputIntent );
$prince->addStyleSheet( $css_file );
if ( $this->exportScriptPath ) {
$prince->addScript( $this->exportScriptPath );
}
$prince->setLog( $this->logfile );
$retval = $prince->convert_file_to_file( $this->url, $this->outputPath, $msg );

// Prince XML is very flexible. There could be errors but Prince will still render a PDF.
// We want to log those errors but we won't alert the user.
if ( count( $msg ) ) {
$this->logError( file_get_contents( $this->logfile ) );
}
protected function getPdfProfile() {
return 'PDF/X-1a:2003';
}

return $retval;
/**
* Return the desired PDF output intent.
*
* @return string
*/
protected function getPdfOutputIntent() {
return '/usr/lib/prince/icc/USWebCoatedSWOP.icc';
}

}
5 changes: 3 additions & 2 deletions inc/modules/export/xhtml/class-xhtml11.php
Expand Up @@ -8,6 +8,7 @@

use Pressbooks\Modules\Export\Export;
use Pressbooks\Sanitize;
use function Pressbooks\Sanitize\clean_filename;

class Xhtml11 extends Export {

Expand Down Expand Up @@ -195,12 +196,12 @@ function transform() {
echo '<title>' . get_bloginfo( 'name' ) . "</title>\n";

if ( ! empty( $_GET['style'] ) ) {
$url = \Pressbooks\Container::get( 'Sass' )->urlToUserGeneratedCss() . '/' . $_GET['style'] . '.css';
$url = \Pressbooks\Container::get( 'Sass' )->urlToUserGeneratedCss() . '/' . clean_filename( $_GET['style'] ) . '.css';
echo "<link rel='stylesheet' href='$url' type='text/css' />\n";
}

if ( ! empty( $_GET['script'] ) ) {
$url = $this->getExportScriptUrl( $_GET['script'] ) . '/script.js';
$url = $this->getExportScriptUrl( clean_filename( $_GET['script'] ) ) . '/script.js';
if ( $url ) {
echo "<script src='$url' type='text/javascript'></script>\n";
}
Expand Down
16 changes: 16 additions & 0 deletions inc/sanitize/namespace.php
Expand Up @@ -444,3 +444,19 @@ function allow_post_content() {

return;
}


/**
* Sanitizer for filename
*
* @param string $file
*
* @return string
*/
function clean_filename( $file ) {
// Remove anything which isn't a word, whitespace, number or any of the following caracters -_~,;[]().
$file = mb_ereg_replace( '([^\w\s\d\-_~,;\[\]\(\).])', '', $file );
// Remove any runs of periods
$file = mb_ereg_replace( '([\.]{2,})', '', $file );
return $file;
}
31 changes: 24 additions & 7 deletions symbionts/pressbooks-latex/automattic-latex-wpcom.php
@@ -1,10 +1,12 @@
<?php
/*
Version: 1.1
Copyright: Automattic, Inc.
License: GPL2+
*/

/**
*
* This plugin is forked from the original WP Latex (c) Sidney Markowitz, Automattic, Inc.
* It modifies the plugin to work with Pressbooks, strips unwanted features, adds others — activated at the network level
*
* @see https://github.com/wp-plugins/wp-latex
*/
class Automattic_Latex_WPCOM {
var $latex;
var $bg_hex;
Expand Down Expand Up @@ -44,7 +46,22 @@ function sanitize_hex( $color ) {
function wrapper( $wrapper = false ) {}

function url() {
$this->url = 'https://s.wordpress.com/latex.php?latex=' . rawurlencode( $this->latex ) . "&bg=$this->bg_hex&fg=$this->fg_hex&s=$this->size";

if ( ! empty( $_GET['pb-latex-zoom'] ) ) {
$this->zoom = (int) $_GET['pb-latex-zoom'];
}

$this->url = add_query_arg(
urlencode_deep( array(
'latex' => $this->latex,
'bg' => $this->bg_hex,
'fg' => $this->fg_hex,
's' => $this->size,
'zoom' => $this->zoom,
) ),
( is_ssl() ? 'https' : 'http' ) . '://s0.wp.com/latex.php'
);

return $this->url;
}
}
}
26 changes: 21 additions & 5 deletions symbionts/pressbooks-latex/pb-latex.php
Expand Up @@ -44,7 +44,8 @@ function init() {

add_action( 'wp_head', array( &$this, 'wpHead' ) );

add_filter( 'the_content', array( &$this, 'inlineToShortcode' ), 8 );
add_filter( 'the_content', array( &$this, 'inlineToShortcode' ), 7 ); // Before wptexturize()
add_filter( 'the_content', array( &$this, 'doThisShortcode' ), 8 ); // Before wpautop()

/**
* Add additional style/script/shortcode dependencies for a given latex renderer.
Expand Down Expand Up @@ -111,7 +112,9 @@ function shortCode( $_atts, $latex ) {
$latex = preg_replace( array( '#<br\s*/?>#i', '#</?p>#i' ), ' ', $latex );

$latex = str_replace(
array( '&lt;', '&gt;', '&quot;', '&#8220;', '&#8221;', '&#039;', '&#8125;', '&#8127;', '&#8217;', '&#038;', '&amp;', "\n", "\r", "\xa0", '&#8211;' ), array( '<', '>', '"', '``', "''", "'", "'", "'", "'", '&', '&', ' ', ' ', ' ', '-' ), $latex
array( '&lt;', '&gt;', '&quot;', '&#8220;', '&#8221;', '&#039;', '&#8125;', '&#8127;', '&#8217;', '&#038;', '&amp;', "\n", "\r", "\xa0", '&#8211;' ),
array( '<', '>', '"', '``', "''", "'", "'", "'", "'", '&', '&', ' ', ' ', ' ', '-' ),
$latex
);

$latex_object = $this->latex( $latex, $atts['background'], $atts['color'], $atts['size'] );
Expand Down Expand Up @@ -157,24 +160,37 @@ function inlineToShortcode( $content ) {
function inlineToShortcodeCallback( $matches ) {
$r = "{$matches[1]}[latex";

if ( preg_match( '/.+((?:&#038;|&amp;)s=(-?[0-4])).*/i', $matches[2], $s_matches ) ) {
if ( preg_match( '/.+((?:&#038;|&amp;|&)s=(-?[0-4])).*/i', $matches[2], $s_matches ) ) {
$r .= ' size="' . ( int ) $s_matches[2] . '"';
$matches[2] = str_replace( $s_matches[1], '', $matches[2] );
}

if ( preg_match( '/.+((?:&#038;|&amp;)fg=([0-9a-f]{6})).*/i', $matches[2], $fg_matches ) ) {
if ( preg_match( '/.+((?:&#038;|&amp;|&)fg=([0-9a-f]{6})).*/i', $matches[2], $fg_matches ) ) {
$r .= ' color="' . $fg_matches[2] . '"';
$matches[2] = str_replace( $fg_matches[1], '', $matches[2] );
}

if ( preg_match( '/.+((?:&#038;|&amp;)bg=([0-9a-f]{6})).*/i', $matches[2], $bg_matches ) ) {
if ( preg_match( '/.+((?:&#038;|&amp;|&)bg=([0-9a-f]{6})).*/i', $matches[2], $bg_matches ) ) {
$r .= ' background="' . $bg_matches[2] . '"';
$matches[2] = str_replace( $bg_matches[1], '', $matches[2] );
}

return "$r]{$matches[2]}[/latex]{$matches[3]}";
}

function doThisShortcode( $text ) {
$current_shortcodes = $GLOBALS['shortcode_tags'];
remove_all_shortcodes();

add_shortcode( 'latex', [ $this, 'shortCode' ] );

$text = do_shortcode( $text );

$GLOBALS['shortcode_tags'] = $current_shortcodes;

return $text;
}

}

if ( is_admin() ) {
Expand Down
15 changes: 15 additions & 0 deletions tests/test-sanitize.php
Expand Up @@ -233,4 +233,19 @@ public function test_allow_post_content() {
$this->assertTrue( $allowedposttags['h1']['xml:lang'] );
}

public function test_clean_filename() {

$file = '../../hacker.php';
$file = \Pressbooks\Sanitize\clean_filename( $file );
$this->assertEquals( $file, 'hacker.php' );

$file = '../../hacker.php;../../~more-hacks.php...';
$file = \Pressbooks\Sanitize\clean_filename( $file );
$this->assertEquals( $file, 'hacker.php;~more-hacks.php' );

$file = 'フランス語.txt'; // UTF-8
$file = \Pressbooks\Sanitize\clean_filename( $file );
$this->assertEquals( $file, 'フランス語.txt' );
}

}