Make WordPress Core


Ignore:
Timestamp:
02/20/2007 07:46:40 AM (20 years ago)
Author:
ryan
Message:

Update blogger importer.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-admin/import/blogger.php

    r4679 r4896  
    11<?php
    22
     3define( 'MAX_RESULTS',        50 ); // How many records per GData query
     4define( 'MAX_EXECUTION_TIME', 20 ); // How many seconds to let the script run
     5define( 'STATUS_INTERVAL',     3 ); // How many seconds between status bar updates
     6
    37class Blogger_Import {
    48
    5         var $lump_authors = false;
    6         var $import = array();
    7 
    8         // Shows the welcome screen and the magic iframe.
     9        // Shows the welcome screen and the magic auth link.
    910        function greet() {
    10                 $title = __('Import Old Blogger');
    11                 $welcome = __('Howdy! This importer allows you to import posts and comments from your Old Blogger account into your WordPress blog.');
    12                 $noiframes = __('This feature requires iframe support.');
    13                 $warning = js_escape(__('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                 echo "<p>" . __('Please note that this importer <em>does not work with new Blogger (using your Google account)</em>.') . "</p>";
    19                 if ( function_exists('curl_init') )
    20                         echo "<iframe src='admin.php?import=blogger&amp;noheader=true' height='350px' width = '99%'>$noiframes</iframe><p><a href='admin.php?import=blogger&amp;restart=true&amp;noheader=true' onclick='return confirm(\"$warning\")'>$reset</a></p>";
     11                $next_url = get_option('siteurl') . '/wp-admin/index.php?import=blogger&noheader=true';
     12                $auth_url = "https://www.google.com/accounts/AuthSubRequest";
     13                $title = __('Import Blogger');
     14                $welcome = __('Howdy! This importer allows you to import posts and comments from your Blogger account into your WordPress blog.');
     15                $prereqs = __('To use this importer, you must have a Google account, an upgraded (New, was Beta) blog, and it must be on blogspot or a custom domain (not FTP).');
     16                $stepone = __('The first thing you need to do is tell Blogger to let WordPress access your account. You will be sent back here after providing authorization.');
     17                $auth = __('Authorize');
     18
     19                echo "
     20                <div class='wrap'><h2>$title</h2><p>$welcome</p><p>$prereqs</p><p>$stepone</p>
     21                        <form action='$auth_url' method='get'>
     22                                <p class='submit' style='text-align:left;'>
     23                                        <input type='submit' value='$auth' />
     24                                        <input type='hidden' name='scope' value='http://www.blogger.com/feeds/' />
     25                                        <input type='hidden' name='session' value='1' />
     26                                        <input type='hidden' name='secure' value='0' />
     27                                        <input type='hidden' name='next' value='$next_url' />
     28                                </p>
     29                        </form>
     30                </div>\n";
     31        }
     32
     33        function uh_oh($title, $message, $info) {
     34                echo "<div class='wrap'><h2>$title</h2><p>$message</p><pre>$info</pre></div>";
     35        }
     36
     37        function auth() {
     38                // We have a single-use token that must be upgraded to a session token.
     39                $token = preg_replace( '/[^-_0-9a-zA-Z]/', '', $_GET['token'] );
     40                $headers = array(
     41                        "GET /accounts/AuthSubSessionToken HTTP/1.0",
     42                        "Authorization: AuthSub token=\"$token\""
     43                );
     44                $request = join( "\r\n", $headers ) . "\r\n\r\n";
     45                $sock = $this->_get_auth_sock( );
     46                if ( ! $sock ) return false;
     47                $response = $this->_txrx( $sock, $request );
     48                preg_match( '/token=([-_0-9a-z]+)/i', $response, $matches );
     49                if ( empty( $matches[1] ) ) {
     50                        $this->uh_oh(
     51                                __( 'Authorization failed' ),
     52                                __( 'Something went wrong. If the problem persists, send this info to support:' ),
     53                                htmlspecialchars($response)
     54                        );
     55                        return false;
     56                }
     57                $this->token = $matches[1];
     58               
     59                wp_redirect( remove_query_arg( array( 'token', 'noheader' ) ) );
     60        }
     61
     62        function get_token_info() {
     63                $headers = array(
     64                        "GET /accounts/AuthSubTokenInfo  HTTP/1.0",
     65                        "Authorization: AuthSub token=\"$this->token\""
     66                );
     67                $request = join( "\r\n", $headers ) . "\r\n\r\n";
     68                $sock = $this->_get_auth_sock( );
     69                if ( ! $sock ) return;
     70                $response = $this->_txrx( $sock, $request );
     71                return $this->parse_response($response);
     72        }
     73
     74        function token_is_valid() {
     75                $info = $this->get_token_info();
     76
     77                if ( $info['code'] == 200 )
     78                        return true;
     79
     80                return false;
     81        }
     82
     83        function show_blogs($iter = 0) {
     84                if ( empty($this->blogs) ) {
     85                        $headers = array(
     86                                "GET /feeds/default/blogs HTTP/1.0",
     87                                "Host: www.blogger.com",
     88                                "Authorization: AuthSub token=\"$this->token\""
     89                        );
     90                        $request = join( "\r\n", $headers ) . "\r\n\r\n";
     91                        $sock = $this->_get_blogger_sock( );
     92                        if ( ! $sock ) return;
     93                        $response = $this->_txrx( $sock, $request );
     94
     95                        // Quick and dirty XML mining.
     96                        list( $headers, $xml ) = explode( "\r\n\r\n", $response );
     97                        $p = xml_parser_create();
     98                        xml_parse_into_struct($p, $xml, $vals, $index);
     99                        xml_parser_free($p);
     100
     101                        $this->title = $vals[$index['TITLE'][0]]['value'];
     102
     103                        // Give it a few retries... this step often flakes out the first time.
     104                        if ( empty( $index['ENTRY'] ) ) {
     105                                if ( $iter < 3 ) {
     106                                        return $this->show_blogs($iter + 1);
     107                                } else {
     108                                        $this->uh_oh(
     109                                                __('Trouble signing in'),
     110                                                __('We were not able to gain access to your account. Try starting over.'),
     111                                                ''
     112                                        );
     113                                        return false;
     114                                }
     115                        }
     116
     117                        foreach ( $index['ENTRY'] as $i ) {
     118                                $blog = array();
     119                                while ( ( $tag = $vals[$i] ) && ! ( $tag['tag'] == 'ENTRY' && $tag['type'] == 'close' ) ) {
     120                                        if ( $tag['tag'] == 'TITLE' ) {
     121                                                $blog['title'] = $tag['value'];
     122                                        } elseif ( $tag['tag'] == 'SUMMARY' ) {
     123                                                $blog['summary'] == $tag['value'];
     124                                        } elseif ( $tag['tag'] == 'LINK' ) {
     125                                                if ( $tag['attributes']['REL'] == 'alternate' && $tag['attributes']['TYPE'] == 'text/html' ) {
     126                                                        $parts = parse_url( $tag['attributes']['HREF'] );
     127                                                        $blog['host'] = $parts['host'];
     128                                                } elseif ( $tag['attributes']['REL'] == 'edit' )
     129                                                        $blog['gateway'] = $tag['attributes']['HREF'];
     130                                        }
     131                                        ++$i;
     132                                }
     133                                if ( ! empty ( $blog ) ) {
     134                                        $blog['total_posts'] = $this->get_total_results('posts', $blog['host']);
     135                                        $blog['total_comments'] = $this->get_total_results('comments', $blog['host']);
     136                                        $blog['mode'] = 'init';
     137                                        $this->blogs[] = $blog;
     138                                }
     139                        }
     140
     141                        if ( empty( $this->blogs ) ) {
     142                                $this->uh_oh(
     143                                        __('No blogs found'),
     144                                        __('We were able to log in but there were no blogs. Try a different account next time.'),
     145                                        ''
     146                                );
     147                                return false;
     148                        }
     149                }
     150//echo '<pre>'.print_r($this,1).'</pre>';
     151                $start    = js_escape( __('Import') );
     152                $continue = js_escape( __('Continue') );
     153                $stop     = js_escape( __('Importing...') );
     154                $authors  = js_escape( __('Set Authors') );
     155                $loadauth = js_escape( __('Preparing author mapping form...') );
     156                $authhead = js_escape( __('Final Step: Author Mapping') );
     157                $nothing  = js_escape( __('Nothing was imported. Had you already imported this blog?') );
     158                $title    = __('Blogger Blogs');
     159                $name     = __('Blog Name');
     160                $url      = __('Blog URL');
     161                $action   = __('The Magic Button');
     162                $posts    = __('Posts');
     163                $comments = __('Comments');
     164                $noscript = __('This feature requires Javascript but it seems to be disabled. Please enable Javascript and then reload this page. Don\'t worry, you can turn it back off when you\'re done.');
     165
     166                $interval = STATUS_INTERVAL * 1000;
     167
     168                foreach ( $this->blogs as $i => $blog ) {
     169                        if ( $blog['mode'] == 'init' )
     170                                $value = $start;
     171                        elseif ( $blog['mode'] == 'posts' || $blog['mode'] == 'comments' )
     172                                $value = $continue;
     173                        else
     174                                $value = $authors;
     175                        $blogtitle = js_escape( $blog['title'] );
     176                        $pdone = isset($blog['posts_done']) ? (int) $blog['posts_done'] : 0;
     177                        $cdone = isset($blog['comments_done']) ? (int) $blog['comments_done'] : 0;
     178                        $init .= "blogs[$i]=new blog($i,'$blogtitle','{$blog['mode']}'," . $this->get_js_status($i) . ');';
     179                        $pstat = "<div class='ind' id='pind$i'>&nbsp;</div><div id='pstat$i' class='stat'>$pdone/{$blog['total_posts']}</div>";
     180                        $cstat = "<div class='ind' id='cind$i'>&nbsp;</div><div id='cstat$i' class='stat'>$cdone/{$blog['total_comments']}</div>";
     181                        $rows .= "<tr id='blog$i'><td class='blogtitle'>$blogtitle</td><td class='bloghost'>{$blog['host']}</td><td class='bar'>$pstat</td><td class='bar'>$cstat</td><td class='submit'><input type='submit' id='submit$i' value='$value' /><input type='hidden' name='blog' value='$i' /></td></tr>\n";
     182                }
     183
     184                echo "<div class='wrap'><h2>$title</h2><noscript>$noscript</noscript><table cellpadding='5px'><thead><td>$name</td><td>$url</td><td>$posts</td><td>$comments</td><td>$action</td></thead>\n$rows</table></form></div>";
     185                echo "
     186                <script type='text/javascript'>
     187                        var strings = {cont:'$continue',stop:'$stop',stopping:'$stopping',authors:'$authors',nothing:'$nothing'};
     188                        var blogs = {};
     189                        function blog(i, title, mode, status){
     190                                this.blog   = i;
     191                                this.mode   = mode;
     192                                this.title  = title;
     193                                this.status = status;
     194                                this.button = document.getElementById('submit'+this.blog);
     195                        };
     196                        blog.prototype = {
     197                                start: function() {
     198                                        this.cont = true;
     199                                        this.kick();
     200                                        this.check();
     201                                },
     202                                kick: function() {
     203                                        ++this.kicks;
     204                                        var i = this.blog;
     205                                        jQuery.post('admin.php?import=blogger&noheader=true',{blog:this.blog},function(text,result){blogs[i].kickd(text,result)});
     206                                },
     207                                check: function() {
     208                                        ++this.checks;
     209                                        var i = this.blog;
     210                                        jQuery.post('admin.php?import=blogger&noheader=true&status=true',{blog:this.blog},function(text,result){blogs[i].checkd(text,result)});
     211                                },
     212                                kickd: function(text, result) {
     213                                        if ( result == 'error' ) {
     214                                                // TODO: exception handling
     215                                                if ( this.cont )
     216                                                        setTimeout('blogs['+this.blog+'].kick()', 1000);
     217                                        } else {
     218                                                if ( text == 'done' ) {
     219                                                        this.stop();
     220                                                        this.done();
     221                                                } else if ( text == 'nothing' ) {
     222                                                        this.stop();
     223                                                        this.nothing();
     224                                                } else if ( text == 'continue' ) {
     225                                                        this.kick();
     226                                                } else if ( this.mode = 'stopped' )
     227                                                        jQuery(this.button).attr('value', strings.cont);
     228                                        }
     229                                        --this.kicks;
     230                                },
     231                                checkd: function(text, result) {
     232                                        if ( result == 'error' ) {
     233                                                // TODO: exception handling
     234                                        } else {
     235                                                eval('this.status='+text);
     236                                                jQuery('#pstat'+this.blog).empty().append(this.status.p1+'/'+this.status.p2);
     237                                                jQuery('#cstat'+this.blog).empty().append(this.status.c1+'/'+this.status.c2);
     238                                                this.update();
     239                                                if ( this.cont || this.kicks > 0 )
     240                                                        setTimeout('blogs['+this.blog+'].check()', $interval);
     241                                        }
     242                                        --this.checks;
     243                                },
     244                                update: function() {
     245                                        jQuery('#pind'+this.blog).width(((this.status.p1>0&&this.status.p2>0)?(this.status.p1/this.status.p2*jQuery('#pind'+this.blog).parent().width()):1)+'px');
     246                                        jQuery('#cind'+this.blog).width(((this.status.c1>0&&this.status.c2>0)?(this.status.c1/this.status.c2*jQuery('#cind'+this.blog).parent().width()):1)+'px');
     247                                },
     248                                stop: function() {
     249                                        this.cont = false;
     250                                },
     251                                done: function() {
     252                                        this.mode = 'authors';
     253                                        jQuery(this.button).attr('value', strings.authors);
     254                                },
     255                                nothing: function() {
     256                                        this.mode = 'nothing';
     257                                        jQuery(this.button).remove();
     258                                        alert(strings.nothing);
     259                                },
     260                                getauthors: function() {
     261                                        if ( jQuery('div.wrap').length > 1 )
     262                                                jQuery('div.wrap').gt(0).remove();
     263                                        jQuery('div.wrap').empty().append('<h2>$authhead</h2><h3>' + this.title + '</h3>');
     264                                        jQuery('div.wrap').append('<p id=\"auth\">$loadauth</p>');
     265                                        jQuery('p#auth').load('index.php?import=blogger&noheader=true&authors=1',{blog:this.blog});
     266                                },
     267                                init: function() {
     268                                        this.update();
     269                                        var i = this.blog;
     270                                        jQuery(this.button).bind('click', function(){return blogs[i].click();});
     271                                        this.kicks = 0;
     272                                        this.checks = 0;
     273                                },
     274                                click: function() {
     275                                        if ( this.mode == 'init' || this.mode == 'stopped' || this.mode == 'posts' || this.mode == 'comments' ) {
     276                                                this.mode = 'started';
     277                                                this.start();
     278                                                jQuery(this.button).attr('value', strings.stop);
     279                                        } else if ( this.mode == 'started' ) {
     280                                                return false; // let it run...
     281                                                this.mode = 'stopped';
     282                                                this.stop();
     283                                                if ( this.checks > 0 || this.kicks > 0 ) {
     284                                                        this.mode = 'stopping';
     285                                                        jQuery(this.button).attr('value', strings.stopping);
     286                                                } else {
     287                                                        jQuery(this.button).attr('value', strings.cont);
     288                                                }
     289                                        } else if ( this.mode == 'authors' ) {
     290                                                document.location = 'index.php?import=blogger&authors=1&blog='+this.blog;
     291                                                //this.mode = 'authors2';
     292                                                //this.getauthors();
     293                                        }
     294                                        return false;
     295                                }
     296                        };
     297                        $init
     298                        jQuery.each(blogs, function(i, me){me.init();});
     299                </script>\n";
     300        }
     301
     302        // Handy function for stopping the script after a number of seconds.
     303        function have_time() {
     304                global $importer_started;
     305                if ( time() - $importer_started > MAX_EXECUTION_TIME )
     306                        die('continue');
     307                return true;
     308        }
     309
     310        function get_total_results($type, $host) {
     311                $headers = array(
     312                        "GET /feeds/$type/default?max-results=1&start-index=2 HTTP/1.0",
     313                        "Host: $host",
     314                        "Authorization: AuthSub token=\"$this->token\""
     315                );
     316                $request = join( "\r\n", $headers ) . "\r\n\r\n";
     317                $sock = $this->_get_blogger_sock( $host );
     318                if ( ! $sock ) return;
     319                $response = $this->_txrx( $sock, $request );
     320                $response = $this->parse_response( $response );
     321                $parser = xml_parser_create();
     322                xml_parse_into_struct($parser, $response['body'], $struct, $index);
     323                xml_parser_free($parser);
     324                $total_results = $struct[$index['OPENSEARCH:TOTALRESULTS'][0]]['value'];
     325                return (int) $total_results;
     326        }
     327
     328        function import_blog($blogID) {
     329                global $importing_blog;
     330                $importing_blog = $blogID;
     331
     332                if ( isset($_GET['authors']) )
     333                        return print($this->get_author_form());
     334
     335                header('Content-Type: text/plain');
     336
     337                if ( isset($_GET['status']) )
     338                        die($this->get_js_status());
     339
     340                if ( isset($_GET['saveauthors']) )
     341                        die($this->save_authors());
     342
     343                $blog = $this->blogs[$blogID];
     344                $total_results = $this->get_total_results('posts', $blog['host']);
     345                $this->blogs[$importing_blog]['total_posts'] = $total_results;
     346
     347                $start_index = $total_results - MAX_RESULTS + 1;
     348
     349                if ( isset( $this->blogs[$importing_blog]['posts_start_index'] ) )
     350                        $start_index = (int) $this->blogs[$importing_blog]['posts_start_index'];
     351                elseif ( $total_results > MAX_RESULTS )
     352                        $start_index = $total_results - MAX_RESULTS + 1;
    21353                else
    22                         echo "<p>$incompat</p>";
    23                 echo "</div>\n";
    24         }
    25 
    26         // Deletes saved data and redirect.
     354                        $start_index = 1;
     355
     356                // This will be positive until we have finished importing posts
     357                if ( $start_index > 0 ) {
     358                        // Grab all the posts
     359                        $this->blogs[$importing_blog]['mode'] = 'posts';
     360                        $query = "start-index=$start_index&max-results=" . MAX_RESULTS;
     361                        do {
     362                                $index = $struct = $entries = array();
     363                                $headers = array(
     364                                        "GET /feeds/posts/default?$query HTTP/1.0",
     365                                        "Host: {$blog['host']}",
     366                                        "Authorization: AuthSub token=\"$this->token\""
     367                                );
     368                                $request = join( "\r\n", $headers ) . "\r\n\r\n";
     369                                $sock = $this->_get_blogger_sock( $blog['host'] );
     370                                if ( ! $sock ) return; // TODO: Error handling
     371                                $response = $this->_txrx( $sock, $request );
     372       
     373                                $response = $this->parse_response( $response );
     374       
     375                                // Extract the entries and send for insertion
     376                                preg_match_all( '/<entry[^>]*>.*?<\/entry>/s', $response['body'], $matches );
     377                                if ( count( $matches[0] ) ) {
     378                                        $entries = array_reverse($matches[0]);
     379                                        foreach ( $entries as $entry ) {
     380                                                $entry = "<feed>$entry</feed>";
     381                                                $AtomParser = new AtomParser();
     382                                                $AtomParser->parse( $entry );
     383                                                $this->import_post($AtomParser->entry);
     384                                                unset($AtomParser);
     385                                        }
     386                                } else break;
     387
     388                                // Get the 'previous' query string which we'll use on the next iteration
     389                                $query = '';
     390                                $links = preg_match_all('/<link([^>]*)>/', $response['body'], $matches);
     391                                if ( count( $matches[1] ) )
     392                                        foreach ( $matches[1] as $match )
     393                                                if ( preg_match('/rel=.previous./', $match) )
     394                                                        $query = html_entity_decode( preg_replace('/^.*href=[\'"].*\?(.+)[\'"].*$/', '$1', $match) );
     395
     396                                if ( $query ) {
     397                                        parse_str($query, $q);
     398                                        $this->blogs[$importing_blog]['posts_start_index'] = (int) $q['start-index'];
     399                                } else
     400                                        $this->blogs[$importing_blog]['posts_start_index'] = 0;
     401                                $this->save_vars();
     402                        } while ( !empty( $query ) && $this->have_time() );
     403                }
     404
     405                $total_results = $this->get_total_results( 'comments', $blog['host'] );
     406                $this->blogs[$importing_blog]['total_comments'] = $total_results;
     407
     408                if ( isset( $this->blogs[$importing_blog]['comments_start_index'] ) )
     409                        $start_index = (int) $this->blogs[$importing_blog]['comments_start_index'];
     410                elseif ( $total_results > MAX_RESULTS )
     411                        $start_index = $total_results - MAX_RESULTS + 1;
     412                else
     413                        $start_index = 1;
     414
     415                if ( $start_index > 0 ) {
     416                        // Grab all the comments
     417                        $this->blogs[$importing_blog]['mode'] = 'comments';
     418                        $query = "start-index=$start_index&max-results=" . MAX_RESULTS;
     419                        do {
     420                                $index = $struct = $entries = array();
     421                                $headers = array(
     422                                        "GET /feeds/comments/default?$query HTTP/1.0",
     423                                        "Host: {$blog['host']}",
     424                                        "Authorization: AuthSub token=\"$this->token\""
     425                                );
     426                                $request = join( "\r\n", $headers ) . "\r\n\r\n";
     427                                $sock = $this->_get_blogger_sock( $blog['host'] );
     428                                if ( ! $sock ) return; // TODO: Error handling
     429                                $response = $this->_txrx( $sock, $request );
     430
     431                                $response = $this->parse_response( $response );
     432
     433                                // Extract the comments and send for insertion
     434                                preg_match_all( '/<entry[^>]*>.*?<\/entry>/s', $response['body'], $matches );
     435                                if ( count( $matches[0] ) ) {
     436                                        $entries = array_reverse( $matches[0] );
     437                                        foreach ( $entries as $entry ) {
     438                                                $entry = "<feed>$entry</feed>";
     439                                                $AtomParser = new AtomParser();
     440                                                $AtomParser->parse( $entry );   
     441                                                $this->import_comment($AtomParser->entry);
     442                                                unset($AtomParser);
     443                                        }
     444                                }
     445
     446                                // Get the 'previous' query string which we'll use on the next iteration
     447                                $query = '';
     448                                $links = preg_match_all('/<link([^>]*)>/', $response['body'], $matches);
     449                                if ( count( $matches[1] ) )
     450                                        foreach ( $matches[1] as $match )
     451                                                if ( preg_match('/rel=.previous./', $match) )
     452                                                        $query = html_entity_decode( preg_replace('/^.*href=[\'"].*\?(.+)[\'"].*$/', '$1', $match) );
     453
     454                                parse_str($query, $q);
     455
     456                                $this->blogs[$importing_blog]['comments_start_index'] = (int) $q['start-index'];
     457                                $this->save_vars();
     458                        } while ( !empty( $query ) && $this->have_time() );
     459                }
     460                $this->blogs[$importing_blog]['mode'] = 'authors';
     461                $this->save_vars();
     462                if ( !$this->blogs[$importing_blog]['posts_done'] && !$this->blogs[$importing_blog]['comments_done'] )
     463                        die('nothing');
     464                do_action('import_done', 'blogger');
     465                die('done');
     466        }
     467
     468        function convert_date( $date ) {
     469            preg_match('#([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(?:\.[0-9]+)?(Z|[\+|\-][0-9]{2,4}){0,1}#', $date, $date_bits);
     470            $offset = iso8601_timezone_to_offset( $date_bits[7] );
     471                $timestamp = gmmktime($date_bits[4], $date_bits[5], $date_bits[6], $date_bits[2], $date_bits[3], $date_bits[1]);
     472                $timestamp -= $offset; // Convert from Blogger local time to GMT
     473                $timestamp += get_option('gmt_offset') * 3600; // Convert from GMT to WP local time
     474                return gmdate('Y-m-d H:i:s', $timestamp);
     475        }
     476
     477        function no_apos( $string ) {
     478                return str_replace( '&apos;', "'", $string);
     479        }
     480
     481        function min_whitespace( $string ) {
     482                return preg_replace( '|\s+|', ' ', $string );
     483        }
     484
     485        function import_post( $entry ) {
     486                global $wpdb, $importing_blog;
     487
     488                // The old permalink is all Blogger gives us to link comments to their posts.
     489                if ( isset( $entry->draft ) )
     490                        $rel = 'self';
     491                else
     492                        $rel = 'alternate';
     493                foreach ( $entry->links as $link ) {
     494                        if ( $link['rel'] == $rel ) {
     495                                $parts = parse_url( $link['href'] );
     496                                $entry->old_permalink = $parts['path'];
     497                                break;
     498                        }
     499                }
     500
     501                $post_date    = $this->convert_date( $entry->published );
     502                $post_content = trim( addslashes( $this->no_apos( html_entity_decode( $entry->content ) ) ) );
     503                $post_title   = trim( addslashes( $this->no_apos( $this->min_whitespace( $entry->title ) ) ) );
     504                $post_status  = isset( $entry->draft ) ? 'draft' : 'publish';
     505
     506                // Clean up content
     507                $post_content = preg_replace('|<(/?[A-Z]+)|e', "'<' . strtolower('$1')", $post_content);
     508                $post_content = str_replace('<br>', '<br />', $post_content);
     509                $post_content = str_replace('<hr>', '<hr />', $post_content);
     510
     511                // Checks for duplicates
     512                if (
     513                        isset( $this->blogs[$importing_blog]['posts'][$entry->old_permalink] ) ||
     514                        post_exists( $post_title, $post_content, $post_date )
     515                ) {
     516                        ++$this->blogs[$importing_blog]['posts_skipped'];
     517                } else {
     518                        $post = compact('post_date', 'post_content', 'post_title', 'post_status');
     519
     520                        $post_id = wp_insert_post($post);
     521
     522                        wp_create_categories( array_map( 'addslashes', $entry->categories ), $post_id );
     523
     524                        $author = $this->no_apos( strip_tags( $entry->author ) );
     525
     526                        add_post_meta( $post_id, 'blogger_blog', $this->blogs[$importing_blog]['host'], true );
     527                        add_post_meta( $post_id, 'blogger_author', $author, true );
     528                        add_post_meta( $post_id, 'blogger_permalink', $entry->old_permalink, true );
     529
     530                        $this->blogs[$importing_blog]['posts'][$entry->old_permalink] = $post_id;
     531                        ++$this->blogs[$importing_blog]['posts_done'];
     532                }
     533                $this->save_vars();
     534        }
     535
     536        function import_comment( $entry ) {
     537                global $importing_blog;
     538
     539                // Drop the #fragment and we have the comment's old post permalink.
     540                foreach ( $entry->links as $link ) {
     541                        if ( $link['rel'] == 'alternate' ) {
     542                                $parts = parse_url( $link['href'] );
     543                                $entry->old_permalink = $parts['fragment'];
     544                                $entry->old_post_permalink = $parts['path'];
     545                                break;
     546                        }
     547                }
     548
     549                $comment_post_ID = $this->blogs[$importing_blog]['posts'][$entry->old_post_permalink];
     550                $comment_author  = addslashes( $this->no_apos( strip_tags( $entry->author ) ) );
     551                $comment_date    = $this->convert_date( $entry->updated );
     552                $comment_content = addslashes( $this->no_apos( html_entity_decode( $entry->content ) ) );
     553
     554                // Clean up content
     555                $comment_content = preg_replace('|<(/?[A-Z]+)|e', "'<' . strtolower('$1')", $comment_content);
     556                $comment_content = str_replace('<br>', '<br />', $comment_content);
     557                $comment_content = str_replace('<hr>', '<hr />', $comment_content);
     558
     559                // Checks for duplicates
     560                if (
     561                        isset( $this->blogs[$importing_blog]['comments'][$entry->old_permalink] ) ||
     562                        comment_exists( $comment_author, $comment_date )
     563                ) {
     564                        ++$this->blogs[$importing_blog]['comments_skipped'];
     565                } else {
     566                        $comment = compact('comment_post_ID', 'comment_author', 'comment_date', 'comment_content');
     567
     568                        $comment_id = wp_insert_comment($comment);
     569
     570                        $this->blogs[$importing_blog]['comments'][$entry->old_permalink] = $comment_id;
     571
     572                        ++$this->blogs[$importing_blog]['comments_done'];
     573                }
     574                $this->save_vars();
     575        }
     576
     577        function get_js_status($blog = false) {
     578                global $importing_blog;
     579                if ( $blog === false )
     580                        $blog = $this->blogs[$importing_blog];
     581                else
     582                        $blog = $this->blogs[$blog];
     583                $p1 = isset( $blog['posts_done'] ) ? (int) $blog['posts_done'] : 0;
     584                $p2 = isset( $blog['total_posts'] ) ? (int) $blog['total_posts'] : 0;
     585                $c1 = isset( $blog['comments_done'] ) ? (int) $blog['comments_done'] : 0;
     586                $c2 = isset( $blog['total_comments'] ) ? (int) $blog['total_comments'] : 0;
     587                return "{p1:$p1,p2:$p2,c1:$c1,c2:$c2}";
     588        }
     589
     590        function get_author_form($blog = false) {
     591                global $importing_blog, $wpdb, $current_user;
     592                if ( $blog === false )
     593                        $blog = & $this->blogs[$importing_blog];
     594                else
     595                        $blog = & $this->blogs[$blog];
     596
     597                if ( !isset( $blog['authors'] ) ) {
     598                        $post_ids = array_values($blog['posts']);
     599                        $authors = (array) $wpdb->get_col("SELECT DISTINCT meta_value FROM $wpdb->postmeta WHERE meta_key = 'blogger_author' AND post_id IN (" . join( ',', $post_ids ) . ")");
     600                        $blog['authors'] = array_map(null, $authors, array_fill(0, count($authors), $current_user->ID));
     601                        $this->save_vars();
     602                }
     603
     604                $directions = __('All posts were imported with the current user as author. Use this form to move each Blogger user\'s posts to a different WordPress user. You may <a href="users.php">add users</a> and then return to this page and complete the user mapping. This form may be used as many times as you like until you activate the "Restart" function below.');
     605                $heading = __('Author mapping');
     606                $blogtitle = "{$blog['title']} ({$blog['host']})";
     607                $mapthis = __('Blogger username');
     608                $tothis = __('WordPress login');
     609                $submit = js_escape( __('Save Changes &raquo;') );
     610
     611                foreach ( $blog['authors'] as $i => $author )
     612                        $rows .= "<tr><td><label for='authors[$i]'>{$author[0]}</label></td><td><select name='authors[$i]' id='authors[$i]'>" . $this->get_user_options($author[1]) . "</select></td></tr>";
     613
     614                return "<div class='wrap'><h2>$heading</h2><h3>$blogtitle</h3><p>$directions</p><form action='index.php?import=blogger&noheader=true&saveauthors=1' method='post'><input type='hidden' name='blog' value='$importing_blog' /><table cellpadding='5'><thead><td>$mapthis</td><td>$tothis</td></thead>$rows<tr><td></td><td class='submit'><input type='submit' class='authorsubmit' value='$submit' /></td></tr></table></form></div>";
     615        }
     616
     617        function get_user_options($current) {
     618                global $wpdb, $importer_users;
     619                if ( ! isset( $importer_users ) )
     620                        $importer_users = (array) get_users_of_blog();
     621
     622                foreach ( $importer_users as $user ) {
     623                        $sel = ( $user->user_id == $current ) ? " selected='selected'" : '';
     624                        $options .= "<option value='$user->user_id'$sel>$user->display_name</option>";
     625                }
     626               
     627                return $options;
     628        }
     629
     630        function save_authors() {
     631                global $importing_blog, $wpdb;
     632                $authors = (array) $_POST['authors'];
     633
     634                $host = $this->blogs[$importing_blog]['host'];
     635
     636                // Get an array of posts => authors
     637                $post_ids = (array) $wpdb->get_col("SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'blogger_blog' AND meta_value = '$host'");
     638                $post_ids = join( ',', $post_ids );
     639                $results = (array) $wpdb->get_results("SELECT post_id, meta_value FROM $wpdb->postmeta WHERE meta_key = 'blogger_author' AND post_id IN ($post_ids)");
     640                foreach ( $results as $row )
     641                        $authors_posts[$row->post_id] = $row->meta_value;
     642
     643                foreach ( $authors as $author => $user_id ) {
     644                        $user_id = (int) $user_id;
     645
     646                        // Skip authors that haven't been changed
     647                        if ( $user_id == $this->blogs[$importing_blog]['authors'][$author][1] )
     648                                continue;
     649
     650                        // Get a list of the selected author's posts
     651                        $post_ids = (array) array_keys( $authors_posts, $this->blogs[$importing_blog]['authors'][$author][0] );
     652                        $post_ids = join( ',', $post_ids);
     653
     654                        $wpdb->query("UPDATE $wpdb->posts SET post_author = $user_id WHERE id IN ($post_ids)");
     655                        $this->blogs[$importing_blog]['authors'][$author][1] = $user_id;
     656                }
     657                $this->save_vars();
     658
     659                wp_redirect('edit.php');
     660        }
     661
     662        function _get_auth_sock() {
     663                // Connect to https://www.google.com
     664                if ( !$sock = @ fsockopen('ssl://www.google.com', 443, $errno, $errstr) ) {
     665                        $this->uh_oh(
     666                                __('Could not connect to https://www.google.com'),
     667                                __('There was a problem opening a secure connection to Google. This is what went wrong:'),
     668                                "$errstr ($errno)"
     669                        );
     670                        return false;
     671                }
     672                return $sock;
     673        }
     674
     675        function _get_blogger_sock($host = 'www.blogger.com') {
     676                if ( !$sock = @ fsockopen($host, 80, $errno, $errstr) ) {
     677                        $this->uh_oh(
     678                                sprintf( __('Could not connect to %s'), $host ),
     679                                __('There was a problem opening a connection to Blogger. This is what went wrong:'),
     680                                "$errstr ($errno)"
     681                        );
     682                        return false;
     683                }
     684                return $sock;
     685        }
     686
     687        function _txrx( $sock, $request ) {
     688                fwrite( $sock, $request );
     689                while ( ! feof( $sock ) )
     690                        $response .= @ fread ( $sock, 8192 );
     691                fclose( $sock );
     692                return $response;
     693        }
     694
     695        function revoke($token) {
     696                $headers = array(
     697                        "GET /accounts/AuthSubRevokeToken HTTP/1.0",
     698                        "Authorization: AuthSub token=\"$token\""
     699                );
     700                $request = join( "\r\n", $headers ) . "\r\n\r\n";
     701                $sock = $this->_get_auth_sock( );
     702                if ( ! $sock ) return false;
     703                $this->_txrx( $sock, $request );
     704        }
     705
    27706        function restart() {
    28                 delete_option('import-blogger');
    29                 wp_redirect("admin.php?import=blogger");
    30                 die();
    31         }
    32 
    33         // Generates a string that will make the page reload in a specified interval.
    34         function refresher($msec) {
    35                 if ( $msec )
    36                         return "<html><head><script type='text/javascript'>window.onload=setTimeout('window.location.reload()', $msec);</script>\n</head>\n<body>\n";
    37                 else
    38                         return "<html><head><script type='text/javascript'>window.onload=window.location.reload();</script>\n</head>\n<body>\n";
     707                global $wpdb;
     708                $options = get_option( 'blogger_importer' );
     709               
     710                if ( isset( $options['token'] ) )
     711                        $this->revoke( $options['token'] );
     712
     713                delete_option('blogger_importer');
     714                $wpdb->query("DELETE FROM $wpdb->postmeta WHERE meta_key = 'blogger_author'");
     715                wp_redirect('?import=blogger');
    39716        }
    40717
    … …  
    61738
    62739                return array("code" => $response_code, "header" => $response_header_array, "cookies" => $cookie_array, "body" => $response_body);
    63         }
    64 
    65         // Prints a form for the user to enter Blogger creds.
    66         function login_form($text='') {
    67                 echo '<h1>' . __('Log in to Blogger') . "</h1>\n$text\n";
    68                 echo '<form method="post" action="admin.php?import=blogger&amp;noheader=true&amp;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>';
    69                 die;
    70         }
    71 
    72         // Sends creds to Blogger, returns the session cookies an array of headers.
    73         function login_blogger($user, $pass) {
    74                 $_url = 'http://www.blogger.com/login.do';
    75                 $params = "username=$user&password=$pass";
    76                 $ch = curl_init();
    77                 curl_setopt($ch, CURLOPT_POST,1);
    78                 curl_setopt($ch, CURLOPT_POSTFIELDS,$params);
    79                 curl_setopt($ch, CURLOPT_URL,$_url);
    80                 curl_setopt($ch, CURLOPT_USERAGENT, 'Blogger Exporter');
    81                 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
    82                 curl_setopt($ch, CURLOPT_HEADER,1);
    83                 curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
    84                 $response = curl_exec ($ch);
    85 
    86                 $response = $this->parse_response($response);
    87 
    88                 sleep(1);
    89 
    90                 return $response['cookies'];
    91         }
    92 
    93         // Requests page from Blogger, returns the response array.
    94         function get_blogger($url, $header = '', $user=false, $pass=false) {
    95                 $ch = curl_init();
    96                 if ($user && $pass) curl_setopt($ch, CURLOPT_USERPWD,"{$user}:{$pass}");
    97                 curl_setopt($ch, CURLOPT_URL,$url);
    98                 curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    99                 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    100                 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    101                 curl_setopt($ch, CURLOPT_USERAGENT, 'Blogger Exporter');
    102                 curl_setopt($ch, CURLOPT_HEADER,1);
    103                 if (is_array($header)) curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    104                 $response = curl_exec ($ch);
    105 
    106                 $response = $this->parse_response($response);
    107                 $response['url'] = $url;
    108 
    109                 if (curl_errno($ch)) {
    110                         print curl_error($ch);
    111                 } else {
    112                         curl_close($ch);
    113                 }
    114 
    115                 return $response;
    116         }
    117 
    118         // Posts data to Blogger, returns response array.
    119         function post_blogger($url, $header = false, $paramary = false, $parse=true) {
    120                 $params = '';
    121                 if ( is_array($paramary) ) {
    122                         foreach($paramary as $key=>$value)
    123                                 if($key && $value != '')
    124                                         $params.=$key."=".urlencode(stripslashes($value))."&";
    125                 }
    126                 if ($user && $pass) $params .= "username=$user&password=$pass";
    127                 $params = trim($params,'&');
    128                 $ch = curl_init();
    129                 curl_setopt($ch, CURLOPT_POST,1);
    130                 curl_setopt($ch, CURLOPT_POSTFIELDS,$params);
    131                 if ($user && $pass) curl_setopt($ch, CURLOPT_USERPWD,"{$user}:{$pass}");
    132                 curl_setopt($ch, CURLOPT_URL,$url);
    133                 curl_setopt($ch, CURLOPT_USERAGENT, 'Blogger Exporter');
    134                 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    135                 curl_setopt($ch, CURLOPT_HEADER,$parse);
    136                 curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
    137                 if ($header) curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    138                 $response = curl_exec ($ch);
    139 
    140                 if ($parse) {
    141                         $response = $this->parse_response($response);
    142                         $response['url'] = $url;
    143                         return $response;
    144                 }
    145 
    146                 return $response;
    147         }
    148 
    149         // Prints the list of blogs for import.
    150         function show_blogs() {
    151                 global $import;
    152                 echo '<h1>' . __('Selecting a Blog') . "</h1>\n<ul>";
    153                 foreach ( $this->import['blogs'] as $blog ) {
    154                         if (9 == $blog['nextstep']) $status = "100%";
    155                         elseif (8 == $blog['nextstep']) $status = "90%";
    156                         elseif (7 == $blog['nextstep']) $status = "82.5%";
    157                         elseif (6 == $blog['nextstep']) $status = "75%";
    158                         elseif (5 == $blog['nextstep']) $status = "57%";
    159                         elseif (4 == $blog['nextstep']) $status = "28%";
    160                         elseif (3 == $blog['nextstep']) $status = "14%";
    161                         else $status = "0%";
    162                         echo "\t<li><a href='admin.php?import=blogger&amp;noheader=true&amp;blog={$blog['id']}'>{$blog['title']}</a> $status</li>\n";
    163                 }
    164                 die("</ul>\n");
    165         }
    166 
    167         // Publishes.
    168         function publish_blogger($i, $text) {
    169                 $head = $this->refresher(2000) . "<h1>$text</h1>\n";
    170                 if ( ! strstr($this->import['blogs'][$_GET['blog']]['publish'][$i], 'http') ) {
    171                         // First call. Start the publish process with a fresh set of cookies.
    172                         $this->import['cookies'] = $this->login_blogger($this->import['user'], $this->import['pass']);
    173                         update_option('import-blogger', $this->import);
    174                         $paramary = array('blogID' => $_GET['blog'], 'all' => '1', 'republishAll' => 'Republish Entire Blog', 'publish' => '1', 'redirectUrl' => "/publish.do?blogID={$_GET['blog']}&inprogress=true");
    175 
    176                         $response = $this->post_blogger("http://www.blogger.com/publish.do?blogID={$_GET['blog']}", $this->import['cookies'], $paramary);
    177                         if ( $response['code'] == '302' ) {
    178                                 $url = str_replace('publish.g', 'publish-body.g', $response['header']['Location']);
    179                                 $this->import['blogs'][$_GET['blog']]['publish'][$i] = $url;
    180                                 update_option('import-blogger', $this->import);
    181                                 $response = $this->get_blogger($url, $this->import['cookies']);
    182                                 preg_match('#<p class="progressIndicator">.*</p>#U', $response['body'], $matches);
    183                                 $progress = $matches[0];
    184                                 die($head . $progress);
    185                         } else {
    186                                 $this->import['blogs'][$_GET['blog']]['publish'][$i] = false;
    187                                 update_option('import-blogger', $this->import);
    188                                 die($head);
    189                         }
    190                 } else {
    191                         // Subsequent call. Keep checking status until Blogger reports publish complete.
    192                         $url = $this->import['blogs'][$_GET['blog']]['publish'][$i];
    193                         $response = $this->get_blogger($url, $this->import['cookies']);
    194                         if ( preg_match('#<p class="progressIndicator">.*</p>#U', $response['body'], $matches) ) {
    195                                 $progress = $matches[0];
    196                                 if ( strstr($progress, '100%') ) {
    197                                         $this->set_next_step($i);
    198                                         $progress .= '<p>'.__('Moving on...').'</p>';
    199                                 }
    200                                 die($head . $progress);
    201                         } else {
    202                                 $this->import['blogs'][$_GET['blog']]['publish'][$i] = false;
    203                                 update_option('import-blogger', $this->import);
    204                                 die("$head<p>" . __('Trying again...') . '</p>');
    205                         }
    206                 }
    207         }
    208 
    209         // Sets next step, saves options
    210         function set_next_step($step) {
    211                 $this->import['blogs'][$_GET['blog']]['nextstep'] = $step;
    212                 update_option('import-blogger', $this->import);
    213         }
    214 
    215         // Redirects to next step
    216         function do_next_step() {
    217                 wp_redirect("admin.php?import=blogger&noheader=true&blog={$_GET['blog']}");
    218                 die();
    219         }
    220 
    221         // Step 0: Do Blogger login, get blogid/title pairs.
    222         function do_login() {
    223                 if ( ( ! $this->import['user'] && ! is_array($this->import['cookies']) ) ) {
    224                         // The user must provide a Blogger username and password.
    225                         if ( ! ( $_POST['user'] && $_POST['pass'] ) ) {
    226                                 $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>');
    227                         }
    228 
    229                         // Try logging in. If we get an array of cookies back, we at least connected.
    230                         $this->import['cookies'] = $this->login_blogger($_POST['user'], $_POST['pass']);
    231                         if ( !is_array( $this->import['cookies'] ) ) {
    232                                 $this->login_form(__('Login failed. Please enter your credentials again.'));
    233                         }
    234 
    235                         // Save the password so we can log the browser in when it's time to publish.
    236                         $this->import['pass'] = $_POST['pass'];
    237                         $this->import['user'] = $_POST['user'];
    238 
    239                         // Get the Blogger welcome page and scrape the blog numbers and names from it
    240                         $response = $this->get_blogger('http://www.blogger.com/home', $this->import['cookies']);
    241                         if (! stristr($response['body'], 'signed in as') ) $this->login_form(__('Login failed. Please re-enter your username and password.'));
    242                         $blogsary = array();
    243                         preg_match_all('#posts\.g\?blogID=(\d+)">([^<]+)</a>#U', $response['body'], $blogsary);
    244                         if ( ! count( $blogsary[1] < 1 ) )
    245                                 wp_die(__('No blogs found for this user.'));
    246                         $this->import['blogs'] = array();
    247                         $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>';
    248                         foreach ( $blogsary[1] as $key => $id ) {
    249                                 // Define the required Blogger options.
    250                                 $blog_opts = array(
    251                                         'blog-options-basic' => false,
    252                                         'blog-options-archiving' => array('archiveFrequency' => 'm'),
    253                                         'blog-publishing' => array('publishMode'=>'0', 'blogID' => "$id", 'subdomain' => mt_rand().mt_rand(), 'pingWeblogs' => 'false'),
    254                                         'blog-formatting' => array('timeStampFormat' => '0', 'encoding'=>'UTF-8', 'convertLineBreaks'=>'false', 'floatAlignment'=>'false'),
    255                                         'blog-comments' => array('commentsTimeStampFormat' => '0'),
    256                                         'template-edit' => array( 'templateText' =>  str_replace('%title%', trim($blogsary[2][$key]), $template) )
    257                                 );
    258 
    259                                 // Build the blog options array template
    260                                 foreach ($blog_opts as $blog_opt => $modify)
    261                                         $new_opts["$blog_opt"] = array('backup'=>false, 'modify' => $modify, 'error'=>false);
    262 
    263                                 $this->import['blogs']["$id"] = array(
    264                                         'id' => $id,
    265                                         'title' => trim($blogsary[2][$key]),
    266                                         'options' => $new_opts,
    267                                         'url' => false,
    268                                         'publish_cookies' => false,
    269                                         'published' => false,
    270                                         'archives' => false,
    271                                         'lump_authors' => false,
    272                                         'newusers' => array(),
    273                                         'nextstep' => 2
    274                                 );
    275                         }
    276                         update_option('import-blogger', $this->import);
    277                         wp_redirect("admin.php?import=blogger&noheader=true&step=1");
    278                 }
    279                 die();
    280         }
    281 
    282         // Step 1: Select one of the blogs belonging to the user logged in.
    283         function select_blog() {
    284                 if ( is_array($this->import['blogs']) ) {
    285                         $this->show_blogs();
    286                         die();
    287                 } else {
    288                         $this->restart();
    289                 }
    290         }
    291 
    292         // Step 2: Backup the Blogger options pages, updating some of them.
    293         function backup_settings() {
    294                 $output.= '<h1>'.__('Backing up Blogger options')."</h1>\n";
    295                 $form = false;
    296                 foreach ($this->import['blogs'][$_GET['blog']]['options'] as $blog_opt => $optary) {
    297                         if ( $blog_opt == $_GET['form'] ) {
    298                                 // Save the posted form data
    299                                 $this->import['blogs'][$_GET['blog']]['options']["$blog_opt"]['backup'] = $_POST;
    300                                 update_option('import-blogger',$this->import);
    301 
    302                                 // Post the modified form data to Blogger
    303                                 if ( $optary['modify'] ) {
    304                                         $posturl = "http://www.blogger.com/{$blog_opt}.do";
    305                                         $headers = array_merge($this->import['blogs'][$_GET['blog']]['options']["$blog_opt"]['cookies'], $this->import['cookies']);
    306                                         if ( 'blog-publishing' == $blog_opt ) {
    307                                                 if ( $_POST['publishMode'] > 0 ) {
    308                                                         $response = $this->get_blogger("http://www.blogger.com/blog-publishing.g?blogID={$_GET['blog']}&publishMode=0", $headers);
    309                                                         if ( $response['code'] >= 400 )
    310                                                                 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>');
    311                                                         $this->import['blogs'][$_GET['blog']]['url'] = 'http://' . $optary['modify']['subdomain'] . '.blogspot.com/';
    312                                                         sleep(2);
    313                                                 } else {
    314                                                         $this->import['blogs'][$_GET['blog']]['url'] = 'http://' . $_POST['subdomain'] . '.blogspot.com/';
    315                                                         update_option('import-blogger', $this->import);
    316                                                         $output .= "<del><p>$blog_opt</p></del>\n";
    317                                                         continue;
    318                                                 }
    319                                                 $paramary = $optary['modify'];
    320                                         } else {
    321                                                 $paramary = array_merge($_POST, $optary['modify']);
    322                                         }
    323                                         $response = $this->post_blogger($posturl, $headers, $paramary);
    324                                         if ( $response['code'] >= 400 || strstr($response['body'], 'There are errors on this form') )
    325                                                 wp_die('<p>'.__('Error on form submission. Retry or reset the importer.').'</p>' . addslashes(print_r($response, 1)));
    326                                 }
    327                                 $output .= "<del><p>$blog_opt</p></del>\n";
    328                         } elseif ( is_array($this->import['blogs'][$_GET['blog']]['options']["$blog_opt"]['backup']) ) {
    329                                 // This option set has already been backed up.
    330                                 $output .= "<del><p>$blog_opt</p></del>\n";
    331                         } elseif ( ! $form ) {
    332                                 // This option page needs to be downloaded and given to the browser for submission back to this script.
    333                                 $response = $this->get_blogger("http://www.blogger.com/{$blog_opt}.g?blogID={$_GET['blog']}", $this->import['cookies']);
    334                                 $this->import['blogs'][$_GET['blog']]['options']["$blog_opt"]['cookies'] = $response['cookies'];
    335                                 update_option('import-blogger',$this->import);
    336                                 $body = $response['body'];
    337                                 $body = preg_replace("|\<!DOCTYPE.*\<body[^>]*>|ms","",$body);
    338                                 $body = preg_replace("|/?{$blog_opt}.do|","admin.php?import=blogger&amp;noheader=true&amp;step=2&amp;blog={$_GET['blog']}&amp;form={$blog_opt}",$body);
    339                                 $body = str_replace("name='submit'","name='supermit'",$body);
    340                                 $body = str_replace('name="submit"','name="supermit"',$body);
    341                                 $body = str_replace('</body>','',str_replace('</html>','',$body));
    342                                 $form = "<div style='height:0px;width:0px;overflow:hidden;'>";
    343                                 $form.= $body;
    344                                 $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>";
    345                                 $output.= '<p>'.sprintf(__('<strong>%s</strong> in progress, please wait...'), $blog_opt)."</p>\n";
    346                         } else {
    347                                 $output.= "<p>$blog_opt</p>\n";
    348                         }
    349                 }
    350                 if ( $form )
    351                         die($output . $form);
    352 
    353                 $this->set_next_step(4);
    354                 $this->do_next_step();
    355         }
    356 
    357         // Step 3: Cancelled :-)
    358 
    359         // Step 4: Publish with the new template and settings.
    360         function publish_blog() {
    361                 $this->publish_blogger(5, __('Publishing with new template and options'));
    362         }
    363 
    364         // Step 5: Get the archive URLs from the new blog.
    365         function get_archive_urls() {
    366                 $bloghtml = $this->get_blogger($this->import['blogs'][$_GET['blog']]['url']);
    367                 if (! strstr($bloghtml['body'], '<a class="archive"') )
    368                         wp_die(__('Your Blogger blog did not take the new template or did not respond.'));
    369                 preg_match_all('#<a class="archive" href="([^"]*)"#', $bloghtml['body'], $archives);
    370                 foreach ($archives[1] as $archive) {
    371                         $this->import['blogs'][$_GET['blog']]['archives'][$archive] = false;
    372                 }
    373                 $this->set_next_step(6);
    374                 $this->do_next_step();
    375         }
    376 
    377         // Step 6: Get each monthly archive, import it, mark it done.
    378         function get_archive() {
    379                 global $wpdb;
    380                 $output = '<h2>'.__('Importing Blogger archives into WordPress').'</h2>';
    381                 $did_one = false;
    382                 $post_array = $posts = array();
    383                 foreach ( $this->import['blogs'][$_GET['blog']]['archives'] as $url => $status ) {
    384                         $archivename = substr(basename($url),0,7);
    385                         if ( $status || $did_one ) {
    386                                 $foo = 'bar';
    387                                 // Do nothing.
    388                         } else {
    389                                 // Import the selected month
    390                                 $postcount = 0;
    391                                 $skippedpostcount = 0;
    392                                 $commentcount = 0;
    393                                 $skippedcommentcount = 0;
    394                                 $status = __('in progress...');
    395                                 $this->import['blogs'][$_GET['blog']]['archives']["$url"] = $status;
    396                                 update_option('import-blogger', $import);
    397                                 $archive = $this->get_blogger($url);
    398                                 if ( $archive['code'] > 200 )
    399                                         continue;
    400                                 $posts = explode('<wordpresspost>', $archive['body']);
    401                                 for ($i = 1; $i < count($posts); $i = $i + 1) {
    402                                         $postparts = explode('<wordpresscomment>', $posts[$i]);
    403                                         $postinfo = explode('|W|P|', $postparts[0]);
    404                                         $post_date = $postinfo[0];
    405                                         $post_content = $postinfo[2];
    406                                         // Don't try to re-use the original numbers
    407                                         // because the new, longer numbers are too
    408                                         // big to handle as ints.
    409                                         //$post_number = $postinfo[3];
    410                                         $post_title = ( $postinfo[4] != '' ) ? $postinfo[4] : $postinfo[3];
    411                                         $post_author_name = $wpdb->escape(trim($postinfo[1]));
    412                                         $post_author_email = $postinfo[5] ? $postinfo[5] : 'user@wordpress.org';
    413 
    414                                         if ( $this->lump_authors ) {
    415                                                 // Ignore Blogger authors. Use the current user_ID for all posts imported.
    416                                                 $post_author = $GLOBALS['user_ID'];
    417                                         } else {
    418                                                 // Add a user for each new author encountered.
    419                                                 if (! username_exists($post_author_name) ) {
    420                                                         $user_login = $wpdb->escape($post_author_name);
    421                                                         $user_email = $wpdb->escape($post_author_email);
    422                                                         $user_password = substr(md5(uniqid(microtime())), 0, 6);
    423                                                         $result = wp_create_user( $user_login, $user_password, $user_email );
    424                                                         $status.= sprintf(__('Registered user <strong>%s</strong>.'), $user_login);
    425                                                         $this->import['blogs'][$_GET['blog']]['newusers'][] = $user_login;
    426                                                 }
    427                                                 $userdata = get_userdatabylogin( $post_author_name );
    428                                                 $post_author = $userdata->ID;
    429                                         }
    430                                         $post_date = explode(' ', $post_date);
    431                                         $post_date_Ymd = explode('/', $post_date[0]);
    432                                         $postyear = $post_date_Ymd[2];
    433                                         $postmonth = zeroise($post_date_Ymd[0], 2);
    434                                         $postday = zeroise($post_date_Ymd[1], 2);
    435                                         $post_date_His = explode(':', $post_date[1]);
    436                                         $posthour = zeroise($post_date_His[0], 2);
    437                                         $postminute = zeroise($post_date_His[1], 2);
    438                                         $postsecond = zeroise($post_date_His[2], 2);
    439 
    440                                         if (($post_date[2] == 'PM') && ($posthour != '12'))
    441                                                 $posthour = $posthour + 12;
    442                                         else if (($post_date[2] == 'AM') && ($posthour == '12'))
    443                                                 $posthour = '00';
    444 
    445                                         $post_date = "$postyear-$postmonth-$postday $posthour:$postminute:$postsecond";
    446 
    447                                         $post_content = addslashes($post_content);
    448                                         $post_content = str_replace(array('<br>','<BR>','<br/>','<BR/>','<br />','<BR />'), "\n", $post_content); // the XHTML touch... ;)
    449 
    450                                         $post_title = addslashes($post_title);
    451 
    452                                         $post_status = 'publish';
    453 
    454                                         if ( $ID = post_exists($post_title, '', $post_date) ) {
    455                                                 $post_array[$i]['ID'] = $ID;
    456                                                 $skippedpostcount++;
    457                                         } else {
    458                                                 $post_array[$i]['post'] = compact('post_author', 'post_content', 'post_title', 'post_category', 'post_author', 'post_date', 'post_status');
    459                                                 $post_array[$i]['comments'] = false;
    460                                         }
    461 
    462                                         // Import any comments attached to this post.
    463                                         if ($postparts[1]) :
    464                                         for ($j = 1; $j < count($postparts); $j = $j + 1) {
    465                                                 $commentinfo = explode('|W|P|', $postparts[$j]);
    466                                                 $comment_date = explode(' ', $commentinfo[0]);
    467                                                 $comment_date_Ymd = explode('/', $comment_date[0]);
    468                                                 $commentyear = $comment_date_Ymd[2];
    469                                                 $commentmonth = zeroise($comment_date_Ymd[0], 2);
    470                                                 $commentday = zeroise($comment_date_Ymd[1], 2);
    471                                                 $comment_date_His = explode(':', $comment_date[1]);
    472                                                 $commenthour = zeroise($comment_date_His[0], 2);
    473                                                 $commentminute = zeroise($comment_date_His[1], 2);
    474                                                 $commentsecond = '00';
    475                                                 if (($comment_date[2] == 'PM') && ($commenthour != '12'))
    476                                                         $commenthour = $commenthour + 12;
    477                                                 else if (($comment_date[2] == 'AM') && ($commenthour == '12'))
    478                                                         $commenthour = '00';
    479                                                 $comment_date = "$commentyear-$commentmonth-$commentday $commenthour:$commentminute:$commentsecond";
    480                                                 $comment_author = addslashes(strip_tags($commentinfo[1]));
    481                                                 if ( strpos($commentinfo[1], 'a href') ) {
    482                                                         $comment_author_parts = explode('&quot;', htmlentities($commentinfo[1]));
    483                                                         $comment_author_url = $comment_author_parts[1];
    484                                                 } else $comment_author_url = '';
    485                                                 $comment_content = $commentinfo[2];
    486                                                 $comment_content = str_replace(array('<br>','<BR>','<br/>','<BR/>','<br />','<BR />'), "\n", $comment_content);
    487                                                 $comment_approved = 1;
    488                                                 if ( comment_exists($comment_author, $comment_date) ) {
    489                                                         $skippedcommentcount++;
    490                                                 } else {
    491                                                         $comment = compact('comment_author', 'comment_author_url', 'comment_date', 'comment_content', 'comment_approved');
    492                                                         $post_array[$i]['comments'][$j] = wp_filter_comment($comment);
    493                                                 }
    494                                                 $commentcount++;
    495                                         }
    496                                         endif;
    497                                         $postcount++;
    498                                 }
    499                                 if ( count($post_array) ) {
    500                                         krsort($post_array);
    501                                         foreach($post_array as $post) {
    502                                                 if ( ! $comment_post_ID = $post['ID'] )
    503                                                         $comment_post_ID = wp_insert_post($post['post']);
    504                                                 if ( $post['comments'] ) {
    505                                                         foreach ( $post['comments'] as $comment ) {
    506                                                                 $comment['comment_post_ID'] = $comment_post_ID;
    507                                                                 wp_insert_comment($comment);
    508                                                         }
    509                                                 }
    510                                         }
    511                                 }
    512                                 $status = sprintf(__('%s post(s) parsed, %s skipped...'), $postcount,  $skippedpostcount).' '.
    513                                         sprintf(__('%s comment(s) parsed, %s skipped...'), $commentcount, $skippedcommentcount).' '.
    514                                         ' <strong>'.__('Done').'</strong>';
    515                                 $import = $this->import;
    516                                 $import['blogs'][$_GET['blog']]['archives']["$url"] = $status;
    517                                 update_option('import-blogger', $import);
    518                                 $did_one = true;
    519                         }
    520                         $output.= "<p>$archivename $status</p>\n";
    521                 }
    522                 if ( ! $did_one )
    523                         $this->set_next_step(7);
    524                 die( $this->refresher(1000) . $output );
    525         }
    526 
    527         // Step 7: Restore the backed-up settings to Blogger
    528         function restore_settings() {
    529                 $output = '<h1>'.__('Restoring your Blogger options')."</h1>\n";
    530                 $did_one = false;
    531                 // Restore options in reverse order.
    532                 if ( ! $this->import['reversed'] ) {
    533                         $this->import['blogs'][$_GET['blog']]['options'] = array_reverse($this->import['blogs'][$_GET['blog']]['options'], true);
    534                         $this->import['reversed'] = true;
    535                         update_option('import-blogger', $this->import);
    536                 }
    537                 foreach ( $this->import['blogs'][$_GET['blog']]['options'] as $blog_opt => $optary ) {
    538                         if ( $did_one ) {
    539                                 $output .= "<p>$blog_opt</p>\n";
    540                         } elseif ( $optary['restored'] || ! $optary['modify'] ) {
    541                                 $output .= "<p><del>$blog_opt</del></p>\n";
    542                         } else {
    543                                 $posturl = "http://www.blogger.com/{$blog_opt}.do";
    544                                 $headers = array_merge($this->import['blogs'][$_GET['blog']]['options']["$blog_opt"]['cookies'], $this->import['cookies']);
    545                                 if ( 'blog-publishing' == $blog_opt) {
    546                                         if ( $optary['backup']['publishMode'] > 0 ) {
    547                                                 $response = $this->get_blogger("http://www.blogger.com/blog-publishing.g?blogID={$_GET['blog']}&publishMode={$optary['backup']['publishMode']}", $headers);
    548                                                 sleep(2);
    549                                                 if ( $response['code'] >= 400 )
    550                                                         wp_die('<h1>'.__('Error restoring publishMode').'</h1><p>'.__('Please tell the devs.').'</p>' . addslashes(print_r($response, 1)) );
    551                                         }
    552                                 }
    553                                 if ( $optary['backup'] != $optary['modify'] ) {
    554                                         $response = $this->post_blogger($posturl, $headers, $optary['backup']);
    555                                         if ( $response['code'] >= 400 || strstr($response['body'], 'There are errors on this form') ) {
    556                                                 $this->import['blogs'][$_GET['blog']]['options']["$blog_opt"]['error'] = true;
    557                                                 update_option('import-blogger', $this->import);
    558                                                 $output .= sprintf(__('%s failed. Trying again.'), "<p><strong>$blog_opt</strong> ").'</p>';
    559                                         } else {
    560                                                 $this->import['blogs'][$_GET['blog']]['options']["$blog_opt"]['restored'] = true;
    561                                                 update_option('import-blogger', $this->import);
    562                                                 $output .= sprintf(__('%s restored.'), "<p><strong>$blog_opt</strong> ").'</p>';
    563                                         }
    564                                 }
    565                                 $did_one = true;
    566                         }
    567                 }
    568 
    569                 if ( $did_one ) {
    570                         die( $this->refresher(1000) . $output );
    571                 } elseif ( $this->import['blogs'][$_GET['blog']]['options']['blog-publishing']['backup']['publishMode'] > 0 ) {
    572                         $this->set_next_step(9);
    573                 } else {
    574                         $this->set_next_step(8);
    575                 }
    576 
    577                 $this->do_next_step();
    578         }
    579 
    580         // Step 8: Republish, all back to normal
    581         function republish_blog() {
    582                 $this->publish_blogger(9, __('Publishing with original template and options'));
    583740        }
    584741
    … …  
    590747                if ( $n = count($this->import['blogs'][$_GET['blog']]['newusers']) )
    591748                        echo '<li>'.sprintf(__('Go to <a href="%s" target="%s">Authors &amp; Users</a>, where you can modify the new user(s) or delete them. If you want to make all of the imported posts yours, you will be given that option when you delete the new authors.'), 'users.php', '_parent').'</li>';
    592                 echo '<li>'.__('For security, click the link below to reset this importer. That will clear your Blogger credentials and options from the database.').'</li>';
     749                echo '<li>'.__('For security, click the link below to reset this importer.').'</li>';
    593750                echo '</ul>';
    594751        }
    … …  
    596753        // Figures out what to do, then does it.
    597754        function start() {
    598                 if ( $_GET['restart'] == 'true' ) {
     755                if ( isset($_POST['restart']) )
    599756                        $this->restart();
    600                 }
    601 
    602                 if ( isset($_GET['noheader']) ) {
    603                         header('Content-Type: text/html; charset=utf-8');
    604 
    605                         $this->import = get_option('import-blogger');
    606 
    607                         if ( false === $this->import ) {
    608                                 $step = 0;
    609                         } elseif ( isset($_GET['step']) ) {
    610                                 $step = (int) $_GET['step'];
    611                         } elseif ( isset($_GET['blog']) && isset($this->import['blogs'][$_GET['blog']]['nextstep']) ) {
    612                                 $step = $this->import['blogs'][$_GET['blog']]['nextstep'];
    613                         } elseif ( is_array($this->import['blogs']) ) {
    614                                 $step = 1;
     757
     758                $options = get_option('blogger_importer');
     759
     760                if ( is_array($options) )
     761                        foreach ( $options as $key => $value )
     762                                $this->$key = $value;
     763
     764                if ( isset( $_REQUEST['blog'] ) ) {
     765                        $blog = is_array($_REQUEST['blog']) ? array_shift( array_keys( $_REQUEST['blog'] ) ) : $_REQUEST['blog'];
     766                        $this->import_blog( $blog );
     767                } elseif ( isset($_GET['token']) )
     768                        $this->auth();
     769                elseif ( $this->token && $this->token_is_valid() )
     770                        $this->show_blogs();
     771                else
     772                        $this->greet();
     773
     774                $saved = $this->save_vars();
     775
     776                if ( $saved && !isset($_GET['noheader']) ) {
     777                        $restart = __('Restart');
     778                        $message = __('We have saved some information about your Blogger account in your WordPress database. Clearing this information will allow you to start over. Restarting will not affect any posts you have already imported. If you attempt to re-import a blog, duplicate posts and comments will be skipped.');
     779                        $submit = __('Clear account information');
     780                        echo "<div class='wrap'><h2>$restart</h2><p>$message</p><form method='post' action='?import=blogger&noheader=true'><p class='submit' style='text-align:left;'><input type='submit' value='$submit' name='restart' /></p></form></div>";
     781                }
     782        }
     783
     784        function save_vars() {
     785                $vars = get_object_vars($this);
     786                update_option( 'blogger_importer', $vars );
     787
     788                return !empty($vars);
     789        }
     790
     791        function admin_head() {
     792?>
     793<style type="text/css">
     794td { text-align: center; line-height: 2em;}
     795thead td { font-weight: bold; }
     796.bar {
     797        width: 200px;
     798        text-align: left;
     799        line-height: 2em;
     800        padding: 0px;
     801}
     802.ind {
     803        position: absolute;
     804        background-color: #83B4D8;
     805        width: 1px;
     806        z-index: 9;
     807}
     808.stat {
     809        z-index: 10;
     810        position: relative;
     811        text-align: center;
     812}
     813.submit {
     814        text-align: center !important;
     815}
     816</style>
     817<?php
     818        }
     819
     820        function Blogger_Import() {
     821                global $importer_started;
     822                $importer_started = time();
     823                if ( isset( $_GET['import'] ) && $_GET['import'] == 'blogger' ) {
     824                        wp_enqueue_script('jquery');
     825                        add_action('admin_head', array(&$this, 'admin_head'));
     826                }
     827        }
     828}
     829
     830$blogger_import = new Blogger_Import();
     831
     832register_importer('blogger', __('Blogger'), __('Import posts, comments, and users from a Blogger blog'), array ($blogger_import, 'start'));
     833
     834class AtomEntry {
     835        var $links = array();
     836        var $categories = array();
     837}
     838
     839class AtomParser {
     840
     841        var $ATOM_CONTENT_ELEMENTS = array('content','summary','title','subtitle','rights');
     842        var $ATOM_SIMPLE_ELEMENTS = array('id','updated','published','draft','author');
     843
     844        var $depth = 0;
     845        var $indent = 2;
     846        var $in_content;
     847        var $ns_contexts = array();
     848        var $ns_decls = array();
     849        var $is_xhtml = false;
     850        var $skipped_div = false;
     851
     852        var $entry;
     853
     854        function AtomParser() {
     855
     856                $this->entry = new AtomEntry();
     857                $this->map_attrs_func = create_function('$k,$v', 'return "$k=\"$v\"";');
     858                $this->map_xmlns_func = create_function('$p,$n', '$xd = "xmlns"; if(strlen($n[0])>0) $xd .= ":{$n[0]}"; return "{$xd}=\"{$n[1]}\"";');
     859        }
     860
     861        function parse($xml) {
     862
     863                global $app_logging;
     864                array_unshift($this->ns_contexts, array());
     865
     866                $parser = xml_parser_create_ns();
     867                xml_set_object($parser, $this);
     868                xml_set_element_handler($parser, "start_element", "end_element");
     869                xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
     870                xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,0);
     871                xml_set_character_data_handler($parser, "cdata");
     872                xml_set_default_handler($parser, "_default");
     873                xml_set_start_namespace_decl_handler($parser, "start_ns");
     874                xml_set_end_namespace_decl_handler($parser, "end_ns");
     875
     876                $contents = "";
     877
     878                xml_parse($parser, $xml);
     879
     880                xml_parser_free($parser);
     881
     882                return true;
     883        }
     884
     885        function start_element($parser, $name, $attrs) {
     886
     887                $tag = array_pop(split(":", $name));
     888
     889                array_unshift($this->ns_contexts, $this->ns_decls);
     890
     891                $this->depth++;
     892
     893                if(!empty($this->in_content)) {
     894                        $attrs_prefix = array();
     895
     896                        // resolve prefixes for attributes
     897                        foreach($attrs as $key => $value) {
     898                                $attrs_prefix[$this->ns_to_prefix($key)] = $this->xml_escape($value);
     899                        }
     900                        $attrs_str = join(' ', array_map($this->map_attrs_func, array_keys($attrs_prefix), array_values($attrs_prefix)));
     901                        if(strlen($attrs_str) > 0) {
     902                                $attrs_str = " " . $attrs_str;
     903                        }
     904
     905                        $xmlns_str = join(' ', array_map($this->map_xmlns_func, array_keys($this->ns_contexts[0]), array_values($this->ns_contexts[0])));
     906                        if(strlen($xmlns_str) > 0) {
     907                                $xmlns_str = " " . $xmlns_str;
     908                        }
     909
     910                        // handle self-closing tags (case: a new child found right-away, no text node)
     911                        if(count($this->in_content) == 2) {
     912                                array_push($this->in_content, ">");
     913                        }
     914                 
     915                        array_push($this->in_content, "<". $this->ns_to_prefix($name) ."{$xmlns_str}{$attrs_str}");
     916                } else if(in_array($tag, $this->ATOM_CONTENT_ELEMENTS) || in_array($tag, $this->ATOM_SIMPLE_ELEMENTS)) {
     917                        $this->in_content = array();
     918                        $this->is_xhtml = $attrs['type'] == 'xhtml';
     919                        array_push($this->in_content, array($tag,$this->depth));
     920                } else if($tag == 'link') {
     921                        array_push($this->entry->links, $attrs);
     922                } else if($tag == 'category') {
     923                        array_push($this->entry->categories, $attrs['term']);
     924                }
     925               
     926                $this->ns_decls = array();
     927        }
     928
     929        function end_element($parser, $name) {
     930
     931                $tag = array_pop(split(":", $name));
     932
     933                if(!empty($this->in_content)) {
     934                        if($this->in_content[0][0] == $tag &&
     935                        $this->in_content[0][1] == $this->depth) {
     936                                array_shift($this->in_content);
     937                                if($this->is_xhtml) {
     938                                        $this->in_content = array_slice($this->in_content, 2, count($this->in_content)-3);
     939                                }
     940                                $this->entry->$tag = join('',$this->in_content);
     941                                $this->in_content = array();
    615942                        } else {
    616                                 $step = 0;
    617                         }
    618 //echo "Step $step.";
    619 //wp_die('<pre>'.print_r($this->import,1).'</pre');
    620                         switch ($step) {
    621                                 case 0 :
    622                                         $this->do_login();
    623                                         break;
    624                                 case 1 :
    625                                         $this->select_blog();
    626                                         break;
    627                                 case 2 :
    628                                         $this->backup_settings();
    629                                         break;
    630                                 case 3 :
    631                                         $this->wait_for_blogger();
    632                                         break;
    633                                 case 4 :
    634                                         $this->publish_blog();
    635                                         break;
    636                                 case 5 :
    637                                         $this->get_archive_urls();
    638                                         break;
    639                                 case 6 :
    640                                         $this->get_archive();
    641                                         break;
    642                                 case 7 :
    643                                         $this->restore_settings();
    644                                         break;
    645                                 case 8 :
    646                                         $this->republish_blog();
    647                                         break;
    648                                 case 9 :
    649                                         $this->congrats();
    650                                         break;
    651                         }
    652                         die;
    653 
    654                 } else {
    655                         $this->greet();
    656                 }
    657         }
    658 
    659         function Blogger_Import() {
    660                 // This space intentionally left blank.
     943                                $endtag = $this->ns_to_prefix($name);
     944                                if(strstr($this->in_content[count($this->in_content)-1], "<$endtag")) {
     945                                        array_push($this->in_content, "/>");
     946                                } else {
     947                                        array_push($this->in_content, "</$endtag>");
     948                                }
     949                        }
     950                }
     951
     952                array_shift($this->ns_contexts);
     953               
     954                #print str_repeat(" ", $this->depth * $this->indent) . "end_element('$name')" ."\n";
     955
     956                $this->depth--;
     957        }
     958
     959        function start_ns($parser, $prefix, $uri) {
     960                #print str_repeat(" ", $this->depth * $this->indent) . "starting: " . $prefix . ":" . $uri . "\n";
     961                array_push($this->ns_decls, array($prefix,$uri));
     962        }
     963
     964        function end_ns($parser, $prefix) {
     965                #print str_repeat(" ", $this->depth * $this->indent) . "ending: #" . $prefix . "#\n";
     966        }
     967
     968        function cdata($parser, $data) {
     969                #print str_repeat(" ", $this->depth * $this->indent) . "data: #" . $data . "#\n";
     970                if(!empty($this->in_content)) {
     971                        // handle self-closing tags (case: text node found, need to close element started)
     972                        if(strstr($this->in_content[count($this->in_content)-1], "<")) {
     973                                array_push($this->in_content, ">");
     974                        }
     975                        array_push($this->in_content, $this->xml_escape($data));
     976                }
     977        }
     978
     979        function _default($parser, $data) {
     980                # when does this gets called?
     981        }
     982
     983
     984        function ns_to_prefix($qname) {
     985                $components = split(":", $qname);
     986                $name = array_pop($components);
     987
     988                if(!empty($components)) {
     989                        $ns = join(":",$components);
     990                        foreach($this->ns_contexts as $context) {
     991                                foreach($context as $mapping) {
     992                                        if($mapping[1] == $ns && strlen($mapping[0]) > 0) {
     993                                                return "$mapping[0]:$name";
     994                                        }
     995                                }
     996                        }
     997                }
     998                return $name;
     999        }
     1000
     1001        function xml_escape($string)
     1002        {
     1003                         return str_replace(array('&','"',"'",'<','>'),
     1004                                array('&amp;','&quot;','&apos;','&lt;','&gt;'),
     1005                                $string );
    6611006        }
    6621007}
    6631008
    664 $blogger_import = new Blogger_Import();
    665 
    666 register_importer('blogger', __('Old Blogger'), __('Import posts, comments, and users from an Old Blogger blog'), array ($blogger_import, 'start'));
    667 
    6681009?>
Note: See TracChangeset for help on using the changeset viewer.