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
00087 var $updateIdentity = '';
00088 var $deletedPrefixKey = 'zzz_deleted_';
00089 var $dbUpdateCheckboxPrefix = 'TYPO3_INSTALL[database_update]';
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
00108 function t3lib_install() {
00109 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['multiplyDBfieldSize']>= 1 && $GLOBALS['TYPO3_CONF_VARS']['SYS']['multiplyDBfieldSize']<=5) {
00110 $this->multiplySize = (double)$GLOBALS['TYPO3_CONF_VARS']['SYS']['multiplyDBfieldSize'];
00111 }
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00132 function setValueInLocalconfFile(&$line_array, $variable, $value) {
00133 if (!$this->checkForBadString($value)) return 0;
00134
00135
00136 $found = 0;
00137 $this->touchedLine = '';
00138 $commentKey = '## ';
00139 $inArray = in_array($commentKey.$this->localconf_editPointToken,$line_array);
00140 $tokenSet = ($this->localconf_editPointToken && !$inArray);
00141 $stopAtToken = ($this->localconf_editPointToken && $inArray);
00142 $comment = ' Modified or inserted by '.$this->updateIdentity.'.';
00143
00144
00145 if (!$this->localconf_addLinesOnly && !$tokenSet) {
00146 $line_array = array_reverse($line_array);
00147 foreach($line_array as $k => $v) {
00148 $v2 = trim($v);
00149 if ($stopAtToken && !strcmp($v2,$commentKey.$this->localconf_editPointToken)) break;
00150 if (!strcmp(substr($v2,0,strlen($variable.' ')),$variable.' ')) {
00151 $mainparts = explode($variable,$v,2);
00152 if (count($mainparts)==2) {
00153 $subparts = explode('
00154 $line_array[$k] = $mainparts[0].$variable." = '".$this->slashValueForSingleDashes($value)."'; ".('
00155 $this->touchedLine = count($line_array)-$k-1;
00156 $found = 1;
00157 break;
00158 }
00159 }
00160 }
00161 $line_array = array_reverse($line_array);
00162 }
00163 if (!$found) {
00164 if ($tokenSet) {
00165 $line_array[] = $commentKey.$this->localconf_editPointToken;
00166 $line_array[] = '';
00167 }
00168 $line_array[] = $variable." = '".$this->slashValueForSingleDashes($value)."'; // ".$comment;
00169 $this->touchedLine = -1;
00170 }
00171 $this->messages[] = $variable." = '".htmlspecialchars($value)."'";
00172 $this->setLocalconf = 1;
00173 }
00174
00183 function writeToLocalconf_control($inlines='',$absFullPath='') {
00184 $writeToLocalconf_dat['file'] = $absFullPath ? $absFullPath : PATH_typo3conf.'localconf.php';
00185
00186
00187 if (!$this->allowUpdateLocalConf) {
00188 die("->allowUpdateLocalConf flag in the install object is not set and therefore 'localconf.php' cannot be altered.");
00189 }
00190 if (!@is_writable($writeToLocalconf_dat['file'])) {
00191 die($writeToLocalconf_dat['file'].' is not writable!');
00192 }
00193
00194
00195 $lines = explode(chr(10),trim(t3lib_div::getUrl($writeToLocalconf_dat['file'])));
00196 $writeToLocalconf_dat['endLine'] = array_pop($lines);
00197
00198
00199 $updatedLine = array_pop($lines);
00200 $writeToLocalconf_dat['updatedText'] = '
00201 if (!strstr($updatedLine, $writeToLocalconf_dat['updatedText'])) {
00202 array_push($lines,$updatedLine);
00203 }
00204
00205 if (is_array($inlines)) {
00206
00207 $updatedLine = $writeToLocalconf_dat['updatedText'].date('d-m-Y H:i:s');
00208 array_push($inlines,$updatedLine);
00209 array_push($inlines,$writeToLocalconf_dat['endLine']);
00210
00211 if ($this->setLocalconf) {
00212 t3lib_div::writeFile($writeToLocalconf_dat['file'],implode(chr(10),$inlines));
00213
00214 if (strcmp(t3lib_div::getUrl($writeToLocalconf_dat['file']), implode(chr(10),$inlines))) {
00215 die('typo3conf/localconf.php was NOT updated properly (written content didn\'t match file content) - maybe write access problem?');
00216 }
00217
00218 $this->messages[]= 'Configuration written to typo3conf/localconf.php';
00219 return 'continue';
00220 } else {
00221 return 'nochange';
00222 }
00223 } else {
00224 return $lines;
00225 }
00226 }
00227
00235 function checkForBadString($string) {
00236 if (ereg('['.chr(10).chr(13).']',$string)){
00237 return FALSE;
00238 } else return TRUE;
00239 }
00240
00248 function slashValueForSingleDashes($value) {
00249 return str_replace("'","\'",str_replace('\\','\\\\',$value));
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00273 function getFieldDefinitions_sqlContent($sqlContent) {
00274 $lines = t3lib_div::trimExplode(chr(10), $sqlContent,1);
00275 $isTable = '';
00276
00277 foreach($lines as $value) {
00278 if ($value[0]!='#') {
00279 if (!$isTable) {
00280 $parts = explode(' ',$value);
00281 if ($parts[0]=='CREATE' && $parts[1]=='TABLE') {
00282 $isTable = $parts[2];
00283 if (TYPO3_OS=='WIN') {
00284 $isTable = strtolower($isTable);
00285 }
00286 }
00287 } else {
00288 if (substr($value,0,1)==')' && substr($value,-1)==';') {
00289 preg_match('/(ENGINE|TYPE)=([a-zA-Z]*)/',$value,$ttype);
00290 $total[$isTable]['extra']['ttype'] = $ttype[2];
00291 $isTable = '';
00292 } else {
00293 $lineV = ereg_replace(',$','',$value);
00294 $parts = explode(' ',$lineV,2);
00295
00296
00297 if(stristr($parts[1],'auto_increment')) {
00298 $parts[1] = preg_replace('/ default \'0\'/i','',$parts[1]);
00299 }
00300
00301 if(strstr($parts[1], ' DEFAULT ')) {
00302 $parts[1] = str_replace(' DEFAULT ', ' default ', $parts[1]);
00303 }
00304
00305 $parts[1] = preg_replace('/(.*) (default .*) (NOT NULL)/', '$1 $3 $2', $parts[1]);
00306 $parts[1] = preg_replace('/(.*) (default .*) (NULL)/', '$1 $3 $2', $parts[1]);
00307
00308 if ($parts[0]!='PRIMARY' && $parts[0]!='KEY' && $parts[0]!='UNIQUE') {
00309 $total[$isTable]['fields'][$parts[0]] = $parts[1];
00310 } else {
00311 $newParts = explode(' ',$parts[1],2);
00312 $total[$isTable]['keys'][($parts[0]=='PRIMARY'?$parts[0]:$newParts[0])] = $lineV;
00313 }
00314 }
00315 }
00316 }
00317 }
00318
00319 $this->getFieldDefinitions_sqlContent_parseTypes($total);
00320 return $total;
00321 }
00322
00332 function getFieldDefinitions_sqlContent_parseTypes(&$total) {
00333
00334 $mSize = (double)$this->multiplySize;
00335 if ($mSize > 1) {
00336
00337
00338 $sqlParser = t3lib_div::makeInstance('t3lib_sqlparser');
00339 foreach($total as $table => $cfg) {
00340 foreach($cfg['fields'] as $fN => $fType) {
00341 $orig_fType = $fType;
00342 $fInfo = $sqlParser->parseFieldDef($fType);
00343
00344 switch($fInfo['fieldType']) {
00345 case 'char':
00346 case 'varchar':
00347 $newSize = round($fInfo['value']*$mSize);
00348
00349 if ($newSize <= 255) {
00350 $fInfo['value'] = $newSize;
00351 } else {
00352 $fInfo = array(
00353 'fieldType' => 'text',
00354 'featureIndex' => array(
00355 'NOTNULL' => array(
00356 'keyword' => 'NOT NULL'
00357 )
00358 )
00359 );
00360 }
00361 break;
00362 case 'tinytext':
00363 $fInfo['fieldType'] = 'text';
00364 break;
00365 }
00366
00367 $total[$table]['fields'][$fN] = $sqlParser->compileFieldCfg($fInfo);
00368 if ($sqlParser->parse_error) die($sqlParser->parse_error);
00369 }
00370 }
00371 }
00372 }
00373
00379 function getFieldDefinitions_database() {
00380 $total = array();
00381 $GLOBALS['TYPO3_DB']->sql_select_db(TYPO3_db);
00382 echo $GLOBALS['TYPO3_DB']->sql_error();
00383
00384 $tables = $GLOBALS['TYPO3_DB']->admin_get_tables(TYPO3_db);
00385 foreach($tables as $tableName) {
00386
00387
00388 $fieldInformation = $GLOBALS['TYPO3_DB']->admin_get_fields($tableName);
00389 foreach($fieldInformation as $fN => $fieldRow) {
00390 $total[$tableName]['fields'][$fN] = $this->assembleFieldDefinition($fieldRow);
00391 }
00392
00393
00394 $keyInformation = $GLOBALS['TYPO3_DB']->admin_get_keys($tableName);
00395 foreach($keyInformation as $kN => $keyRow) {
00396 $tempKeys[$tableName][$keyRow['Key_name']][$keyRow['Seq_in_index']] = $keyRow['Column_name'];
00397 $tempKeysPrefix[$tableName][$keyRow['Key_name']]= ($keyRow['Key_name']=='PRIMARY'?'PRIMARY KEY':($keyRow['Non_unique']?'KEY':'UNIQUE').' '.$keyRow['Key_name']);
00398 }
00399 }
00400
00401
00402 if (is_array($tempKeys)) {
00403 foreach($tempKeys as $table => $keyInf) {
00404 foreach($keyInf as $kName => $index) {
00405 ksort($index);
00406 $total[$table]['keys'][$kName] = $tempKeysPrefix[$table][$kName].' ('.implode(',',$index).')';
00407 }
00408 }
00409 }
00410
00411 return $total;
00412 }
00413
00423 function getDatabaseExtra($FDsrc, $FDcomp, $onlyTableList='') {
00424 $extraArr = array();
00425 $diffArr = array();
00426
00427 if (is_array($FDsrc)) {
00428 foreach($FDsrc as $table => $info) {
00429 if (!strlen($onlyTableList) || t3lib_div::inList($onlyTableList, $table)) {
00430 if (!isset($FDcomp[$table])) {
00431 $extraArr[$table] = $info;
00432 $extraArr[$table]['whole_table']=1;
00433 } else {
00434 $keyTypes = explode(',','fields,keys');
00435 foreach($keyTypes as $theKey) {
00436 if (is_array($info[$theKey])) {
00437 foreach($info[$theKey] as $fieldN => $fieldC) {
00438 if (!isset($FDcomp[$table][$theKey][$fieldN])) {
00439 $extraArr[$table][$theKey][$fieldN] = $fieldC;
00440 } elseif (strcmp($FDcomp[$table][$theKey][$fieldN], $fieldC)) {
00441 $diffArr[$table][$theKey][$fieldN] = $fieldC;
00442 $diffArr_cur[$table][$theKey][$fieldN] = $FDcomp[$table][$theKey][$fieldN];
00443 }
00444 }
00445 }
00446 }
00447 }
00448 }
00449 }
00450 }
00451
00452 $output = array(
00453 'extra' => $extraArr,
00454 'diff' => $diffArr,
00455 'diff_currentValues' => $diffArr_cur
00456 );
00457
00458 return $output;
00459 }
00460
00468 function getUpdateSuggestions($diffArr,$keyList='extra,diff') {
00469 $statements = array();
00470 $deletedPrefixKey = $this->deletedPrefixKey;
00471 $remove = 0;
00472 if ($keyList == 'remove') {
00473 $remove = 1;
00474 $keyList = 'extra';
00475 }
00476 $keyList = explode(',',$keyList);
00477 foreach($keyList as $theKey) {
00478 if (is_array($diffArr[$theKey])) {
00479 foreach($diffArr[$theKey] as $table => $info) {
00480 $whole_table = array();
00481 if (is_array($info['fields'])) {
00482 foreach($info['fields'] as $fN => $fV) {
00483 if ($info['whole_table']) {
00484 $whole_table[]=$fN.' '.$fV;
00485 } else {
00486 if ($theKey=='extra') {
00487 if ($remove) {
00488 if (substr($fN,0,strlen($deletedPrefixKey))!=$deletedPrefixKey) {
00489 $statement = 'ALTER TABLE '.$table.' CHANGE '.$fN.' '.$deletedPrefixKey.$fN.' '.$fV.';';
00490 $statements['change'][md5($statement)] = $statement;
00491 } else {
00492 $statement = 'ALTER TABLE '.$table.' DROP '.$fN.';';
00493 $statements['drop'][md5($statement)] = $statement;
00494 }
00495 } else {
00496 $statement = 'ALTER TABLE '.$table.' ADD '.$fN.' '.$fV.';';
00497 $statements['add'][md5($statement)] = $statement;
00498 }
00499 } elseif ($theKey=='diff') {
00500 $statement = 'ALTER TABLE '.$table.' CHANGE '.$fN.' '.$fN.' '.$fV.';';
00501 $statements['change'][md5($statement)] = $statement;
00502 $statements['change_currentValue'][md5($statement)] = $diffArr['diff_currentValues'][$table]['fields'][$fN];
00503 }
00504 }
00505 }
00506 }
00507 if (is_array($info['keys'])) {
00508 foreach($info['keys'] as $fN => $fV) {
00509 if ($info['whole_table']) {
00510 if ($fN=='PRIMARY') {
00511 $whole_table[] = $fV;
00512 } else {
00513 $whole_table[] = $fV;
00514 }
00515 } else {
00516 if ($theKey=='extra') {
00517 if ($remove) {
00518 $statement = 'ALTER TABLE '.$table.($fN=='PRIMARY' ? ' DROP PRIMARY KEY' : ' DROP KEY '.$fN).';';
00519 $statements['drop'][md5($statement)] = $statement;
00520 } else {
00521 $statement = 'ALTER TABLE '.$table.' ADD '.$fV.';';
00522 $statements['add'][md5($statement)] = $statement;
00523 }
00524 } elseif ($theKey=='diff') {
00525 $statement = 'ALTER TABLE '.$table.($fN=='PRIMARY' ? ' DROP PRIMARY KEY' : ' DROP KEY '.$fN).';';
00526 $statements['change'][md5($statement)] = $statement;
00527 $statement = 'ALTER TABLE '.$table.' ADD '.$fV.';';
00528 $statements['change'][md5($statement)] = $statement;
00529 }
00530 }
00531 }
00532 }
00533 if ($info['whole_table']) {
00534 if ($remove) {
00535 if (substr($table,0,strlen($deletedPrefixKey))!=$deletedPrefixKey) {
00536 $statement = 'ALTER TABLE '.$table.' RENAME '.$deletedPrefixKey.$table.';';
00537 $statements['change_table'][md5($statement)]=$statement;
00538 } else {
00539 $statement = 'DROP TABLE '.$table.';';
00540 $statements['drop_table'][md5($statement)]=$statement;
00541 }
00542
00543 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*)', $table, '');
00544 list($count) = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
00545 $statements['tables_count'][md5($statement)] = $count?'Records in table: '.$count:'';
00546 } else {
00547 $statement = 'CREATE TABLE '.$table." (\n".implode(",\n",$whole_table)."\n)";
00548 $statement .= ($info['extra']['ttype']) ? ' TYPE='.$info['extra']['ttype'].';' : ';';
00549 $statements['create_table'][md5($statement)]=$statement;
00550 }
00551 }
00552 }
00553 }
00554 }
00555
00556 return $statements;
00557 }
00558
00565 function assembleFieldDefinition($row) {
00566 $field[] = $row['Type'];
00567 if (!$row['Null']) { $field[] = 'NOT NULL'; }
00568 if (!strstr($row['Type'],'blob') && !strstr($row['Type'],'text')) {
00569
00570 if (!stristr($row['Extra'],'auto_increment')) {
00571 $field[] = 'default '."'".(addslashes($row['Default']))."'";
00572 }
00573 }
00574 if ($row['Extra']) { $field[] = $row['Extra']; }
00575
00576 return implode(' ',$field);
00577 }
00578
00587 function getStatementArray($sqlcode,$removeNonSQL=0,$query_regex='') {
00588 $sqlcodeArr = explode(chr(10),$sqlcode);
00589
00590
00591 $statementArray = array();
00592 $statementArrayPointer = 0;
00593
00594 foreach($sqlcodeArr as $line => $linecontent) {
00595 $is_set = 0;
00596 if(stristr($linecontent,'auto_increment')) {
00597 $linecontent = eregi_replace(' default \'0\'','',$linecontent);
00598 }
00599
00600 if (!$removeNonSQL || (strcmp(trim($linecontent),'') && substr(trim($linecontent),0,1)!='#' && substr(trim($linecontent),0,2)!='--')) {
00601 $statementArray[$statementArrayPointer].= $linecontent;
00602 $is_set = 1;
00603 }
00604 if (substr(trim($linecontent),-1)==';') {
00605 if (isset($statementArray[$statementArrayPointer])) {
00606 if (!trim($statementArray[$statementArrayPointer]) || ($query_regex && !eregi($query_regex,trim($statementArray[$statementArrayPointer])))) {
00607 unset($statementArray[$statementArrayPointer]);
00608 }
00609 }
00610 $statementArrayPointer++;
00611 } elseif ($is_set) {
00612 $statementArray[$statementArrayPointer].=chr(10);
00613 }
00614 }
00615 return $statementArray;
00616 }
00617
00625 function getCreateTables($statements, $insertCountFlag=0) {
00626 $crTables = array();
00627 foreach($statements as $line => $linecontent) {
00628 if (eregi('^create[[:space:]]*table[[:space:]]*([[:alnum:]_]*)',substr($linecontent,0,100),$reg)) {
00629 $table = trim($reg[1]);
00630 if ($table) {
00631 if (TYPO3_OS=='WIN') { $table=strtolower($table); }
00632 $sqlLines = explode(chr(10), $linecontent);
00633 foreach($sqlLines as $k=>$v) {
00634 if(stristr($v,'auto_increment')) {
00635 $sqlLines[$k] = eregi_replace(' default \'0\'','',$v);
00636 }
00637 }
00638 $linecontent = implode(chr(10), $sqlLines);
00639 $crTables[$table] = $linecontent;
00640 }
00641 } elseif ($insertCountFlag && eregi('^insert[[:space:]]*into[[:space:]]*([[:alnum:]_]*)',substr($linecontent,0,100),$reg)) {
00642 $nTable = trim($reg[1]);
00643 $insertCount[$nTable]++;
00644 }
00645 }
00646 return array($crTables,$insertCount);
00647 }
00648
00656 function getTableInsertStatements($statements, $table) {
00657 $outStatements=array();
00658 foreach($statements as $line => $linecontent) {
00659 if (eregi('^insert[[:space:]]*into[[:space:]]*([[:alnum:]_]*)',substr($linecontent,0,100),$reg)) {
00660 $nTable = trim($reg[1]);
00661 if ($nTable && !strcmp($table,$nTable)) {
00662 $outStatements[]=$linecontent;
00663 }
00664 }
00665 }
00666 return $outStatements;
00667 }
00668
00676 function performUpdateQueries($arr,$keyArr) {
00677 if (is_array($arr)) {
00678 foreach($arr as $key => $string) {
00679 if (isset($keyArr[$key]) && $keyArr[$key]) {
00680 $GLOBALS['TYPO3_DB']->admin_query($string);
00681 }
00682 }
00683 }
00684 }
00685
00692 function getListOfTables() {
00693 $whichTables = $GLOBALS['TYPO3_DB']->admin_get_tables(TYPO3_db);
00694 return $whichTables;
00695 }
00696
00708 function generateUpdateDatabaseForm_checkboxes($arr,$label,$checked=1,$iconDis=0,$currentValue=array(),$cVfullMsg=0) {
00709 $out = array();
00710 if (is_array($arr)) {
00711 foreach($arr as $key => $string) {
00712 $ico = '';
00713 if ($iconDis) {
00714 if (stristr($string,' user_')) {
00715 $ico.= '<img src="'.$this->backPath.'t3lib/gfx/icon_warning.gif" width="18" height="16" align="top" alt="" /><strong>(USER) </strong>';
00716 }
00717 if (stristr($string,' app_')) {
00718 $ico.= '<img src="'.$this->backPath.'t3lib/gfx/icon_warning.gif" width="18" height="16" align="top" alt="" /><strong>(APP) </strong>';
00719 }
00720 if (stristr($string,' ttx_') || stristr($string,' tx_')) {
00721 $ico.= '<img src="'.$this->backPath.'t3lib/gfx/icon_warning.gif" width="18" height="16" align="top" alt="" /><strong>(EXT) </strong>';
00722 }
00723 }
00724 $out[]='
00725 <tr>
00726 <td valign="top"><input type="checkbox" name="'.$this->dbUpdateCheckboxPrefix.'['.$key.']" value="1"'.($checked?' checked="checked"':'').' /></td>
00727 <td nowrap="nowrap">'.nl2br($ico.htmlspecialchars($string)).'</td>
00728 </tr>';
00729 if (isset($currentValue[$key])) {
00730 $out[]='
00731 <tr>
00732 <td valign="top"></td>
00733 <td nowrap="nowrap" style="color : #666666;">'.nl2br((!$cVfullMsg?"Current value: ":"").'<em>'.$currentValue[$key].'</em>').'</td>
00734 </tr>';
00735 }
00736 }
00737
00738
00739 $content = '
00740 <!-- Update database fields / tables -->
00741 <h3>'.$label.'</h3>
00742 <table border="0" cellpadding="2" cellspacing="2" class="update-db-fields">'.implode('',$out).'
00743 </table>';
00744 }
00745
00746 return $content;
00747 }
00748 }
00749
00750 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_install.php']) {
00751 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_install.php']);
00752 }
00753 ?>