#731 Closing Tag ignored when Start is implied/inferred

closed-fixed
nobody
7
2005-11-10
2005-10-19
No

It appears that Tidy is ignoring the closing tag when
the opening/start tag is implied when using the HASH
lookup functionality (ELEMENT_HASH_LOOKUP). A trace
into the code shows that:

- when creating a new tag from a token in the input
stream, Tidy calls lookup() [in tags.c] which will
check the Hash Table and return the item.

- when creating an implied/inferred tag, Tidy calls
LookupTagDef() [in tags.c] which does NOT check the
Hash Table (nor the custom tags table) - only the
original def table.

When Tidy encounters the closing tag for the element
(e.g. for table close in ParseTable() [in parser.c]),
it does a check to see if the tag pointers are the same
(not the contents of the pointers). This comparison
fails because one of the pointers is from the original
def table and the other is from the hash table.

I see two options to address this:

1) Change all the pointer comparisons to key/unique
fields in the tag def structure.

2) Add the hash lookup functionality to LookupTagDef():

#ifdef ELEMENT_HASH_LOOKUP
/* this breaks if declared elements get changed
between two */
/* parser runs since Tidy would use the cached
version rather */
/* than the new one
*/
for (np = tags->hashtab[hash(s)]; np != NULL; np =
np->next)
if (tmbstrcmp(s, np->name) == 0)
return np;

for (np = tag_defs + 1; np < tag_defs +
N_TIDY_TAGS; ++np)
if (tmbstrcmp(s, np->name) == 0)
return install(tags, np);

#else

for (np = tag_defs + 1; np < tag_defs +
N_TIDY_TAGS; ++np )
if (np->id == tid)
return np;

#endif /* ELEMENT_HASH_LOOKUP */

(Note: I did not include the declared tags list in this
functional change but it probably should be included
for consistency.)

Discussion

