Report abuse

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<?php
// lib/Asciidoc.php

/**
 * Supplies functions that convert Asciidoc source text into HTML or PDF output.
 */
class Asciidoc
{
    /**
     * Converts Asciidoc source text into HTML output.
     *
     * @param string $source_text Asciidoc source text.
     */
    public static function convert_to_html($source_text)
    {
        return self::run_asciidoc($source_text);
    }

    /**
     * Converts Asciidoc source text into HTML output.
     *
     * @param string $source_text Asciidoc source text.
     */
    public static function convert_to_pdf($source_text)
    {
        return self::run_a2x($source_text);
    }

    /**
     * Runs the 'asciidoc' executable. Returns the resulting HTML as a string.
     *
     * @param string $source_text Asciidoc source text.
     */
    private static function run_asciidoc($source_text)
    {
        $result =
            self::run_shell_command(
                self::get_home_dir() . '/bin/asciidoc',
                array(
                    '--out-file=-',
                    '-',
                    self::SHELL_MULTILINE_TEXT_START
                        . self::SHELL_NEWLINE
                        . addslashes($source_text)
                        . self::SHELL_NEWLINE
                        . self::SHELL_MULTILINE_TEXT_END
                        . self::SHELL_NEWLINE,
                ));

        return $result;
    }

    /**
     * Runs the 'a2x' executable. Returns the resulting PDF as binary data.
     *
     * @param string $source_text Asciidoc source text.
     */
    private static function run_a2x($source_text)
    {
        $base_temp_file_path = tempnam(sys_get_temp_dir(), 'a2x');

        $temp_input_file_path = $base_temp_file_path . '.txt';
        $temp_output_file_path = $base_temp_file_path . '.pdf';

        file_put_contents($temp_input_file_path, $source_text);

        self::run_shell_command(
            self::get_home_dir() . '/bin/a2x',
            array(
                '--no-xmllint',
                '--format=pdf',
                '--conf-file='
                    . escapeshellarg(
                        self::get_home_dir() . '/.asciidoc/a2x.conf'),
                '--destination-dir='
                    . escapeshellarg(dirname($temp_output_file_path)),
                escapeshellarg($temp_input_file_path),
            ));

        return file_get_contents($temp_output_file_path);
    }

    /**
     * Runs a shell command.
     *
     * @param string $executable_path Path to the executable.
     * @param array $arguments
     *     Command-line arguments to pass to the executable.
     */
    private static function run_shell_command(
        $executable_path,
        array $arguments=array())
    {
        $command =
            escapeshellcmd($executable_path)
                . self::SHELL_ARGUMENT_SEPARATOR
                . implode(
                    self::SHELL_ARGUMENT_SEPARATOR,
                    $arguments);

        return system($command);
    }

    /**
     * Gets the current user's home directory.
     */
    private static function get_home_dir()
    {
        $process_user = posix_getpwuid(posix_geteuid());

        $result = '/home/' . $process_user['name'];

        return $result;
    }

    /**
     * Separator placed between command arguments, in the OS shell.
     */
    const SHELL_ARGUMENT_SEPARATOR = ' ';

    /**
     * Delimiter for the start of a multiline block of text, in the OS shell.
     */
    const SHELL_MULTILINE_TEXT_START = '<<EOF';

    /**
     * Delimiter for the end of a multiline block of text, in the OS shell.
     */
    const SHELL_MULTILINE_TEXT_END = 'EOF';

    /**
     * Newline, in the OS shell.
     *
     * Double quotes are necessary for an unescaped newline.
     * Single quotes result in an esacaped newline (backslash followed by the letter 'n').
     */
    const SHELL_NEWLINE = "\n";
}

?>