Quick.Cart.Pro bug fixes list

Quick.Cart.Pro v4.2 bugs

1) There is possibility to upload files with for e.g. PHP extension if someone have access to admin panel

    • Edit core/banners-admin.php and find code:
        if( isset( $_FILES['sFile']['name'] ) && !empty( $_FILES['sFile']['name'] ) ){
          $aForm['sFile'] = $oFF->uploadFile( $_FILES['sFile'], DIR_FILES );
        }
    • And replace to:
        if( isset( $_FILES['sFile']['name'] ) && !empty( $_FILES['sFile']['name'] ) ){
          if( preg_match( '/(jpg|gif|jpeg|png|swf)/i', $oFFS->throwExtOfFile( $_FILES['sFile']['name'] ) ) )
            $aForm['sFile'] = $oFFS->uploadFile( $_FILES['sFile'], DIR_FILES );
          else
            return null;
        }

2) Email encoding problem

    • Edit core/common.php and find code:
      function sendEmail( $aForm, $sFile = 'messages.tpl', $sTargetEmail = null ){
        extract( $aForm );
        $oTpl = TplParser::getInstance( );
      
        if( !empty( $sTopic ) && !empty( $sMailContent ) && checkEmail( $sSender ) === 1 ){
          $sMailContent = change2Latin( $sMailContent );
          $sTopic = change2Latin( $sTopic );
      
          if( !empty( $sPhone ) )
            $sMailContent = $GLOBALS['lang']['Telephone'].': '.change2Latin( $sPhone )."\n".$sMailContent;
          if( !empty( $sName ) )
            $sMailContent = $GLOBALS['lang']['Name_and_surname'].': '.change2Latin( $sName )."\n".$sMailContent;
      
          if( !isset( $sTargetEmail ) )
            $sTargetEmail = $GLOBALS['config']['email'];
      
          if( @mail( $sTargetEmail, $sTopic, $sMailContent, 'From: '.$sSender ) ){
            if( isset( $sFile ) )
              return $oTpl->tbHtml( $sFile, 'MAIL_SEND_CORRECT' );
          }
          else{
            if( isset( $sFile ) )
              return $oTpl->tbHtml( $sFile, 'MAIL_SEND_ERROR' );
          }
        }
        else{
          if( isset( $sFile ) )
            return $oTpl->tbHtml( $sFile, 'REQUIRED_FIELDS' );
        }
      } // end function sendEmail
    • And replace to:
      function sendEmail( $aForm, $sFile = 'messages.tpl', $sTargetEmail = null ){
        extract( $aForm );
        $oTpl = TplParser::getInstance( );
      
        if( !empty( $sTopic ) && !empty( $sMailContent ) && checkEmail( $sSender ) === 1 ){
          if( !empty( $sPhone ) )
            $sMailContent = $GLOBALS['lang']['Telephone'].': '.$sPhone."\n".$sMailContent;
          if( !empty( $sName ) )
            $sMailContent = $GLOBALS['lang']['Name_and_surname'].': '.$sName."\n".$sMailContent;
      
          if( !isset( $sTargetEmail ) )
            $sTargetEmail = $GLOBALS['config']['email'];
      
          #$sMailContent = change2Latin( $sMailContent );
          #$sTopic = change2Latin( $sTopic );
          $sHeader = 'MIME-Version: 1.0'."\r\n".'Content-type: text/plain; charset=UTF-8'."\r\n".'From: '.$sSender;
          $sTopic = '=?UTF-8?B?'.base64_encode( $sTopic ).'?=';
          if( @mail( $sTargetEmail, $sTopic, $sMailContent, $sHeader ) ){
            if( isset( $sFile ) )
              return $oTpl->tbHtml( $sFile, 'MAIL_SEND_CORRECT' );
          }
          else{
            if( isset( $sFile ) )
              return $oTpl->tbHtml( $sFile, 'MAIL_SEND_ERROR' );
          }
        }
        else{
          if( isset( $sFile ) )
            return $oTpl->tbHtml( $sFile, 'REQUIRED_FIELDS' );
        }
      } // end function sendEmail

