00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00074 require_once(PATH_t3lib.'class.t3lib_sqlparser.php');
00075
00083 class t3lib_install {
00084
00085
00086 var $updateIdentity = '';
00087 var $deletedPrefixKey = 'zzz_deleted_';
00088 var $dbUpdateCheckboxPrefix = 'TYPO3_INSTALL[database_update]';
00089 var $mysqlVersion = '3.22';
00090 var $localconf_addLinesOnly = 0;
00091 var $localconf_editPointToken = 'INSTALL SCRIPT EDIT POINT TOKEN - all lines after this points may be changed by the install script!';
00092 var $allowUpdateLocalConf = 0;
00093 var $backPath = '../';
00094
00095 var $multiplySize = 1;
00096
00097
00098 var $setLocalconf = 0;
00099 var $messages = array();
00100 var $touchedLine = 0;
00101
00102
00103
00104
00105
00111 function t3lib_install() {
00112 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['multiplyDBfieldSize']>= 1 && $GLOBALS['TYPO3_CONF_VARS']['SYS']['multiplyDBfieldSize']<=5) {
00113 $this->multiplySize = (double)$GLOBALS['TYPO3_CONF_VARS']['SYS']['multiplyDBfieldSize'];
00114 }
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00134 function setValueInLocalconfFile(&$line_array, $variable, $value) {
00135 if (!$this->checkForBadString($value)) return 0;
00136
00137
00138 $found = 0;
00139 $this->touchedLine = '';
00140 $commentKey = '## ';
00141 $inArray = in_array($commentKey.$this->localconf_editPointToken,$line_array);
00142 $tokenSet = ($this->localconf_editPointToken && !$inArray);
00143 $stopAtToken = ($this->localconf_editPointToken && $inArray);
00144 $comment = ' Modified or inserted by '.$this->updateIdentity.'.';
00145
00146
00147 if (!$this->localconf_addLinesOnly && !$tokenSet) {
00148 $line_array = array_reverse($line_array);
00149 foreach($line_array as $k => $v) {
00150 $v2 = trim($v);
00151 if ($stopAtToken && !strcmp($v2,$commentKey.$this->localconf_editPointToken)) break;
00152 if (!strcmp(substr($v2,0,strlen($variable.' ')),$variable.' ')) {
00153 $mainparts = explode($variable,$v,2);
00154 if (count($mainparts)==2) {
00155 $subparts = explode('
00156 $line_array[$k] = $mainparts[0].$variable." = '".$this->slashValueForSingleDashes($value)."'; ".('
00157 $this->touchedLine = count($line_array)-$k-1;
00158 $found = 1;
00159 break;
00160 }
00161 }
00162 }
00163 $line_array = array_reverse($line_array);
00164 }
00165 if (!$found) {
00166 if ($tokenSet) {
00167 $line_array[] = $commentKey.$this->localconf_editPointToken;
00168 $line_array[] = '';
00169 }
00170 $line_array[] = $variable." = '".$this->slashValueForSingleDashes($value)."'; // ".$comment;
00171 $this->touchedLine = -1;
00172 }
00173 $this->messages[] = $variable." = '".htmlspecialchars($value)."'";
00174 $this->setLocalconf = 1;
00175 }
00176
00184 function writeToLocalconf_control($inlines='') {
00185 $writeToLocalconf_dat['file'] = PATH_typo3conf.'localconf.php';
00186
00187
00188 if (!$this->allowUpdateLocalConf) {
00189 die("->allowUpdateLocalConf flag in the install object is not set and therefore 'localconf.php' cannot be altered.");
00190 }
00191 if (!@is_writeable($writeToLocalconf_dat['file'])) {
00192 die($writeToLocalconf_dat['file'].' is not writeable!');
00193 }
00194
00195
00196 $lines = explode(chr(10),trim(t3lib_div::getUrl($writeToLocalconf_dat['file'])));
00197 $writeToLocalconf_dat['endLine'] = array_pop($lines);
00198
00199
00200 $updatedLine = array_pop($lines);
00201 $writeToLocalconf_dat['updatedText'] = '
00202 if (!strstr($updatedLine, $writeToLocalconf_dat['updatedText'])) {
00203 array_push($lines,$updatedLine);
00204 }
00205
00206 if (is_array($inlines)) {
00207
00208 $updatedLine = $writeToLocalconf_dat['updatedText'].date('d-m-Y H:i:s');
00209 array_push($inlines,$updatedLine);
00210 array_push($inlines,$writeToLocalconf_dat['endLine']);
00211
00212 if ($this->setLocalconf) {
00213 t3lib_div::writeFile($writeToLocalconf_dat['file'],implode(chr(10),$inlines));
00214
00215 if (strcmp(t3lib_div::getUrl($writeToLocalconf_dat['file']), implode(chr(10),$inlines))) {
00216 die('typo3temp/localconf.php was NOT updated properly (written content didn\'t match file content) - maybe write access problem?');
00217 }
00218
00219 $this->messages[]= 'Configuration written to typo3conf/localconf.php';
00220 return 'continue';
00221 } else {
00222 return 'nochange';
00223 }
00224 } else {
00225 return $lines;
00226 }
00227 }
00228
00236 function checkForBadString($string) {
00237 if (ereg('['.chr(10).chr(13).']',$string)){
00238 return FALSE;
00239 } else return TRUE;
00240 }
00241
00249 function slashValueForSingleDashes($value) {
00250 return str_replace("'","\'",str_replace('\\','\\\\',$value));
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00274 function getFieldDefinitions_sqlContent($sqlContent) {
00275 $lines = t3lib_div::trimExplode(chr(10), $sqlContent,1);
00276 $isTable = '';
00277
00278 foreach($lines as $value) {
00279 if ($value[0]!='#') {
00280 if (!$isTable) {
00281 $parts = explode(' ',$value);
00282 if ($parts[0]=='CREATE' && $parts[1]=='TABLE') {
00283 $isTable = $parts[2];
00284 if (TYPO3_OS=='WIN') {
00285 $isTable = strtolower($isTable);
00286 }
00287 }
00288 } else {
00289 if (substr($value,0,1)==')' && substr($value,-1)==';') {
00290 $isTable = '';
00291 } else {
00292 $lineV = ereg_replace(',$','',$value);
00293 $parts = explode(' ',$lineV,2);
00294 if ($parts[0]!='PRIMARY' && $parts[0]!='KEY' && $parts[0]!='UNIQUE') {
00295 $total[$isTable]['fields'][$parts[0]] = $parts[1];
00296 } else {
00297 $newParts = explode(' ',$parts[1],2);
00298 $total[$isTable]['keys'][($parts[0]=='PRIMARY'?$parts[0]:$newParts[0])] = $lineV;
00299 }
00300 }
00301 }
00302 }
00303 }
00304
00305 $this->getFieldDefinitions_sqlContent_parseTypes($total);
00306 return $total;
00307 }
00308
00318 function getFieldDefinitions_sqlContent_parseTypes(&$total) {
00319
00320 $mSize = (double)$this->multiplySize;
00321 if ($mSize > 1) {
00322
00323
00324 $sqlParser = t3lib_div::makeInstance('t3lib_sqlparser');
00325 foreach($total as $table => $cfg) {
00326 foreach($cfg['fields'] as $fN => $fType) {
00327 $orig_fType = $fType;
00328 $fInfo = $sqlParser->parseFieldDef($fType);
00329
00330 switch($fInfo['fieldType']) {
00331 case 'char':
00332 case 'varchar':
00333 $newSize = round($fInfo['value']*$mSize);
00334
00335 if ($newSize <= 255) {
00336 $fInfo['value'] = $newSize;
00337 } else {
00338 $fInfo = array(
00339 'fieldType' => 'text',
00340 'featureIndex' => array(
00341 'NOTNULL' => array(
00342 'keyword' => 'NOT NULL'
00343 )
00344 )
00345 );
00346 }
00347 break;
00348 case 'tinytext':
00349 $fInfo['fieldType'] = 'text';
00350 break;
00351 }
00352
00353 $total[$table]['fields'][$fN] = $sqlParser->compileFieldCfg($fInfo);
00354 if ($sqlParser->parse_error) die($sqlParser->parse_error);
00355 }
00356 }
00357 }
00358 }
00359
00365 function getFieldDefinitions_database() {
00366 $total = array();
00367 $GLOBALS['TYPO3_DB']->sql_select_db(TYPO3_db);
00368 echo $GLOBALS['TYPO3_DB']->sql_error();
00369
00370 $tables = $GLOBALS['TYPO3_DB']->admin_get_tables(TYPO3_db);
00371 foreach($tables as $tableName) {
00372
00373
00374 $fieldInformation = $GLOBALS['TYPO3_DB']->admin_get_fields($tableName);
00375 foreach($fieldInformation as $fN => $fieldRow) {
00376 $total[$tableName]['fields'][$fN] = $this->assembleFieldDefinition($fieldRow);
00377 }
00378
00379
00380 $keyInformation = $GLOBALS['TYPO3_DB']->admin_get_keys($tableName);
00381 foreach($keyInformation as $kN => $keyRow) {
00382 $tempKeys[$tableName][$keyRow['Key_name']][$keyRow['Seq_in_index']] = $keyRow['Column_name'];
00383 $tempKeysPrefix[$tableName][$keyRow['Key_name']]= ($keyRow['Key_name']=='PRIMARY'?'PRIMARY KEY':($keyRow['Non_unique']?'KEY':'UNIQUE').' '.$keyRow['Key_name']);
00384 }
00385 }
00386
00387
00388 if (is_array($tempKeys)) {
00389 foreach($tempKeys as $table => $keyInf) {
00390 foreach($keyInf as $kName => $index) {
00391 ksort($index);
00392 $total[$table]['keys'][$kName] = $tempKeysPrefix[$table][$kName].' ('.implode(',',$index).')';
00393 }
00394 }
00395 }
00396
00397 return $total;
00398 }
00399
00409 function getDatabaseExtra($FDsrc, $FDcomp, $onlyTableList='') {
00410 $extraArr = array();
00411 $diffArr = array();
00412
00413 if (is_array($FDsrc)) {
00414 foreach($FDsrc as $table => $info) {
00415 if (!strlen($onlyTableList) || t3lib_div::inList($onlyTableList, $table)) {
00416 if (!isset($FDcomp[$table])) {
00417 $extraArr[$table] = $info;
00418 $extraArr[$table]['whole_table']=1;
00419 } else {
00420 $keyTypes = explode(',','fields,keys');
00421 foreach($keyTypes as $theKey) {
00422 if (is_array($info[$theKey])) {
00423 foreach($info[$theKey] as $fieldN => $fieldC) {
00424 if (!isset($FDcomp[$table][$theKey][$fieldN])) {
00425 $extraArr[$table][$theKey][$fieldN] = $fieldC;
00426 } elseif (strcmp($FDcomp[$table][$theKey][$fieldN], $fieldC)){
00427 $diffArr[$table][$theKey][$fieldN] = $fieldC;
00428 $diffArr_cur[$table][$theKey][$fieldN] = $FDcomp[$table][$theKey][$fieldN];
00429 }
00430 }
00431 }
00432 }
00433 }
00434 }
00435 }
00436 }
00437
00438 $output = array(
00439 'extra' => $extraArr,
00440 'diff' => $diffArr,
00441 'diff_currentValues' => $diffArr_cur
00442 );
00443
00444 return $output;
00445 }
00446
00454 function getUpdateSuggestions($diffArr,$keyList='extra,diff') {
00455 $statements = array();
00456 $deletedPrefixKey = $this->deletedPrefixKey;
00457 $remove = 0;
00458 if ($keyList == 'remove') {
00459 $remove = 1;
00460 $keyList = 'extra';
00461 }
00462 $keyList = explode(',',$keyList);
00463 foreach($keyList as $theKey) {
00464 if (is_array($diffArr[$theKey])) {
00465 foreach($diffArr[$theKey] as $table => $info) {
00466 $whole_table = array();
00467 if (is_array($info['fields'])) {
00468 foreach($info['fields'] as $fN => $fV) {
00469 if ($info['whole_table']) {
00470 $whole_table[]=$fN.' '.$fV;
00471 } else {
00472 if ($theKey=='extra') {
00473 if ($remove) {
00474 if (substr($fN,0,strlen($deletedPrefixKey))!=$deletedPrefixKey) {
00475 $statement = 'ALTER TABLE '.$table.' CHANGE '.$fN.' '.$deletedPrefixKey.$fN.' '.$fV.';';
00476 $statements['change'][md5($statement)] = $statement;
00477 } else {
00478 $statement = 'ALTER TABLE '.$table.' DROP '.$fN.';';
00479 $statements['drop'][md5($statement)] = $statement;
00480 }
00481 } else {
00482 $statement = 'ALTER TABLE '.$table.' ADD '.$fN.' '.$fV.';';
00483 $statements['add'][md5($statement)] = $statement;
00484 }
00485 } elseif ($theKey=='diff') {
00486 $statement = 'ALTER TABLE '.$table.' CHANGE '.$fN.' '.$fN.' '.$fV.';';
00487 $statements['change'][md5($statement)] = $statement;
00488 $statements['change_currentValue'][md5($statement)] = $diffArr['diff_currentValues'][$table]['fields'][$fN];
00489 }
00490 }
00491 }
00492 }
00493 if (is_array($info['keys'])) {
00494 foreach($info['keys'] as $fN => $fV) {
00495 if ($info['whole_table']) {
00496 if ($fN=='PRIMARY') {
00497 $whole_table[] = $fV;
00498 } else {
00499 $whole_table[] = $fV;
00500 }
00501 } else {
00502 if ($theKey=='extra') {
00503 if ($remove) {
00504 $statement = 'ALTER TABLE '.$table.($fN=='PRIMARY' ? ' DROP PRIMARY KEY' : ' DROP KEY '.$fN).';';
00505 $statements['drop'][md5($statement)] = $statement;
00506 } else {
00507 $statement = 'ALTER TABLE '.$table.' ADD '.$fV.';';
00508 $statements['add'][md5($statement)] = $statement;
00509 }
00510 } elseif ($theKey=='diff') {
00511 $statement = 'ALTER TABLE '.$table.($fN=='PRIMARY' ? ' DROP PRIMARY KEY' : ' DROP KEY '.$fN).';';
00512 $statements['change'][md5($statement)] = $statement;
00513 $statement = 'ALTER TABLE '.$table.' ADD '.$fV.';';
00514 $statements['change'][md5($statement)] = $statement;
00515 }
00516 }
00517 }
00518 }
00519 if ($info['whole_table']) {
00520 if ($remove) {
00521 if (substr($table,0,strlen($deletedPrefixKey))!=$deletedPrefixKey) {
00522 $statement = 'ALTER TABLE '.$table.' RENAME '.$deletedPrefixKey.$table.';';
00523 $statements['change_table'][md5($statement)]=$statement;
00524 } else {
00525 $statement = 'DROP TABLE '.$table.';';
00526 $statements['drop_table'][md5($statement)]=$statement;
00527 }
00528
00529 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*)', $table, '');
00530 list($count) = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
00531 $statements['tables_count'][md5($statement)] = $count?'Records in table: '.$count:'';
00532 } else {
00533 $statement = 'CREATE TABLE '.$table." (\n".implode(",\n",$whole_table)."\n) TYPE=MyISAM;";
00534 $statements['create_table'][md5($statement)]=$statement;
00535 }
00536 }
00537 }
00538 }
00539 }
00540
00541 return $statements;
00542 }
00543
00550 function assembleFieldDefinition($row) {
00551 $field[] = $row['Type'];
00552 if ($this->mysqlVersion=='3.23' && !$row['Null']) {
00553 $field[] = 'NOT NULL';
00554 }
00555 if (!strstr($row['Type'],'blob') && !strstr($row['Type'],'text')) {
00556
00557
00558 if ($this->mysqlVersion!='3.23' || !stristr($row['Extra'],'auto_increment')) {
00559 $field[] = ($this->mysqlVersion=='3.23'?'default':'DEFAULT')." '".(stristr($row['Extra'],'auto_increment')?intval($row['Default']):addslashes($row['Default']))."'";
00560 }
00561 }
00562 if ($this->mysqlVersion!='3.23' && !$row['Null']) {
00563 $field[] = 'NOT NULL';
00564 }
00565 if ($row['Extra']) {
00566 $field[] = $row['Extra'];
00567 }
00568 return implode(' ',$field);
00569 }
00570
00579 function getStatementArray($sqlcode,$removeNonSQL=0,$query_regex='') {
00580 $sqlcodeArr = explode(chr(10),$sqlcode);
00581
00582
00583 $statementArray = array();
00584 $statementArrayPointer = 0;
00585
00586 foreach($sqlcodeArr as $line => $linecontent) {
00587
00588
00589 if (substr(trim($linecontent),0,16)=='# Server version') {
00590 $this->mysqlVersion = doubleval(substr(trim($linecontent),16));
00591 }
00592 $is_set = 0;
00593
00594 if (!$removeNonSQL || (strcmp(trim($linecontent),'') && substr(trim($linecontent),0,1)!='#' && substr(trim($linecontent),0,2)!='--')) {
00595 $statementArray[$statementArrayPointer].= $linecontent;
00596 $is_set = 1;
00597 }
00598 if (substr(trim($linecontent),-1)==';') {
00599 if (isset($statementArray[$statementArrayPointer])) {
00600 if (!trim($statementArray[$statementArrayPointer]) || ($query_regex && !eregi($query_regex,trim($statementArray[$statementArrayPointer])))) {
00601 unset($statementArray[$statementArrayPointer]);
00602 }
00603 }
00604 $statementArrayPointer++;
00605 } elseif ($is_set) {
00606 $statementArray[$statementArrayPointer].=chr(10);
00607 }
00608 }
00609 return $statementArray;
00610 }
00611
00619 function getCreateTables($statements, $insertCountFlag=0) {
00620 $crTables = array();
00621 foreach($statements as $line => $linecontent) {
00622 if (eregi('^create[[:space:]]*table[[:space:]]*([[:alnum:]_]*)',substr($linecontent,0,100),$reg)) {
00623 $table = trim($reg[1]);
00624 if ($table) {
00625 if (TYPO3_OS=='WIN') {$table=strtolower($table);}
00626 $crTables[$table] = $linecontent;
00627 }
00628 } elseif ($insertCountFlag && eregi('^insert[[:space:]]*into[[:space:]]*([[:alnum:]_]*)',substr($linecontent,0,100),$reg)) {
00629 $nTable = trim($reg[1]);
00630 $insertCount[$nTable]++;
00631 }
00632 }
00633 return array($crTables,$insertCount);
00634 }
00635
00643 function getTableInsertStatements($statements, $table) {
00644 $outStatements=array();
00645 foreach($statements as $line => $linecontent) {
00646 if (eregi('^insert[[:space:]]*into[[:space:]]*([[:alnum:]_]*)',substr($linecontent,0,100),$reg)) {
00647 $nTable = trim($reg[1]);
00648 if ($nTable && !strcmp($table,$nTable)) {
00649 $outStatements[]=$linecontent;
00650 }
00651 }
00652 }
00653 return $outStatements;
00654 }
00655
00663 function performUpdateQueries($arr,$keyArr) {
00664 if (is_array($arr)) {
00665 foreach($arr as $key => $string) {
00666 if (isset($keyArr[$key]) && $keyArr[$key]) {
00667 $GLOBALS['TYPO3_DB']->admin_query($string);
00668 }
00669 }
00670 }
00671 }
00672
00679 function getListOfTables() {
00680 $whichTables = $GLOBALS['TYPO3_DB']->admin_get_tables(TYPO3_db);
00681 return $whichTables;
00682 }
00683
00695 function generateUpdateDatabaseForm_checkboxes($arr,$label,$checked=1,$iconDis=0,$currentValue=array(),$cVfullMsg=0) {
00696 $out = array();
00697 if (is_array($arr)) {
00698 foreach($arr as $key => $string) {
00699 $ico = '';
00700 if ($iconDis) {
00701 if (stristr($string,' user_')) {
00702 $ico.= '<img src="'.$this->backPath.'t3lib/gfx/icon_warning.gif" width="18" height="16" align="top" alt="" /><strong>(USER) </strong>';
00703 }
00704 if (stristr($string,' app_')) {
00705 $ico.= '<img src="'.$this->backPath.'t3lib/gfx/icon_warning.gif" width="18" height="16" align="top" alt="" /><strong>(APP) </strong>';
00706 }
00707 if (stristr($string,' ttx_') || stristr($string,' tx_')) {
00708 $ico.= '<img src="'.$this->backPath.'t3lib/gfx/icon_warning.gif" width="18" height="16" align="top" alt="" /><strong>(EXT) </strong>';
00709 }
00710 }
00711 $out[]='
00712 <tr>
00713 <td valign="top"><input type="checkbox" name="'.$this->dbUpdateCheckboxPrefix.'['.$key.']" value="1"'.($checked?' checked="checked"':'').' /></td>
00714 <td nowrap="nowrap">'.nl2br($ico.htmlspecialchars($string)).'</td>
00715 </tr>';
00716 if (isset($currentValue[$key])) {
00717 $out[]='
00718 <tr>
00719 <td valign="top"></td>
00720 <td nowrap="nowrap" style="color : #666666;">'.nl2br((!$cVfullMsg?"Current value: ":"").'<em>'.$currentValue[$key].'</em>').'</td>
00721 </tr>';
00722 }
00723 }
00724
00725
00726 $content = '
00727 <!-- Update database fields / tables -->
00728 <h3>'.$label.'</h3>
00729 <table border="0" cellpadding="2" cellspacing="2" class="update-db-fields">'.implode('',$out).'
00730 </table>';
00731 }
00732
00733 return $content;
00734 }
00735 }
00736
00737 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_install.php']) {
00738 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_install.php']);
00739 }
00740 ?>