HomeHelpTrac

Ignore:
Timestamp:
05/12/09 01:42:02 (3 years ago)
Author:
Andrey Prikaznov
Message:
 
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/install/index.php

    r10460 r10474  
    1919***************************************************************************/ 
    2020 
    21 define('CHECK_DOLPHIN_REQUIREMENTS', 1); 
     21define('CHECK_DOLPHIN_REQUIREMENTS', 1); //Don`t recommend to skip this step 
    2222if (defined('CHECK_DOLPHIN_REQUIREMENTS')) { 
    2323    //check requirements 
     
    6868    $aConf['dolFile'] = '../inc/header.inc.php'; 
    6969    $aConf['periodicFile'] = '../periodic/periodic.file'; 
    70     $aConf['cmdFile'] = '../periodic/cmd.php'; 
     70    //$aConf['cmdFile'] = '../periodic/cmd.php'; 
    7171    $aConf['rayMp3Periodic'] = '../flash/modules/mp3/cron.php'; 
    7272    $aConf['rayVideoPeriodic'] = '../flash/modules/video/cron.php'; 
    73     $aConf['notifiesFile'] = '../periodic/notifies.php'; 
    74     $aConf['cupidFile'] = '../periodic/cupid.php'; 
     73    //$aConf['notifiesFile'] = '../periodic/notifies.php'; 
     74    //$aConf['cupidFile'] = '../periodic/cupid.php'; 
    7575    $aConf['confDir'] = '../inc/';   
    7676    $aConf['headerTempl'] = <<<EOS 
     
    467467    require_once( BX_DIRECTORY_PATH_INC . 'db.inc.php' ); 
    468468    require_once( BX_DIRECTORY_PATH_INC . 'design.inc.php' ); 
    469     // require_once( BX_DIRECTORY_PATH_INC . 'utils.inc.php' ); 
    470     // require_once( BX_DIRECTORY_PATH_BASE . 'scripts/BxBaseFormView.php' ); 
    471     // require_once( BX_DIRECTORY_PATH_CLASSES . 'BxDolInstallerUi.php' ); 
    472469} 
    473470// -------------------------------------------- 
     
    487484 
    488485    switch ($_REQUEST['action']) { 
     486        case 'compile_languages': 
     487            performInstallLanguages(); 
     488            $sRet .= 'Default Dolphin language was recompiled'; 
     489            break; 
    489490        /*case 'step8': 
    490491            $sRet .= genMainDolphinPage(); 
     
    508509        case 'step6': 
    509510            $sErrorMessage = checkPostInstallPermissions($sError); 
    510             //$sRet .= (strlen($sErrorMessage)) ? genPostInstallPermissionTable($sErrorMessage) : genInstallModulesPage(); 
    511511            $sRet .= (strlen($sErrorMessage)) ? genPostInstallPermissionTable($sErrorMessage) : genMainDolphinPage(); 
    512512        break; 
     
    630630    } 
    631631 
    632     $sRet = <<<EOF 
     632    return <<<EOF 
    633633<div class="position">Modules.</div> 
    634634{$sErrors} 
     
    661661</div> 
    662662EOF; 
    663  
    664     return $sRet; 
    665663} 
    666664 
    667665function genInstallationProcessPage($sErrorMessage = '') { 
    668     global $aConf,  $confFirst, $aDbConf, $aGeneral; 
     666    global $aConf, $confFirst, $aDbConf, $aGeneral; 
    669667 
    670668    $sAdminName     = get_magic_quotes_gpc() ? stripslashes($_REQUEST['admin_username']) : $_REQUEST['admin_username']; 
     
    672670    $resRunSQL = RunSQL( $sAdminName, $sAdminPassword ); 
    673671 
    674     $sRet = ''; 
     672    $sForm = ''; 
    675673     
    676674    if ('done' ==  $resRunSQL) { 
    677         $sRet = ' 
     675        $sForm = ' 
    678676        <div class="formKeeper"> 
    679677            <form action="' . $_SERVER['PHP_SELF'] . '" method="post"> 
     
    684682        <div class="clearBoth"></div>'; 
    685683    } else { 
    686         $sRet = $resRunSQL; 
    687         $sRet .= ' 
     684        $sForm = $resRunSQL . ' 
    688685        <div class="formKeeper"> 
    689686            <form action="' . $_SERVER['PHP_SELF'] . '" method="post"> 
     
    691688        foreach ($_POST as $sKey => $sValue) { 
    692689            if ($sKey != "action") 
    693                 $sRet .= '<input type="hidden" name="' . $sKey . '" value="' . $sValue . '" />'; 
     690                $sForm .= '<input type="hidden" name="' . $sKey . '" value="' . $sValue . '" />'; 
    694691        } 
    695         $sRet .= '<input type="hidden" name="action" value="step2" /> 
     692        $sForm .= '<input type="hidden" name="action" value="step2" /> 
    696693            </form> 
    697694        </div> 
    698695        <div class="clearBoth"></div>'; 
    699         return $sRet; 
     696        return $sForm; 
    700697    } 
    701698 
     
    714711    $aConf['periodicTempl'] = str_replace("%dir_php%",    $_POST['dir_php'],    $aConf['periodicTempl']); 
    715712 
    716     $ret = ''; 
    717     $ret .= '<div class="position">Cron Jobs</div>'; 
    718     $ret .= '<div class="LeftRirght">'; 
     713    $sInnerCode = ''; 
    719714    $fp = fopen($aConf['dolFile'], 'w'); 
    720715    if ($fp) { 
     
    722717        fclose($fp); 
    723718        chmod($aConf['dolFile'], 0666); 
    724         //$ret .='Config file was successfully written to <strong>' . $aConf['dolFile'] . '</strong><br />'; 
     719        //$sInnerCode .='Config file was successfully written to <strong>' . $aConf['dolFile'] . '</strong><br />'; 
    725720    } else { 
    726721        $text = 'Warning!!! can not get write access to config file ' . $aConf['dolFile'] . '. Here is config file</font><br>'; 
    727         $ret .= printInstallError($text); 
     722        $sInnerCode .= printInstallError($text); 
    728723        $trans = get_html_translation_table(HTML_ENTITIES); 
    729724        $templ = strtr($aConf['headerTempl'], $trans); 
    730         $ret .= '<textarea cols="20" rows="10" class="headerTextarea">' . $aConf['headerTempl'] . '</textarea>'; 
     725        $sInnerCode .= '<textarea cols="20" rows="10" class="headerTextarea">' . $aConf['headerTempl'] . '</textarea>'; 
    731726    } 
    732727    $fp = fopen($aConf['periodicFile'], 'w'); 
     
    735730        fclose($fp); 
    736731        chmod($aConf['dolFile'], 0666); 
    737         //$ret .='Config file was successfully written to <strong>' . $aConf['periodicFile'] . '</strong><br />'; 
    738         $ret .= '<div class="left"> 
    739                 Please, setup Cron Jobs as specified below. Helpful info about Cron Jobs is <a href="http://www.boonex.net/dolphin/wiki/DetailedInstall#SettingupCronjobs">available here</a>.'; 
    740         $ret .= '</div>'; 
    741  
    742         $ret .= '<div class="debug">'; 
     732        //$sInnerCode .='Config file was successfully written to <strong>' . $aConf['periodicFile'] . '</strong><br />'; 
     733        $sInnerCode .= <<<EOF 
     734<div class="left"> 
     735    Please, setup Cron Jobs as specified below. Helpful info about Cron Jobs is <a href="http://www.boonex.com/trac/dolphin/wiki/DetailedInstall#SettingupCronjobs">available here</a>.</div> 
     736    <div class="debug"> 
     737EOF; 
    743738            $aFileLines = file($aConf['periodicFile']); 
    744739            foreach($aFileLines as $sLine) 
    745                 $ret .= $sLine . '<br />'; 
    746         $ret .= '</div>'; 
     740                $sInnerCode .= $sLine . '<br />'; 
     741        $sInnerCode .= '</div>'; 
    747742    } else { 
    748743        $text = '<font color=red>Warning!!! can not get write access to config file ' . $aConf['periodicFile'] . '. Here is config file</font><br>'; 
    749         $ret .= printInstallError($text); 
     744        $sInnerCode .= printInstallError($text); 
    750745        $trans = get_html_translation_table(HTML_ENTITIES); 
    751746        $templ = strtr($aConf['periodicTempl'], $trans); 
    752         $ret .= '<textarea cols="20" rows="10" class="headerTextarea">' . $aConf['periodicTempl'] . '</textarea>'; 
    753     } 
    754     @rewriteFile('[path_to]', $_POST['dir_root'], $aConf['cmdFile']); 
    755     @rewriteFile('[path_to]', $_POST['dir_root'], $aConf['notifiesFile']); 
    756     @rewriteFile('[path_to]', $_POST['dir_root'], $aConf['cupidFile']); 
    757  
    758     $ret .= $sRet; 
    759  
    760     $ret .= '</div>'; 
    761  
    762     return $ret; 
     747        $sInnerCode .= '<textarea cols="20" rows="10" class="headerTextarea">' . $aConf['periodicTempl'] . '</textarea>'; 
     748    } 
     749 
     750    return <<<EOF 
     751<div class="position">Cron Jobs</div> 
     752<div class="LeftRirght"> 
     753    {$sInnerCode}{$sForm} 
     754</div> 
     755EOF; 
    763756} 
    764757 
     
    851844    } 
    852845 
    853     $sRet = <<<EOF 
     846    return <<<EOF 
    854847<div class="position">Permissions Reversal</div> 
    855848{$sErrors} 
     
    896889</div> 
    897890EOF; 
    898  
    899     return $sRet; 
    900891} 
    901892 
     
    917908    $sOldDataParams = ''; 
    918909    foreach($_POST as $postKey => $postValue) { 
    919         if('action' == $postKey || isset($aGeneral[$postKey])) { 
    920             $sOldDataParams .= ''; 
    921         } else { 
    922             $sOldDataParams .= '<input type="hidden" name="' . $postKey . '" value="' . $postValue . '" />'; 
    923         } 
    924     } 
    925  
    926     $sRet = <<<EOF 
     910        $sOldDataParams .= ('action' == $postKey || isset($aGeneral[$postKey])) ? '' : '<input type="hidden" name="' . $postKey . '" value="' . $postValue . '" />'; 
     911    } 
     912 
     913    return <<<EOF 
    927914<div class="position">Configuration</div> 
    928915{$sErrors} 
     
    949936</div> 
    950937EOF; 
    951  
    952     return $sRet; 
    953938} 
    954939 
     
    971956            $error_arr[$sKey] = 1; 
    972957            unset($_POST[$sKey]); 
    973         } 
    974         else 
     958        } else 
    975959            $error_arr[$sKey] = 0; 
    976960 
     
    1001985    $sOldDataParams = ''; 
    1002986    foreach($_POST as $postKey => $postValue) { 
    1003         if('action' == $postKey || isset($aDbConf[$postKey])) { 
    1004             $sOldDataParams .= ''; 
    1005         } else { 
    1006             $sOldDataParams .= '<input type="hidden" name="' . $postKey . '" value="' . $postValue . '" />'; 
    1007         } 
    1008     } 
    1009  
    1010     $sRet = <<<EOF 
     987        $sOldDataParams .= ('action' == $postKey || isset($aDbConf[$postKey])) ? '' : '<input type="hidden" name="' . $postKey . '" value="' . $postValue . '" />'; 
     988    } 
     989 
     990    return <<<EOF 
    1011991<div class="position">Database</div> 
    1012992{$sErrors} 
     
    1014994    <div class="clearBoth"></div> 
    1015995    <div class="left"> 
    1016         Please <a href="http://www.boonex.net/cgi-bin/trac_dolphin.cgi/wiki/DetailedInstall#Step2:CreateaDatabaseandaUser">create a database</a> and tell Dolphin about it. 
     996        Please <a href="http://www.boonex.com/trac/dolphin/wiki/DetailedInstall#Step2:CreateaDatabaseandaUser">create a database</a> and tell Dolphin about it. 
    1017997    </div> 
    1018998    <div class="right"> 
     
    10351015</div> 
    10361016EOF; 
    1037  
    1038     return $sRet; 
    10391017} 
    10401018 
     
    10501028    $sPathsTable = createTable($confFirst); 
    10511029 
    1052     $sRet = <<<EOF 
     1030    return <<<EOF 
    10531031<div class="position">Paths Check</div> 
    10541032{$sError} 
     
    10841062</div> 
    10851063EOF; 
    1086  
    1087     return $sRet; 
    10881064} 
    10891065 
     
    11471123    $sPermTable .= $oAdmTools->GenPermTable(); 
    11481124 
    1149     $sRet = <<<EOF 
     1125    return <<<EOF 
    11501126<div class="position">Permissions</div> 
    11511127{$sError} 
     
    11771153</div> 
    11781154EOF; 
    1179  
    1180     return $sRet; 
    11811155} 
    11821156 
     
    11841158    global $aConf; 
    11851159 
    1186     $ret .= '<div class="install_pic">'; 
    1187         $ret .= 'Dolphin ' . $aConf['iVersion'] . '.' . $aConf['iPatch']; 
    1188     $ret .= '</div>'; 
    1189  
    1190     $ret .= '<div class="install_text">'; 
    1191         $ret .= 'Thank you for choosing Dolphin Smart Community Builder!<br />'; 
    1192         $ret .= 'Click the button below to create your own community.'; 
    1193     $ret .= '</div>'; 
    1194  
    1195     $ret .= '<div class="install_button">'; 
    1196         $ret .= '<form action="' . $_SERVER['PHP_SELF'] . '" method="post">'; 
    1197         $ret .= '<input id="button" type="image" src="images/install.gif" />'; 
    1198         $ret .= '<input type="hidden" name="action" value="preInstall" />'; 
    1199         $ret .= '</form>'; 
    1200     $ret .= '</div>'; 
    1201  
    1202     return $ret; 
     1160    return <<<EOF 
     1161<div class="install_pic"> 
     1162    Dolphin {$aConf['iVersion']}.{$aConf['iPatch']} 
     1163</div> 
     1164 
     1165<div class="install_text"> 
     1166    Thank you for choosing Dolphin Smart Community Builder!<br /> 
     1167    Click the button below to create your own community. 
     1168</div> 
     1169 
     1170<div class="install_button"> 
     1171    <form action="{$_SERVER['PHP_SELF']}" method="post"> 
     1172    <input id="button" type="image" src="images/install.gif" /> 
     1173    <input type="hidden" name="action" value="preInstall" /> 
     1174    </form> 
     1175</div> 
     1176EOF; 
    12031177} 
    12041178 
     
    12371211        $sAction = "startInstall"; 
    12381212 
    1239     $ret = <<<EOJ 
     1213    $sActiveStyle = ($sAction == "step6") ? 'Active' : 'Inactive'; 
     1214 
     1215    $iCounterCurrent = 1; 
     1216    $iCounterActive  = 1; 
     1217 
     1218    foreach ($aActions as $sActionKey => $sActionValue) { 
     1219        if ($sAction != $sActionKey) { 
     1220            $iCounterActive++; 
     1221        } else 
     1222            break; 
     1223    } 
     1224 
     1225    if (strlen($sError)) 
     1226        $iCounterActive--; 
     1227 
     1228    $sSubActions = ''; 
     1229    foreach ($aActions as $sActionKey => $sActionValue) { 
     1230        if ($iCounterActive == $iCounterCurrent) { 
     1231            $sSubActions .= '<div id="topActive">' . $sActionValue . '</div>'; 
     1232        } elseif (($iCounterActive - $iCounterCurrent) == -1) { 
     1233            $sSubActions .= '<img src="images/active_inactive.gif" /><div id="topInactive">' . $sActionValue . '</div><img src="images/inactive_inactive.gif" />'; 
     1234        } elseif (($iCounterActive - $iCounterCurrent) == 1) { 
     1235            $sSubActions .= '<div id="topInactive">' . $sActionValue . '</div><img src="images/inactive_active.gif" />'; 
     1236        } else { 
     1237            $sSubActions .= '<div id="topInactive">' . $sActionValue . '</div>'; 
     1238            if ($sActionKey != "step6") 
     1239                $sSubActions .= '<img src="images/inactive_inactive.gif" />'; 
     1240        } 
     1241        $iCounterCurrent++; 
     1242    } 
     1243 
     1244    return <<<EOF 
    12401245<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
    12411246    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US"> 
     
    12511256        <body> 
    12521257            <div id="main"> 
    1253 EOJ; 
    1254      
    1255     if ($sAction == "step6") 
    1256         $ret .= '<div id="topMenuActive">'; 
    1257     else 
    1258         $ret .= '<div id="topMenuInactive">'; 
    1259  
    1260     $iCounterCurrent = 1; 
    1261     $iCounterActive  = 1; 
    1262  
    1263     foreach ($aActions as $sActionKey => $sActionValue) { 
    1264         if ($sAction != $sActionKey) { 
    1265             $iCounterActive++; 
    1266         } else 
    1267             break; 
    1268     } 
    1269  
    1270     if (strlen($sError)) 
    1271         $iCounterActive--; 
    1272  
    1273     foreach ($aActions as $sActionKey => $sActionValue) { 
    1274         if ($iCounterActive == $iCounterCurrent) { 
    1275             $ret .= '<div id="topActive">'; 
    1276             $ret .= $sActionValue; 
    1277             $ret .= '</div>'; 
    1278         } elseif (($iCounterActive - $iCounterCurrent) == -1) { 
    1279             $ret .= '<img src="images/active_inactive.gif" />'; 
    1280             $ret .= '<div id="topInactive">'; 
    1281             $ret .= $sActionValue; 
    1282             $ret .= '</div>'; 
    1283             $ret .= '<img src="images/inactive_inactive.gif" />'; 
    1284         } elseif (($iCounterActive - $iCounterCurrent) == 1) { 
    1285             $ret .= '<div id="topInactive">'; 
    1286             $ret .= $sActionValue; 
    1287             $ret .= '</div>'; 
    1288             $ret .= '<img src="images/inactive_active.gif" />'; 
    1289         } else { 
    1290             $ret .= '<div id="topInactive">'; 
    1291             $ret .= $sActionValue; 
    1292             $ret .= '</div>'; 
    1293             if ($sActionKey != "step6") 
    1294                 $ret .= '<img src="images/inactive_inactive.gif" />'; 
    1295         } 
    1296         $iCounterCurrent++; 
    1297     } 
    1298  
    1299     $ret .= ' 
     1258                <div id="topMenu{$sActiveStyle}"> 
     1259                    {$sSubActions} 
    13001260                </div> 
    13011261            <div id="header"> 
    13021262                <img src="images/boonex_logo.gif" alt="" /></div> 
    1303             <div id="content">'; 
    1304  
    1305     return $ret; 
     1263            <div id="content"> 
     1264EOF; 
    13061265} 
    13071266 
    13081267function PageFooter($sAction) { 
    1309     $ret = ' 
    1310             </div>'; 
    1311  
    1312     if( $sAction ) 
    1313         $ret .= ' 
    1314             <div id="footer"> 
    1315                 <img src="images/dolphin_transparent.jpg" alt="" /> 
    1316             </div>'; 
    1317  
    1318     $ret .= ' 
     1268    $sAdminAdd = ($sAction) ? '<div id="footer"><img src="images/dolphin_transparent.jpg" alt="" /></div>' ? ''; 
     1269 
     1270    return <<<EOF 
     1271            </div> 
     1272        {$sAdminAdd} 
    13191273        </div> 
    13201274    </body> 
    1321 </html>'; 
    1322  
    1323     return $ret; 
     1275</html> 
     1276EOF; 
    13241277} 
    13251278 
     
    13381291function isFullAccessible($filename) { 
    13391292    clearstatcache(); 
    1340     return is_writable($filename) && is_readable($filename) && is_executable($filename); 
    1341     // $perms = fileperms($filename); 
    1342     // return ($perms & 0x0004 && $perms & 0x0002 && $perms & 0x0001 && !($perms & 0x0200)) ? true : false; 
     1293    if(is_dir($filename))  
     1294        return (@file_exists($filename . '/.') && is_readable( $filename ) && is_writable( $filename ) ) ? true : false; 
     1295    else 
     1296        return (is_file($filename) && is_readable( $filename ) && is_writable( $filename ) && is_executable( $filename ) ) ? true : false; 
    13431297} 
    13441298 
     
    13461300    clearstatcache(); 
    13471301    return is_writable($filename) && is_readable($filename); 
    1348     // $perms = fileperms($filename); 
    1349     // return ($perms & 0x0004 && $perms & 0x0002) ? true : false; 
    13501302} 
    13511303 
     
    13541306    $i = ''; 
    13551307    foreach($arr as $key => $value) { 
    1356         if( ($i%2) == 0 ) { 
    1357             $sStyleAdd = 'background-color:#ede9e9;'; 
    1358         } else { 
    1359             $sStyleAdd = 'background-color:#fff;'; 
    1360         } 
     1308        $sStyleAdd = (($i%2) == 0) ? 'background-color:#ede9e9;' : 'background-color:#fff;'; 
    13611309 
    13621310        $def_exp_text = ""; 
     
    13731321        } 
    13741322 
    1375         if ($error_arr[$key] == 1) { 
    1376             $st_err = ' style="background-color:#FFDDDD;" '; 
    1377         } else 
    1378             $st_err = ''; 
    1379  
    1380         $ret .= ' 
    1381         <tr class="cont" style="' . $sStyleAdd . '"> 
    1382             <td> 
    1383             <div> 
    1384             ' . $value['name'] . ' 
    1385             </div> 
    1386             <div> 
    1387                 Description: 
    1388             </div> 
    1389             <div> 
    1390                 Example: 
    1391             </div> 
    1392             </td> 
    1393             <td> 
    1394                 <div> 
    1395                     <input ' . $st_err . ' size="30" name="' . $key . '" value="' . $value['def'] . '" />' . $def_exp_text . ' 
    1396                 </div> 
    1397                 <div> 
    1398                     ' .  $value['desc'] . ' 
    1399                 </div> 
    1400                 <div> 
    1401                     ' . $value['ex'] . ' 
    1402                 </div> 
    1403             </td> 
    1404         </tr>'; 
     1323        $st_err = ($error_arr[$key] == 1) ? ' style="background-color:#FFDDDD;" ' : ''; 
     1324 
     1325        $ret .= <<<EOF 
     1326    <tr class="cont" style="{$sStyleAdd}"> 
     1327        <td> 
     1328            <div>{$value['name']}</div> 
     1329            <div>Description:</div> 
     1330            <div>Example:</div> 
     1331        </td> 
     1332        <td> 
     1333            <div><input {$st_err} size="30" name="{$key}" value="{$value['def']}" /> {$def_exp_text}</div> 
     1334            <div>{$value['desc']}</div> 
     1335            <div>{$value['ex']}</div> 
     1336        </td> 
     1337    </tr> 
     1338EOF; 
    14051339        $i ++; 
    14061340    } 
     
    14521386    if( !$vLink ) 
    14531387        return printInstallError( mysql_error() ); 
    1454         //return ("<font color=red>Could not connect to MySQL server: " . mysql_error()."</font>"); 
    14551388 
    14561389    if (!mysql_select_db ($aDbConf['db'], $vLink)) 
     
    14591392    if (! ($f = fopen ( $filename, "r" ))) 
    14601393        return printInstallError( 'Could not open file with sql instructions:' . $filename  ); 
    1461        //return ("<font color=red>Could not open file with sql instructions: $filename </font>"); 
    14621394 
    14631395    //Begin SQL script executing 
     
    14821414    } 
    14831415 
    1484     //mysql_query("UPDATE `sys_admins` SET `Name`='{$sAdminName}', `Password`=md5('{$sAdminPassword}') WHERE `Name`='admin'", $vLink); 
    14851416    $sAdminNameDB     = addslashes($sAdminName); 
    14861417    $sAdminPasswordDB = md5($sAdminPassword); 
    14871418    $sAdminQuery = " 
    1488         insert into `Profiles` 
     1419        INSERT INTO `Profiles` 
    14891420            (`NickName`, `Password`, `Status`, `Role`, `DateReg`) 
    1490         values 
    1491             ('$sAdminNameDB', '$sAdminPasswordDB', 'Active', 3, NOW()) 
     1421        VALUES 
     1422            ('{$sAdminNameDB}', '{$sAdminPasswordDB}', 'Active', 3, NOW()) 
    14921423    "; 
    14931424    mysql_query($sAdminQuery, $vLink); 
     
    15511482// set error reporting level 
    15521483error_reporting(E_ALL & ~E_NOTICE); 
     1484 
    15531485?> 
Note: See TracChangeset for help on using the changeset viewer.