3) The problem of XHTML validation of a short description of sub-page, product and sorting options

    • Edit templates/pages_default.tpl and find code:
      <h4>$aData[sDescriptionShort]</h4>
    • And replace to:
      <div class="description">$aData[sDescriptionShort]</div>
    • Edit core/common.js and find code:
      function txtSize( iSize ){
        var aSizes = Array( '95%', '100%', '120%' );
        var aChange = Array( 'pageDescription', 'productDescription', 'basket', 'authWindow', 'available', 'askAboutProduct', 'h2', 'h3', 'h4', 'table', 'li', 'label', 'p', 'dl', 'select' );
        for( var i = 0; i < aChange.length; i++ ){
          if( !aSizes[iSize] )
            iSize = 1;
          if( gEBI( aChange[i] ) ){
            gEBI( aChange[i] ).style.fontSize = ( iSize != 1 ) ? aSizes[iSize] : '';
          }
          else if( gEBI( 'content' ).getElementsByTagName( aChange[i] ) ){
            aElement = gEBI( 'content' ).getElementsByTagName( aChange[i] );
            for( var j = 0; j < aElement.length; j++ ){
              aElement[j].style.fontSize =  ( iSize != 1 ) ? aSizes[iSize] : '';
            }
          }
        }
      }
    • And replace to:
      function txtSize( iSize ){
        var aSizes = Array( '95%', '100%', '120%' );
        var aChange = Array( 'pageDescription', '.description', 'productDescription', 'basket', 'authWindow', 'available', 'askAboutProduct', 'h2', 'h3', 'table', 'li', 'label', 'p', 'dl', 'select' );
        var aSizesDefault = Array( '1.083em', '1em' );
        for( var i = 0; i < aChange.length; i++ ){
          if( !aSizes[iSize] )
            iSize = 1;
          if( aChange[i].indexOf( '.' ) == 0 ){
            aChange[i] = aChange[i].substr( 1 );
            aElement = gEBI( 'content' ).getElementsByTagName( 'div' );
            for( var j = 0; j < aElement.length; j++ ){
              if( aElement[j].className == aChange[i] )
                aElement[j].style.fontSize = ( iSize != 1 ) ? aSizes[iSize] : aSizesDefault[i];
            }
          }
          else if( gEBI( aChange[i] ) ){
            gEBI( aChange[i] ).style.fontSize = ( iSize != 1 ) ? aSizes[iSize] : aSizesDefault[i];
          }
          else if( gEBI( 'content' ).getElementsByTagName( aChange[i] ) ){
            aElement = gEBI( 'content' ).getElementsByTagName( aChange[i] );
            for( var j = 0; j < aElement.length; j++ ){
              aElement[j].style.fontSize = ( iSize != 1 ) ? aSizes[iSize] : aSizesDefault[i];
            }
          }
        }
      }
    • Edit actions_client/p.php and find code:
      $sProductsList = ( $aData['iProducts'] == 1 || ( isset( $sPhrase ) && $config['page_search'] == $iContent ) ) ? $oProduct->listProducts( $aData['sTemplate'], $iContent, $iProductsList ) : null;
    • And replace to:
      $sProductsList = null;
      if( $aData['iProducts'] == 1 || ( isset( $sPhrase ) && $config['page_search'] == $iContent ) ){
        $_SERVER['REQUEST_URI'] = str_replace( '&', '&amp;', $_SERVER['REQUEST_URI'] );
        $sProductsList = $oProduct->listProducts( $aData['sTemplate'], $iContent, $iProductsList );
      }

