Skip to content

Instantly share code, notes, and snippets.

@crankycoder
Forked from coryalder/blogpost.md
Created January 22, 2014 17:23

Revisions

  1. @coryalder coryalder revised this gist Aug 19, 2011. 1 changed file with 67 additions and 0 deletions.
    67 changes: 67 additions & 0 deletions safariparse_single_file.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,67 @@
    <?php

    // same as safariparse.php, except it outputs one big html file.
    // instead of putting each individual chapter in a separate html file.

    try
    {
    //create or open the database
    $database = new SQLite3('/Users/cory/Desktop/Safari.sqlite');
    if ($database) echo "Database connection open...\n";
    $booksQuery = 'SELECT * from ZBOOK where ZOFFLINESTATUS = "offline"';
    if($result = $database->query($booksQuery)) {
    echo "Found " . $result->numColumns() . " books stored offline\n";
    while($row = $result->fetchArray()) {
    echo "Saving book " . $row['ZTITLE'] . "\n";
    save_a_book($row['ZTITLE'], $row['Z_PK'], $database, $row['ZFPID']);
    }
    } else echo "Database failed to return results for query: " . $booksQuery;

    }
    catch(Exception $e)
    {
    die($error);
    }


    function save_a_book($name, $book_id, $database, $fpid) {
    $top = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><title>' . $name . '</title></head><body>';
    $bottom = '</body></html>';

    $query = 'SELECT ZHTMLBODY, Z_PK, ZORDERINDEX from ZPAGE where ZBOOK = "' . $book_id . '" ORDER BY ZORDERINDEX';
    if($result = $database->query($query)) {
    // make dir
    $myFile = "./" . sanitize($name, TRUE) . ".html";
    $fh = fopen($myFile, 'w') or die("can't open file ". $myFile);
    fwrite($fh, $top);
    mkdir_recursive(sanitize($name, TRUE));
    $counter = 1;
    while($row = $result->fetchArray()) {
    $stringData = $row['ZHTMLBODY'];
    fwrite($fh, $stringData);
    $counter++;
    print("Wrote page #: {$row['Z_PK']} to file {$myFile}\n");// . "Director: {$row['Director']} <br />" . "Year: {$row['Year']} <br /><br />");
    }
    fwrite($fh, $bottom);
    fclose($fh);
    mkdir_recursive(sanitize($name, TRUE) . "/images/" . $fpid);
    }
    }

    function mkdir_recursive($pathname)
    {
    is_dir(dirname($pathname)) || mkdir_recursive(dirname($pathname));
    return is_dir($pathname) || @mkdir($pathname);
    }


    function sanitize($string = '', $is_filename = FALSE)
    {
    // Replace all weird characters with dashes
    $string = preg_replace('/[^\w\-'. ($is_filename ? '~_\.' : ''). ']+/u', '-', $string);

    // Only allow one dash separator at a time (and make string lowercase)
    return mb_strtolower(preg_replace('/--+/u', '-', $string), 'UTF-8');
    }

    ?>
  2. @coryalder coryalder revised this gist Aug 17, 2011. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion safariparse.php
    Original file line number Diff line number Diff line change
    @@ -22,6 +22,9 @@


    function save_a_book($name, $book_id, $database, $fpid) {
    $top = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/></head><body>';
    $bottom = '</body></html>';

    $query = 'SELECT ZHTMLBODY, Z_PK, ZORDERINDEX from ZPAGE where ZBOOK = "' . $book_id . '" ORDER BY ZORDERINDEX';
    if($result = $database->query($query)) {
    // make dir
    @@ -30,7 +33,7 @@ function save_a_book($name, $book_id, $database, $fpid) {
    while($row = $result->fetchArray()) {
    $myFile = "./" . sanitize($name, TRUE) . "/pg_" . $counter . ".html";
    $fh = fopen($myFile, 'w') or die("can't open file ". $row['Z_PK']);
    $stringData = $row['ZHTMLBODY'];
    $stringData = $top . $row['ZHTMLBODY'] . $bottom;
    fwrite($fh, $stringData);
    fclose($fh);
    $counter++;
  3. @coryalder coryalder revised this gist Aug 17, 2011. 2 changed files with 2 additions and 1 deletion.
    2 changes: 2 additions & 0 deletions blogpost.md
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,7 @@
    *Save books out of Safari Books Online*

    From http://objectivesea.tumblr.com/post/9033067018/safaribooks

    This is hard. I spent way too much time figuring this out, because I was annoyed that a book I bought (Addison-Wesley) was available online for free, except only for 45 days after which payment was required. So I made this hack... probably useful to no one else, but here it is.

    Requirements:
    1 change: 0 additions & 1 deletion safariparse.php
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,5 @@
    <?php
    // code to accompany this blog post http://objectivesea.tumblr.com/post/9033067018/safaribooks
    // body of blog post is included in a separate file from this gist.
    try
    {
    //create or open the database
  4. @coryalder coryalder revised this gist Aug 17, 2011. 1 changed file with 29 additions and 0 deletions.
    29 changes: 29 additions & 0 deletions blogpost.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,29 @@
    *Save books out of Safari Books Online*

    This is hard. I spent way too much time figuring this out, because I was annoyed that a book I bought (Addison-Wesley) was available online for free, except only for 45 days after which payment was required. So I made this hack... probably useful to no one else, but here it is.

    Requirements:

    1. iPad.
    2. Safari To Go (the Safari Books Online iPad app).
    3. a Mac (could be done on a PC, but you'd have to tweak the php script).

    First, get Safari To Go on your iPad. Log in, and add all books you want to download to your "Offline Bookbag" (hint: tap the heart when viewing a book).

    Now go get [iPhone Explorer](http://www.macroplant.com/iphoneexplorer/). This allows you to pull files off your iPad.
    You'll need to grab the Safari.sqlite file from

    `/<your ipad>/Apps/Safari To Go/Documents/Safari.sqlite`

    You also need to grab the images for each individual book.
    They're in

    `/<your ipad>/Apps/Safari To Go/Documents/<some long number>-plain-folder/`

    Grab the folder called "images" for each book you're saving.

    Now download [this php script I wrote](https://gist.github.com/1151042), which extracts all the offline books from the "Safari.sqlite" file. Place it in the same folder, and run it from the terminal (hint: `cd ~/Desktop/` and then `php safariparse.php` will run it if it's on your desktop).

    You should now have a number of folders for each of the books you've extracted. Hooray. Now comes the manual step. You have to manually match up the image folder with the right html files. It's not too hard, as I've added a hint folder to each of the book folders. You should see something like `your-book-title/images/<some long number>`. Find the matching image folder from the iPhone Explorer step earlier, and place so graphics are at the path `your-book-name/images/<some long number>/graphics/01_01.jpg` where the html can find it.

    You now have an offline backup of any Safari Books Online book you own on your Mac. Win.
  5. @coryalder coryalder revised this gist Aug 17, 2011. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion safariparse.php
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,6 @@
    <?php

    // code to accompany this blog post http://objectivesea.tumblr.com/post/9033067018/safaribooks
    // body of blog post is included in a separate file from this gist.
    try
    {
    //create or open the database
  6. @coryalder coryalder created this gist Aug 17, 2011.
    59 changes: 59 additions & 0 deletions safariparse.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,59 @@
    <?php

    try
    {
    //create or open the database
    $database = new SQLite3('/Users/cory/Desktop/Safari.sqlite');
    if ($database) echo "Database connection open...\n";
    $booksQuery = 'SELECT * from ZBOOK where ZOFFLINESTATUS = "offline"';
    if($result = $database->query($booksQuery)) {
    echo "Found " . $result->numColumns() . " books stored offline\n";
    while($row = $result->fetchArray()) {
    echo "Saving book " . $row['ZTITLE'] . "\n";
    save_a_book($row['ZTITLE'], $row['Z_PK'], $database, $row['ZFPID']);
    }
    } else echo "Database failed to return results for query: " . $booksQuery;

    }
    catch(Exception $e)
    {
    die($error);
    }


    function save_a_book($name, $book_id, $database, $fpid) {
    $query = 'SELECT ZHTMLBODY, Z_PK, ZORDERINDEX from ZPAGE where ZBOOK = "' . $book_id . '" ORDER BY ZORDERINDEX';
    if($result = $database->query($query)) {
    // make dir
    mkdir_recursive(sanitize($name, TRUE));
    $counter = 1;
    while($row = $result->fetchArray()) {
    $myFile = "./" . sanitize($name, TRUE) . "/pg_" . $counter . ".html";
    $fh = fopen($myFile, 'w') or die("can't open file ". $row['Z_PK']);
    $stringData = $row['ZHTMLBODY'];
    fwrite($fh, $stringData);
    fclose($fh);
    $counter++;
    print("Wrote page #: {$row['Z_PK']} to file {$myFile}\n");// . "Director: {$row['Director']} <br />" . "Year: {$row['Year']} <br /><br />");
    }
    mkdir_recursive(sanitize($name, TRUE) . "/images/" . $fpid);
    }
    }

    function mkdir_recursive($pathname)
    {
    is_dir(dirname($pathname)) || mkdir_recursive(dirname($pathname));
    return is_dir($pathname) || @mkdir($pathname);
    }


    function sanitize($string = '', $is_filename = FALSE)
    {
    // Replace all weird characters with dashes
    $string = preg_replace('/[^\w\-'. ($is_filename ? '~_\.' : ''). ']+/u', '-', $string);

    // Only allow one dash separator at a time (and make string lowercase)
    return mb_strtolower(preg_replace('/--+/u', '-', $string), 'UTF-8');
    }

    ?>