odtPHP 1.0.1 Repair Document Warning Bug Solved alongwith Replacing tags in header/footer

Hello..

Recently I was working on odtPHP to generate OpenOffice.org  writer (.odt) file on the fly using PHP. I was using lastest version (1.0.1) of odtPHP. But I found a bug in software. Whenever I try to insert images in the document (specially in a segment), I was getting warning by OpenOffice (3.x) that the resultant file is corrupted and asks to repair document or not. Sometimes this warning can occur if your template is not correctly formated but I verified that this problem also exists with tutorial 5 present in odtPHP package (tested on Ubuntu 10.04 with OpenOffice 3.2).  Although the document repaired by OpenOffice is perfectly fine, but it seems unusual and awkward to people. Also this bug seems to me as a big stone in a smooth path as I can’t be able to convert odt to pdf on the fly using any available tools. The reason is that as the resultant file is corrupted all available tools fail to load/open the document. As said by some great personality “Necessity is the Mother of Invention”, I tried to solve the problem and got success. Below is the reason of problem and solution:

Reason of Problem (bug):-

As I tested the odtPHP software with OpenOffice 3.x, I found that OpenOffice  keeps the record of all files present in .odt archieve file in the manifest.xml file present under META-INF directory. You can open OpenOffice .odt file with any archive manager to see files present under the document. You must find the above said file there.

Now the problem with odtPHP 1.0 is that it only modifies content.xml file and does not edit manifest.xml file. So, when your odt document (generated by odtPHP) contains images, it means you are increasing the number of files in the archive without informing the OpenOffice about their type, path etc. in the manifest.xml file. This has resulted to the corrupted document warning upon opening the file.

Solution of above Bug:-

I have modified odf.php and Segment.php files (present in the library directory of odtPHP package) so that they also modify manifest.xml file to add information about images. You can download these files as zip package from the following link-:

https://docs.google.com/leaf?id=0B0BfaiUk95FTNTJiODk1MTEtYjc4OS00Y2RiLTgyNTktZDE0YTA5OTdlMWZh&hl=en&authkey=CMXv9NgN

Download odtPHP-1.0.1 from odtPHP official website-:

http://www.odtphp.com/

Extract the zip archive and replace the original files (in the library directory) with these files. Now try again the tutorial 5 present in tests directory of odtPHP, you will find that now OpenOffice opens the downloaded file without any warning. If still you are getting corrupt file warning, feel free to ask me.

Replacing tags in header/footer:-

Also, odtPHP version (1.0.1) does not support replacing tags in header or footer sections of document. It requires the editing of styles.xml file of OO template. So, recently I modified odf.php file so that it also replaces tags with text in header or footer sections odt document just it does for body section of the document. Also, now images information is added in manifest.xml file according to extension of image (for compatibility with future releases of OO). 🙂

Have Fun..!!