4) The problem of homepage link duplication

    • Edit core/pages.php and find code:
      $this->aPages[$aExp[0]]['sLinkName'] = '?'.$sLanguageUrl.change2Url( $sUrlName ).','.$aExp[0];
    • And replace to:
      $this->aPages[$aExp[0]]['sLinkName'] = '?'.$sLanguageUrl.change2Url( $sUrlName ).','.$aExp[0];
      if( $GLOBALS['config']['start_page'] == $aExp[0] ){
        $sLinkHome = './';
        if( !defined( 'MOBILE' ) ){
          $this->aPages[$aExp[0]]['sLinkNameHome'] = $this->aPages[$aExp[0]]['sLinkName'];
          $this->aPages[$aExp[0]]['sLinkName'] = $sLinkHome;
        }
        if( !defined( 'INDEX' ) ){
          $GLOBALS['config']['index'] = $sLinkHome;
          define( 'INDEX', $GLOBALS['config']['index'] );          
        }
      }
    • Edit core/pages.php and find code:
      $aData['sPages'] = countPages( count( $aExp ), 1, $iPageContent, $this->aPages[$iPage]['sLinkName'].',,', null, null, null, MAX_PAGES );
    • And replace to:
      $sLink = isset( $this->aPages[$iPage]['sLinkNameHome'] ) ? $this->aPages[$iPage]['sLinkNameHome'] : $this->aPages[$iPage]['sLinkName'];
      $aData['sPages'] = countPages( count( $aExp ), 1, $iPageContent, $sLink.',,', null, null, null, MAX_PAGES );
    • Edit templates/admin/pages.tpl and find code:
      <a href="index.php$aData[sLinkName]" target="_blank" class="preview">
    • And replace to:
      <a href="./$aData[sLinkName]" target="_blank" class="preview">
    • Edit core/products.php and find code:
      $aData['sPages'] = countPages( $iCount, $iList, $iPageNumber, $oPage->aPages[$iContent]['sLinkName'], $sUrlExt );
    • And replace to:
      $aData['sPages'] = countPages( $iCount, $iList, $iPageNumber, ( isset( $oPage->aPages[$iContent]['sLinkNameHome'] ) ? $oPage->aPages[$iContent]['sLinkNameHome'] : $oPage->aPages[$iContent]['sLinkName'] ), $sUrlExt );
    • Edit core/products.php and find code:
      $aData['sPageLinkName'] = $oPage->aPages[$iContent]['sLinkName'];
      if( isset( $GLOBALS['sPhrase'] ) && !empty( $GLOBALS['sPhrase'] ) )
        $aData['sPageLinkName'] .= '&amp;sPhrase='.$GLOBALS['sPhrase'].'&amp;';
      else
        $aData['sPageLinkName'] .= '&amp;';
    • And replace to:
      $aData['sPageLinkName'] = ( isset( $oPage->aPages[$iContent]['sLinkNameHome'] ) ? $oPage->aPages[$iContent]['sLinkNameHome'] : $oPage->aPages[$iContent]['sLinkName'] ).( isset( $GLOBALS['sPhrase'] ) && !empty( $GLOBALS['sPhrase'] ) ? '&amp;sPhrase='.$GLOBALS['sPhrase'].'&amp;' : '&amp;' );

5) Increased list of restricted file extensions that can't be uploaded by admin

    • Edit core/files-admin.php and find code:
      !preg_match( '/(\.php|\.php2|\.php3|\.php4|\.php5|\.phtml|\.pwml|\.inc|\.asp|\.aspx|\.ascx|\.jsp|\.cfm|\.cfc|\.pl|\.bat|\.exe|\.com|\.dll|\.vbs|\.js|\.reg|\.cgi|\.htaccess|\.asis|\.sh|\.shtml|\.shtm|\.phtm)/i', $_FILES['aNewFiles']['name'][$i] )
    • And replace to:
      !preg_match( '/(\.phtml|\.php|\.php3|\.php4|\.php5|\.php6|\.asp|\.aspx|\.py|\.pyc|\.jse|\.js|\.as|\.sh|\.ksh|\.zsh|\.bat|\.cmd|\.shs|\.vb|\.vbe|\.vbs|\.wsc|\.wsf|\.htaccess|\.wsh|\.url|\.exe|\.msi|\.msp|\.reg|\.scr|\.ocx)/i', $_FILES['aNewFiles']['name'][$i] )

6) Better protection against cross-site request forgery

    • Edit admin.php and find code:
      if( $a == 'delete' && !empty( $_SERVER['HTTP_REFERER'] ) && !strstr( $_SERVER['HTTP_REFERER'], $_SERVER['SCRIPT_NAME'] ) ){
    • And replace to:
      if( ( $a == 'delete' || count( $_POST ) > 0 ) && !empty( $_SERVER['HTTP_REFERER'] ) && !strstr( $_SERVER['HTTP_REFERER'], $_SERVER['SCRIPT_NAME'] ) ){

7) The script saves the customer data from the order form (before ordering) to the cookies, even if he later turns off the browser.

    • Edit core/common.js and find code:
      createCookie( sName, sValue, 2 );
    • And replace to:
      createCookie( sName, sValue );

8) After sorting products files redirect to pages files

    • Edit templates/admin/files.tpl and find code:
      <a href="?p=$p
    • And replace to:
      <a href="?p=$p&amp;iLinkType=$iLinkType

9) Don't save search results after saving data in pages, products and orders list

    • Edit templates/admin/pages.tpl and find code:
      <form action="?p=$p" method="post">
    • And replace to:
      <form action="?p=$p&sPhrase=$sPhrase" method="post">
    • Edit templates/admin/products.tpl and find code:
      <form action="?p=$p" method="post">
    • And replace to:
      <form action="?p=$p&sPhrase=$sPhrase" method="post">
    • Edit templates/admin/orders.tpl and find code:
      <form action="?p=$p" method="post">
    • And replace to:
      <form action="?p=$p&amp;iStatus=$iStatus&amp;sPhrase=$sPhrase&amp;iProducts=$iProducts&amp;iUser=$iUser" method="post">

