OSDN Git Service

045cbdb9a68e992deb500a037b9a983420ac2b0f
[nucleus-jp/nucleus-next.git] / nucleus / convert / functions.inc.php
1 <?php
2 /*
3  * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
4  * Copyright (C) 2002-2006 The Nucleus Group
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  * (see nucleus/documentation/index.html#license for more info)
11  */
12 /**
13  * @license http://nucleuscms.org/license.txt GNU General Public License
14  * @copyright Copyright (C) 2002-2006 The Nucleus Group
15  * @version $Id: functions.inc.php 1624 2012-01-09 11:36:20Z sakamocchi $
16  */
17
18 // try to set a long timeout time
19 @set_time_limit(1200);
20
21 /**
22  * Generic class that can import XML files with either blog items or comments
23  * to be imported into a Nucleus blog
24  *
25  */
26 class BlogImport {
27
28         /**
29          * Creates a new BlogImport object
30          *
31          *
32          * @param iBlogId
33          *              Nucleus blogid to which the content of the XML file must be added
34          * @param aOptions
35          *              Import options
36          *                      $aOptions['PreserveIds'] = 1 (NOT IMPLEMENTED)
37          *                              try to use the same ID for the nucleus item as the ID listed
38          *                              in the XML
39          *                      $aOptions['ReadNamesOnly']
40          *                              Reads all category names and author names (items
41          *                              only) into $aAuthorNames and $aCategoryNames
42          * @param aMapUserToNucleusId
43          *              Array with mapping from user names (as listed in the XML file) to
44          *              Nucleus member Ids. '_default' lists the default user.
45          *                      example: array('karma' => 1, 'xiffy' => 2, 'roel' => 3, '_default' => 1)
46          * @param aMapCategoryToNucleusId
47          *              Similar to $aMapUserToNucleusId, but this array maps category names to
48          *              category ids. Please note that the category IDs need to come from the
49          *              same blog as $iBlogId
50          *                      example: array('general' => 11, 'funny' => 33)
51          * @param strCallback
52          *              name of a callback function to be called on each item. Such a callback
53          *              function should have a format like:
54          *                      function myCallback(&$data)
55          *              where $data is an associative array with all item data ('title','body',
56          *              ...)
57          */
58         function BlogImport($iBlogId = -1, $aOptions = array('ReadNamesOnly' => 0), $aMapUserToNucleusId = array(), $aMapCategoryToNucleusId = array(), $strCallback = '') {
59                 global $manager;
60
61                 $this->iBlog                                    = $iBlogId;
62                 if ($iBlogId != -1)
63                         $this->oBlog                            =& $manager->getBlog($iBlogId);
64                 else
65                         $this->oBlog                            = 0;
66                 $this->aOptions                                 = $aOptions;
67                 $this->aMapUserToNucleusId              = $aMapUserToNucleusId;
68                 $this->aMapCategoryToNucleusId  = $aMapCategoryToNucleusId;
69                 $this->strCallback                              = $strCallback;
70                 $this->aMapIdToNucleusId                = array();
71
72                 $this->bReadNamesOnly                   = $this->aOptions['ReadNamesOnly'] == 1;
73                 $this->aCategoryNames                   = array();
74                 $this->aAuthorNames                             = array();
75
76
77                 // disable magic_quotes_runtime if it's turned on
78                 set_magic_quotes_runtime(0);
79
80                 // debugging mode?
81                 $this->bDebug = 0;
82
83                 // XML file pointer
84                 $this->fp = 0;
85
86                 // to maintain track of where we are inside the XML file
87                 $this->inXml            = 0;
88                 $this->inData           = 0;
89                 $this->inItem           = 0;
90                 $this->inComment        = 0;
91                 $this->aCurrentItem = $this->_blankItem();
92                 $this->aCurrentComment = $this->_blankComment();
93
94                 // character data pile
95                 $this->cdata = '';
96
97                 // init XML parser
98                 $this->parser = xml_parser_create();
99                 xml_set_object($this->parser, $this);
100                 xml_set_element_handler($this->parser, 'startElement', 'endElement');
101                 xml_set_character_data_handler($this->parser, 'characterData');
102                 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
103
104                 // TODO: add data checking
105                 $this->bValid                                   = 1;
106
107                 // data structures
108                 $this->strErrorMessage                  = '';
109
110         }
111
112         /**
113          * Gets the import library version
114          */
115         function getVersion() {
116                 return '0.2';
117         }
118
119         /**
120          * Returns an array with all the author names used in the file (only
121          * the authors of items are included)
122          *
123          * @require importXmlFile should be called prior to calling this
124          */
125         function getAuthorNames() {
126                 return $this->aAuthorNames;
127         }
128
129         /**
130          * Returns an array with all the category names used in the file
131          *
132          * @require importXmlFile should be called prior to calling this
133          */
134         function getCategoryNames() {
135                 return $this->aCategoryNames;
136         }
137
138         /**
139          * Imports an XML file into a given blog
140          *
141          * also fills $this->aMapIdToNucleusId
142          *              array with info for each item having a Nucleus ID that is different
143          *              from the original ID
144          *                      example: array(9999 => 1, 1234 => 2, 12 => 3)
145          *
146          * @param strXmlFile
147          *              Location of the XML file. The XML file must be in the correct
148          *              Nucleus import format
149          * @returns
150          *              0 on failure. Use getLastError() to get error message
151          *              1 on success
152          *
153          */
154         function importXmlFile($strXmlFile) {
155                 $this->resetErrorMessage();
156
157                 flush();
158
159                 if (!$this->bValid)
160                         return $this->setErrorMessage('BlogImport object is invalid');
161                 if (!@file_exists($strXmlFile))
162                         return $this->setErrorMessage($strXmlFile . ' does not exist');
163                 if (!@is_readable($strXmlFile))
164                         return $this->setErrorMessage($strXmlFile . ' is not readable');
165
166                 // open file
167                 $this->fp = @fopen($strXmlFile, 'r');
168                 if (!$this->fp)
169                         return $this->setErrorMessage('Failed to open file/URL');
170
171                 // here we go!
172                 $this->inXml = 1;
173
174                 // parse file contents
175                 while ($buffer = fread($this->fp, 4096)) {
176                         $err = xml_parse( $this->parser, $buffer, feof($this->fp) );
177                         if (!$err && $this->bDebug)
178                                 echo 'ERROR: ', xml_error_string(xml_get_error_code($this->parser)), '<br />';
179                 }
180
181                 // all done
182                 $this->inXml = 0;
183                 fclose($this->fp);
184
185                 return 1;
186         }
187
188         /**
189          * Identical to importXmlFile, but takes an almost-ready-for-addition array
190          *
191          * @param aData
192          *              Array with item data, as prepared by import_fromXML
193          *
194          * @returns
195          *              0 on failure. Use getLastError() to get error message
196          *              1 on success
197          */
198         function importOneItem(&$aData) {
199                 $this->resetErrorMessage();
200
201                 // - do some logic to determine nucleus users and categories
202                 // * find member id
203                 // * find blog id
204                 // * find category id
205                 $aData['nucleus_blogid']        = $this->iBlog;
206                 $aData['nucleus_catid']         = $this->_findCategoryId($aData['category']);
207                 $aData['nucleus_memberid']      = $this->_findMemberId($aData['author']);
208                 if ($aData['nucleus_memberid'] == 0) {
209                         $aData['nucleus_memberid'] = $this->aMapUserToNucleusId['_default'];
210                 }
211
212                 // - apply logic to comments
213                 foreach (array_keys($aData['comments']) as $key) {
214                         // * find member id
215                         $aData['comments'][$key]['nucleus_memberid']
216                                 = $this->_findMemberId($aData['comments'][$key]['author']);
217                         // * extract authorid
218                         if ($aData['comments'][$key]['nucleus_memberid'] == 0) {
219                                 $url = $aData['comments'][$key]['url'];
220                                 $email = $aData['comments'][$key]['email'];
221                                 $authid = $aData['comments'][$key]['authorid'];
222
223                                 if (!$authid && $url)
224                                         $aData['comments'][$key]['authorid'] = $url;
225                                 else if (!$authid && $email)
226                                         $aData['comments'][$key]['authorid'] = $email;
227                         }
228                 }
229
230                 // - call callback
231                 if ($this->strCallback && function_exists($this->strCallback)) {
232                         call_user_func_array($this->strCallback, array(&$aData));
233                 }
234
235                 if ($this->bDebug) {
236                         echo '<pre>';
237                         print_r($aData);
238                         echo '</pre>';
239                 }
240
241                 // - insert item into nucleus database
242                 $iNewId = $this->sql_addToItem(
243                         $aData['title'],
244                         $aData['body'],
245                         $aData['extended'],
246                         $aData['nucleus_blogid'],
247                         $aData['nucleus_memberid'],
248                         $aData['timestamp'],
249                         ($aData['itemstatus'] == 'open') ? 0 : 1,
250                         $aData['nucleus_catid'],
251                         $aData['posvotes'],
252                         $aData['negvotes']
253                 );
254
255                 // - store id mapping if needed
256                 $aData['nucleus_id'] = $iNewId;
257                 if ($aData['nucleus_id'] != $aData['id'])
258                         $this->aMapIdToNucleusId[$aData['id']] = $aData['nucleus_id'];
259
260                 // - insert comments into nucleus database
261                 foreach ($aData['comments'] as $comment) {
262                         $cId = $this->sql_addToComments(
263                                 $comment['author'],
264                                 $comment['authorid'],
265                                 $comment['body'],
266                                 $aData['nucleus_blogid'],
267                                 $aData['nucleus_id'],
268                                 $comment['nucleus_memberid'],
269                                 $comment['timestamp'],
270                                 $comment['host'],
271                                 $comment['ip']
272                         );
273                 }
274
275                 echo ' .'; // progress indicator
276                 flush();
277
278                 return 1;
279         }
280
281         function getHtmlCode($what) {
282                 ob_start();
283                 switch($what) {
284 // ----------------------------------------------------------------------------------------
285                         case 'NucleusMemberOptions':
286                                 $res = DB::getResult('SELECT mname as text, mnumber as value FROM '.sql_table('member'));
287                                 foreach ( $res as $row )
288                                 {
289                                         echo '<option value="'.Entity::hsc($row['value']).'">'.Entity::hsc($row['text']).'</option>';
290                                 }
291                                 break;
292 // ----------------------------------------------------------------------------------------
293                         case 'NucleusBlogSelect':
294                                 $query =  'SELECT bname as text, bnumber as value FROM '.sql_table('blog');
295                                 $template['name'] = 'blogid';
296                                 $template['selected'] = $CONF['DefaultBlog'];
297                                 showlist($query,'select',$template);
298                                 break;
299 // ----------------------------------------------------------------------------------------
300                         case 'ConvertSelectMembers':
301                         ?>
302                                 <h2>Assign Members to Authors</h2>
303
304                                 <p>
305                                 Below is a list of all the authors that Nucleus could discover (only authors that have posted at least one entry are listed). Please assign a Nucleus Member to all of these authors.
306                                 </p>
307
308
309                                 <table>
310                                 <tr>
311                                         <th>Author</th>
312                                         <th>Nucleus Member</th>
313                                         <th>Blog Admin?</th>
314                                 </tr>
315
316                                 <?php
317
318                                 $authors = $this->getAuthorNames();
319
320                                 // get HTML code for selection list
321                                 $optionsHtml = $this->getHtmlCode('NucleusMemberOptions');
322                                 $idx = 0;
323                                 while ($a_name = array_pop($authors)) {
324                                         ?>
325                                                 <tr>
326                                                         <td>
327                                                                 <strong><?php echo $a_name?></strong>
328                                                                 <input name="author[<?php echo $idx?>]" value="<?php echo Entity::hsc($a_name)?>" type="hidden" />
329                                                         </td>
330                                                         <td>
331                                                                 <select name="memberid[<?php echo $idx?>]">
332                                                                         <?php echo $optionsHtml; ?>
333                                                                 </select>
334                                                         </td>
335                                                         <td>
336                                                                 <input name="admin[<?php echo $idx?>]" type="checkbox" value="1" id="admin<?php echo $idx?>" /><label for="admin<?php echo $idx?>">Blog Admin</label>
337                                                         </td>
338                                                 </tr>
339                                         <?php   $idx++;
340                                 } // while
341
342                                 ?>
343                                         <tr>
344                                                 <td><em>Default Member</em></td>
345                                                 <td>
346                                                         <input name="author[<?php echo $idx?>]" value="_default" type="hidden" />
347                                                         <select name="memberid[<?php echo $idx?>]">
348                                                                 <?php echo $optionsHtml; ?>
349                                                         </select>
350                                                         <td><input name="admin[<?php echo $idx?>]" type="hidden" value="0" id="admin<?php echo $idx?>" /></td>
351                                                 </td>
352
353                                         </tr>
354                                 </table>
355                                 <input type="hidden" name="authorcount" value="<?php echo ++$idx?>" />
356                         <?php
357                                 break;
358 // ----------------------------------------------------------------------------------------
359                         case 'ConvertSelectCategories':
360                         ?>
361                                 <h2>Assign Categories</h2>
362
363                                 <p>
364                                 Below is a list of all the categories that Nucleus could discover (only categories that have been used at least once are listed). Please assign a Nucleus Category to all of these categories.
365                                 </p>
366
367
368                                 <table>
369                                 <tr>
370                                         <th>Category</th>
371                                         <th>Nucleus Category</th>
372                                 </tr>
373
374                                 <?php
375
376                                 $catnames = $this->getCategoryNames();
377
378                                 // get HTML code for selection list
379                                 $optionsHtml = $this->getHtmlCode('NucleusCategoryOptions');
380                                 $idx = 0;
381                                 while ($a_name = array_pop($catnames)) {
382                                         ?>
383                                                 <tr>
384                                                         <td>
385                                                                 <strong><?php echo $a_name?></strong>
386                                                                 <input name="category[<?php echo $idx?>]" value="<?php echo Entity::hsc($a_name)?>" type="hidden" />
387                                                         </td>
388                                                         <td>
389                                                                 <select name="catid[<?php echo $idx?>]">
390                                                                         <?php echo $optionsHtml; ?>
391                                                                 </select>
392                                                         </td>
393                                                 </tr>
394                                         <?php   $idx++;
395                                 } // while
396                                 ?>
397                                 </table>
398                                 <input type="hidden" name="catcount" value="<?php echo $idx?>" />
399                         <?php
400                                 break;
401 // ----------------------------------------------------------------------------------------
402                         case 'ConvertSelectBlog':
403                         ?>
404                                 <h2>Choose Destination Weblog</h2>
405
406                                 <p>
407                                 There are two options: you can either choose an existing blog to add the entries into, or you can choose to create a new weblog.
408                                 </p>
409
410                                 <div>
411                                         <input name="createnew" value="0" type="radio" checked='checked' id="createnew_no" /><label for="createnew_no">Choose existing weblog to add to:</label>
412
413                                         <?php echo $this->getHtmlCode('NucleusBlogSelect'); ?>
414                                 </div>
415                                 <div>
416                                         <input name="createnew" value="1" type="radio" id="createnew_yes" /><label for="createnew_yes">Create new weblog</label>
417                                         <ul>
418                                                 <li>New blog name: <input name="newblogname" /></li>
419                                                 <li>Blog owner:
420                                                         <select name="newowner">
421                                                                 <?php echo $this->getHtmlCode('NucleusMemberOptions'); ?>
422                                                         </select>
423                                                 </li>
424                                         </ul>
425                                 </div>
426                         <?php
427                                 break;
428 // ----------------------------------------------------------------------------------------
429                         case 'ConvertStart':
430                         ?>
431                                 <h2>Do the conversion!</h2>
432
433                                 <p>
434                                 <input type="submit" value="Step 3: Do the conversion!" />
435                                 <input type="hidden" name="action" value="doConversion" />
436                                 </p>
437
438                                 <div class="note">
439                                 <strong>Note:</strong> Clicking the button once is enough, even if it takes a while to complete.
440                                 </div>
441                         <?php
442                                 break;
443                 }
444                 $htmlCode = ob_get_contents();
445                 ob_end_clean();
446                 return $htmlCode;
447         }
448
449         /**
450          * Create blog if needed
451          * (request vars: blogid, createnew, newblogname, newowner)
452          *
453          * (static!)
454          */
455         function getBlogIdFromRequest() {
456                 $createnew              = intPostVar('createnew');
457                 $newowner               = intPostVar('newowner');
458                 $newblogname    = postVar('newblogname');
459                 $blogid                 = intPostVar('blogid');
460
461                 if ($createnew == 1) {
462                         // choose unique name
463                         $shortname = 'import';
464                         if (Blog::exists($shortname)) {
465                                 $idx = 1;
466                                 while (Blog::exists($shortname . $idx))
467                                         $idx++;
468                                 $shortname = $shortname . $idx;
469                         }
470
471                         $nucleus_blogid = BlogImport::sql_addToBlog($newblogname, $shortname, $newowner);
472
473                         echo '<h2>Creating new blog</h2>';
474                         echo '<p>Your new weblog has been created.</p>';
475
476                         return $nucleus_blogid;
477                 } else {
478                         return $blogid;
479                 }
480
481         }
482
483         function getFromRequest($what) {
484                 $aResult = array();
485
486                 switch ($what) {
487                         case 'authors':
488                                 $authorcount = intPostVar('authorcount');
489
490                                 $author = requestArray('author');
491                                 $memberid = requestIntArray('memberid');
492                                 $isadmin = requestIntArray('admin');
493
494                                 for ($i=0;$i<$authorcount;$i++) {
495                                         $authorname = undoMagic($author[$i]);
496
497                                         // add authors to team
498                                         $this->oBlog->addTeamMember(intval($memberid[$i]),intval($isadmin[$i]));
499
500                                         $aResult[$authorname] = $memberid[$i];
501                                 }
502
503                                 $this->aMapUserToNucleusId = $aResult;
504                                 break;
505                         case 'categories':
506                                 // TODO
507                                 $this->aMapCategoryToNucleusId = $aResult;
508                                 break;
509                 }
510
511                 return $aResult;
512         }
513
514         function _findCategoryId($name) {
515                 $catid = @$this->aMapCategoryToNucleusId[$name];
516                 if (!$catid && $this->oBlog)
517                         // get default category for weblog
518                         $catid = $this->oBlog->getDefaultCategory();
519                 return $catid;
520         }
521
522         function _findMemberId($name) {
523                 $memberid = intval(@$this->aMapUserToNucleusId[$name]);
524                 return $memberid;
525         }
526
527         /**
528          * Returns the last error message. Use it to find out the reason for failure
529          */
530         function getLastError() {
531                 return $this->strErrorMessage;
532         }
533         function resetErrorMessage() {
534                 $this->strErrorMessage = '';
535         }
536         function setErrorMessage($strMsg) {
537                 $this->strErrorMessage = $strMsg;
538                 return 0;
539         }
540
541         /**
542          * Called by XML parser for each new start element encountered
543          */
544         function startElement($parser, $name, $attrs) {
545                 if ($this->bDebug) echo 'START: ', $name, '<br />';
546
547                 switch ($name) {
548                         case 'blog':
549                                 $this->inData = 1;
550                                 $this->strImportFileVersion = $attrs['version'];
551                                 // TODO: check version number
552                                 break;
553                         case 'item':
554                                 $this->inItem = 1;
555                                 $this->aCurrentItem = $this->_blankItem($attrs['id']);
556                                 if (@$attrs['commentsOnly'] == 'true')
557                                         $this->aCurrentItem['commentsOnly'] = 1;
558                                 else
559                                         $this->aCurrentItem['commentsOnly'] = 0;
560                                 break;
561                         case 'timestamp':
562                                 if ($this->inItem || $this->inComment) {
563                                         // store time format
564                                         $this->currentTSFormat = $attrs['type'];
565                                 }
566                                 break;
567                         case 'author':
568                         case 'title':
569                         case 'body':
570                         case 'extended':
571                         case 'category':
572                         case 'itemstatus':
573                         case 'posvotes':
574                         case 'negvotes':
575                                 // nothing to do
576                                 break;
577                         case 'comment':
578                                 if ($this->inItem) {
579                                         $this->inComment = 1;
580                                         $this->aCurrentComment = $this->_blankComment($attrs['id']);
581                                 }
582                                 break;
583                         case 'email':
584                         case 'url':
585                         case 'authorid':
586                         case 'host':
587                         case 'ip':
588                                 // nothing to do
589                                 break;
590                         default:
591                                 echo 'UNEXPECTED TAG: ' , $name , '<br />';
592                                 break;
593                 }
594
595                 // character data never contains other tags
596                 $this->clearCharacterData();
597
598         }
599
600         /**
601           * Called by the XML parser for each closing tag encountered
602           */
603         function endElement($parser, $name) {
604                 if ($this->bDebug) echo 'END: ', $name, '<br />';
605
606                 switch ($name) {
607                         case 'blog':
608                                 $this->inData = 0;
609                                 break;
610                         case 'item':
611                                 if (!$this->bReadNamesOnly) {
612                                         // write to database
613                                         // TODO: check if succes or failure
614                                         $this->importOneItem($this->aCurrentItem);
615                                 }
616                                 $this->inItem = 0;
617
618                                 // initialize item structure
619                                 $this->aCurrentItem = $this->_blankItem();
620                                 break;
621                         case 'timestamp':
622                                 $timestamp = $this->getTime($this->getCharacterData(), $this->currentTSFormat);
623                                 if ($this->inComment)
624                                         $this->aCurrentComment['timestamp'] = $timestamp;
625                                 else if ($this->inItem)
626                                         $this->aCurrentItem['timestamp'] = $timestamp;
627                                 break;
628                         case 'author':
629                                 if ($this->inItem && !$this->inComment)
630                                         $this->_addAuthorName($this->getCharacterData());
631                                 if ($this->inComment)
632                                         $this->aCurrentComment['author'] = $this->getCharacterData();
633                                 else if ($this->inItem)
634                                         $this->aCurrentItem['author'] = $this->getCharacterData();
635                                 break;
636                         case 'title':
637                                 if ($this->inComment)
638                                         $this->aCurrentComment['title'] = $this->getCharacterData();
639                                 else if ($this->inItem)
640                                         $this->aCurrentItem['title'] = $this->getCharacterData();
641                                 break;
642                         case 'body':
643                                 if ($this->inComment)
644                                         $this->aCurrentComment['body'] = $this->getCharacterData();
645                                 else if ($this->inItem)
646                                         $this->aCurrentItem['body'] = $this->getCharacterData();
647                                 break;
648                         case 'extended':
649                                 if ($this->inItem)
650                                         $this->aCurrentItem['extended'] = $this->getCharacterData();
651                                 break;
652                         case 'category':
653                                 $this->_addCategoryName($this->getCharacterData());
654                                 if ($this->inItem && !$this->aCurrentItem['category']) {
655                                         $this->aCurrentItem['category'] = $this->getCharacterData();
656                                 }
657                                 break;
658                         case 'itemstatus':
659                                 if ($this->inItem)
660                                         $this->aCurrentItem['itemstatus'] = $this->getCharacterData();
661                                 break;
662                         case 'posvotes':
663                                 if ($this->inItem)
664                                         $this->aCurrentItem['posvotes'] = $this->getCharacterData();
665                                 break;
666                         case 'negvotes':
667                                 if ($this->inItem)
668                                         $this->aCurrentItem['negvotes'] = $this->getCharacterData();
669                                 break;
670                         case 'comment':
671                                 if ($this->inComment) {
672                                         array_push($this->aCurrentItem['comments'], $this->aCurrentComment);
673                                         $this->aCurrentComment = $this->_blankComment();
674                                         $this->inComment = 0;
675                                 }
676                                 break;
677                         case 'email':
678                                 if ($this->inComment)
679                                         $this->aCurrentComment['email'] = $this->getCharacterData();
680                                 break;
681                         case 'url':
682                                 if ($this->inComment)
683                                         $this->aCurrentComment['url'] = $this->getCharacterData();
684                                 break;
685                         case 'authorid':
686                                 if ($this->inComment)
687                                         $this->aCurrentComment['authorid'] = $this->getCharacterData();
688                                 break;
689                         case 'host':
690                                 if ($this->inComment)
691                                         $this->aCurrentComment['host'] = $this->getCharacterData();
692                                 break;
693                         case 'ip':
694                                 if ($this->inComment)
695                                         $this->aCurrentComment['ip'] = $this->getCharacterData();
696                                 break;
697                         default:
698                                 echo 'UNEXPECTED TAG: ' , $name, '<br />';
699                                 break;
700                 }
701                 $this->clearCharacterData();
702
703         }
704
705         /**
706          * Called by XML parser for data inside elements
707          */
708         function characterData ($parser, $data) {
709                 if ($this->bDebug) echo 'NEW DATA: ', Entity::hsc($data), '<br />';
710                 $this->cdata .= $data;
711         }
712
713         /**
714          * Returns the data collected so far
715          */
716         function getCharacterData() {
717                 return $this->cdata;
718         }
719
720         /**
721          * Clears the data buffer
722          */
723         function clearCharacterData() {
724                 $this->cdata = '';
725         }
726
727         /**
728          * Parses a given string into a unix timestamp.
729          *
730          * @param strTime
731          *              String, formatted as given in $strFormat
732          * @param strFormat
733          *              Multiple date formats are supported:
734          *                      'unix': plain unix timestamp (numeric)
735          *                      'blogger': for blogger import: MM/DD/YYYY hh:MM:SS AM
736          */
737         function getTime($strTime, $strFormat = 'unix') {
738                 $strFormat = strtolower($strFormat);
739                 switch($strFormat) {
740                         case 'unix':
741                                 return intval($strTime);
742                         case 'blogger':
743                                 // 7/24/2000 11:27:13 AM
744                                 if (eregi("(.*)/(.*)/(.*) (.*):(.*):(.*) (.*)",$strTime,$regs) != false) {
745                                         if (($regs[7] == "PM") && ($regs[4] != "12"))
746                                                 $regs[4] += 12;
747
748                                         return mktime($regs[4],$regs[5],$regs[6],$regs[1],$regs[2],$regs[3]);
749                                 } else {
750                                         return 0;
751                                 }
752                 }
753         }
754
755
756         function _blankItem($id = -1) {
757                 return array(
758                                 'id'                    => $id,
759                                 'commentsOnly'  => 0,
760                                 'timestamp'     => time(),
761                                 'author'                => '',
762                                 'title'                 => '',
763                                 'body'                  => '',
764                                 'extended'              => '',
765                                 'category'              => '',
766                                 'itemstatus'    => 'open',
767                                 'posvotes'              => 0,
768                                 'negvotes'              => 0,
769                                 'comments'              => array()
770                 );
771         }
772
773         function _blankComment($id = -1) {
774                 return array(
775                                 'id'                    => $id,
776                                 'timestamp'     => time(),
777                                 'author'                => '',
778                                 'title'                 => '',
779                                 'body'                  => '',
780                                 'email'                 => '',
781                                 'url'                   => '',
782                                 'authorid'              => '',
783                                 'host'                  => '',
784                                 'ip'                    => ''
785                 );
786         }
787
788         function _addAuthorName($name) {
789                 if (!in_array($name, $this->aAuthorNames))
790                         array_push($this->aAuthorNames, $name);
791         }
792
793         function _addCategoryName($name) {
794                 if (!in_array($name, $this->aCategoryNames))
795                         array_push($this->aCategoryNames, $name);
796         }
797
798         function sql_addToItem($title, $body, $more, $blogid, $authorid, $timestamp, $closed, $category, $karmapos, $karmaneg) {
799                 $title          = DB::quoteValue(trim($title));
800                 $body           = DB::quoteValue(trim($body));
801                 $more           = DB::quoteValue(trim($more));
802                 $timestamp      = DB::formatDateTime($timestamp);
803
804                 $query = 'INSERT INTO '.sql_table('item').' (ITITLE, IBODY, IMORE, IBLOG, IAUTHOR, ITIME, ICLOSED, IKARMAPOS, IKARMANEG, ICAT) '
805                            . "VALUES ($title, $body, $more, $blogid, $authorid, $timestamp, $closed, $karmapos, $karmaneg,  $category)";
806
807                 if ( DB::execute($query) === FALSE )
808                 {
809                         die('Error while executing query: ' . $query);
810                 }
811
812                 return DB::getInsertId();
813         }
814
815         function sql_addToBlog($name, $shortname, $ownerid) {
816                 $name           = DB::quoteValue($name);
817                 $shortname      = DB::quoteValue($shortname);
818
819                 // create new category first
820                 DB::execute('INSERT INTO '.sql_table('category')." (CNAME, CDESC) VALUES ('General','Items that do not fit in another category')");
821                 $defcat = DB::getInsertId();
822
823                 $query = 'INSERT INTO '.sql_table('blog')." (BNAME, BSHORTNAME, BCOMMENTS, BMAXCOMMENTS, BDEFCAT) VALUES ($name, $shortname, 1, 0, $defcat)";
824                 if ( DB::execute($query) === FALSE )
825                 {
826                         die('Error while executing query: ' . $query);
827                 }
828                 $id = DB::getInsertId();
829
830                 // update category row so it links to blog
831                 DB::execute('UPDATE ' . sql_table('category') . ' SET cblog=' . intval($id). ' WHERE catid=' . intval($defcat));
832
833                 BlogImport::sql_addToTeam($id,$ownerid,1);
834
835
836                 return $id;
837         }
838
839         function sql_addToComments($name, $url, $body, $blogid, $itemid, $memberid, $timestamp, $host, $ip='') {
840                 $name           = DB::quoteValue($name);
841                 $url            = DB::quoteValue($url);
842                 $body           = DB::quoteValue(trim($body));
843                 $host           = DB::quoteValue($host);
844                 $ip             = DB::quoteValue($ip);
845                 $timestamp      = DB::formatDateTime($timestamp);
846
847                 $query = 'INSERT INTO '.sql_table('comment')
848                            . ' (CUSER, CMAIL, CMEMBER, CBODY, CITEM, CTIME, CHOST, CBLOG, CIP) '
849                            . "VALUES ($name, $url, $memberid, $body, $itemid, $timestamp, $host, $blogid, $ip)";
850
851                 if ( DB::execute($query) === FALSE )
852                 {
853                         die('Error while executing query: ' . $query);
854                 }
855
856                 return DB::getInsertId();
857         }
858
859         function sql_addToTeam($blogid, $memberid, $admin) {
860
861                 $query = 'INSERT INTO '.sql_table('team').' (TMEMBER, TBLOG, TADMIN) '
862                            . "VALUES ($memberid, $blogid, $admin)";
863
864                 if ( DB::execute($query) === FALSE )
865                 {
866                         die('Error while executing query: ' . $query);
867                 }
868
869                 return DB::getInsertId();
870         }
871
872 }
873
874 // some sort of version checking
875 $ver = convert_getNucleusVersion();
876 if ($ver > 250)
877         convert_doError("You should check the Nucleus website for updates to this convert tool. This one might not work with your current Nucleus installation.");
878
879         // make sure the request variables get reqistered in the global scope
880         // Doing this should be avoided on code rewrite (this is a potential security risk)
881         if ((phpversion() >= "4.1.0") && (ini_get("register_globals") == 0)) {
882                 @import_request_variables("gp",'');
883         }
884
885         /** this function gets the nucleus version, even if the getNucleusVersion
886          * function does not exist yet
887          * return 96 for all versions < 100
888          */
889         function convert_getNucleusVersion() {
890                 if (!function_exists('getNucleusVersion')) return 96;
891                 return getNucleusVersion();
892         }
893
894         // TODO: remove this function (replaced by BlogImport::sql_addToItem)
895         function convert_addToItem($title, $body, $more, $blogid, $authorid, $timestamp, $closed, $category, $karmapos, $karmaneg) {
896                 $title = DB::quoteValue(trim($title));
897                 $body = DB::quoteValue(trim($body));
898                 $more = DB::quoteValue(trim($more));
899
900                 $query = 'INSERT INTO '.sql_table('item').' (ITITLE, IBODY, IMORE, IBLOG, IAUTHOR, ITIME, ICLOSED, IKARMAPOS, IKARMANEG, ICAT) '
901                            . "VALUES ($title, $body, $more, $blogid, $authorid, '$timestamp', $closed, $karmapos, $karmaneg,  $category)";
902
903                 if ( DB::execute($query) === FALSE )
904                 {
905                         die('Error while executing query: ' . $query);
906                 }
907
908                 return DB::getInsertId();
909         }
910
911
912         // TODO: remove this function (replaced by BlogImport::sql_addToBlog)
913         function convert_addToBlog($name, $shortname, $ownerid) {
914                 $name = DB::quoteValue($name);
915                 $shortname = DB::quoteValue($shortname);
916
917                 // create new category first
918                 DB::execute('INSERT INTO '.sql_table('category')." (CNAME, CDESC) VALUES ('General','Items that do not fit in another categort')");
919                 $defcat = DB::getInsertId();
920
921                 $query = 'INSERT INTO '.sql_table('blog')." (BNAME, BSHORTNAME, BCOMMENTS, BMAXCOMMENTS, BDEFCAT) VALUES ($name, $shortname, 1, 0, $defcat)";
922                 if ( DB::execute($query) === FALSE )
923                 {
924                         die('Error while executing query: ' . $query);
925                 }
926                 $id = DB::getInsertId();
927
928                 convert_addToTeam($id,$ownerid,1);
929
930                 return $id;
931         }
932
933         // TODO: remove this function (replaced by BlogImport::sql_addToComments)
934         function convert_addToComments($name, $url, $body, $blogid, $itemid, $memberid, $timestamp, $host, $ip='') {
935                 $name = DB::quoteValue($name);
936                 $url = DB::quoteValue($url);
937                 $body = DB::quoteValue(trim($body));
938                 $host = DB::quoteValue($host);
939                 $ip = DB::quoteValue($ip);
940
941                 $query = 'INSERT INTO '.sql_table('comment')
942                            . ' (CUSER, CMAIL, CMEMBER, CBODY, CITEM, CTIME, CHOST, CBLOG, CIP) '
943                            . "VALUES ($name, $url, $memberid, $body, $itemid, '$timestamp', $host, $blogid, $ip)";
944
945                 if ( DB::execute($query) === FALSE )
946                 {
947                         die("Error while executing query: " . $query);
948                 }
949
950                 return DB::getInsertId();
951         }
952
953         // TODO: remove this function (replaced by BlogImport::sql_addToTeam)
954         function convert_addToTeam($blogid, $memberid, $admin) {
955
956                 $query = 'INSERT INTO '.sql_table('team').' (TMEMBER, TBLOG, TADMIN) '
957                            . "VALUES ($memberid, $blogid, $admin)";
958
959                 if ( DB::execute($query) === FALSE )
960                 {
961                         die("Error while executing query: " . $query);
962                 }
963                 
964                 return DB::getInsertId();
965         }
966
967         function convert_showLogin($type) {
968                 convert_head();
969         ?>
970                 <h1>Please Log in First</h1>
971                 <p>Enter your data below:</p>
972
973                 <form method="post" action="<?php echo $type?>">
974
975                         <ul>
976                                 <li>Name: <input name="login" /></li>
977                                 <li>Password <input name="password" type="password" /></li>
978                         </ul>
979
980                         <p>
981                                 <input name="action" value="login" type="hidden" />
982                                 <input type="submit" value="Log in" />
983                         </p>
984
985                 </form>
986         <?php           convert_foot();
987                 exit;
988         }
989
990         function convert_head() {
991         ?>
992                 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
993                 <html xmlns="http://www.w3.org/1999/xhtml">
994                 <head>
995                         <title>Nucleus Convert</title>
996                         <style><!--
997                                 @import url('../styles/manual.css');
998                         --></style>
999                 </head>
1000                 <body>
1001         <?php   }
1002
1003         function convert_foot() {
1004         ?>
1005                 </body>
1006                 </html>
1007         <?php   }
1008
1009         function convert_doError($msg) {
1010                 convert_head();
1011                 ?>
1012                 <h1>Error!</h1>
1013
1014                 <p>Message was:</p>
1015
1016                 <blockquote><div>
1017                 <?php echo $msg?>
1018                 </div></blockquote>
1019
1020                 <p><a href="index.php" onclick="history.back();">Go Back</a></p>
1021                 <?php
1022                 convert_foot();
1023                 exit;
1024         }
1025
1026         function endsWithSlash($s) {
1027                 return (strrpos($s,'/') == strlen($s) - 1);
1028         }
1029
1030
1031 ?>