'; echo '

'.__('Use ZappoMan\'s Improved WordPress Importer').'

'; } /********************************************************************************** * fuction: store_internal_comment_links() * * description: This function will scan the comment_content and look for links. * These links are stored for future processing. There is an important * special case of $has_internal_pingback, which should be set to * true by the caller if we want to store a "internal_pingback" tag * for this comment. The idea behind this parameter is that if the * comment_author_url looks like it's from the blogs author or from * a pingback from an internal blog url, then we will want to do the URL * replacement on the comment author also (assuming that pingback url * is imported). */ function store_internal_comment_links($comment_id,$comment_content,$has_internal_pingback) { //echo "store_internal_comment_links\n
"; if (!isset($this->comment_links)) $this->comment_links = Array(); $urlpreg = "/(src|href|link)=(\"|'|\\\\\"|\\\\')(.*?)(\"|'|\\\\\"|\\\\')/i"; preg_match_all(trim($urlpreg), $comment_content, $out, PREG_PATTERN_ORDER); $values = $out[3]; //echo "values--->"; print_r($values); echo "\n
"; if ($has_internal_pingback) { //echo "adding internal_pingback\n
"; $values[] = 'internal_pingback'; } if (count($values) > 0) { //echo "comment_links[$comment_id] = values--->"; print_r($values); echo "\n
"; $this->comment_links[$comment_id] = $values; } } /********************************************************************************** * fuction: store_internal_post_links() * description: This function will scan the post_content and look for links. * These links are stored for future processing. */ function store_internal_post_links($post_id,$post_content) { //echo "store_internal_post_links\n
"; if (!isset($this->post_links)) $this->post_links = Array(); $urlpreg = "/(src|href|link)=(\"|'|\\\\\"|\\\\')(.*?)(\"|'|\\\\\"|\\\\')/i"; preg_match_all(trim($urlpreg), $post_content, $out, PREG_PATTERN_ORDER); $values = $out[3]; if (count($values) > 0) { //echo "post_links[$post_id] = values--->"; print_r($values); echo "\n
"; $this->post_links[$post_id] = $values; } } /********************************************************************************** * fuction: report_links_mappings() * description: Isn't it clear? */ function report_links_mappings() { echo "Internal Links old to new:
"; } /********************************************************************************** * fuction: process_internal_post_links() * description: This function handles the process of replacing mapped links in * post content. It should be run after all the posts have been * imported so that backward links (like pingbacks) or edits get * handled properly. */ function process_internal_post_links() { global $wpdb; if (!isset($this->post_links)) return; foreach ($this->post_links as $post_id => $url_list) { echo "Links in post:$post_id
"; if (isset($post_content)) { //echo "UPDATE-ing posts database table
"; $post_content = $wpdb->escape($post_content); $wpdb->query( "UPDATE $wpdb->posts SET post_content = '$post_content' WHERE ID = '$post_id'" ); } unset($post_content); } } /********************************************************************************** * fuction: process_internal_comment_links() * description: This function handles the process of replacing mapped links in * comment content. It should be run after all the posts have been * imported so that backward links get handled properly. */ function process_internal_comment_links() { global $wpdb; if (!isset($this->comment_links)) return; foreach ($this->comment_links as $comment_id => $url_list) { echo "Links in comment:$comment_id
"; if (isset($comment_content)) { //echo "UPDATE-ing comments database table
"; $comment_content = $wpdb->escape($comment_content); $wpdb->query( "UPDATE $wpdb->comments SET comment_content = '$comment_content' WHERE comment_ID = '$comment_id'" ); } unset($comment_content); } } /********************************************************************************** * fuction: footer() * description: Isn't it clear? */ function footer() { echo ''; } /********************************************************************************** * fuction: unhtmlentities() * description: From php.net for < 4.3 compat */ function unhtmlentities($string) { $trans_tbl = get_html_translation_table(HTML_ENTITIES); $trans_tbl = array_flip($trans_tbl); return strtr($string, $trans_tbl); } /********************************************************************************** * fuction: greet() * description: Isn't it clear? */ function greet() { echo '
'; echo '

'.__('Upload your WordPress eXtended RSS (WXR) file and we’ll import your blog.').'

'; echo '

'.__('This will import posts, comments, custom fields, pages, and categories from a WordPress export file. Will also fixup internal links, pingbacks, and image references. And as if that wasn\'t enough, it also skips comments marked as spam and fetches and imports image attachements.').'

'; echo '

'.__('Choose a WordPress WXR file to upload, then click Upload file and import.').'

'; wp_import_upload_form("admin.php?import=zappo_wordpress&step=1"); echo '
'; } /********************************************************************************** * fuction: get_tag() * description: Isn't it clear? */ function get_tag( $string, $tag ) { preg_match("|<$tag.*?>(.*?)|is", $string, $return); $return = addslashes( trim( $return[1] ) ); return $return; } /********************************************************************************** * fuction: users_form() * description: This will display a list of the blog users to allow you to do * author remapping. If there are multiple "authors" in your imported * blog, this little form will be displayed for each author. */ function users_form($n) { global $wpdb; $users = get_users_of_blog($wpdb->blogid); ?> ) and category () * lists and stores them in our object. */ function get_entries() { set_magic_quotes_runtime(0); $importdata = file($this->file); // Read the file into an array $importdata = implode('', $importdata); // squish it $importdata = preg_replace("/(\r\n|\n|\r)/", "\n", $importdata); //This will pull out the original root link, so we can do internal link replacement. //..... ??? This one probably gets multiple objects>>>> preg_match_all('|(.*?)|is', $importdata, $this->posts); $this->original_link = $this->get_tag( $importdata, 'link' ); $this->new_link = get_bloginfo('url'); echo "Original base URL:$this->original_link
"; echo "New base URL:$this->new_link
"; /* * Store our base url in the mapping array, this will handle references to ourselves * particularly in comments on our own blog. */ if (!isset($this->old_guid_to_new_guid)) $this->old_guid_to_new_guid = Array(); $this->old_guid_to_new_guid[$this->original_link] = $this->new_link; $this->old_guid_to_new_guid[trailingslashit($this->original_link)] = trailingslashit($this->new_link); preg_match_all('|(.*?)|is', $importdata, $this->posts); $this->posts = $this->posts[1]; preg_match_all('|(.*?)|is', $importdata, $this->categories); $this->categories = $this->categories[1]; } /********************************************************************************** * fuction: get_old_authors() * description: This scans the posts list (previously loaded) and creates a list of * authors from our imported file. */ function get_old_authors() { $temp = array (); $i = -1; foreach ($this->posts as $post) { if ('' != trim($post)) { ++ $i; $author = $this->get_tag( $post, 'dc:creator' ); array_push($temp, "$author"); //store the extracted author names in a temporary array } } // We need to find unique values of author names, while preserving the order, so this function emulates the unique_value(); php function, without the sorting. $authors[0] = array_shift($temp); $y = count($temp) + 1; for ($x = 1; $x < $y; $x ++) { $next = array_shift($temp); if (!(in_array($next, $authors))) array_push($authors, "$next"); } return $authors; } /********************************************************************************** * fuction: get_authors_from_post() * description: helps handle the authors mapping */ function get_authors_from_post() { $formnames = array (); $selectnames = array (); foreach ($_POST['user'] as $key => $line) { $newname = trim(stripslashes($line)); if ($newname == '') $newname = 'left_blank'; //passing author names from step 1 to step 2 is accomplished by using POST. left_blank denotes an empty entry in the form. array_push($formnames, "$newname"); } // $formnames is the array with the form entered names foreach ($_POST['userselect'] as $user => $key) { $selected = trim(stripslashes($key)); array_push($selectnames, "$selected"); } $count = count($formnames); for ($i = 0; $i < $count; $i ++) { if ($selectnames[$i] != '#NONE#') { //if no name was selected from the select menu, use the name entered in the form array_push($this->newauthornames, "$selectnames[$i]"); } else { array_push($this->newauthornames, "$formnames[$i]"); } } } /********************************************************************************** * fuction: show_authors_form() * description: helps handle the authors mapping, shows a form to * allow you to set how post authors should be mapped. */ function show_authors_form() { ?>

get_old_authors(); echo '
    '; echo '
    '; $j = -1; foreach ($authors as $author) { ++ $j; echo '
  1. '.__('Current author:').' '.$author.'
    '.'Map to existing: '; $this->users_form($j); echo '
  2. '; } echo ''.'
    '; echo '
    '; echo '
'; } /********************************************************************************** * fuction: select_authors() * description: helps handle the authors mapping, uploads the file, and * shows a form to allow you to set how post authors should be mapped. */ function select_authors() { $file = wp_import_handle_upload(); if ( isset($file['error']) ) { $this->header(); echo '

'.__('Sorry, there has been an error.').'

'; echo '

' . $file['error'] . '

'; $this->footer(); return; } $this->file = $file['file']; $this->id = (int) $file['id']; $this->get_entries(); $this->show_authors_form(); } /********************************************************************************** * fuction: process_categories() * description: imports categories, what more is there to say? */ function process_categories() { global $wpdb; $cat_names = (array) $wpdb->get_col("SELECT cat_name FROM $wpdb->categories"); while ( $c = array_shift($this->categories) ) { $cat_name = trim(str_replace(array (''), '', $this->get_tag( $c, 'wp:cat_name' ))); // If the category exists we leave it alone if ( in_array($cat_name, $cat_names) ) continue; $category_nicename = $this->get_tag( $c, 'wp:category_nicename' ); $posts_private = (int) $this->get_tag( $c, 'wp:posts_private' ); $links_private = (int) $this->get_tag( $c, 'wp:links_private' ); $parent = $this->get_tag( $c, 'wp:category_parent' ); if ( empty($parent) ) $category_parent = '0'; else $category_parent = category_exists($parent); $catarr = compact('category_nicename', 'category_parent', 'posts_private', 'links_private', 'posts_private', 'cat_name'); $cat_ID = wp_insert_category($catarr); } } /********************************************************************************** * fuction: handle_attachment_post_type() * description: helper that does most of the work of processing attachment types * * Basically attachements get special treatment. Namely we attempt to download * and store the resource on our server. And we will also call a modified version * of the WordPress insert_attachment() process so that we get files put in the * right upload location. This also handles making thumbnails, and it's an already * good time! * * Thumbnails don't get their own items, so we want to check for * thumbnail name in the meta data and add it to our URL mappings. We don't * have to reimport or download the thumbnail image because we'll create our * own when we "insert" the attachment. * * returns: $post_id (-1 on failure) */ function handle_attachment_post_type ( $post_title , $post_date , $post_date_gmt , $comment_status, $ping_status , $post_status , $post_parent , $post_type , $guid , $link , $post_author , $categories , &$postmeta ) { printf(__('

Post %s is an attachment we want to download it from %s

'), stripslashes($post_title),$guid); /* * Create our little Http client to download our attachments. These files * are going to be downloaded form the old blog's server to our server. So * no download is required to the client's actual machine. Also note that * this means we have to go through a modified version of the wp_insert_attachment * process that doesn't assume the files were "uploaded" to the server using php * upload. */ $client = new zappo_HttpClient(); $client->setGetUrl($guid); /* * enable this if you want to see the details of the fetching process. */ //$client->setDebug(true); if (!$client->doRequest()) { echo "

Sorry, I tried and failed to download this image.

"; } else { /* * Cool, we successfully downloaded the file and now have contents. */ $attachmentContents = $client->getContent(); $filename_stub = basename($client->path); echo "

Looks like I was able to download $filename_stub.

"; /* * We will now save a temporary file on the server with a stub name * of the file's base name from our downloaded URL. */ $tmpfname = tempnam("/tmp", $filename_stub); $handle = fopen($tmpfname, "w"); fwrite($handle, $attachmentContents); fclose($handle); /* * Construct the attachment array which is closely related to what * an wordpress attachment array would have looked like had this * file been uploaded by the user. */ $attachment = array( 'post_category_names' => $categories, 'post_parent' => $post_parent, 'post_title' => $post_title ? $post_title : $filename_stub, 'post_type' => 'attachment', 'post_mime_type' => $client->headers['content-type'], 'post_date' => $post_date ); /* * Construct the file array which is closely related to what * php's uploaded file array would have looked like had this * file been uploaded by the user. */ $file = Array ( 'name' => $filename_stub, 'tmp_name' => $tmpfname, 'size' => $client->headers['content-length'] ); /* * Call our modified version of insert_attachment. */ $post_id = zappo_insert_attachment($file,$attachment); if ($post_id != -1) { /* * We want to store the old URL and new URL into our mappings array. This * works on all types of posts: attachment, posts, and pages. Using get_the_guid() * would fail for attachments and pages. */ global $wpdb; /* * This will retrieve the new meta-date for the newly inserted attachment. */ $new_attachment_metadata = get_post_meta( $post_id, '_wp_attachment_metadata', true ); $new_thumb = $new_attachment_metadata['thumb']; /* * Get the new guid from the DB, and replace the filename stub with the thumb stub. */ $new_attach_url = $wpdb->get_var("SELECT guid FROM $wpdb->posts WHERE ID = '$post_id'"); $new_thumb_url = str_replace(basename($new_attach_url), $new_thumb, $new_attach_url); //echo "new_thumb= $new_thumb
"; //echo "new_thumb_url= $new_thumb_url
"; /* * The old attach url is our guid so we can add the main attachment mapping */ $old_attach_url = $guid; $this->old_guid_to_new_guid[$old_attach_url] = $new_attach_url; //echo "OLD ATTACHMENT URL=$old_attach_url
new attachment url=$new_attach_url\n
"; /* * Now, to deal with the old thumb. First of all, look in the import "metadata" to see * if there was a thumb filename listed. To do that we need to get the serialized meta data * unserialize it and make sure everythings cool. */ $old_metadata_serialized = $postmeta['_wp_attachment_metadata']; if (isset($old_metadata_serialized)) { $old_metadata = unserialize($old_metadata_serialized); if ($old_metadata !== false) { $old_thumb = $old_metadata['thumb']; if (isset($old_thumb)) { $old_thumb_url = str_replace($filename_stub, $old_thumb, $old_attach_url); /* * phew... after all that work we finally have a mapping of the old thumb * url to a new thumb url. Add it to our link map! */ $this->old_guid_to_new_guid[$old_thumb_url] = $new_thumb_url; //echo "old_thumb= $old_thumb
"; //echo "OLD THUMB URL=$old_thumb_url
new thumb url=$new_thumb_url\n
"; } } } } /* * Some house keeping... unlink our temp file so that * it will be deleted. * * AND: This is important, remove the '_wp_attached_file' * and '_wp_attachment_metadata' keys from our $postmeta[] * array so that we don't add those metavalues overtop of * the ones set during the insert_attachment() process. */ unlink($tmpfname); unset($postmeta['_wp_attached_file']); unset($postmeta['_wp_attachment_metadata']); } return $post_id; } /********************************************************************************** * fuction: process_posts() * description: This is the main engine of the import process. It does the bulk * of the work to parse the XML and import posts. */ function process_posts() { global $wpdb; $i = -1; echo '
    '; /* * Get ready to store some guid mappings */ if (!isset($this->old_guid_to_new_guid)) $this->old_guid_to_new_guid = Array(); /* * Related to giving ourselves extra time to process each * post, we want to remember this value for after the loop */ $ini_val_max_execution_time = ini_get('max_execution_time'); foreach ($this->posts as $post) { /* * We want to give ourselves a lot of time to complete each post. */ set_time_limit(60); /* * Get the title/date details from the import file. These will identify * our posts until we have a new post_id. */ $post_title = $this->get_tag( $post, 'title' ); $post_date = $this->get_tag( $post, 'wp:post_date' ); /* * So this checks if a post with that title and date already exists. We assume * that this is an error if this happens and we don't import that post or any * of it's comments. */ if ($post_id = post_exists($post_title, '', $post_date)) { printf(__('

    Post %s already exists.

    '), stripslashes($post_title)); } else { /* * Alright, now we know we have a new post. We will read out most of the * important information from the xml file and begine processing. */ $post_date_gmt = $this->get_tag( $post, 'wp:post_date_gmt' ); $comment_status = $this->get_tag( $post, 'wp:comment_status' ); $ping_status = $this->get_tag( $post, 'wp:ping_status' ); $post_status = $this->get_tag( $post, 'wp:status' ); $post_parent = $this->get_tag( $post, 'wp:post_parent' ); $post_type = $this->get_tag( $post, 'wp:post_type' ); $guid = $this->get_tag( $post, 'guid' ); $link = $this->get_tag( $post, 'link' ); $post_author = $this->get_tag( $post, 'dc:creator' ); /* * All post types can have categories, so do this processing here. */ preg_match_all('|(.*?)|is', $post, $categories); $categories = $categories[1]; $cat_index = 0; foreach ($categories as $category) { $categories[$cat_index] = $wpdb->escape($this->unhtmlentities(str_replace(array (''), '', $category))); $cat_index++; } /* * All post types can theoretically have meta data so do this processing here */ preg_match_all('|(.*?)|is', $post, $temp_postmeta); $temp_postmeta = $temp_postmeta[1]; if ($temp_postmeta) { foreach ($temp_postmeta as $p) { $key = $this->get_tag( $p, 'wp:meta_key' ); $value = $this->get_tag( $p, 'wp:meta_value' ); // The get_tag calls addslashes() and we don't really want that. $postmeta[$key] = stripslashes($value); /* Can't quite add post_meta yet! We need the new post_id * to pull that off, but we want to collect our post meta * data and also check to see if this is an orphined * attachment. * * Later we'll call: add_post_meta( $post_id, $key, $value ); */ } /* * This addresses an issue where sometimes attachments get * marked as normal posts and orphaned. If there's an attached * file then we will restamp this post as an attachment. */ if (!empty($postmeta['_wp_attached_file'])) { $post_type = 'attachment'; } } /* * If we're in verbose mode, then dump all the post attributes. */ echo '
  1. '; echo "Post Attributes:
      "; echo "
    • post_title :$post_title
    • "; echo "
    • post_date :$post_date
    • "; echo "
    • post_date_gmt :$post_date_gmt
    • "; echo "
    • comment_status :$comment_status
    • "; echo "
    • ping_status :$ping_status
    • "; echo "
    • post_status :$post_status
    • "; echo "
    • post_parent :$post_parent
    • "; echo "
    • post_type :$post_type
    • "; echo "
    • guid :$guid
    • "; echo "
    • link :$link
    • "; echo "
    • post_author :$post_author
    • "; echo "
    • categories:"; foreach ($categories as $category) { echo "$category "; } echo "
    • "; if (isset($postmeta)) { echo "
    • metadata:
        "; foreach ($postmeta as $key => $value) { echo "
      • $key = $value
      • "; } echo "
    • "; } echo "
    "; /* * Ok, here's where we are going to handle some post_type specific processing. */ if ($post_type == 'attachment') { $post_id = $this->handle_attachment_post_type ( $post_title , $post_date , $post_date_gmt , $comment_status, $ping_status , $post_status , $post_parent , $post_type , $guid , $link , $post_author , $categories , $postmeta ); } /* * Ready to process normal posts and pages, which we can handle the same. * This mostly involves doing a little cleanup on the content and calling * the normal wp_insert_post() method. */ else { printf(__('

    Importing post %s...'), stripslashes($post_title)); echo "

      "; $post_content = $this->get_tag( $post, 'content:encoded' ); $post_content = str_replace(array (''), '', $post_content); $post_content = preg_replace('|<(/?[A-Z]+)|e', "'<' . strtolower('$1')", $post_content); $post_content = str_replace('
      ', '
      ', $post_content); $post_content = str_replace('
      ', '
      ', $post_content); /* * just so that if a post already exists, new users are not created by checkauthor */ $post_author = $this->checkauthor($post_author); $postdata = compact('post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_title', 'post_excerpt', 'post_status', 'comment_status', 'ping_status', 'post_modified', 'post_modified_gmt', 'guid', 'post_parent', 'post_type'); $comment_post_ID = $post_id = wp_insert_post($postdata); /* * We want to store the old URL and new URL into our mappings array. This * works on all types of posts: attachment, posts, and pages. Using get_the_guid() * would fail for attachments and pages. */ global $wpdb; $new_guid = $wpdb->get_var("SELECT guid FROM $wpdb->posts WHERE ID = '$post_id'"); // note: this is the old_guid if ($guid) { $this->old_guid_to_new_guid[$guid] = $new_guid; echo "POST old guid=$guid ... new guid=$new_guid\n
      "; // post's list item } if (($link != $guid) && $link) { echo "POST link different from guid (adding both)=$link ... new guid=$new_guid\n
      "; // post's list item $this->old_guid_to_new_guid[$link] = $new_guid; } } /* * If eather wp_insert_post() or handle_attachment() returned -1, then we don't * do any further import of the post related info (comments and categories included) */ if ($post_id != -1) { /* * Here's where we scan the post_content and check for any other embedded links. * We want to make a collection of all links inside of the post_content. Some of these * links will be to our own posts and so we will be able to replace them. But * we will need to wait until our import process is over in case there are references * to posts or attachments that we haven't yet imported. */ $this->store_internal_post_links($post_id,$post_content); /* * Here's where we actually add categories to our post. */ if (0 != count($categories)) { wp_create_categories($categories, $post_id); } /* * Now for comments... we do this processing for pages, posts, and attachments, * since theoretically they all could have comments. */ preg_match_all('|(.*?)|is', $post, $comments); $comments = $comments[1]; $num_comments = 0; $num_spam_comments_skipped = 0; if ( $comments) { foreach ($comments as $comment) { $comment_author = $this->get_tag( $comment, 'wp:comment_author'); $comment_author_email = $this->get_tag( $comment, 'wp:comment_author_email'); $comment_author_IP = $this->get_tag( $comment, 'wp:comment_author_IP'); $comment_author_url = $this->get_tag( $comment, 'wp:comment_author_url'); $comment_date = $this->get_tag( $comment, 'wp:comment_date'); $comment_date_gmt = $this->get_tag( $comment, 'wp:comment_date_gmt'); $comment_content = $this->get_tag( $comment, 'wp:comment_content'); $comment_approved = $this->get_tag( $comment, 'wp:comment_approved'); $comment_type = $this->get_tag( $comment, 'wp:comment_type'); $comment_parent = $this->get_tag( $comment, 'wp:comment_parent'); /* * I'm actually skeptical of this, I mean, we just imported the post, so * we should probably assume all of the comments are legit. * So I am taking this out! * * if ( !comment_exists($comment_author, $comment_date) ) */ /* * I have no idea why WordPress export decides to include spam comments * in the export. I guess then you get a near copy of what was in the * original db. But for me, I don't think it makes sense to import them, * we will will only do comment processing on non-spam. ;) */ if ($comment_approved != 'spam') { $commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_url', 'comment_author_email', 'comment_author_IP', 'comment_date', 'comment_date_gmt', 'comment_content', 'comment_approved', 'comment_type', 'comment_parent'); $comment_id = wp_insert_comment($commentdata); $num_comments++; /* * Same as posts, we want to scan comments for links. * * Here's where we scan the comment_content and check for any other embedded links. * We want to make a collection of all links inside of the post_content. Some of these * links will be to our own posts and so we will be able to replace them. But * we will need to wait until our import process is over in case there are references * to posts or attachments that we haven't yet imported. * We also check to see if the comment_author_url is from our original blog, if it is * this this comment is an internal pingback and we want to add that to our replace * list as well. */ $internal_pingback = (strpos($comment_author_url,$this->original_link) !== FALSE) ? true : false; $this->store_internal_comment_links($comment_id,$comment_content,$internal_pingback); } else $num_spam_comments_skipped++; } // end foreach of comments if ( $num_comments ) printf(' '.__('
    • (%s comments)
    • '), $num_comments); if ( $num_spam_comments_skipped ) printf(' '.__('
    • (%s spam comments intentionally skipped... I mean, who wants them?!)
    • '), $num_spam_comments_skipped); } // end if (comments) } // end if post_id != -1 echo "

    \n"; } // end else case for if (post_exists()) echo "end of post:".(($post_id != -1) ? $post_id : "no post inserted" )."
  2. \n"; // post's list item $index++; } // end foreach of posts // reset the original value set_time_limit($ini_val_max_execution_time); echo '
'; /* * Now we're all done importing posts and comments, it's time to go back and fix * up all our links. */ $this->report_links_mappings(); $this->process_internal_post_links(); $this->process_internal_comment_links(); wp_import_cleanup($this->id); echo '

'.sprintf(__('All done.').' '.__('Have fun!').'', get_option('home')).'

'; } /********************************************************************************** * fuction: import() * description: Main entry point for importer plugin */ function import() { $this->id = (int) $_GET['id']; $this->file = get_attached_file($this->id); $this->get_authors_from_post(); $this->get_entries(); $this->process_categories(); $this->process_posts(); } /********************************************************************************** * fuction: dispatch() * description: Main entry point for rendering pages, does the right thing based on * step param */ function dispatch() { if (empty ($_GET['step'])) $step = 0; else $step = (int) $_GET['step']; $this->header(); switch ($step) { case 0 : $this->greet(); break; case 1 : $this->select_authors(); break; case 2: $this->import(); break; } $this->footer(); } /********************************************************************************** * fuction: [constructor] * description: Ahh, life is good. */ function ZappoMans_Improved_Wordpress_Importer() { // Nothing. } } $zap_improved_wp_importer = new ZappoMans_Improved_Wordpress_Importer(); register_importer('zappo_wordpress', 'ZappoMan\'s Improved WordPress Import', __('Import posts, comments, custom fields, pages, and categories from a WordPress export file. Will also fixup internal links, pingbacks, and image references. And as if that wasn\'t enough, it also skips comments marked as spam and fetches and imports image attachements.'), array ($zap_improved_wp_importer, 'dispatch')); /**************************************************************************************************** * class: zappo_HttpClient * * based on: Version 0.9, 6th April 2003 - Simon Willison ( http://simon.incutio.com/ ) * Manual: http://scripts.incutio.com/httpclient/ * * changes: * * Added support for delayed initialization of client from URL via setGetUrl() method. * This is similar to the QuickGet() except that it allows you to use other setup * methods and more directly control the flow. * * * Added support for 302 redirect to different hosts. */ if ( !class_exists('zappo_HttpClient') ) : class zappo_HttpClient { // Request vars var $host; var $port; var $path; var $method; var $postdata = ''; var $cookies = array(); var $referer; var $accept = 'text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,image/jpeg,image/gif,*/*'; var $accept_encoding = 'gzip'; var $accept_language = 'en-us'; var $user_agent = 'Incutio HttpClient v0.9'; // Options var $timeout = 20; var $use_gzip = true; var $no_cache = false; var $persist_cookies = true; // If true, received cookies are placed in the $this->cookies array ready for the next request // Note: This currently ignores the cookie path (and time) completely. Time is not important, // but path could possibly lead to security problems. var $persist_referers = true; // For each request, sends path of last request as referer var $debug = false; var $handle_redirects = true; // Auaomtically redirect if Location or URI header is found var $max_redirects = 5; var $headers_only = false; // If true, stops receiving once headers have been read. // Basic authorization variables var $username; var $password; // Response vars var $status; var $headers = array(); var $content = ''; var $errormsg; // Tracker variables var $redirect_count = 0; var $cookie_host = ''; function setGetUrl($url) { $bits = parse_url($url); $this->host = $bits['host']; $this->port = isset($bits['port']) ? $bits['port'] : 80; $this->path = isset($bits['path']) ? $bits['path'] : '/'; $this->method = 'GET'; if (isset($bits['query'])) { $this->path .= '?'.$bits['query']; } } function HttpClient($host='', $port=80) { $this->host = $host; $this->port = $port; } function get($path, $data = false) { $this->path = $path; $this->method = 'GET'; if ($data) { $this->path .= '?'.$this->buildQueryString($data); } return $this->doRequest(); } function post($path, $data) { $this->path = $path; $this->method = 'POST'; $this->postdata = $this->buildQueryString($data); return $this->doRequest(); } function buildQueryString($data) { $querystring = ''; if (is_array($data)) { // Change data in to postable data foreach ($data as $key => $val) { if (is_array($val)) { foreach ($val as $val2) { $querystring .= urlencode($key).'='.urlencode($val2).'&'; } } else { $querystring .= urlencode($key).'='.urlencode($val).'&'; } } $querystring = substr($querystring, 0, -1); // Eliminate unnecessary & } else { $querystring = $data; } return $querystring; } function doRequest() { // Performs the actual HTTP request, returning true or false depending on outcome if (!$fp = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout)) { // Set error message switch($errno) { case -3: $this->errormsg = 'Socket creation failed (-3)'; case -4: $this->errormsg = 'DNS lookup failure (-4)'; case -5: $this->errormsg = 'Connection refused or timed out (-5)'; default: $this->errormsg = 'Connection failed ('.$errno.')'; $this->errormsg .= ' '.$errstr; $this->debug($this->errormsg); } return false; } socket_set_timeout($fp, $this->timeout); $request = $this->buildRequest(); $this->debug('Request', $request); fwrite($fp, $request); // Reset all the variables that should not persist between requests $this->headers = array(); $this->content = ''; $this->errormsg = ''; // Set a couple of flags $inHeaders = true; // Now start reading back the response $line = fgets($fp, 4096); // Deal with first line of returned data if (!preg_match('/HTTP\/(\\d\\.\\d)\\s*(\\d+)\\s*(.*)/', $line, $m)) { $this->errormsg = "Status code line invalid: ".htmlentities($line); $this->debug($this->errormsg); return false; } $http_version = $m[1]; // not used $this->status = $m[2]; $status_string = $m[3]; // not used $this->debug(trim($line)); while (!feof($fp)) { $line = fgets($fp, 4096); if ($inHeaders) { if (trim($line) == '') { $inHeaders = false; $this->debug('Received Headers', $this->headers); if ($this->headers_only) { break; // Skip the rest of the input } continue; } if (!preg_match('/([^:]+):\\s*(.*)/', $line, $m)) { // Skip to the next header continue; } $key = strtolower(trim($m[1])); $val = trim($m[2]); // Deal with the possibility of multiple headers of same name if (isset($this->headers[$key])) { if (is_array($this->headers[$key])) { $this->headers[$key][] = $val; } else { $this->headers[$key] = array($this->headers[$key], $val); } } else { $this->headers[$key] = $val; } continue; } // We're not in the headers, so append the line to the contents $this->content .= $line; } fclose($fp); if ($this->status == 301) { $this->debug("301 status result!!! location is:".$this->headers['location']); } // If data is compressed, uncompress it if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] == 'gzip') { $this->debug('Content is gzip encoded, unzipping it'); $this->content = substr($this->content, 10); // See http://www.php.net/manual/en/function.gzencode.php $this->content = gzinflate($this->content); } // If $persist_cookies, deal with any cookies if ($this->persist_cookies && isset($this->headers['set-cookie']) && $this->host == $this->cookie_host) { $cookies = $this->headers['set-cookie']; if (!is_array($cookies)) { $cookies = array($cookies); } foreach ($cookies as $cookie) { if (preg_match('/([^=]+)=([^;]+);/', $cookie, $m)) { $this->cookies[$m[1]] = $m[2]; } } // Record domain of cookies for security reasons $this->cookie_host = $this->host; } // If $persist_referers, set the referer ready for the next request if ($this->persist_referers) { $this->debug('Persisting referer: '.$this->getRequestURL()); $this->referer = $this->getRequestURL(); } $this->debug('right before handle-redirects: '.$this->handle_redirects); // Finally, if handle_redirects and a redirect is sent, do that if ($this->handle_redirects) { $this->debug('redirect count: '.$this->redirect_count); if (++$this->redirect_count >= $this->max_redirects) { $this->errormsg = 'Number of redirects exceeded maximum ('.$this->max_redirects.')'; $this->debug($this->errormsg); $this->redirect_count = 0; return false; } $location = isset($this->headers['location']) ? $this->headers['location'] : ''; $uri = isset($this->headers['uri']) ? $this->headers['uri'] : ''; $this->debug("location or uri? loc=$location uri=$uri"); if ($location || $uri) { $url = parse_url($location.$uri); // This will FAIL if redirect is to a different site if ($this->host != $url['host']) { $this->debug("apparently host changed... {$this->host} != {$url['host']} try again!"); $this->setGetUrl($location.$uri); return $this->doRequest(); } return $this->get($url['path']); } } return true; } function buildRequest() { $headers = array(); $headers[] = "{$this->method} {$this->path} HTTP/1.0"; // Using 1.1 leads to all manner of problems, such as "chunked" encoding $headers[] = "Host: {$this->host}"; $headers[] = "User-Agent: {$this->user_agent}"; $headers[] = "Accept: {$this->accept}"; if ($this->use_gzip) { $headers[] = "Accept-encoding: {$this->accept_encoding}"; } $headers[] = "Accept-language: {$this->accept_language}"; if ($this->referer) { $headers[] = "Referer: {$this->referer}"; } if ($this->no_cache) { $headers[] = "Pragma: no-cache"; $headers[] = "Cache-control: no-cache"; } // Cookies if ($this->cookies) { $cookie = 'Cookie: '; foreach ($this->cookies as $key => $value) { $cookie .= "$key=$value; "; } $headers[] = $cookie; } // Basic authentication if ($this->username && $this->password) { $headers[] = 'Authorization: BASIC '.base64_encode($this->username.':'.$this->password); } // If this is a POST, set the content type and length if ($this->postdata) { $headers[] = 'Content-Type: application/x-www-form-urlencoded'; $headers[] = 'Content-Length: '.strlen($this->postdata); } $request = implode("\r\n", $headers)."\r\n\r\n".$this->postdata; return $request; } function getStatus() { return $this->status; } function getContent() { return $this->content; } function getHeaders() { return $this->headers; } function getHeader($header) { $header = strtolower($header); if (isset($this->headers[$header])) { return $this->headers[$header]; } else { return false; } } function getError() { return $this->errormsg; } function getCookies() { return $this->cookies; } function getRequestURL() { $url = 'http://'.$this->host; if ($this->port != 80) { $url .= ':'.$this->port; } $url .= $this->path; return $url; } // Setter methods function setUserAgent($string) { $this->user_agent = $string; } function setAuthorization($username, $password) { $this->username = $username; $this->password = $password; } function setCookies($array) { $this->cookies = $array; } // Option setting methods function useGzip($boolean) { $this->use_gzip = $boolean; } function setPersistCookies($boolean) { $this->persist_cookies = $boolean; } function setPersistReferers($boolean) { $this->persist_referers = $boolean; } function setHandleRedirects($boolean) { $this->handle_redirects = $boolean; } function setMaxRedirects($num) { $this->max_redirects = $num; } function setHeadersOnly($boolean) { $this->headers_only = $boolean; } function setDebug($boolean) { $this->debug = $boolean; } // "Quick" static methods function quickGet($url) { $bits = parse_url($url); $host = $bits['host']; $port = isset($bits['port']) ? $bits['port'] : 80; $path = isset($bits['path']) ? $bits['path'] : '/'; if (isset($bits['query'])) { $path .= '?'.$bits['query']; } $client = new HttpClient($host, $port); if (!$client->get($path)) { return false; } else { return $client->getContent(); } } function quickPost($url, $data) { $bits = parse_url($url); $host = $bits['host']; $port = isset($bits['port']) ? $bits['port'] : 80; $path = isset($bits['path']) ? $bits['path'] : '/'; $client = new HttpClient($host, $port); if (!$client->post($path, $data)) { return false; } else { return $client->getContent(); } } function debug($msg, $object = false) { if ($this->debug) { print '
HttpClient Debug: '.$msg; if ($object) { ob_start(); print_r($object); $content = htmlentities(ob_get_contents()); ob_end_clean(); print '
'.$content.'
'; } print '
'; } } } endif; /********************************************************************************** * fuction: zappo_insert_attachment() * * description: * * This week on Law & Order - ripped from the headlines: upload-functions.php * Accounts of description of events that seem similar are purly coincidental. * * VERY VERY Similar to wp_upload_tab_upload_action() from upload-functions.php * * The main purpose of this function is to handle the "uploading" of files * to the blog that are actually already living on the server. Since we * download them to the server. * */ function zappo_insert_attachment($file_in,$attachment) { //echo "zappo_insert_attachment("; //print_r($file_in); //print_r($attachment); //echo ")\n
"; $overrides = array('action'=>'upload','test_form'=>false, 'test_size'=>false); $file = zappo_handle_upload($file_in, $overrides, $attachment); if ( isset($file['error']) ) { echo "Error: {$file['error']}
"; return -1; // return some kind of meaningful error here! } $url = $file['url']; $type = $file['type']; $file = $file['file']; $filename = basename($file); //echo "url=$url type=$type file=$file filename=$filename post_parent={$attachment['post_parent']}\n
"; //print_r($file); // Save the data $attachment['guid'] = $url; $id = wp_insert_attachment($attachment, $file, $attachment['post_parent']); // Note: the attachment object had a list of category names with it but wp_insert_attachment // doesn't process those, because it wants category id's so this little loop here will actually // process the category names into ids and associate them with the attachement $categories = $attachment['post_category_names']; if (0 != count($categories)) { wp_create_categories($categories, $id); } //echo "called wp_insert_attachment() ==> id=$id\n
"; if ( preg_match('!^image/!', $attachment['post_mime_type']) ) { //echo "It's an IMAGE!\n
"; // Generate the attachment's postmeta. $imagesize = getimagesize($file); $imagedata['width'] = $imagesize['0']; $imagedata['height'] = $imagesize['1']; list($uwidth, $uheight) = get_udims($imagedata['width'], $imagedata['height']); $imagedata['hwstring_small'] = "height='$uheight' width='$uwidth'"; $imagedata['file'] = $file; add_post_meta($id, '_wp_attachment_metadata', $imagedata); if ( $imagedata['width'] * $imagedata['height'] < 3 * 1024 * 1024 ) { if ( $imagedata['width'] > 128 && $imagedata['width'] >= $imagedata['height'] * 4 / 3 ) $thumb = wp_create_thumbnail($file, 128); elseif ( $imagedata['height'] > 96 ) $thumb = wp_create_thumbnail($file, 96); if ( @file_exists($thumb) ) { $newdata = $imagedata; $newdata['thumb'] = basename($thumb); update_post_meta($id, '_wp_attachment_metadata', $newdata, $imagedata); } else { $error = $thumb; } } } else { add_post_meta($id, '_wp_attachment_metadata', array()); } //echo "DONE\n
"; return $id; // post_id of attachment } /********************************************************************************** * fuction: zappo_handle_upload() * * description: * * This week on Law & Order - ripped from the headlines: wp_handle_upload() * Accounts of description of events that seem similar are purly coincidental. * * VERY VERY Similar to wp_handle_upload() from admin-functions.php * * The main purpose of this function is to handle the "uploading" of files * to the blog that are actually already living on the server. Since we * download them to the server. * * parameters: * * file: reference to an array that LOOKS like a php $_FILES. * * overrides: an associative array of names=>values to override default * variables with extract($overrides, EXTR_OVERWRITE). * * attachment: an associative array of names=>values with attachment details * we mostly need this so we can create the files in the correct * date based folder if the server is configured to handle that * case. * * returns: array * * On success- returns an associative array of file attributes. * * On failure- returns $overrides['upload_error_handler'](&$file, $message) * or array('error'=>$message). * */ function zappo_handle_upload(&$file, $overrides = false, $attachment = '') { // The default error handler. if (! function_exists('wp_handle_upload_error') ) { function wp_handle_upload_error(&$file, $message) { return array('error'=>$message); } } //echo "file=\n
"; //print_r($file); //echo "\n
"; // You may define your own function and pass the name in $overrides['upload_error_handler'] $upload_error_handler = 'wp_handle_upload_error'; // $_POST['action'] must be set and its value must equal $overrides['action'] or this: $action = 'wp_handle_upload'; // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error']. $upload_error_strings = array(false, __("The uploaded file exceeds the upload_max_filesize directive in php.ini."), __("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form."), __("The uploaded file was only partially uploaded."), __("No file was uploaded."), __("Missing a temporary folder."), __("Failed to write file to disk.")); // All tests are on by default. Most can be turned off by $override[{test_name}] = false; $test_form = true; $test_size = true; // If you override this, you must provide $ext and $type!!!! $test_type = true; // Install user overrides. Did we mention that this voids your warranty? if ( is_array($overrides) ) extract($overrides, EXTR_OVERWRITE); // A correct form post will pass this test. if ( $test_form && (!isset($_POST['action']) || ($_POST['action'] != $action)) ) return $upload_error_handler($file, __('Invalid form submission.')); // A successful upload will pass this test. It makes no sense to override this one. if ( $file['error'] > 0 ) return $upload_error_handler($file, $upload_error_strings[$file['error']]); // A non-empty file will pass this test. if ( $test_size && !($file['size'] > 0) ) return $upload_error_handler($file, __('File is empty. Please upload something more substantial.')); /******************************************************************************** Zappo : But since these files weren't uploaded by a user, they were downloaded by our server, we can't use this function or the move_uploaded_files() function later... ********************************************************************************/ // A properly uploaded file will pass this test. There should be no reason to override this one. //if (! @ is_uploaded_file($file['tmp_name']) ) // return $upload_error_handler($file, __('Specified file failed upload test.')); //echo "ln 925\n
"; // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter. if ( $test_type ) { $wp_filetype = wp_check_filetype($file['name'], $mimes); extract($wp_filetype); if ( !$type || !$ext ) return $upload_error_handler($file, __('File type does not meet security guidelines. Try another.')); } // A writable uploads dir will pass this test. Override with $uploads = array('path'=>$path, 'url'=>$url); if ( ( empty($uploads['path']) || empty($uploads['url']) ) && !( ($uploads = zappo_wp_upload_dir($attachment['post_date'])) && false === $uploads['error'] ) ) return $upload_error_handler($file, $uploads['error']); // Increment the file number until we have a unique file to save in $dir. Use $override['unique_filename_callback'] if supplied. if ( isset($unique_filename_callback) && function_exists($unique_filename_callback) ) { $filename = $unique_filename_callback($uploads['path'], $file['name']); } else { $number = ''; $filename = str_replace('#', '_', $file['name']); $filename = str_replace(array('\\', "'"), '', $filename); if ( empty($ext) ) $ext = ''; else $ext = ".$ext"; while ( file_exists($uploads['path'] . "/$filename") ) { if ( '' == "$number$ext" ) $filename = $filename . ++$number . $ext; else $filename = str_replace("$number$ext", ++$number . $ext, $filename); } $filename = str_replace($ext, '', $filename); $filename = sanitize_title_with_dashes($filename) . $ext; } // Move the file to the uploads dir $new_file = $uploads['path'] . "/$filename"; //echo "Here we go.... about to attempt to move the file from {$file['tmp_name']} to ----> $new_file \n
"; // Can we use move_uploaded_file? maybe copy() will work! if (!copy($file['tmp_name'], $new_file)) wp_die(printf(__('The uploaded file could not be moved to %s.'), $uploads['path'])); //echo "SUCCESS!! File uploaded\n
"; // Set correct file permissions $stat = stat(dirname($new_file)); $perms = $stat['mode'] & 0000666; @ chmod($new_file, $perms); // Compute the URL $url = $uploads['url'] . "/$filename"; //echo "url=$url\n
"; $return = apply_filters( 'wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type) ); //echo "return=\n
"; //print_r($return); return $return; } /********************************************************************************** * fuction: zappo_wp_upload_dir() * * description: Returns an array containing the current upload * directory's path and url, or an error message. * * This week on Law & Order - ripped from the headlines: wp_upload_dir() * Accounts of description of events that seem similar are purly coincidental. * * VERY VERY Similar to wp_upload_dir() from functions.php * * The main purpose of this function is to handle the creating an upload dir * but instead of using today's date it will create a directory based on the * date requested. * * parameters: * * post_date: the date the post was created on. * * returns: array * * On success- creates the directory if necessary and returns an array * with path and url info * * On failure- array('error'=>$message). * */ // function zappo_wp_upload_dir($post_date='') { $siteurl = get_option('siteurl'); //prepend ABSPATH to $dir and $siteurl to $url if they're not already there $path = str_replace(ABSPATH, '', trim(get_option('upload_path'))); $dir = ABSPATH . $path; $url = trailingslashit($siteurl) . $path; if ( $dir == ABSPATH ) { //the option was empty $dir = ABSPATH . 'wp-content/uploads'; } if ( defined('UPLOADS') ) { $dir = ABSPATH . UPLOADS; $url = trailingslashit($siteurl) . UPLOADS; } if ( get_option('uploads_use_yearmonth_folders')) { if ($post_date == '') { // Generate the yearly and monthly dirs $time = current_time( 'mysql' ); $y = substr( $time, 0, 4 ); $m = substr( $time, 5, 2 ); } else { // Should extract from $post_date $date_array = explode("-",$post_date); $y = $date_array[0]; $m = $date_array[1]; } $dir = $dir . "/$y/$m"; $url = $url . "/$y/$m"; } // Make sure we have an uploads dir if ( ! wp_mkdir_p( $dir ) ) { $message = sprintf(__('Unable to create directory %s. Is its parent directory writable by the server?'), $dir); return array('error' => $message); } $uploads = array('path' => $dir, 'url' => $url, 'error' => false); return apply_filters('upload_dir', $uploads); } ?>