10) The script incorrectly deletes files that are duplicated in different languages

    • Edit core/files-admin.php and find code:
      $aFiles = $this->throwDbNames( );
      $sKey = ( $iLinkType == 1 ) ? 'iPage' : 'iProduct';
      $iLink = $this->aFilesImages[$iLinkType][$iFile][$sKey];
      foreach( $aFiles as $iDbLinkType => $sDbName ){
        if( isset( $this->aFilesImages[$iDbLinkType] ) ){
          foreach( $this->aFilesImages[$iDbLinkType] as $aFile ){
            $bDelete = true;
      
            if( $aFile['sFileName'] == $sFileName && ( $iDbLinkType != $iLinkType || $aFile['iFile'] != $iFile ) ){
              $bDelete = null;
              break;
            }
          } // end foreach
        }
      } // end foreach
      
      if( !isset( $bDelete ) ) 
        return null;
    • And replace to:
      if( !isset( $this->aFilesAll ) ){
        foreach( new DirectoryIterator( DIR_LANG ) as $oFileDir ) {
          if( $oFileDir->isFile( ) && strstr( $oFileDir->getFileName( ), '.php' ) ){
            $aLangs[] = substr( $oFileDir->getFileName( ), 0, 2 );
          }
        } // end foreach
      
        foreach( $aLangs as $sLang ){
          $sFunction = 'pages_files';
          $rFile = fopen( str_replace( LANGUAGE.'_', $sLang.'_', DB_PAGES_FILES ), 'r' );
          $i2 = 0;
          while( !feof( $rFile ) ){
            $sContent = fgets( $rFile, 10000 );
            if( $i2 > 0 && !empty( $sContent ) ){
              $aData = $sFunction( explode( '$', ( trim( $sContent ) ) ) );
              if( !isset( $this->aFilesAll[$aData['sFileName']] ) )
                $this->aFilesAll[$aData['sFileName']] = 0;
              $this->aFilesAll[$aData['sFileName']]++;
            }
            $i2++;
          } // end while
          fclose( $rFile );    
        } // end foreach
      }
      
      if( isset( $this->aFilesAll[$sFileName] ) && $this->aFilesAll[$sFileName] > 0 )
        return null;
    • Edit core/files-admin.php and find code:
      if( !isset( $bWithoutFiles ) ){
        foreach( $this->aFilesImages[$iLinkType] as $iFile => $aFile ){
          if( isset( $aData[$aFile[$sIndex]] ) ){
            $this->deleteFilesFromDirs( $aFile['sFileName'], $aFile['iPhoto'], $iLinkType, $iFile );
          }
        }
      }
      
      $oFF->deleteInFile( $sFileName, $aData, $sIndex );
    • And replace to:
      $oFF->deleteInFile( $sFileName, $aData, $sIndex );
      if( !isset( $bWithoutFiles ) ){
        foreach( $this->aFilesImages[$iLinkType] as $iFile => $aFile ){
          if( isset( $aData[$aFile[$sIndex]] ) ){
            $this->deleteFilesFromDirs( $aFile['sFileName'], $aFile['iPhoto'], $iLinkType, $iFile );
          }
        }
      }
    • Edit core/files-admin.php and find code:
      foreach( $aFiles as $iFile => $iValue ){
        if( isset( $this->aFilesImages[$iLinkType][$iFile] ) ){
          $this->deleteFilesFromDirs( $this->aFilesImages[$iLinkType][$iFile]['sFileName'], $this->aFilesImages[$iLinkType][$iFile]['iPhoto'], $iLinkType, $iFile ); 
        }
      }
      
      $oFF->deleteInFile( $sFileName, $aFiles, 'iFile' );
    • And replace to:
      $oFF->deleteInFile( $sFileName, $aFiles, 'iFile' );
      foreach( $aFiles as $iFile => $iValue ){
        if( isset( $this->aFilesImages[$iLinkType][$iFile] ) ){
          $this->deleteFilesFromDirs( $this->aFilesImages[$iLinkType][$iFile]['sFileName'], $this->aFilesImages[$iLinkType][$iFile]['iPhoto'], $iLinkType, $iFile ); 
        }
      }

Quick.Cart.Pro v4.1 bugs

1) New FotoJobs library which gives posibility to add transparent .png files to pages.

  • download Quick.Cart_v4.2.zip from download »
  • replace libraries/FotoJobs.php file in your script by file from downloaded package copy