1 2 > >> (Page 1 of 2)
  • Christopher M. Woods

    Implied table start w/ actual table close.

     
    Attachments
  • Björn Höhrmann

    Logged In: YES
    user_id=188003

    Which kind of problem does this cause?

     
  • Christopher M. Woods

    Logged In: YES
    user_id=576763

    "When Tidy encounters the closing tag for the element
    (e.g. for table close in ParseTable() [in parser.c]),
    it does a check to see if the tag pointers are the same
    (not the contents of the pointers). This comparison
    fails because one of the pointers is from the original
    def table and the other is from the hash table."

    This means that if an inferred table is started, it does not
    exit when </table> is encountered.

    Using the sample file Tidy generates:
    line 6 column 1 - Warning: <tr> isn't allowed in <body> elements
    line 9 column 1 - Warning: inserting implicit <table>
    line 25 column 1 - Warning: discarding unexpected </table>
    line 9 column 1 - Warning: plain text isn't allowed in
    <table> elements
    line 29 column 1 - Warning: missing <tr>
    line 29 column 1 - Warning: discarding unexpected <table>
    line 29 column 1 - Warning: <tr> isn't allowed in <tr> elements
    line 37 column 1 - Warning: discarding unexpected </tr>
    line 29 column 1 - Warning: <tr> isn't allowed in <tr> elements
    line 45 column 1 - Warning: discarding unexpected </tr>
    line 46 column 1 - Warning: discarding unexpected </table>
    line 9 column 1 - Warning: plain text isn't allowed in
    <table> elements
    line 9 column 1 - Warning: missing </table> before </body>
    line 9 column 1 - Warning: <table> lacks "summary" attribute

    The output is incorrectly ordered and the two tables are
    merged into one (see input vs. output in browser).

     
  • Christopher M. Woods

    Logged In: YES
    user_id=576763

    I should add to my last comment that this issue is not
    experienced with the new hash lookup functionality disabled
    - as both functions then return pointers from the tag def table.

    It manifests specifically because pointer comparisons are
    occurring and the hash table functionality creates a copy of
    the tag def - the pointers are different but the content is
    the same. This could be addressed by changing the hash
    logic to add an extra layer of indirection (a pointer
    instead of a copy) or by something similar to the change I
    specified in the original issue report.

     
  • Christopher M. Woods

    Logged In: YES
    user_id=576763

    I must appologize here - I just C/C/P and grabbed the wrong
    snippet of code when I pasted my suggest code change. What
    I pasted does not compile but it is conceptually what needs
    to change.

    If the Hash functionality is being used then it must be used
    in this function as well so that the pointer comparisons
    used throughout the code function as originally intended.

    I will try to update with a corrected code change suggestion
    once I look into the code some more and determine how to get
    a clean reference to the hash table.

     
  • Christopher M. Woods

    Logged In: YES
    user_id=576763

    This issue is somewhat bigger than I originally thought and
    beyond the scope of what I can suggest for changes to the
    codebase.

    The core issue here lies in the usage of direct pointer
    comparisons when the Hash Table functionality is enabled.

    One area where this problem manifests is where inferred
    nodes are compared against non-inferred nodes (as I
    originally outlined). The inferred node is created with a
    Dict pointer reference into the tag_def static table. The
    non-inferred node is created with a Dict pointer reference
    into the hashtable dynamic table. All direct pointer
    comparisons will fail in this situation - which is not
    correct nor do I think intended. Either the direct pointer
    comparisons must change or the hash table must be used when
    creating the inferred node.

    I can not say that this issue is limited only to the
    situation in which I initially discovered above. Any code
    that calls LookupTagDef() or directly references the tag_def
    static table is suspect and needs to be reviewed. If the
    Dict pointer reference returned from LookupTagDef() is
    directly used for comparison then this code is affected as
    well. If the Dict pointer reference is stored then this
    code may or may not be affected depending on whether the
    stored pointer is directly compared later.

    Considering that no one else has reported an issue with the
    hash table functionality, then probably either:
    a) the scope is limited to only the situation that I found
    (aka inferred table start or potentially any inferred table)
    b) hash table functionality is generally not being enabled
    when people build the libs/application

    Regardless the code should be double checked.

    If you'd like me to delete this [messy] bug and re-file a
    new [clean] issue report, just let me know.

     
  • Christopher M. Woods

    Modified Sourcecode files to address direct pointer comparisons with Hash table functionality enabled

     
    Attachments
  • Christopher M. Woods

    Logged In: YES
    user_id=576763

    I'm attaching a modified version of the Hash table
    functionality. I *think* these changes should address
    any/all cases where direct pointer comparisons could be
    suspect when the Hash functionality is enabled.

    The files modified are:
    attrs.c, v1.115
    attrs.h, v1.20
    forward.h, v1.3
    tags.c, v1.58
    tags.h, v1.14

    The versions numbers given represent the latest version in
    CVS when the modifications were made.

    In these modified files, the hash table for both tags and
    attributes contains const pointer references to the Dict and
    Attribute tables instead of copies of the items.

    The install, lookup, and *Free functions for both Dict and
    Attribute have been modified to work with the new
    structures. lookup still returns the same Dict/Attribute
    pointer reference as before but now that reference is
    against the original table and not a copy (and it's const
    now as well).

    These changes also result in a reduction in the memory foot
    print with only a minor performance penalty (the indirection
    during lookup()).

    I have complied and tested these results against the sample
    file that I provided but have not regressed them against the
    test set in CVS (somewhere the test set on Windows seems to
    enter an infinite loop and I've not looked into it).

     
  • Björn Höhrmann

    Logged In: YES
    user_id=188003

    It would be good to know how the 04 Aug 2000 release
    handled this.

    Arnaud, could you have a look at this?

     
  • Arnaud Desitter

    Arnaud Desitter - 2005-11-09
    • priority: 5 --> 7
     
  • Arnaud Desitter

    Arnaud Desitter - 2005-11-09

    Logged In: YES
    user_id=566665

    Fixed in CVS. Hashing can now be used by default if necessary.

     
  • Arnaud Desitter

    Arnaud Desitter - 2005-11-09
    • status: open --> pending-fixed
     
  • Björn Höhrmann

    Logged In: YES
    user_id=188003

    Could you announce that on the -develop list, including how
    you changed to code such that it avoids the problem I noted
    in the source code?

     
  • Christopher M. Woods

    Logged In: YES
    user_id=576763

    Do you mean me or Arnaud?

    Not sure what you mean by "avoids the problem I noted in the
    source code"? Could you please explain further?

     
  • Christopher M. Woods

    • status: pending-fixed --> open-fixed
     
  • Arnaud Desitter

    Arnaud Desitter - 2005-11-09

    Logged In: YES
    user_id=566665

    The changes are two-fold:
    - The reporter, C.M. Woods, fixed a hash table handling so
    that the results with and without hash table handling are
    identical.
    - My contribution is to add some code so that
    FreeDeclaredTags() updates the hash table as needed. It was
    necessary for the first change to work. I think that it
    deals as well with the problem advertised in a comment next
    to lookup() in tags.c. As there is no example, I leave it to
    somebody else to test it. Announce it on the mailing list is
    unnecessary in my opinion. But it is your call.
    Note that hash tables handling is still disabled by default
    at the moment.

    The credit should go Christopher and not me.

     
  • Björn Höhrmann

    Logged In: YES
    user_id=188003

    I meant arnaud. It would be good to announce it there so
    people could test it and our porters update their makefiles
    if they prefer to offer the hashtable versions. Could you
    do it Christopher?

     
  • Arnaud Desitter

    Arnaud Desitter - 2005-11-10

    Logged In: YES
    user_id=566665

    The best way to have it tested is to enable the hashing by
    default while providing a way to disable it (that's easy).
    The test suite produces identical results with and without
    hashing. The run-time are similar. Consequently the hashing
    overhead should be acceptable for small test cases.
    Therefore, I would enable it, announce it on the web page
    and see.
    Equally, I am happy to leave it and move on.
    Comments ?

     
  • Björn Höhrmann

    Logged In: YES
    user_id=188003

    Some of the people providing binaries don't regularily read
    the web page, so if you make that enable, announce on web
    page and on the -develop mailing list that certainly works
    for me.

     
  • Christopher M. Woods

    Logged In: YES
    user_id=576763

    Arnaud,
    I'm concerned about your additional changes to remove the
    "removeFromHash" functions and calls in attrs.c and tags.c.
    I do not think you can remove these calls.

    When someone flushes the Declared Tags, any hash reference
    to that tag must also be flushed just as before. This is
    even more true now in that the Hash table doesn't contain a
    copy of the tag but rather a pointer. By removing these
    calls, you are leaving "dirty" entries in the Hash Table -
    entries with pointers to freed memory blocks (previously
    Declared Tags).

    Those removeFromHash functions and calls need to be put back
    in place - unless I'm completely missing something here?

    Bjrn,
    My changes to the Hash functionality were only meant as a
    correction to issues directly related to direct pointer
    comparisons throughout the code. I do not feel that these
    changes have any impact on the usage of the Hash Table or
    any previously expressed caveats for its usage. As such, I
    also do not feel that any announce needs to be made
    regarding them as all previous conditionalities still apply.

    -Chris

     
  • Christopher M. Woods

    Logged In: YES
    user_id=576763

    Disregard my last comment...

    I was looking at the difference via Windiff and am used to
    having the files in the panes in the reverse order.
    Combined with the fact that I'm not overly familiar with the
    codebase, I thought the removeFromHash functionality was
    being deleted - not added.

    Arnaud's change is correct and removes dirty entries from
    the Hash Table that both my code and the previous code left
    behind.

    The issue looks resolved so I'm going to close it.

     
  • Christopher M. Woods

    • status: open-fixed --> closed-fixed
     
  • Nobody/Anonymous

    Logged In: NO

    <html>
    <head>

     
  • Nobody/Anonymous

    Logged In: NO

    <?php
    /*
    $Id: index.php,v 1.1 2003/06/11 17:37:59 hpdl Exp $

    osCommerce, Open Source E-Commerce Solutions
    http://www.oscommerce.com

    Copyright (c) 2003 osCommerce
    </head>

    <body marginwidth="0" marginheight="0" topmargin="0"
    bottommargin="0" leftmargin="0" rightmargin="0">

    Released under the GNU General Public License
    */

    require('includes/application_top.php');

    // the following cPath references come from application_top.php
    $category_depth = 'top';
    if (isset($cPath) && tep_not_null($cPath)) {
    $categories_products_query = tep_db_query("select
    count(*) as total from " . TABLE_PRODUCTS_TO_CATEGORIES . "
    where categories_id = '" . (int)$current_category_id . "'");
    $cateqories_products =
    tep_db_fetch_array($categories_products_query);
    if ($cateqories_products['total'] > 0) {
    $category_depth = 'products'; // display products
    } else {
    $category_parent_query = tep_db_query("select count(*)
    as total from " . TABLE_CATEGORIES . " where parent_id = '"
    . (int)$current_category_id . "'");
    $category_parent =
    tep_db_fetch_array($category_parent_query);
    if ($category_parent['total'] > 0) {
    $category_depth = 'nested'; // navigate through the
    categories
    } else {
    $category_depth = 'products'; // category has no
    products, but display the 'no products' message
    }
    }
    }

    require(DIR_WS_LANGUAGES . $language . '/' .
    FILENAME_DEFAULT);
    ?>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01
    Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html <?php echo HTML_PARAMS; ?>>
    <head>

    <meta http-equiv="Content-Type" content="text/html;
    charset=<?php echo CHARSET; ?>">
    <title><?php echo TITLE; ?></title>
    <meta http-equiv="Content-Type" content="text/html;
    charset=iso-8859-1">
    <meta http-equiv="content-languaje" content="es">
    <meta name="DC.Language" content="Spanish">
    <link rel="shortcut icon" href="/infotinta.ico">
    <meta name="generator" content="OpenOffice.org 2.0 (Win32)">
    <meta name="description" content="aqui podras comprar las
    RECARGAS DE TINTA ideales para tu impresora, TINTA A GRANEL
    en botellas de litro, BOTELLINES DE TINTA y CARTUCHOS
    COMPATIBLES a precios muy economicos y todo tipo de
    accesorios">
    <meta name="keywords"
    content="recargas,tinta,cartuchos,granel,consumibles,instrucciones,herrramientas,utiles,accesorios,
    patel,inkjet,inyeccion,etiquetas,laser,laserjet,impresoras,cinta
    termica,compatibles">
    <meta name="title" content="Recargas tinta cartuchos">
    <meta name="DC.Title" content="Recargas tinta cartuchos">
    <meta name="Revisit" content="1 days">
    <meta name="revisit-after" content="1 days">
    <meta http-equiv="title" content="Recargas tinta cartuchos ">
    <meta http-equiv="dc.Description" content="Aqui podras
    comprar las RECARGAS DE TINTA ideales para tu impresora,
    TINTA A GRANEL en botellas de litro, BOTELLINES DE TINTA y
    CARTUCHOS COMPATIBLES a precios muy economicos y todo tipo
    de accesorios">
    <meta http-equiv="content-languaje" content="es">
    <meta name="rating" content="General">
    <meta name="robots" content="all,follow">
    <meta name="distribution" content="spain">
    <meta name="resource-type" content="document">
    <meta http-equiv="Pragma" content="cache">
    <!--// Aqui encontraras las RECARGAS DE TINTA ideales para
    tu impresora, TINTA A GRANEL en botellas de litro,
    BOTELLINES DE TINTA y CARTUCHOS COMPATIBLES a precios muy
    economicos //-->
    <base href="<?php echo (($request_type == 'SSL') ?
    HTTPS_SERVER : HTTP_SERVER) . DIR_WS_CATALOG; ?>">
    <link rel="stylesheet" type="text/css" href="stylesheet.css">

    </head>

    <!-- header //-->
    <?php require(DIR_WS_INCLUDES . 'header.php'); ?>
    <!-- header_eof //-->

    <!-- body //-->
    <body>
    <table border="0" width="100%" cellspacing="3" cellpadding="3">
    <tr>
    <td width="<?php echo BOX_WIDTH; ?>" valign="top"><table
    border="0" width="<?php echo BOX_WIDTH; ?>" cellspacing="0"
    cellpadding="2">
    <!-- left_navigation //-->
    <?php require(DIR_WS_INCLUDES . 'column_left.php'); ?>
    <!-- left_navigation_eof //-->
    </table></td>
    <!-- body_text //-->
    <?php
    if ($category_depth == 'nested') {
    $category_query = tep_db_query("select
    cd.categories_name, c.categories_image from " .
    TABLE_CATEGORIES . " c, " . TABLE_CATEGORIES_DESCRIPTION . "
    cd where c.categories_id = '" . (int)$current_category_id .
    "' and cd.categories_id = '" . (int)$current_category_id .
    "' and cd.language_id = '" . (int)$languages_id . "'");
    $category = tep_db_fetch_array($category_query);
    ?>
    <td width="100%" valign="top"><table border="0"
    width="100%" cellspacing="0" cellpadding="0">
    <tr>
    <td><table border="0" width="100%" cellspacing="0"
    cellpadding="0">
    <tr>
    <td class="pageHeading"><?php echo
    HEADING_TITLE; ?></td>
    <td class="pageHeading" align="right"><?php echo
    tep_image(DIR_WS_IMAGES . $category['categories_image'],
    $category['categories_name'], HEADING_IMAGE_WIDTH,
    HEADING_IMAGE_HEIGHT); ?></td>
    </tr>
    </table></td>
    </tr>
    <tr>
    <td><?php echo tep_draw_separator('pixel_trans.gif',
    '100%', '10'); ?></td>
    </tr>
    <tr>
    <td><table border="0" width="100%" cellspacing="0"
    cellpadding="2">
    <tr>
    <td><table border="0" width="100%"
    cellspacing="0" cellpadding="2">
    <tr>
    <?php
    if (isset($cPath) && strpos('_', $cPath)) {
    // check to see if there are deeper categories within the
    current category
    $category_links = array_reverse($cPath_array);
    for($i=0, $n=sizeof($category_links); $i<$n; $i++) {
    $categories_query = tep_db_query("select count(*) as
    total from " . TABLE_CATEGORIES . " c, " .
    TABLE_CATEGORIES_DESCRIPTION . " cd where c.parent_id = '" .
    (int)$category_links[$i] . "' and c.categories_id =
    cd.categories_id and cd.language_id = '" .
    (int)$languages_id . "'");
    $categories = tep_db_fetch_array($categories_query);
    if ($categories['total'] < 1) {
    // do nothing, go through the loop
    } else {
    $categories_query = tep_db_query("select
    c.categories_id, cd.categories_name, c.categories_image,
    c.parent_id from " . TABLE_CATEGORIES . " c, " .
    TABLE_CATEGORIES_DESCRIPTION . " cd where c.parent_id = '" .
    (int)$category_links[$i] . "' and c.categories_id =
    cd.categories_id and cd.language_id = '" .
    (int)$languages_id . "' order by sort_order,
    cd.categories_name");
    break; // we've found the deepest category the
    customer is in
    }
    }
    } else {
    $categories_query = tep_db_query("select
    c.categories_id, cd.categories_name, c.categories_image,
    c.parent_id from " . TABLE_CATEGORIES . " c, " .
    TABLE_CATEGORIES_DESCRIPTION . " cd where c.parent_id = '" .
    (int)$current_category_id . "' and c.categories_id =
    cd.categories_id and cd.language_id = '" .
    (int)$languages_id . "' order by sort_order,
    cd.categories_name");
    }

    $number_of_categories = tep_db_num_rows($categories_query);

    $rows = 0;
    while ($categories =
    tep_db_fetch_array($categories_query)) {
    $rows++;
    $cPath_new = tep_get_path($categories['categories_id']);
    $width = (int)(100 / MAX_DISPLAY_CATEGORIES_PER_ROW) .
    '%';
    echo ' <td align="center"
    class="smallText" width="' . $width . '" valign="top"><a
    href="' . tep_href_link(FILENAME_DEFAULT, $cPath_new) . '">'
    . tep_image(DIR_WS_IMAGES . $categories['categories_image'],
    $categories['categories_name'], SUBCATEGORY_IMAGE_WIDTH,
    SUBCATEGORY_IMAGE_HEIGHT) . '<br>' .
    $categories['categories_name'] . '</a></td>' . "\n";
    if ((($rows / MAX_DISPLAY_CATEGORIES_PER_ROW) ==
    floor($rows / MAX_DISPLAY_CATEGORIES_PER_ROW)) && ($rows !=
    $number_of_categories)) {
    echo ' </tr>' . "\n";
    echo ' <tr>' . "\n";
    }
    }

    // needed for the new products module shown below
    $new_products_category_id = $current_category_id;
    ?>
    </tr>
    </table></td>
    </tr>
    <tr>
    <td><?php echo
    tep_draw_separator('pixel_trans.gif', '100%', '10'); ?></td>
    </tr>
    <tr>
    <td><?php include(DIR_WS_MODULES .
    FILENAME_NEW_PRODUCTS); ?></td>
    </tr>
    </table></td>
    </tr>
    </table></td>
    <?php
    } elseif ($category_depth == 'products' ||
    isset($HTTP_GET_VARS['manufacturers_id'])) {
    // create column list
    $define_list = array('PRODUCT_LIST_MODEL' =>
    PRODUCT_LIST_MODEL,
    'PRODUCT_LIST_NAME' =>
    PRODUCT_LIST_NAME,
    'PRODUCT_LIST_MANUFACTURER' =>
    PRODUCT_LIST_MANUFACTURER,
    'PRODUCT_LIST_PRICE' =>
    PRODUCT_LIST_PRICE,
    'PRODUCT_LIST_QUANTITY' =>
    PRODUCT_LIST_QUANTITY,
    'PRODUCT_LIST_WEIGHT' =>
    PRODUCT_LIST_WEIGHT,
    //'PRODUCT_LIST_IMAGE' => PRODUCT_LIST_IMAGE,
    'PRODUCT_LIST_BUY_NOW' =>
    PRODUCT_LIST_BUY_NOW);

    //Listado_Produtos_Con/Sin_Imagenes_Start
    $productListWithImagesIni = '';
    $productListWithImagesEnd = '';
    $productListWithOutImagesIni = '';
    $productListWithOutImagesEnd = '';
    //si está registrada la variable de sesion
    productListImages y el valor es false entonces no mostramos
    las imágenes
    if
    (isset($_SESSION['productListImages'][$HTTP_GET_VARS['cPath']])
    && $_SESSION['productListImages'][$HTTP_GET_VARS['cPath']]
    == 'false'){
    $productListWithOutImagesIni = '<b>';
    $productListWithOutImagesEnd = '</b>';
    }else{//si por el contrario no está registrada la variable
    de sesión o el valor es true entonces mostramos las imágenes
    $productListWithImagesIni = '<b>';
    $productListWithImagesEnd = '</b>';
    $define_list['PRODUCT_LIST_IMAGE'] = PRODUCT_LIST_IMAGE;
    }
    //Listado_Produtos_Con/Sin_Imagenes_End

    asort($define_list);

    $column_list = array();
    reset($define_list);
    while (list($key, $value) = each($define_list)) {
    if ($value > 0) $column_list[] = $key;
    }

    $select_column_list = '';

    for ($i=0, $n=sizeof($column_list); $i<$n; $i++) {
    switch ($column_list[$i]) {
    case 'PRODUCT_LIST_MODEL':
    $select_column_list .= 'p.products_model, ';
    break;
    case 'PRODUCT_LIST_NAME':
    $select_column_list .= 'pd.products_name, ';
    break;
    case 'PRODUCT_LIST_MANUFACTURER':
    $select_column_list .= 'm.manufacturers_name, ';
    break;
    case 'PRODUCT_LIST_QUANTITY':
    $select_column_list .= 'p.products_quantity, ';
    break;
    case 'PRODUCT_LIST_IMAGE':
    $select_column_list .= 'p.products_image, ';
    break;
    case 'PRODUCT_LIST_WEIGHT':
    $select_column_list .= 'p.products_weight, ';
    break;
    }
    }

    // show the products of a specified manufacturer
    if (isset($HTTP_GET_VARS['manufacturers_id'])) {
    if (isset($HTTP_GET_VARS['filter_id']) &&
    tep_not_null($HTTP_GET_VARS['filter_id'])) {
    // We are asked to show only a specific category
    $listing_sql = "select " . $select_column_list . "
    p.products_id, p.manufacturers_id, p.products_price,
    p.products_tax_class_id, IF(s.status,
    s.specials_new_products_price, NULL) as
    specials_new_products_price, IF(s.status,
    s.specials_new_products_price, p.products_price) as
    final_price from " . TABLE_PRODUCTS . " p, " .
    TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_MANUFACTURERS .
    " m, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c left join " .
    TABLE_SPECIALS . " s on p.products_id = s.products_id where
    p.products_status = '1' and p.manufacturers_id =
    m.manufacturers_id and m.manufacturers_id = '" .
    (int)$HTTP_GET_VARS['manufacturers_id'] . "' and
    p.products_id = p2c.products_id and pd.products_id =
    p2c.products_id and pd.language_id = '" . (int)$languages_id
    . "' and p2c.categories_id = '" .
    (int)$HTTP_GET_VARS['filter_id'] . "'";
    } else {
    // We show them all
    $listing_sql = "select " . $select_column_list . "
    p.products_id, p.manufacturers_id, p.products_price,
    p.products_tax_class_id, IF(s.status,
    s.specials_new_products_price, NULL) as
    specials_new_products_price, IF(s.status,
    s.specials_new_products_price, p.products_price) as
    final_price from " . TABLE_PRODUCTS . " p, " .
    TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_MANUFACTURERS .
    " m left join " . TABLE_SPECIALS . " s on p.products_id =
    s.products_id where p.products_status = '1' and
    pd.products_id = p.products_id and pd.language_id = '" .
    (int)$languages_id . "' and p.manufacturers_id =
    m.manufacturers_id and m.manufacturers_id = '" .
    (int)$HTTP_GET_VARS['manufacturers_id'] . "'";
    }
    } else {
    // show the products in a given categorie
    if (isset($HTTP_GET_VARS['filter_id']) &&
    tep_not_null($HTTP_GET_VARS['filter_id'])) {
    // We are asked to show only specific catgeory
    $listing_sql = "select " . $select_column_list . "
    p.products_id, p.manufacturers_id, p.products_price,
    p.products_tax_class_id, IF(s.status,
    s.specials_new_products_price, NULL) as
    specials_new_products_price, IF(s.status,
    s.specials_new_products_price, p.products_price) as
    final_price from " . TABLE_PRODUCTS . " p, " .
    TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_MANUFACTURERS .
    " m, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c left join " .
    TABLE_SPECIALS . " s on p.products_id = s.products_id where
    p.products_status = '1' and p.manufacturers_id =
    m.manufacturers_id and m.manufacturers_id = '" .
    (int)$HTTP_GET_VARS['filter_id'] . "' and p.products_id =
    p2c.products_id and pd.products_id = p2c.products_id and
    pd.language_id = '" . (int)$languages_id . "' and
    p2c.categories_id = '" . (int)$current_category_id . "'";
    } else {
    // We show them all
    $listing_sql = "select " . $select_column_list . "
    p.products_id, p.manufacturers_id, p.products_price,
    p.products_tax_class_id, IF(s.status,
    s.specials_new_products_price, NULL) as
    specials_new_products_price, IF(s.status,
    s.specials_new_products_price, p.products_price) as
    final_price from " . TABLE_PRODUCTS_DESCRIPTION . " pd, " .
    TABLE_PRODUCTS . " p left join " . TABLE_MANUFACTURERS . " m
    on p.manufacturers_id = m.manufacturers_id, " .
    TABLE_PRODUCTS_TO_CATEGORIES . " p2c left join " .
    TABLE_SPECIALS . " s on p.products_id = s.products_id where
    p.products_status = '1' and p.products_id = p2c.products_id
    and pd.products_id = p2c.products_id and pd.language_id = '"
    . (int)$languages_id . "' and p2c.categories_id = '" .
    (int)$current_category_id . "'";
    }
    }

    if ( (!isset($HTTP_GET_VARS['sort'])) ||
    (!ereg('[1-8][ad]', $HTTP_GET_VARS['sort'])) ||
    (substr($HTTP_GET_VARS['sort'], 0, 1) >
    sizeof($column_list)) ) {
    for ($i=0, $n=sizeof($column_list); $i<$n; $i++) {
    if ($column_list[$i] == 'PRODUCT_LIST_NAME') {
    $HTTP_GET_VARS['sort'] = $i+1 . 'a';
    $listing_sql .= " order by pd.products_name";
    break;
    }
    }
    } else {
    $sort_col = substr($HTTP_GET_VARS['sort'], 0 , 1);
    $sort_order = substr($HTTP_GET_VARS['sort'], 1);
    $listing_sql .= ' order by ';
    switch ($column_list[$sort_col-1]) {
    case 'PRODUCT_LIST_MODEL':
    $listing_sql .= "p.products_model " . ($sort_order
    == 'd' ? 'desc' : '') . ", pd.products_name";
    break;
    case 'PRODUCT_LIST_NAME':
    $listing_sql .= "pd.products_name " . ($sort_order
    == 'd' ? 'desc' : '');
    break;
    case 'PRODUCT_LIST_MANUFACTURER':
    $listing_sql .= "m.manufacturers_name " .
    ($sort_order == 'd' ? 'desc' : '') . ", pd.products_name";
    break;
    case 'PRODUCT_LIST_QUANTITY':
    $listing_sql .= "p.products_quantity " .
    ($sort_order == 'd' ? 'desc' : '') . ", pd.products_name";
    break;
    case 'PRODUCT_LIST_IMAGE':
    $listing_sql .= "pd.products_name";
    break;
    case 'PRODUCT_LIST_WEIGHT':
    $listing_sql .= "p.products_weight " .
    ($sort_order == 'd' ? 'desc' : '') . ", pd.products_name";
    break;
    case 'PRODUCT_LIST_PRICE':
    $listing_sql .= "final_price " . ($sort_order ==
    'd' ? 'desc' : '') . ", pd.products_name";
    break;
    }
    }
    ?>
    <td width="100%" valign="top"><table border="0"
    width="100%" cellspacing="0" cellpadding="0">
    <tr>
    <td><table border="0" width="100%" cellspacing="0"
    cellpadding="0">
    <tr>
    <td class="pageHeading"><?php echo
    HEADING_TITLE; ?></td>
    <?php
    // optional Product List Filter
    if (PRODUCT_LIST_FILTER > 0) {
    if (isset($HTTP_GET_VARS['manufacturers_id'])) {
    $filterlist_sql = "select distinct c.categories_id
    as id, cd.categories_name as name from " . TABLE_PRODUCTS .
    " p, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c, " .
    TABLE_CATEGORIES . " c, " . TABLE_CATEGORIES_DESCRIPTION . "
    cd where p.products_status = '1' and p.products_id =
    p2c.products_id and p2c.categories_id = c.categories_id and
    p2c.categories_id = cd.categories_id and cd.language_id = '"
    . (int)$languages_id . "' and p.manufacturers_id = '" .
    (int)$HTTP_GET_VARS['manufacturers_id'] . "' order by
    cd.categories_name";
    } else {
    $filterlist_sql= "select distinct m.manufacturers_id
    as id, m.manufacturers_name as name from " . TABLE_PRODUCTS
    . " p, " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c, " .
    TABLE_MANUFACTURERS . " m where p.products_status = '1' and
    p.manufacturers_id = m.manufacturers_id and p.products_id =
    p2c.products_id and p2c.categories_id = '" .
    (int)$current_category_id . "' order by m.manufacturers_name";
    }
    $filterlist_query = tep_db_query($filterlist_sql);
    if (tep_db_num_rows($filterlist_query) > 1) {
    echo ' <td align="center" class="main">'
    . tep_draw_form('filter', FILENAME_DEFAULT, 'get') .
    TEXT_SHOW . '&nbsp;';
    if (isset($HTTP_GET_VARS['manufacturers_id'])) {
    echo tep_draw_hidden_field('manufacturers_id',
    $HTTP_GET_VARS['manufacturers_id']);
    $options = array(array('id' => '', 'text' =>
    TEXT_ALL_CATEGORIES));
    } else {
    echo tep_draw_hidden_field('cPath', $cPath);
    $options = array(array('id' => '', 'text' =>
    TEXT_ALL_MANUFACTURERS));
    }
    echo tep_draw_hidden_field('sort',
    $HTTP_GET_VARS['sort']);
    while ($filterlist =
    tep_db_fetch_array($filterlist_query)) {
    $options[] = array('id' => $filterlist['id'],
    'text' => $filterlist['name']);
    }
    echo tep_draw_pull_down_menu('filter_id', $options,
    (isset($HTTP_GET_VARS['filter_id']) ?
    $HTTP_GET_VARS['filter_id'] : ''),
    'onchange="this.form.submit()"');
    echo '</form></td>' . "\n";
    }
    }

    // Get the right image for the top-right
    $image = DIR_WS_IMAGES . 'table_background_list.gif';
    if (isset($HTTP_GET_VARS['manufacturers_id'])) {
    $image = tep_db_query("select manufacturers_image from
    " . TABLE_MANUFACTURERS . " where manufacturers_id = '" .
    (int)$HTTP_GET_VARS['manufacturers_id'] . "'");
    $image = tep_db_fetch_array($image);
    $image = $image['manufacturers_image'];
    } elseif ($current_category_id) {
    $image = tep_db_query("select categories_image from "
    . TABLE_CATEGORIES . " where categories_id = '" .
    (int)$current_category_id . "'");
    $image = tep_db_fetch_array($image);
    $image = $image['categories_image'];
    }
    ?>
    <td align="right"><?php echo
    tep_image(DIR_WS_IMAGES . $image, HEADING_TITLE,
    HEADING_IMAGE_WIDTH, HEADING_IMAGE_HEIGHT); ?></td>
    </tr>
    </table></td>
    </tr>
    <tr>
    <td><?php echo tep_draw_separator('pixel_trans.gif',
    '100%', '10'); ?></td>
    </tr>
    <!-- //Listado_Produtos_Con/Sin_Imagenes_Start -->
    <tr>
    <td class="main" align="right">
    <?php
    echo $productListWithImagesIni . '<a href="' .
    tep_href_link(basename($PHP_SELF),
    tep_get_all_get_params(array('action','product_list_images',
    'language', 'currency')) .
    'action=product_list_images&product_list_images=true') .
    '">' . TEXT_PRODUCTS_LIST_WITH_IMAGES . '</a>' .
    $productListWithImagesEnd;
    echo ' - ';
    echo $productListWithOutImagesIni . '<a href="' .
    tep_href_link(basename($PHP_SELF),
    tep_get_all_get_params(array('action','product_list_images',
    'language', 'currency')) .
    'action=product_list_images&product_list_images=false') .
    '">' . TEXT_PRODUCTS_LIST_WITHOUT_IMAGES . '</a>' .
    $productListWithOutImagesEnd;
    ?>
    </td>
    </tr>
    <tr>
    <td><?php echo tep_draw_separator('pixel_trans.gif',
    '100%', '10'); ?></td>
    </tr>
    <!-- //Listado_Produtos_Con/Sin_Imagenes_End -->
    <tr>
    <td><?php include(DIR_WS_MODULES .
    FILENAME_PRODUCT_LISTING); ?></td>
    </tr>
    </table></td>
    <?php
    } else { // default page
    ?>
    <td width="100%" valign="top"><table border="0"
    width="100%" cellspacing="0" cellpadding="0">
    <tr>
    <td><table border="0" width="100%" cellspacing="0"
    cellpadding="0">
    <tr>
    <td class="pageHeading"><?php echo
    HEADING_TITLE; ?></td>
    <td class="pageHeading" align="right"><?php echo
    tep_image(DIR_WS_IMAGES . 'table_background_default.gif',
    HEADING_TITLE, HEADING_IMAGE_WIDTH, HEADING_IMAGE_HEIGHT);
    ?></td>
    </tr>
    </table></td>
    </tr>
    <tr>
    <td><?php echo tep_draw_separator('pixel_trans.gif',
    '100%', '10'); ?></td>
    </tr>
    <tr>
    <td><table border="0" width="100%" cellspacing="0"
    cellpadding="0">
    <tr>
    <td class="main"><?php echo
    tep_customer_greeting(); ?></td>
    </tr>
    <tr>
    <td><?php echo
    tep_draw_separator('pixel_trans.gif', '100%', '10'); ?></td>
    </tr>
    <tr>
    <td class="main"><?php echo TEXT_MAIN; ?></td>
    </tr>
    <tr>
    <td><?php echo
    tep_draw_separator('pixel_trans.gif', '100%', '10'); ?></td>
    </tr>
    <tr>
    <td><?php include(DIR_WS_MODULES .
    FILENAME_NEW_PRODUCTS); ?></td>
    </tr>
    <?php
    include(DIR_WS_MODULES . FILENAME_UPCOMING_PRODUCTS);
    ?>
    </table></td>
    </tr>
    </table></td>
    <?php
    }
    ?>
    <!-- body_text_eof //-->
    <td width="<?php echo BOX_WIDTH; ?>" valign="top"><table
    border="0" width="<?php echo BOX_WIDTH; ?>" cellspacing="0"
    cellpadding="2">
    <!-- right_navigation //-->
    <?php require(DIR_WS_INCLUDES . 'column_right.php'); ?>
    <!-- right_navigation_eof //-->
    </table></td>
    </tr>
    </table>
    <!-- body_eof //-->

    <!-- footer //-->
    <?php require(DIR_WS_INCLUDES . 'footer.php'); ?>
    <!-- footer_eof //-->
    <br>
    </body>
    </html>
    <?php require(DIR_WS_INCLUDES . 'application_bottom.php'); ?>

     
  • Nobody/Anonymous

    Logged In: NO

    shoxhe_ime_@hotmail.com

     
1 2 > >> (Page 1 of 2)

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks