| [ Index ] |
WordPress Source Cross Reference |
[Summary view] [Print] [Text view]
1 <?php 2 3 class Blogger_Import { 4 5 var $lump_authors = false; 6 var $import = array(); 7 8 // Shows the welcome screen and the magic iframe. 9 function greet() { 10 $title = __('Import Blogger'); 11 $welcome = __('Howdy! This importer allows you to import posts and comments from your Blogger account into your WordPress blog.'); 12 $noiframes = __('This feature requires iframe support.'); 13 $warning = __('This will delete everything saved by the Blogger importer except your posts and comments. Are you sure you want to do this?'); 14 $reset = __('Reset this importer'); 15 $incompat = __('Your web server is not properly configured to use this importer. Please enable the CURL extension for PHP and then reload this page.'); 16 17 echo "<div class='wrap'><h2>$title</h2><p>$welcome</p>"; 18 if ( function_exists('curl_init') ) 19 echo "<iframe src='admin.php?import=blogger&noheader=true' height='350px' width = '99%'>$noiframes</iframe><p><a href='admin.php?import=blogger&restart=true&noheader=true' onclick='return confirm(\"$warning\")'>$reset</a></p>"; 20 else 21 echo "<p>$incompat</p>"; 22 echo "</div>\n"; 23 } 24 25 // Deletes saved data and redirect. 26 function restart() { 27 delete_option('import-blogger'); 28 wp_redirect("admin.php?import=blogger"); 29 die(); 30 } 31 32 // Generates a string that will make the page reload in a specified interval. 33 function refresher($msec) { 34 if ( $msec ) 35 return "<html><head><script type='text/javascript'>window.onload=setTimeout('window.location.reload()', $msec);</script>\n</head>\n<body>\n"; 36 else 37 return "<html><head><script type='text/javascript'>window.onload=window.location.reload();</script>\n</head>\n<body>\n"; 38 } 39 40 // Returns associative array of code, header, cookies, body. Based on code from php.net. 41 function parse_response($this_response) { 42 // Split response into header and body sections 43 list($response_headers, $response_body) = explode("\r\n\r\n", $this_response, 2); 44 $response_header_lines = explode("\r\n", $response_headers); 45 46 // First line of headers is the HTTP response code 47 $http_response_line = array_shift($response_header_lines); 48 if(preg_match('@^HTTP/[0-9]\.[0-9] ([0-9]{3})@',$http_response_line, $matches)) { $response_code = $matches[1]; } 49 50 // put the rest of the headers in an array 51 $response_header_array = array(); 52 foreach($response_header_lines as $header_line) { 53 list($header,$value) = explode(': ', $header_line, 2); 54 $response_header_array[$header] .= $value."\n"; 55 } 56 57 $cookie_array = array(); 58 $cookies = explode("\n", $response_header_array["Set-Cookie"]); 59 foreach($cookies as $this_cookie) { array_push($cookie_array, "Cookie: ".$this_cookie); } 60 61 return array("code" => $response_code, "header" => $response_header_array, "cookies" => $cookie_array, "body" => $response_body); 62 } 63 64 // Prints a form for the user to enter Blogger creds. 65 function login_form($text='') { 66 echo '<h1>' . __('Log in to Blogger') . "</h1>\n$text\n"; 67 echo '<form method="post" action="admin.php?import=blogger&noheader=true&step=0"><table><tr><td>' . __('Username') . ':</td><td><input type="text" name="user" /></td></tr><tr><td>' . __('Password') . ':</td><td><input type="password" name="pass" /></td><td><input type="submit" value="' . __('Start') . '" /></td></tr></table></form>'; 68 die; 69 } 70 71 // Sends creds to Blogger, returns the session cookies an array of headers. 72 function login_blogger($user, $pass) { 73 $_url = 'http://www.blogger.com/login.do'; 74 $params = "username=$user&password=$pass"; 75 $ch = curl_init(); 76 curl_setopt($ch, CURLOPT_POST,1); 77 curl_setopt($ch, CURLOPT_POSTFIELDS,$params); 78 curl_setopt($ch, CURLOPT_URL,$_url); 79 curl_setopt($ch, CURLOPT_USERAGENT, 'Blogger Exporter'); 80 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0); 81 curl_setopt($ch, CURLOPT_HEADER,1); 82 curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); 83 $response = curl_exec ($ch); 84 85 $response = $this->parse_response($response); 86 87 sleep(1); 88 89 return $response['cookies']; 90 } 91 92 // Requests page from Blogger, returns the response array. 93 function get_blogger($url, $header = '', $user=false, $pass=false) { 94 $ch = curl_init(); 95 if ($user && $pass) curl_setopt($ch, CURLOPT_USERPWD,"{$user}:{$pass}"); 96 curl_setopt($ch, CURLOPT_URL,$url); 97 curl_setopt($ch, CURLOPT_TIMEOUT, 10); 98 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 99 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 100 curl_setopt($ch, CURLOPT_USERAGENT, 'Blogger Exporter'); 101 curl_setopt($ch, CURLOPT_HEADER,1); 102 if (is_array($header)) curl_setopt($ch, CURLOPT_HTTPHEADER, $header); 103 $response = curl_exec ($ch); 104 105 $response = $this->parse_response($response); 106 $response['url'] = $url; 107 108 if (curl_errno($ch)) { 109 print curl_error($ch); 110 } else { 111 curl_close($ch); 112 } 113 114 return $response; 115 } 116 117 // Posts data to Blogger, returns response array. 118 function post_blogger($url, $header = false, $paramary = false, $parse=true) { 119 $params = ''; 120 if ( is_array($paramary) ) { 121 foreach($paramary as $key=>$value) 122 if($key && $value != '') 123 $params.=$key."=".urlencode(stripslashes($value))."&"; 124 } 125 if ($user && $pass) $params .= "username=$user&password=$pass"; 126 $params = trim($params,'&'); 127 $ch = curl_init(); 128 curl_setopt($ch, CURLOPT_POST,1); 129 curl_setopt($ch, CURLOPT_POSTFIELDS,$params); 130 if ($user && $pass) curl_setopt($ch, CURLOPT_USERPWD,"{$user}:{$pass}"); 131 curl_setopt($ch, CURLOPT_URL,$url); 132 curl_setopt($ch, CURLOPT_USERAGENT, 'Blogger Exporter'); 133 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 134 curl_setopt($ch, CURLOPT_HEADER,$parse); 135 curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); 136 if ($header) curl_setopt($ch, CURLOPT_HTTPHEADER, $header); 137 $response = curl_exec ($ch); 138 139 if ($parse) { 140 $response = $this->parse_response($response); 141 $response['url'] = $url; 142 return $response; 143 } 144 145 return $response; 146 } 147 148 // Prints the list of blogs for import. 149 function show_blogs() { 150 global $import; 151 echo '<h1>' . __('Selecting a Blog') . "</h1>\n<ul>"; 152 foreach ( $this->import['blogs'] as $blog ) { 153 if (9 == $blog['nextstep']) $status = "100%"; 154 elseif (8 == $blog['nextstep']) $status = "90%"; 155 elseif (7 == $blog['nextstep']) $status = "82.5%"; 156 elseif (6 == $blog['nextstep']) $status = "75%"; 157 elseif (5 == $blog['nextstep']) $status = "57%"; 158 elseif (4 == $blog['nextstep']) $status = "28%"; 159 elseif (3 == $blog['nextstep']) $status = "14%"; 160 else $status = "0%"; 161 echo "\t<li><a href='admin.php?import=blogger&noheader=true&blog={$blog['id']}'>{$blog['title']}</a> $status</li>\n"; 162 } 163 die("</ul>\n"); 164 } 165 166 // Publishes. 167 function publish_blogger($i, $text) { 168 $head = $this->refresher(2000) . "<h1>$text</h1>\n"; 169 if ( ! strstr($this->import['blogs'][$_GET['blog']]['publish'][$i], 'http') ) { 170 // First call. Start the publish process with a fresh set of cookies. 171 $this->import['cookies'] = $this->login_blogger($this->import['user'], $this->import['pass']); 172 update_option('import-blogger', $this->import); 173 $paramary = array('blogID' => $_GET['blog'], 'all' => '1', 'republishAll' => 'Republish Entire Blog', 'publish' => '1', 'redirectUrl' => "/publish.do?blogID={$_GET['blog']}&inprogress=true"); 174 175 $response = $this->post_blogger("http://www.blogger.com/publish.do?blogID={$_GET['blog']}", $this->import['cookies'], $paramary); 176 if ( $response['code'] == '302' ) { 177 $url = str_replace('publish.g', 'publish-body.g', $response['header']['Location']); 178 $this->import['blogs'][$_GET['blog']]['publish'][$i] = $url; 179 update_option('import-blogger', $this->import); 180 $response = $this->get_blogger($url, $this->import['cookies']); 181 preg_match('#<p class="progressIndicator">.*</p>#U', $response['body'], $matches); 182 $progress = $matches[0]; 183 die($head . $progress); 184 } else { 185 $this->import['blogs'][$_GET['blog']]['publish'][$i] = false; 186 update_option('import-blogger', $this->import); 187 die($head); 188 } 189 } else { 190 // Subsequent call. Keep checking status until Blogger reports publish complete. 191 $url = $this->import['blogs'][$_GET['blog']]['publish'][$i]; 192 $response = $this->get_blogger($url, $this->import['cookies']); 193 if ( preg_match('#<p class="progressIndicator">.*</p>#U', $response['body'], $matches) ) { 194 $progress = $matches[0]; 195 if ( strstr($progress, '100%') ) { 196 $this->set_next_step($i); 197 $progress .= '<p>'.__('Moving on...').'</p>'; 198 } 199 die($head . $progress); 200 } else { 201 $this->import['blogs'][$_GET['blog']]['publish'][$i] = false; 202 update_option('import-blogger', $this->import); 203 die("$head<p>" . __('Trying again...') . '</p>'); 204 } 205 } 206 } 207 208 // Sets next step, saves options 209 function set_next_step($step) { 210 $this->import['blogs'][$_GET['blog']]['nextstep'] = $step; 211 update_option('import-blogger', $this->import); 212 } 213 214 // Redirects to next step 215 function do_next_step() { 216 wp_redirect("admin.php?import=blogger&noheader=true&blog={$_GET['blog']}"); 217 die(); 218 } 219 220 // Step 0: Do Blogger login, get blogid/title pairs. 221 function do_login() { 222 if ( ( ! $this->import['user'] && ! is_array($this->import['cookies']) ) ) { 223 // The user must provide a Blogger username and password. 224 if ( ! ( $_POST['user'] && $_POST['pass'] ) ) { 225 $this->login_form(__('The script will log into your Blogger account, change some settings so it can read your blog, and restore the original settings when it\'s done. Here\'s what you do:').'</p><ol><li>'.__('Back up your Blogger template.').'</li><li>'.__('Back up any other Blogger settings you might need later.').'</li><li>'.__('Log out of Blogger').'</li><li>'.__('Log in <em>here</em> with your Blogger username and password.').'</li><li>'.__('On the next screen, click one of your Blogger blogs.').'</li><li>'.__('Do not close this window or navigate away until the process is complete.').'</li></ol>'); 226 } 227 228 // Try logging in. If we get an array of cookies back, we at least connected. 229 $this->import['cookies'] = $this->login_blogger($_POST['user'], $_POST['pass']); 230 if ( !is_array( $this->import['cookies'] ) ) { 231 $this->login_form(__('Login failed. Please enter your credentials again.')); 232 } 233 234 // Save the password so we can log the browser in when it's time to publish. 235 $this->import['pass'] = $_POST['pass']; 236 $this->import['user'] = $_POST['user']; 237 238 // Get the Blogger welcome page and scrape the blog numbers and names from it 239 $response = $this->get_blogger('http://www.blogger.com/home', $this->import['cookies']); 240 if (! stristr($response['body'], 'signed in as') ) $this->login_form(__('Login failed. Please re-enter your username and password.')); 241 $blogsary = array(); 242 preg_match_all('#posts\.g\?blogID=(\d+)">([^<]+)</a>#U', $response['body'], $blogsary); 243 if ( ! count( $blogsary[1] < 1 ) ) 244 wp_die(__('No blogs found for this user.')); 245 $this->import['blogs'] = array(); 246 $template = '<MainPage><br /><br /><br /><p>'.__('Are you looking for %title%? It is temporarily out of service. Please try again in a few minutes. Meanwhile, discover <a href="http://wordpress.org/">a better blogging tool</a>.').'</p><BloggerArchives><a class="archive" href="<$BlogArchiveURL$>"><$BlogArchiveName$></a><br /></BloggerArchives></MainPage><ArchivePage><Blogger><wordpresspost><$BlogItemDateTime$>|W|P|<$BlogItemAuthorNickname$>|W|P|<$BlogItemBody$>|W|P|<$BlogItemNumber$>|W|P|<$BlogItemTitle$>|W|P|<$BlogItemAuthorEmail$><BlogItemCommentsEnabled><BlogItemComments><wordpresscomment><$BlogCommentDateTime$>|W|P|<$BlogCommentAuthor$>|W|P|<$BlogCommentBody$></BlogItemComments></BlogItemCommentsEnabled></Blogger></ArchivePage>'; 247 foreach ( $blogsary[1] as $key => $id ) { 248 // Define the required Blogger options. 249 $blog_opts = array( 250 'blog-options-basic' => false, 251 'blog-options-archiving' => array('archiveFrequency' => 'm'), 252 'blog-publishing' => array('publishMode'=>'0', 'blogID' => "$id", 'subdomain' => mt_rand().mt_rand(), 'pingWeblogs' => 'false'), 253 'blog-formatting' => array('timeStampFormat' => '0', 'encoding'=>'UTF-8', 'convertLineBreaks'=>'false', 'floatAlignment'=>'false'), 254 'blog-comments' => array('commentsTimeStampFormat' => '0'), 255 'template-edit' => array( 'templateText' => str_replace('%title%', trim($blogsary[2][$key]), $template) ) 256 ); 257 258 // Build the blog options array template 259 foreach ($blog_opts as $blog_opt => $modify) 260 $new_opts["$blog_opt"] = array('backup'=>false, 'modify' => $modify, 'error'=>false); 261 262 $this->import['blogs']["$id"] = array( 263 'id' => $id, 264 'title' => trim($blogsary[2][$key]), 265 'options' => $new_opts, 266 'url' => false, 267 'publish_cookies' => false, 268 'published' => false, 269 'archives' => false, 270 'lump_authors' => false, 271 'newusers' => array(), 272 'nextstep' => 2 273 ); 274 } 275 update_option('import-blogger', $this->import); 276 wp_redirect("admin.php?import=blogger&noheader=true&step=1"); 277 } 278 die(); 279 } 280 281 // Step 1: Select one of the blogs belonging to the user logged in. 282 function select_blog() { 283 if ( is_array($this->import['blogs']) ) { 284 $this->show_blogs(); 285 die(); 286 } else { 287 $this->restart(); 288 } 289 } 290 291 // Step 2: Backup the Blogger options pages, updating some of them. 292 function backup_settings() { 293 $output.= '<h1>'.__('Backing up Blogger options')."</h1>\n"; 294 $form = false; 295 foreach ($this->import['blogs'][$_GET['blog']]['options'] as $blog_opt => $optary) { 296 if ( $blog_opt == $_GET['form'] ) { 297 // Save the posted form data 298 $this->import['blogs'][$_GET['blog']]['options']["$blog_opt"]['backup'] = $_POST; 299 update_option('import-blogger',$this->import); 300 301 // Post the modified form data to Blogger 302 if ( $optary['modify'] ) { 303 $posturl = "http://www.blogger.com/{$blog_opt}.do"; 304 $headers = array_merge($this->import['blogs'][$_GET['blog']]['options']["$blog_opt"]['cookies'], $this->import['cookies']); 305 if ( 'blog-publishing' == $blog_opt ) { 306 if ( $_POST['publishMode'] > 0 ) { 307 $response = $this->get_blogger("http://www.blogger.com/blog-publishing.g?blogID={$_GET['blog']}&publishMode=0", $headers); 308 if ( $response['code'] >= 400 ) 309 wp_die('<h2>'.__('Failed attempt to change publish mode from FTP to BlogSpot.').'</h2><pre>' . addslashes(print_r($headers, 1)) . addslashes(print_r($response, 1)) . '</pre>'); 310 $this->import['blogs'][$_GET['blog']]['url'] = 'http://' . $optary['modify']['subdomain'] . '.blogspot.com/'; 311 sleep(2); 312 } else { 313 $this->import['blogs'][$_GET['blog']]['url'] = 'http://' . $_POST['subdomain'] . '.blogspot.com/'; 314 update_option('import-blogger', $this->import); 315 $output .= "<del><p>$blog_opt</p></del>\n"; 316 continue; 317 } 318 $paramary = $optary['modify']; 319 } else { 320 $paramary = array_merge($_POST, $optary['modify']); 321 } 322 $response = $this->post_blogger($posturl, $headers, $paramary); 323 if ( $response['code'] >= 400 || strstr($response['body'], 'There are errors on this form') ) 324 wp_die('<p>'.__('Error on form submission. Retry or reset the importer.').'</p>' . addslashes(print_r($response, 1))); 325 } 326 $output .= "<del><p>$blog_opt</p></del>\n"; 327 } elseif ( is_array($this->import['blogs'][$_GET['blog']]['options']["$blog_opt"]['backup']) ) { 328 // This option set has already been backed up. 329 $output .= "<del><p>$blog_opt</p></del>\n"; 330 } elseif ( ! $form ) { 331 // This option page needs to be downloaded and given to the browser for submission back to this script. 332 $response = $this->get_blogger("http://www.blogger.com/{$blog_opt}.g?blogID={$_GET['blog']}", $this->import['cookies']); 333 $this->import['blogs'][$_GET['blog']]['options']["$blog_opt"]['cookies'] = $response['cookies']; 334 update_option('import-blogger',$this->import); 335 $body = $response['body']; 336 $body = preg_replace("|\<!DOCTYPE.*\<body[^>]*>|ms","",$body); 337 $body = preg_replace("|/?{$blog_opt}.do|","admin.php?import=blogger&noheader=true&step=2&blog={$_GET['blog']}&form={$blog_opt}",$body); 338 $body = str_replace("name='submit'","name='supermit'",$body); 339 $body = str_replace('name="submit"','name="supermit"',$body); 340 $body = str_replace('</body>','',str_replace('</html>','',$body)); 341 $form = "<div style='height:0px;width:0px;overflow:hidden;'>"; 342 $form.= $body; 343 $form.= "</div><script type='text/javascript'>forms=document.getElementsByTagName('form');for(i=0;i<forms.length;i++){if(forms[i].action.search('{$blog_opt}')){forms[i].submit();break;}}</script>"; 344 $output.= '<p>'.sprintf('<strong>%s</strong> in progress, please wait...', $blog_opt)."</p>\n"; 345 } else { 346