2) On some servers when someone click "next" button in basket, then get "Error 403: Forbidden"

    • Edit templates/orders_basket.tpl and find code:
      <input type="submit" name="sNext" value="$lang[Basket_next]&nbsp;&nbsp;>>" class="submit" />
    • And replace to:
      <input type="submit" name="sNext" value="$lang[Basket_next] &raquo;" class="submit" />

3) CSS fix for products display option: "List"

    • Edit templates/default.css and find code:
      /* PRODUCTS LIST - LIST TEMPLATE */
    • And replace to:
      /* PRODUCTS LIST - LIST TEMPLATE */
      #products.productsList2{border-bottom:1px solid #e7dfbd;}
    • Edit templates/default.css and find code:
      * html #products.productsList2 li{width:100%;}
    • And replace to:
      * html #products.productsList2 li{width:100%;}
      #products.productsList2 li.l1{border-top:1px solid #e7dfbd;}
    • Edit templates/default.css and find code:
      #products.productsList1 li.pages#pagesAfter{border-top:1px solid #cabfa5;padding:8px 0;}
    • And replace to:
      #products.productsList1 li.pages#pagesAfter{border-top:1px solid #cabfa5;}
    • Edit templates/default.css and find code:
      #products li.pages{width:100%;border:0;background:inherit;color:#464032;}
    • And replace to:
      #products li.pages{float:right;width:100%;border:0;background:inherit;color:#464032;}
    • Edit templates/default.css and find code:
      #products li.pages#pagesBefore{float:right;width:auto;}
    • And replace to:
      #products li.pages#pagesBefore{clear:none;width:auto;}
      #products li.pages#pagesAfter{padding:8px 0;}

Quick.Cart.Pro v4.0 bugs

1) When one page have two the same images and one of them was deleted, then script deleted both

    • Edit core/files-admin.php and find code:
                if( $aFile['sFileName'] == $sFileName && ( $iDbLinkType != $iLinkType || $aFile['iFile'] != $iFile ) ){
                  if( $aFile[$sKey] == $iLink && $iDbLinkType == $iLinkType ){
                    $bDelete = true;
                  }
                  else{
                    $bDelete = null;
                    break;
                  }
                }
    • And replace to:
                if( $aFile['sFileName'] == $sFileName && ( $iDbLinkType != $iLinkType || $aFile['iFile'] != $iFile ) ){
                  $bDelete = null;
                  break;
                }

2) Checks valid email addresses only in lower case

    • Edit core/common.php and find code:
      preg_match( "/^[a-z0-9_.-]+([_\\.-][a-z0-9]+)*@([a-z0-9_\.-]+([\.][a-z]{2,4}))+$/", $sEmail );
    • And replace to:
      preg_match( "/^[a-z0-9_.-]+([_\\.-][a-z0-9]+)*@([a-z0-9_\.-]+([\.][a-z]{2,4}))+$/i", $sEmail );

3) IE7 problem with menu displaying in admin panel

    • Edit templates/admin/container.tpl and find code:
      <li onmouseover="return buttonClick( event, 'p' ); buttonMouseover( event, 'p' );"><a href="?p=p-list"><span class="pages">$lang['Pages']</span></a></li>
    • And replace to:
      <li onmouseover="return buttonClick( event, 'pages' ); buttonMouseover( event, 'pages' );"><a href="?p=p-list"><span class="pages">$lang['Pages']</span></a></li>
    • Edit templates/admin/container.tpl and find code:
      <div id="p" class="menu" onmouseover="menuMouseover( event );">
    • And replace to:
      <div id="pages" class="menu" onmouseover="menuMouseover( event );">

4) XSS bug fixes

    • Edit admin.php and find code:
      elseif( isset( $aActions ) && is_file( 'actions_admin/'.$aActions['f'].'.php' ) )
        require 'actions_admin/'.$aActions['f'].'.php';
    • And replace to:
      elseif( isset( $aActions ) && is_file( 'actions_admin/'.$aActions['f'].'.php' ) ){
        if( $a == 'delete' && !empty( $_SERVER['HTTP_REFERER'] ) && !strstr( $_SERVER['HTTP_REFERER'], $_SERVER['SCRIPT_NAME'] ) ){
          header( 'Location: '.$_SERVER['PHP_SELF'].'?p=error' );
          exit;
        }
        require 'actions_admin/'.$aActions['f'].'.php';
      }

5) On main page in admin panel link to products comments redirect to incorrect address

    • Edit core/comments-admin.php and find code:
      $sLink .= '&amp;sFileDb='.$sFileDb;
    • And replace to:
      $sLink .= '&amp;sProducts=';