47 thoughts on “odtPHP 1.0.1 Repair Document Warning Bug Solved alongwith Replacing tags in header/footer

  1. Thanks for the solution!

    BTW, shouldn’t you check for the mimetype for the manifest:media-type attribute for the full compatibility? Now you hardcoded image/jpeg value.

    • Yes, you are right. But upto now, Openoffice (OO) does not warns about image type. So, you can use any image format without getting warning. Even you can mention only manifest:media-type=”image” (without any sub-type), OO will happily accept files 🙂 without giving warning (tested with OO 3.2).
      As this may become an issue for the future releases of OO, so I will correct source files as soon as possible.

      Thanks for pointing out my mistake !!

  2. Hey Vikas,

    Glad you were able to patch it to fix the header/footer limitation. But I can’t seem to download your patched version from the link above. The link seems to be broken.

    Thanks.

    • Hi Kato,
      Link was working fine for me. Just click on it and it will open in another tab from where you can download the zip file. Anyways, I edited it to new one. Are you now able to download zip file? Please reply.

  3. By the way, a bit off-topic, but would you know of an easy way to convert ODT files to PDF programmatically using PHP? I wanted to generate not just ODT documents but also PDF versions of them. I’ve looked into several options, but they all required setting up Open Office as a service, plus Apache Tomcat, plus Java on the server. I’m hoping there’s a easier way…

    • Hello Kato,
      I too was unable to find a tool that converts odt to pdf without using openoffice but there are lot of tools such as JODconvertor, PyODconvertor etc. which can convert odt to pdf by using openoffice in headless mode and I am using JODconvertor for this task. For that, I customised the odf.php to convert odt to pdf in linux environment. You just need to setup once and that is not a much big task 🙂

      • Hi Vikas,

        Would you have a guide or brief description of the steps for setting up JODconverter?

        Thanks again! 🙂

      • Hi Kato, 🙂

        For setting up JODconverter in Linux environment, follow steps given below:-

        1. Install JODconverter. In ubuntu you can you this command to install it:
        # apt-get install jodconverter

        2. Download zip file from this link:
        https://docs.google.com/leaf?id=0B0BfaiUk95FTNWVlYjIzNDEtYTgxOS00ODI2LWJkYjQtNDUwM2RlMGIyYjU4&hl=en&authkey=CJim6tkK

        3. Use odf.php file given in the zip package. I have defined a new function exportAsAttachedPDF() in this file.

        4. Copy odt2pdf.sh file in the same directory in which your php script is placed (Eg- tests directory in original odtphp package) and give execute permission to odt2pdf.sh file.

        5. Use the following line of php code in your script to export the file as pdf:-
        $odf->exportAsAttachedPDF();
        or
        $odf->exportAsAttachedPDF("desired_filename");

        Give desired_filename without any extension.

        NOTE: In order to get this procedure working your webserver user (which is www-data by default in ubuntu) should have write access to its Directory (which is /var/www for www-data user). To ensure this, make www-data owner of /var/www and all sub directories with the following command:
        # chown -R www-data:www-data /var/www

        Are you able to get this procedure working?

      • Hello Vikas Mahajan,
        can you advise me, how to add headers and footers from HTML to PDF file creation using jodconverter.
        $output_file_nm=’invoicetr2.pdf’;
        echo $target_file=’temptest.html’;
        system(“/usr/java/latest/bin/java -jar /usr/local/bin/jodconverter $target_file $output_file_nm”);

        thanks in advance

      • Hello Vikas Mahajan,
        Thanks for your replay,
        HTML is correctly rendered in and cresting the PDF file is fine,mainly footer aligned problem ,please help me aligned the fotter at bootom in pdf file, my html code.

        My Source

        .top1{
        width:100%;
        margin:top;
        background-color:#0079F2;
        text-align:center;
        color:white;
        }
        .buttom1{
        width:100%;
        height:auto;
        bottom:0px;
        background-color:#005B5B;
        text-align:center;
        position:absolute;
        color:white;
        }

        Header : My Source

        I was using lastest version (1.0.1) of odtPHP. But I found a bug in software. Whenever I try to insert images in the document (specially in a segment), I was getting warning by OpenOffice (3.x) that the resultant file is corrupted and asks to repair document or not. Sometimes this warning can occur if your template is not correctly formated but I verified that this problem also exists with tutorial 5 present in odtPHP package (tested on Ubuntu 10.04 with OpenOffice 3.2). Although the document repaired by OpenOffice is perfectly fine, but it seems unusual and awkward to people. Also this bug seems to me as a big stone in a smooth path as I can’t be able to convert odt to pdf on the fly using any available tools. The reason is that as the resultant file is corrupted all available tools fail to load/open the document. As said by some great personality “Necessity is the Mother of Invention”, I tried to solve the problem and got success. Below is the reason of problem and solution:

        Footer : @My Source

        thanks in advance again,
        Madhu.

  4. Hi Vikas,

    Thanks for enumerating the steps. Unfortunately, I’m working with a Windows server. I may have to experiment with JODconverter based on your guide for a Linux environment.

  5. Thank you very much for sharing.
    I just hope odtphp maintainers will include your patch into the library.

    I would like to say that if exportAsAttachedFile() returns a corrupted document but saveToFile() don’t, it can be that the web page is somehow outputting some data along with the odt file, for example as part of a semi-automatic framework behaviour.
    This is, at least, what happened to me using cakephp.
    I had to
    explicity turn off debug messages
    Configure::write(‘debug’, ‘0’);
    and then
    $this->autoLayout = false;
    $this->autoRender = false;

    Hope this helps someone too!
    Bye
    marco

    • Thanks a lot for your appreciation.
      Yes, you are right. We may get corrupted documents when web page sends additional data (warning messages, error messages, other headers etc.) with our attachment. So, we need need to take care of this thing too. Thanks for giving your solution and notifying others about this problem 🙂

  6. There’s also a locale-aware bug.
    If a comma is used instead of a dot as a floating value separator, the wrong size value is inserted in XML, i.e.:
    svg:width=”10,5cm” instead of svg:width=”10.5cm”

    To fix this issue you have to add these lines in odf.php and Segment.php after calculating width and height values:
    $width = sprintf(“%F”, $width);
    $height = sprintf(“%F”, $height);
    These lines change $width and $height values into non-local aware float values as strings.

  7. Hi Vikas,
    many thanks for your job.

    I’m trying to download the file from the link on Google but it doesn’t work.

    I have the same problem that you have solved opening the files with MS Word 2007. Not just when there are the images inside but with all the files. Do you know something about that?

    Ciao,
    Nicola.

    • HI Nicola,

      I edited sharing settings of google docs link, now retry to download the file.
      Are you using some add-on/plugin to open odt files in MS word?
      Try opening same files using OpenOffice and see whether you are facing problem or not. If the error is only with MS Word then that is plugin specific error.

  8. Pingback: Alfredo Braga | Crie PDF com odtPHP

  9. Thank You!
    However I still got the warning whene I call the function exportAsAttachedFile using the library in codeigniter.
    I solved by adding this line
    header(“Content-Length: ” . filesize($this->tmpfile));
    just before the readfile call (line 319 of odf class).
    I hope it will be useful for someone else 😉

  10. Thanks for hard work.
    I have a question if i want use conditional statement for example.
    {abc}
    This paragraph will display if tag abc has some value.This paragraph will display if tag abc has some value.This paragraph will display if tag abc has some value.This paragraph will display if tag abc has some value.
    {/abc}

    I know it is irrelevant but please help me how i can do with library.

    Thanks for your participation.

    • Hi,

      I am not able to fully understand what you actually want to do? What is “abc” in your context? Is it a keyword you want to define like if-else or is it a variable in template to be replaced with actual text later?
      Also, why you want to use conditional statement in template? You can make different templates and can choose one based on conditional statement in code.

      Thanks,
      Vikas

      • Thanks for your reply. Here is my scenario.

        MS Word/Open Office File Content:

        {abc}
        This paragraph will display if tag abc has some value.This paragraph will display if tag abc has some value.This paragraph will display if tag abc has some value.This paragraph will display if tag abc has some value.
        {/abc}

        If i parse the above content then i need to write the above paragraph in generated document if abc variable have some value or if abc variable does not have any value then above paragraph must not be write in generated document.

        Let me know if still confusion.

        Thanks,
        Tanveer Hussain

    • I have implemented the conditionals in ODT-PHP.

      I’ve pasted my odf.php here: http://pastebin.com/cM6bVWzg

      There is a new method setConditional(string $key, bool $value), private class variable $conditionals and reimplemented _parse().

      = Usage =

      In ODT file:
      [!– IF MYKEY –] Some text [!– ENDIF MYKEY –]

      In some cases these conditionals might generate malformed ODT XML (it does not parse XML, but performs a dumb text replace), so beware not to mix styles, paragraphs etc. in the conditional section.

      In PHP:
      $shouldSomeTextBePrinted = true;
      $odf = new Odf;
      $odf->setConditional(‘MYKEY’, $shouldSomeTextBePrinted);

      = CAUTION! =

      This odf.php might be incompatible with the latest ODT-PHP version, since I implimplemented method setStyleVars(), which is used to set text in header/footer. This feature should be also implemented in ODT-PHP 1.0.1.
      So use it at your own risk 🙂

  11. Hello:

    Thank you for your excellent contribution. I propose the following addition:

    /**
    * …. size in centimeters as arguments ….
    */
    public function setImage($key, $value, $width = 0, $height = 0) {
    $filename = strtok(strrchr($value, ‘/’), ‘/.’);
    $file = substr(strrchr($value, ‘/’), 1);
    $size = @getimagesize($value);
    if ($size === false) {
    throw new OdfException(“Invalid image”);
    }
    if (($width == 0) && ($height == 0)) {
    list ($width, $height) = $size;
    $width *= Odf::PIXEL_TO_CM;
    $height *= Odf::PIXEL_TO_CM;
    }
    $xml = ………………

    Saludos

Leave a reply to joshas Cancel reply