cbsezer Posted May 20, 2006 Share Posted May 20, 2006 hi there, I have installed QT Pro on my site, it all works fine in the admin, but when I click on a product image in the online catalog instead of showing the product info and etc. it gives a line like this :huh: Fatal error: Cannot redeclare tep_show_category() (previously declared in /hsphere/local/home/blastr/blaststore.com/includes/header.php:112) in /hsphere/local/home/blastr/blaststore.com/includes/boxes/categories.php on line 13 You know why? Any help would be appreciated, Quote Michelle, ma belle, these are scripts that go together well !! Link to comment Share on other sites More sharing options...
Terra Posted May 20, 2006 Share Posted May 20, 2006 hi there, I have installed QT Pro on my site, it all works fine in the admin, but when I click on a product image in the online catalog instead of showing the product info and etc. it gives a line like this :huh: Fatal error: Cannot redeclare tep_show_category() (previously declared in /hsphere/local/home/blastr/blaststore.com/includes/header.php:112) in /hsphere/local/home/blastr/blaststore.com/includes/boxes/categories.php on line 13 You know why? Any help would be appreciated, The most common cause of "cannot redeclare" errors is to accidentally copy a root level file into the language level. I'd therefore recommend to check your language level files you recently updated - if this is not the cause, please post back. all the best, Terra Quote My code for combining PayPal IPN with ** QTPro 4.25 ** osC Affiliate ** CCGV(trad) and how to solve the invoice already paid error General info: Allow customer to delete order comment ** FTP Programs & Text Editors ** Amending order email ** Link to comment Share on other sites More sharing options...
chooch Posted May 21, 2006 Share Posted May 21, 2006 I have a question about QTPro. I want to find out if there is a way to run a report that will show me all the information about all my stock which would include the new QTPro stock. In other words, I want to run a report that will show me the total stock plus the stock of my attributes all on one report. Rob. Is the low stock report update in the QTPro download not sufficient? Quote Upon receiving fixes and advice, too many people don't bother to post updates informing the forum of how it went. Until of course they need help again on other issues and they come running back! Why receive the information you require in good faith for free, only to then have the attitude to ignore the people who gave it to you? There's no harm in saying, 'Thanks, it worked'. On the contrary, it creates a better atmosphere. CHOOCH Link to comment Share on other sites More sharing options...
Terra Posted May 21, 2006 Share Posted May 21, 2006 This is a code solution for shops wanting to use both QTPro Quantity Tracking Professional (version 4.25 from 27 Feb 2006) and the official osCom team PayPal IPN module inc. tax fix (version 1.0 Mark Evans plus navyhost January 2006). The problem: QTPro amends checkout_process.php. However, the PayPal IPN uses paypal_ipn.php to mirror the function of checkout_process.php so the QTPro code needs to be manually added to /includes/modules/payment/paypal_ipn.php. NB: this version also contains a fix for the "missing attribute or attributes in order confirmation email" with PayPal IPN. 1. Back up your files. I'd strongly recommend to test all file changes on a development / test shop before applying to live shop. If your shop goes down, it's up to you to sort it. 2. Install Paypal IPN and QTPro as per instructions: http://www.oscommerce.com/community/contributions,888/ http://www.oscommerce.com/community/contributions,2679/ 3. Open /includes/modules/payment/paypal_ipn.php and apply the following changes: Find this code: for ($i=0, $n=sizeof($order->products); $i<$n; $i++) { $sql_data_array = array('orders_id' => $insert_id, 'products_id' => tep_get_prid($order->products[$i]['id']), 'products_model' => $order->products[$i]['model'], 'products_name' => $order->products[$i]['name'], 'products_price' => $order->products[$i]['price'], 'final_price' => $order->products[$i]['final_price'], 'products_tax' => $order->products[$i]['tax'], 'products_quantity' => $order->products[$i]['qty']); Replace with this code: //++++ QT Pro: Begin Changed code for ($i=0, $n=sizeof($order->products); $i<$n; $i++) { $products_stock_attributes=null; if (STOCK_LIMITED == 'true') { $products_attributes = $order->products[$i]['attributes']; $stock_query_raw = "SELECT products_quantity, pad.products_attributes_filename FROM " . TABLE_PRODUCTS . " p LEFT JOIN " . TABLE_PRODUCTS_ATTRIBUTES . " pa ON p.products_id=pa.products_id LEFT JOIN " . TABLE_PRODUCTS_ATTRIBUTES_DOWNLOAD . " pad ON pa.products_attributes_id=pad.products_attributes_id WHERE p.products_id = '" . tep_get_prid($order->products[$i]['id']) . "'"; if (is_array($products_attributes)) { $stock_query_raw .= " AND pa.options_id = '" . $products_attributes[0]['option_id'] . "' AND pa.options_values_id = '" . $products_attributes[0]['value_id'] . "'"; } $stock_query = tep_db_query($stock_query_raw); if (tep_db_num_rows($stock_query) > 0) { $stock_values = tep_db_fetch_array($stock_query); $actual_stock_bought = $order->products[$i]['qty']; $download_selected = false; if ((DOWNLOAD_ENABLED == 'true') && isset($stock_values['products_attributes_filename']) && tep_not_null($stock_values['products_attributes_filename'])) { $download_selected = true; $products_stock_attributes='$$DOWNLOAD$$'; } // If not downloadable and attributes present, adjust attribute stock if (!$download_selected && is_array($products_attributes)) { $all_nonstocked = true; $products_stock_attributes_array = array(); foreach ($products_attributes as $attribute) { $products_stock_attributes_array[] = $attribute['option_id'] . "-" . $attribute['value_id']; asort($products_stock_attributes_array, SORT_NUMERIC); $products_stock_attributes = implode(",", $products_stock_attributes_array); } } } } else { if ( is_array($order->products[$i]['attributes']) ) { $products_stock_attributes_array = array(); foreach ($order->products[$i]['attributes'] as $attribute) { $products_stock_attributes_array[] = $attribute['option_id'] . "-" . $attribute['value_id']; } asort($products_stock_attributes_array, SORT_NUMERIC); $products_stock_attributes = implode(",", $products_stock_attributes_array); } } if (!isset($products_stock_attributes)) $products_stock_attributes=null; $sql_data_array = array('orders_id' => $insert_id, 'products_id' => tep_get_prid($order->products[$i]['id']), 'products_model' => $order->products[$i]['model'], 'products_name' => $order->products[$i]['name'], 'products_price' => $order->products[$i]['price'], 'final_price' => $order->products[$i]['final_price'], 'products_tax' => $order->products[$i]['tax'], 'products_quantity' => $order->products[$i]['qty'], 'products_stock_attributes' => $products_stock_attributes); //++++ QT Pro: End Changed Code ************************ Find this code: function before_process() { global $customer_id, $order, $sendto, $billto, $payment, $currencies, $cart, $cart_PayPal_IPN_ID; global $$payment; Replace with this code: function before_process() { global $customer_id, $order, $sendto, $billto, $payment, $languages_id, $currencies, $cart, $cart_PayPal_IPN_ID; global $$payment; ********************************** Find this code: // Stock Update - Joao Correia if (STOCK_LIMITED == 'true') { if (DOWNLOAD_ENABLED == 'true') { Replace with this code: // Stock Update - Joao Correia //++++ QT Pro: Begin Changed code $products_stock_attributes=null; if (STOCK_LIMITED == 'true') { $products_attributes = $order->products[$i]['attributes']; // if (DOWNLOAD_ENABLED == 'true') { //++++ QT Pro: End Changed Code ********************************** Find this code: // Will work with only one option for downloadable products // otherwise, we have to build the query dynamically with a loop $products_attributes = $order->products[$i]['attributes']; if (is_array($products_attributes)) { $stock_query_raw .= " AND pa.options_id = '" . $products_attributes[0]['option_id'] . "' AND pa.options_values_id = '" . $products_attributes[0]['value_id'] . "'"; } $stock_query = tep_db_query($stock_query_raw); } else { $stock_query = tep_db_query("select products_quantity from " . TABLE_PRODUCTS . " where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'"); } if (tep_db_num_rows($stock_query) > 0) { $stock_values = tep_db_fetch_array($stock_query); // do not decrement quantities if products_attributes_filename exists if ((DOWNLOAD_ENABLED != 'true') || (!$stock_values['products_attributes_filename'])) { $stock_left = $stock_values['products_quantity'] - $order->products[$i]['qty']; } else { $stock_left = $stock_values['products_quantity']; } tep_db_query("update " . TABLE_PRODUCTS . " set products_quantity = '" . $stock_left . "' where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'"); if ( ($stock_left < 1) && (STOCK_ALLOW_CHECKOUT == 'false') ) { tep_db_query("update " . TABLE_PRODUCTS . " set products_status = '0' where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'"); } } } // Update products_ordered (for bestsellers list) Replace with this code: // Will work with only one option for downloadable products // otherwise, we have to build the query dynamically with a loop //++++ QT Pro: Begin Changed code // $products_attributes = $order->products[$i]['attributes']; //++++ QT Pro: End Changed Code if (is_array($products_attributes)) { $stock_query_raw .= " AND pa.options_id = '" . $products_attributes[0]['option_id'] . "' AND pa.options_values_id = '" . $products_attributes[0]['value_id'] . "'"; } $stock_query = tep_db_query($stock_query_raw); if (tep_db_num_rows($stock_query) > 0) { $stock_values = tep_db_fetch_array($stock_query); //++++ QT Pro: Begin Changed code $actual_stock_bought = $order->products[$i]['qty']; $download_selected = false; if ((DOWNLOAD_ENABLED == 'true') && isset($stock_values['products_attributes_filename']) && tep_not_null($stock_values['products_attributes_filename'])) { $download_selected = true; $products_stock_attributes='$$DOWNLOAD$$'; } // If not downloadable and attributes present, adjust attribute stock if (!$download_selected && is_array($products_attributes)) { $all_nonstocked = true; $products_stock_attributes_array = array(); foreach ($products_attributes as $attribute) { //**si** 14-11-05 fix missing att list // if ($attribute['track_stock'] == 1) { // $products_stock_attributes_array[] = $attribute['option_id'] . "-" . $attribute['value_id']; $products_stock_attributes_array[] = $attribute['option_id'] . "-" . $attribute['value_id']; if ($attribute['track_stock'] == 1) { //**si** 14-11-05 end $all_nonstocked = false; } } if ($all_nonstocked) { $actual_stock_bought = $order->products[$i]['qty']; //**si** 14-11-05 fix missing att list asort($products_stock_attributes_array, SORT_NUMERIC); $products_stock_attributes = implode(",", $products_stock_attributes_array); //**si** 14-11-05 end } else { asort($products_stock_attributes_array, SORT_NUMERIC); $products_stock_attributes = implode(",", $products_stock_attributes_array); $attributes_stock_query = tep_db_query("select products_stock_quantity from " . TABLE_PRODUCTS_STOCK . " where products_stock_attributes = '$products_stock_attributes' AND products_id = '" . tep_get_prid($order->products[$i]['id']) . "'"); if (tep_db_num_rows($attributes_stock_query) > 0) { $attributes_stock_values = tep_db_fetch_array($attributes_stock_query); $attributes_stock_left = $attributes_stock_values['products_stock_quantity'] - $order->products[$i]['qty']; tep_db_query("update " . TABLE_PRODUCTS_STOCK . " set products_stock_quantity = '" . $attributes_stock_left . "' where products_stock_attributes = '$products_stock_attributes' AND products_id = '" . tep_get_prid($order->products[$i]['id']) . "'"); $actual_stock_bought = ($attributes_stock_left < 1) ? $attributes_stock_values['products_stock_quantity'] : $order->products[$i]['qty']; } else { $attributes_stock_left = 0 - $order->products[$i]['qty']; tep_db_query("insert into " . TABLE_PRODUCTS_STOCK . " (products_id, products_stock_attributes, products_stock_quantity) values ('" . tep_get_prid($order->products[$i]['id']) . "', '" . $products_stock_attributes . "', '" . $attributes_stock_left . "')"); $actual_stock_bought = 0; } } } // $stock_query = tep_db_query("select products_quantity from " . TABLE_PRODUCTS . " where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'"); // } // if (tep_db_num_rows($stock_query) > 0) { // $stock_values = tep_db_fetch_array($stock_query); // do not decrement quantities if products_attributes_filename exists if (!$download_selected) { $stock_left = $stock_values['products_quantity'] - $actual_stock_bought; tep_db_query("UPDATE " . TABLE_PRODUCTS . " SET products_quantity = products_quantity - '" . $actual_stock_bought . "' WHERE products_id = '" . tep_get_prid($order->products[$i]['id']) . "'"); //++++ QT Pro: End Changed Code if ( ($stock_left < 1) && (STOCK_ALLOW_CHECKOUT == 'false') ) { tep_db_query("update " . TABLE_PRODUCTS . " set products_status = '0' where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'"); } } } //++++ QT Pro: Begin Changed code } //**si** 14-11-05 fix missing att list else { if ( is_array($order->products[$i]['attributes']) ) { $products_stock_attributes_array = array(); foreach ($order->products[$i]['attributes'] as $attribute) { $products_stock_attributes_array[] = $attribute['option_id'] . "-" . $attribute['value_id']; } asort($products_stock_attributes_array, SORT_NUMERIC); $products_stock_attributes = implode(",", $products_stock_attributes_array); } } //**si** 14-11-05 end //++++ QT Pro: End Changed Code // Update products_ordered (for bestsellers list) *************************************** 4. Save your file. To test, upload to a dev test shop and test with paypal sand box: http://developer.paypal.com Once you are satisified that all works, upload changed file to your live shop. Happy coding! Terra :thumbsup: Quote My code for combining PayPal IPN with ** QTPro 4.25 ** osC Affiliate ** CCGV(trad) and how to solve the invoice already paid error General info: Allow customer to delete order comment ** FTP Programs & Text Editors ** Amending order email ** Link to comment Share on other sites More sharing options...
iwanttogoas Posted May 21, 2006 Share Posted May 21, 2006 Here is the code as requested... <?php/* $Id: paypal_ipn.php,v 1.1.2.11 2004/12/05 19:14:35 hpdl Exp $ osCommerce, Open Source E-Commerce Solutions http://www.oscommerce.com Copyright (c) 2004 osCommerce Released under the GNU General Public License*/ class paypal_ipn { var $code, $title, $description, $enabled, $identifier; // class constructor function paypal_ipn() { global $order; $this->code = 'paypal_ipn'; $this->title = MODULE_PAYMENT_PAYPAL_IPN_TEXT_TITLE; $this->description = MODULE_PAYMENT_PAYPAL_IPN_TEXT_DESCRIPTION; $this->sort_order = MODULE_PAYMENT_PAYPAL_IPN_SORT_ORDER; $this->enabled = ((MODULE_PAYMENT_PAYPAL_IPN_STATUS == 'True') ? true : false); $this->identifier = 'osCommerce PayPal IPN v1.0'; if ((int)MODULE_PAYMENT_PAYPAL_IPN_PREPARE_ORDER_STATUS_ID > 0) { $this->order_status = MODULE_PAYMENT_PAYPAL_IPN_PREPARE_ORDER_STATUS_ID; } if (is_object($order)) $this->update_status(); if (MODULE_PAYMENT_PAYPAL_IPN_GATEWAY_SERVER == 'Live') { $this->form_action_url = 'https://www.paypal.com/cgi-bin/webscr'; } else { $this->form_action_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr'; } } // class methods function update_status() { global $order; if ( ($this->enabled == true) && ((int)MODULE_PAYMENT_PAYPAL_IPN_ZONE > 0) ) { $check_flag = false; $check_query = tep_db_query("select zone_id from " . TABLE_ZONES_TO_GEO_ZONES . " where geo_zone_id = '" . MODULE_PAYMENT_PAYPAL_IPN_ZONE . "' and zone_country_id = '" . $order->billing['country']['id'] . "' order by zone_id"); while ($check = tep_db_fetch_array($check_query)) { if ($check['zone_id'] < 1) { $check_flag = true; break; } elseif ($check['zone_id'] == $order->billing['zone_id']) { $check_flag = true; break; } } if ($check_flag == false) { $this->enabled = false; } } } function javascript_validation() { return false; } function selection() { return array('id' => $this->code, 'module' => $this->title); } function pre_confirmation_check() { return false; } function confirmation() { global $cartID, $cart_PayPal_IPN_ID, $customer_id, $languages_id, $order, $order_total_modules; if (tep_session_is_registered('cartID')) { $insert_order = false; if (tep_session_is_registered('cart_PayPal_IPN_ID')) { $order_id = substr($cart_PayPal_IPN_ID, strpos($cart_PayPal_IPN_ID, '-')+1); $curr_check = tep_db_query("select currency from " . TABLE_ORDERS . " where orders_id = '" . (int)$order_id . "'"); $curr = tep_db_fetch_array($curr_check); if ( ($curr['currency'] != $order->info['currency']) || ($cartID != substr($cart_PayPal_IPN_ID, 0, strlen($cartID))) ) { $check_query = tep_db_query('select orders_id from ' . TABLE_ORDERS_STATUS_HISTORY . ' where orders_id = "' . (int)$order_id . '" limit 1'); if (tep_db_num_rows($check_query) < 1) { tep_db_query('delete from ' . TABLE_ORDERS . ' where orders_id = "' . (int)$order_id . '"'); tep_db_query('delete from ' . TABLE_ORDERS_TOTAL . ' where orders_id = "' . (int)$order_id . '"'); tep_db_query('delete from ' . TABLE_ORDERS_STATUS_HISTORY . ' where orders_id = "' . (int)$order_id . '"'); tep_db_query('delete from ' . TABLE_ORDERS_PRODUCTS . ' where orders_id = "' . (int)$order_id . '"'); tep_db_query('delete from ' . TABLE_ORDERS_PRODUCTS_ATTRIBUTES . ' where orders_id = "' . (int)$order_id . '"'); tep_db_query('delete from ' . TABLE_ORDERS_PRODUCTS_DOWNLOAD . ' where orders_id = "' . (int)$order_id . '"'); } $insert_order = true; } } else { $insert_order = true; } if ($insert_order == true) { $order_totals = array(); if (is_array($order_total_modules->modules)) { reset($order_total_modules->modules); while (list(, $value) = each($order_total_modules->modules)) { $class = substr($value, 0, strrpos($value, '.')); if ($GLOBALS[$class]->enabled) { for ($i=0, $n=sizeof($GLOBALS[$class]->output); $i<$n; $i++) { if (tep_not_null($GLOBALS[$class]->output[$i]['title']) && tep_not_null($GLOBALS[$class]->output[$i]['text'])) { $order_totals[] = array('code' => $GLOBALS[$class]->code, 'title' => $GLOBALS[$class]->output[$i]['title'], 'text' => $GLOBALS[$class]->output[$i]['text'], 'value' => $GLOBALS[$class]->output[$i]['value'], 'sort_order' => $GLOBALS[$class]->sort_order); } } } } } $sql_data_array = array('customers_id' => $customer_id, 'customers_name' => $order->customer['firstname'] . ' ' . $order->customer['lastname'], 'customers_company' => $order->customer['company'], 'customers_street_address' => $order->customer['street_address'], 'customers_suburb' => $order->customer['suburb'], 'customers_city' => $order->customer['city'], 'customers_postcode' => $order->customer['postcode'], 'customers_state' => $order->customer['state'], 'customers_country' => $order->customer['country']['title'], 'customers_telephone' => $order->customer['telephone'], 'customers_email_address' => $order->customer['email_address'], 'customers_address_format_id' => $order->customer['format_id'], 'delivery_name' => $order->delivery['firstname'] . ' ' . $order->delivery['lastname'], 'delivery_company' => $order->delivery['company'], 'delivery_street_address' => $order->delivery['street_address'], 'delivery_suburb' => $order->delivery['suburb'], 'delivery_city' => $order->delivery['city'], 'delivery_postcode' => $order->delivery['postcode'], 'delivery_state' => $order->delivery['state'], 'delivery_country' => $order->delivery['country']['title'], 'delivery_address_format_id' => $order->delivery['format_id'], 'billing_name' => $order->billing['firstname'] . ' ' . $order->billing['lastname'], 'billing_company' => $order->billing['company'], 'billing_street_address' => $order->billing['street_address'], 'billing_suburb' => $order->billing['suburb'], 'billing_city' => $order->billing['city'], 'billing_postcode' => $order->billing['postcode'], 'billing_state' => $order->billing['state'], 'billing_country' => $order->billing['country']['title'], 'billing_address_format_id' => $order->billing['format_id'], 'payment_method' => $order->info['payment_method'], 'cc_type' => $order->info['cc_type'], 'cc_owner' => $order->info['cc_owner'], 'cc_number' => $order->info['cc_number'], 'cc_expires' => $order->info['cc_expires'], 'date_purchased' => 'now()', 'orders_status' => $order->info['order_status'], 'currency' => $order->info['currency'], 'currency_value' => $order->info['currency_value']); tep_db_perform(TABLE_ORDERS, $sql_data_array); $insert_id = tep_db_insert_id(); for ($i=0, $n=sizeof($order_totals); $i<$n; $i++) { $sql_data_array = array('orders_id' => $insert_id, 'title' => $order_totals[$i]['title'], 'text' => $order_totals[$i]['text'], 'value' => $order_totals[$i]['value'], 'class' => $order_totals[$i]['code'], 'sort_order' => $order_totals[$i]['sort_order']); tep_db_perform(TABLE_ORDERS_TOTAL, $sql_data_array); } for ($i=0, $n=sizeof($order->products); $i<$n; $i++) { $sql_data_array = array('orders_id' => $insert_id, 'products_id' => tep_get_prid($order->products[$i]['id']), 'products_model' => $order->products[$i]['model'], 'products_name' => $order->products[$i]['name'], 'products_price' => $order->products[$i]['price'], 'final_price' => $order->products[$i]['final_price'], 'products_tax' => $order->products[$i]['tax'], 'products_quantity' => $order->products[$i]['qty'], 'products_stock_attributes' => $products_stock_attributes); tep_db_perform(TABLE_ORDERS_PRODUCTS, $sql_data_array); $order_products_id = tep_db_insert_id(); $attributes_exist = '0'; if (isset($order->products[$i]['attributes'])) { $attributes_exist = '1'; for ($j=0, $n2=sizeof($order->products[$i]['attributes']); $j<$n2; $j++) { if (DOWNLOAD_ENABLED == 'true') { $attributes_query = "select popt.products_options_name, poval.products_options_values_name, pa.options_values_price, pa.price_prefix, pad.products_attributes_maxdays, pad.products_attributes_maxcount , pad.products_attributes_filename from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " . TABLE_PRODUCTS_ATTRIBUTES . " pa left join " . TABLE_PRODUCTS_ATTRIBUTES_DOWNLOAD . " pad on pa.products_attributes_id=pad.products_attributes_id where pa.products_id = '" . $order->products[$i]['id'] . "' and pa.options_id = '" . $order->products[$i]['attributes'][$j]['option_id'] . "' and pa.options_id = popt.products_options_id and pa.options_values_id = '" . $order->products[$i]['attributes'][$j]['value_id'] . "' and pa.options_values_id = poval.products_options_values_id and popt.language_id = '" . $languages_id . "' and poval.language_id = '" . $languages_id . "'"; $attributes = tep_db_query($attributes_query); } else { $attributes = tep_db_query("select popt.products_options_name, poval.products_options_values_name, pa.options_values_price, pa.price_prefix from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " . TABLE_PRODUCTS_ATTRIBUTES . " pa where pa.products_id = '" . $order->products[$i]['id'] . "' and pa.options_id = '" . $order->products[$i]['attributes'][$j]['option_id'] . "' and pa.options_id = popt.products_options_id and pa.options_values_id = '" . $order->products[$i]['attributes'][$j]['value_id'] . "' and pa.options_values_id = poval.products_options_values_id and popt.language_id = '" . $languages_id . "' and poval.language_id = '" . $languages_id . "'"); } $attributes_values = tep_db_fetch_array($attributes); $sql_data_array = array('orders_id' => $insert_id, 'orders_products_id' => $order_products_id, 'products_options' => $attributes_values['products_options_name'], 'products_options_values' => $attributes_values['products_options_values_name'], 'options_values_price' => $attributes_values['options_values_price'], 'price_prefix' => $attributes_values['price_prefix']); tep_db_perform(TABLE_ORDERS_PRODUCTS_ATTRIBUTES, $sql_data_array); if ((DOWNLOAD_ENABLED == 'true') && isset($attributes_values['products_attributes_filename']) && tep_not_null($attributes_values['products_attributes_filename'])) { $sql_data_array = array('orders_id' => $insert_id, 'orders_products_id' => $order_products_id, 'orders_products_filename' => $attributes_values['products_attributes_filename'], 'download_maxdays' => $attributes_values['products_attributes_maxdays'], 'download_count' => $attributes_values['products_attributes_maxcount']); tep_db_perform(TABLE_ORDERS_PRODUCTS_DOWNLOAD, $sql_data_array); } } } } tep_session_register('cart_PayPal_IPN_ID'); $cart_PayPal_IPN_ID = $cartID . '-' . $insert_id; } } return false; } function process_button() { global $customer_id, $order, $languages_id, $currencies, $currency, $cart_PayPal_IPN_ID, $shipping; if (MODULE_PAYMENT_PAYPAL_IPN_CURRENCY == 'Selected Currency') { $my_currency = $currency; } else { $my_currency = substr(MODULE_PAYMENT_PAYPAL_IPN_CURRENCY, 5); } if (!in_array($my_currency, array('CAD', 'EUR', 'GBP', 'JPY', 'USD'))) { $my_currency = 'USD'; } $parameters = array(); if ( (MODULE_PAYMENT_PAYPAL_IPN_TRANSACTION_TYPE == 'Per Item') && (MODULE_PAYMENT_PAYPAL_IPN_EWP_STATUS == 'False') ) { $parameters['cmd'] = '_cart'; $parameters['upload'] = '1'; for ($i=0, $n=sizeof($order->products); $i<$n; $i++) { $item = $i+1; $tax_value = ($order->products[$i]['tax'] / 100) * $order->products[$i]['final_price']; $parameters['item_name_' . $item] = $order->products[$i]['name']; $parameters['amount_' . $item] = number_format($order->products[$i]['final_price'] * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency)); $parameters['tax_' . $item] = number_format($tax_value * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency)); $parameters['quantity_' . $item] = $order->products[$i]['qty']; if ($i == 0) { if (DISPLAY_PRICE_WITH_TAX == 'true') { $shipping_cost = $order->info['shipping_cost']; } else { $module = substr($shipping['id'], 0, strpos($shipping['id'], '_')); $shipping_tax = tep_get_tax_rate($GLOBALS[$module]->tax_class, $order->delivery['country']['id'], $order->delivery['zone_id']); $shipping_cost = $order->info['shipping_cost'] + tep_calculate_tax($order->info['shipping_cost'], $shipping_tax); } $parameters['shipping_' . $item] = number_format($shipping_cost * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency)); } if (isset($order->products[$i]['attributes'])) { for ($j=0, $n2=sizeof($order->products[$i]['attributes']); $j<$n2; $j++) { if (DOWNLOAD_ENABLED == 'true') { $attributes_query = "select popt.products_options_name, poval.products_options_values_name, pa.options_values_price, pa.price_prefix, pad.products_attributes_maxdays, pad.products_attributes_maxcount , pad.products_attributes_filename from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " . TABLE_PRODUCTS_ATTRIBUTES . " pa left join " . TABLE_PRODUCTS_ATTRIBUTES_DOWNLOAD . " pad on pa.products_attributes_id=pad.products_attributes_id where pa.products_id = '" . $order->products[$i]['id'] . "' and pa.options_id = '" . $order->products[$i]['attributes'][$j]['option_id'] . "' and pa.options_id = popt.products_options_id and pa.options_values_id = '" . $order->products[$i]['attributes'][$j]['value_id'] . "' and pa.options_values_id = poval.products_options_values_id and popt.language_id = '" . $languages_id . "' and poval.language_id = '" . $languages_id . "'"; $attributes = tep_db_query($attributes_query); } else { $attributes = tep_db_query("select popt.products_options_name, poval.products_options_values_name, pa.options_values_price, pa.price_prefix from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " . TABLE_PRODUCTS_ATTRIBUTES . " pa where pa.products_id = '" . $order->products[$i]['id'] . "' and pa.options_id = '" . $order->products[$i]['attributes'][$j]['option_id'] . "' and pa.options_id = popt.products_options_id and pa.options_values_id = '" . $order->products[$i]['attributes'][$j]['value_id'] . "' and pa.options_values_id = poval.products_options_values_id and popt.language_id = '" . $languages_id . "' and poval.language_id = '" . $languages_id . "'"); } $attributes_values = tep_db_fetch_array($attributes); // Unfortunately PayPal only accepts two attributes per product, so the// third attribute onwards will not be shown at PayPal $parameters['on' . $j . '_' . $item] = $attributes_values['products_options_name']; $parameters['os' . $j . '_' . $item] = $attributes_values['products_options_values_name']; } } } $parameters['num_cart_items'] = $item; } else { $parameters['cmd'] = '_xclick'; $parameters['item_name'] = STORE_NAME; $parameters['shipping'] = number_format($order->info['shipping_cost'] * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency)); $parameters['tax'] = number_format($order->info['tax'] * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency)); } $parameters['business'] = MODULE_PAYMENT_PAYPAL_IPN_ID; $parameters['amount'] = number_format(($order->info['total'] - $order->info['shipping_cost'] - $order->info['tax']) * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency)); $parameters['currency_code'] = $my_currency; $parameters['invoice'] = substr($cart_PayPal_IPN_ID, strpos($cart_PayPal_IPN_ID, '-')+1); $parameters['custom'] = $customer_id; $parameters['no_shipping'] = '1'; $parameters['no_note'] = '1'; $paramerers['cbt'] = 'YOU MUST CLICK HERE TO COMPLETE YOUR ORDER'; $parameters['notify_url'] = tep_href_link('ext/modules/payment/paypal_ipn/ipn.php', '', 'SSL', false, false); $parameters['return'] = tep_href_link(FILENAME_CHECKOUT_PROCESS, '', 'SSL'); $parameters['cancel_return'] = tep_href_link(FILENAME_CHECKOUT_PAYMENT, '', 'SSL'); $parameters['bn'] = $this->identifier; if (tep_not_null(MODULE_PAYMENT_PAYPAL_IPN_PAGE_STYLE)) { $parameters['page_style'] = MODULE_PAYMENT_PAYPAL_IPN_PAGE_STYLE; } if (MODULE_PAYMENT_PAYPAL_IPN_EWP_STATUS == 'True') { $parameters['cert_id'] = MODULE_PAYMENT_PAYPAL_IPN_EWP_CERT_ID; $random_string = rand(100000, 999999) . '-' . $customer_id . '-'; $data = ''; while (list($key, $value) = each($parameters)) { $data .= $key . '=' . $value . "\n"; } $fp = fopen(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'data.txt', 'w'); fwrite($fp, $data); fclose($fp); unset($data); if (function_exists('openssl_pkcs7_sign') && function_exists('openssl_pkcs7_encrypt')) { openssl_pkcs7_sign(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'data.txt', MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'signed.txt', file_get_contents(MODULE_PAYMENT_PAYPAL_IPN_EWP_PUBLIC_KEY), file_get_contents(MODULE_PAYMENT_PAYPAL_IPN_EWP_PRIVATE_KEY), array('From' => MODULE_PAYMENT_PAYPAL_IPN_ID), PKCS7_BINARY); unlink(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'data.txt'); // remove headers from the signature $signed = file_get_contents(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'signed.txt'); $signed = explode("\n\n", $signed); $signed = base64_decode($signed[1]); $fp = fopen(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'signed.txt', 'w'); fwrite($fp, $signed); fclose($fp); unset($signed); openssl_pkcs7_encrypt(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'signed.txt', MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'encrypted.txt', file_get_contents(MODULE_PAYMENT_PAYPAL_IPN_EWP_PAYPAL_KEY), array('From' => MODULE_PAYMENT_PAYPAL_IPN_ID), PKCS7_BINARY); unlink(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'signed.txt'); // remove headers from the encrypted result $data = file_get_contents(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'encrypted.txt'); $data = explode("\n\n", $data); $data = '-----BEGIN PKCS7-----' . "\n" . $data[1] . "\n" . '-----END PKCS7-----'; unlink(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'encrypted.txt'); } else { exec(MODULE_PAYMENT_PAYPAL_IPN_EWP_OPENSSL . ' smime -sign -in ' . MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'data.txt -signer ' . MODULE_PAYMENT_PAYPAL_IPN_EWP_PUBLIC_KEY . ' -inkey ' . MODULE_PAYMENT_PAYPAL_IPN_EWP_PRIVATE_KEY . ' -outform der -nodetach -binary > ' . MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'signed.txt'); unlink(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'data.txt'); exec(MODULE_PAYMENT_PAYPAL_IPN_EWP_OPENSSL . ' smime -encrypt -des3 -binary -outform pem ' . MODULE_PAYMENT_PAYPAL_IPN_EWP_PAYPAL_KEY . ' < ' . MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'signed.txt > ' . MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'encrypted.txt'); unlink(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'signed.txt'); $fh = fopen(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'encrypted.txt', 'rb'); $data = fread($fh, filesize(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'encrypted.txt')); fclose($fh); unlink(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'encrypted.txt'); } $process_button_string = tep_draw_hidden_field('cmd', '_s-xclick') . tep_draw_hidden_field('encrypted', $data); unset($data); } else { while (list($key, $value) = each($parameters)) { echo tep_draw_hidden_field($key, $value); } } return $process_button_string; } function before_process() { global $customer_id, $order, $sendto, $billto, $payment, $currencies, $cart, $cart_PayPal_IPN_ID; global $$payment; include(DIR_WS_CLASSES . 'order_total.php'); $order_total_modules = new order_total; $order_totals = $order_total_modules->process(); $order_id = substr($cart_PayPal_IPN_ID, strpos($cart_PayPal_IPN_ID, '-')+1); $sql_data_array = array('orders_id' => $order_id, 'orders_status_id' => $order->info['order_status'], 'date_added' => 'now()', 'customer_notified' => (SEND_EMAILS == 'true') ? '1' : '0',&n Quote Link to comment Share on other sites More sharing options...
trogette Posted May 21, 2006 Share Posted May 21, 2006 Is the low stock report update in the QTPro download not sufficient? It only shows the stock under the limit in the reorder level part of the stock section of the configuration box, so you could raise that level to whatever your highest stock level would be I suppose. Quote Link to comment Share on other sites More sharing options...
Guest Posted May 22, 2006 Share Posted May 22, 2006 Could someone tell me if it is possible in the near future that there might be a qtpro version to work with CCGV? I have a client that wants both. Or is it possible that there is a similar contribute that will work with CCGV? Just wondering? :thumbsup: Thanks Shelby Quote Link to comment Share on other sites More sharing options...
chooch Posted May 22, 2006 Share Posted May 22, 2006 (edited) Could someone tell me if it is possible in the near future that there might be a qtpro version to work with CCGV? I have a client that wants both. Or is it possible that there is a similar contribute that will work with CCGV? Just wondering? :thumbsup: Thanks Shelby QTPro and CCGV already work together. Edited May 22, 2006 by chooch Quote Upon receiving fixes and advice, too many people don't bother to post updates informing the forum of how it went. Until of course they need help again on other issues and they come running back! Why receive the information you require in good faith for free, only to then have the attitude to ignore the people who gave it to you? There's no harm in saying, 'Thanks, it worked'. On the contrary, it creates a better atmosphere. CHOOCH Link to comment Share on other sites More sharing options...
Terra Posted May 22, 2006 Share Posted May 22, 2006 Could someone tell me if it is possible in the near future that there might be a qtpro version to work with CCGV? I have a client that wants both. Or is it possible that there is a similar contribute that will work with CCGV? Just wondering? :thumbsup: Thanks Shelby Yeap, they work fine. I'm using Vger's CCGV (trad) with QTPro, no problems. You just need to make the file amendments manually, but with a file comparison program (e.g. Winmerge), that's quickly done. all the best, Edith Quote My code for combining PayPal IPN with ** QTPro 4.25 ** osC Affiliate ** CCGV(trad) and how to solve the invoice already paid error General info: Allow customer to delete order comment ** FTP Programs & Text Editors ** Amending order email ** Link to comment Share on other sites More sharing options...
freefall1 Posted May 22, 2006 Share Posted May 22, 2006 Hi all, I want to use qtPro combined with an " add multiple products" contrib (don't care wch one). I can't manage to get this off the ground. Any sugenstions? Quote Link to comment Share on other sites More sharing options...
freefall1 Posted May 22, 2006 Share Posted May 22, 2006 Hi all, I want to use qtPro combined with an " add multiple products" contrib (don't care wch one). I can't manage to get this off the ground. Any sugenstions? Thnx Mark Quote Link to comment Share on other sites More sharing options...
chooch Posted May 22, 2006 Share Posted May 22, 2006 Hi all, I want to use qtPro combined with an " add multiple products" contrib (don't care wch one). I can't manage to get this off the ground. Any sugenstions? Does the 'add multiple products' have a support thread? You can try checking there to see what the state of play is with regards to compatibilty with QTPro too. There are so many (attributes/stock and so on) contributions but I can't see one that is perfect to use alongside QTPro with easy integration for what you want. I suppose it's trial and error - just give it a go and update the results for us too. Quote Upon receiving fixes and advice, too many people don't bother to post updates informing the forum of how it went. Until of course they need help again on other issues and they come running back! Why receive the information you require in good faith for free, only to then have the attitude to ignore the people who gave it to you? There's no harm in saying, 'Thanks, it worked'. On the contrary, it creates a better atmosphere. CHOOCH Link to comment Share on other sites More sharing options...
freefall1 Posted May 23, 2006 Share Posted May 23, 2006 Does the 'add multiple products' have a support thread? You can try checking there to see what the state of play is with regards to compatibilty with QTPro too. There are so many (attributes/stock and so on) contributions but I can't see one that is perfect to use alongside QTPro with easy integration for what you want. I suppose it's trial and error - just give it a go and update the results for us too. Well.... thnx anyway ... I will find a solution (it's between me and osc now... and I will succeed.... well ...so I hope) If I'll find the solution, I'll let u know Quote Link to comment Share on other sites More sharing options...
cbsezer Posted May 23, 2006 Share Posted May 23, 2006 The most common cause of "cannot redeclare" errors is to accidentally copy a root level file into the language level. I'd therefore recommend to check your language level files you recently updated - if this is not the cause, please post back. all the best, Terra :D Thanks Terra, you have been a great help, I solved problem, as you sad the QT pro contr was trying to show a left coloumn with categories in it. But the original page allready had the categories coloumn. have a nice day :thumbsup: Bora Quote Michelle, ma belle, these are scripts that go together well !! Link to comment Share on other sites More sharing options...
chooch Posted May 29, 2006 Share Posted May 29, 2006 I have just posted two versions of the catalog/includes/classes/pad_base.php file They both show the actual attributes prices in QTPro. One shows all attributes prices and the other shows changes in price of attributes only. Hope people find it useful. Quote Upon receiving fixes and advice, too many people don't bother to post updates informing the forum of how it went. Until of course they need help again on other issues and they come running back! Why receive the information you require in good faith for free, only to then have the attitude to ignore the people who gave it to you? There's no harm in saying, 'Thanks, it worked'. On the contrary, it creates a better atmosphere. CHOOCH Link to comment Share on other sites More sharing options...
bczippy Posted May 30, 2006 Share Posted May 30, 2006 Need a little help. I am running a CRELOADED 6.15 site, and trying to integrate this into my site. I have been able to integrate and wade through most of it, but I am having a problem. My product_info page will only display a single_dropdown menu, even though the database and admin section all have single_radioset selected. Don't know if i need to modify the pad_ files. I did initially get the "illegal foreach() on line 388" error, and fixed that by moving the "$out .=" line above the closing brace, but other than that, I haven't been able to locate a reason why it won't populate it as a radioset instead of a dropdown. Any help would be greatly appreciated. Bczippy Quote Link to comment Share on other sites More sharing options...
chooch Posted May 31, 2006 Share Posted May 31, 2006 Need a little help. I am running a CRELOADED 6.15 site, and trying to integrate this into my site. I have been able to integrate and wade through most of it, but I am having a problem. My product_info page will only display a single_dropdown menu, even though the database and admin section all have single_radioset selected. Don't know if i need to modify the pad_ files. I did initially get the "illegal foreach() on line 388" error, and fixed that by moving the "$out .=" line above the closing brace, but other than that, I haven't been able to locate a reason why it won't populate it as a radioset instead of a dropdown. Any help would be greatly appreciated. Bczippy Without knowing the state of play with creloaded coding it's really hard to answer. Have you tried the creloaded forums? Quote Upon receiving fixes and advice, too many people don't bother to post updates informing the forum of how it went. Until of course they need help again on other issues and they come running back! Why receive the information you require in good faith for free, only to then have the attitude to ignore the people who gave it to you? There's no harm in saying, 'Thanks, it worked'. On the contrary, it creates a better atmosphere. CHOOCH Link to comment Share on other sites More sharing options...
cbsezer Posted June 1, 2006 Share Posted June 1, 2006 (edited) Hi beautifull people of oscommerce, I have installed QTPro and it works fine, no offend but when I saw how long it took to add a product such as a T-shirt I kinda got dissapointed. I tried to use EasyPopulate together so perhaps I could manage the whole adding uploading updating process was easier but no.. this time I found out easypopulate does not provide extra coloumns in the exel sheet for extra Quantities (size,color) I nosed the BIG forum and saw that many people have the same complaintments. I call this the DILLEMA of the T-SHIRT STORE OWNER. and suddenly it pop'd .. I thought "some smart guy should be able to create a version of the contribution for the T-shirt people!!!" I mean my god it would be so much easier if it was like in the image below.. dont ya think!? I would appriciate that soOOOooo much!!! B) :thumbsup: Edited June 1, 2006 by cbsezer Quote Michelle, ma belle, these are scripts that go together well !! Link to comment Share on other sites More sharing options...
chooch Posted June 1, 2006 Share Posted June 1, 2006 (edited) I can't anyone actually making what you require especially for you, but there are people who have posted here in this thread who are using QTPro and easypopulate combined. I have seen there is one particular download that states it works with 'QTPro' amongst other contributions. Try using that one and see if it is to your requirements. Edited June 1, 2006 by chooch Quote Upon receiving fixes and advice, too many people don't bother to post updates informing the forum of how it went. Until of course they need help again on other issues and they come running back! Why receive the information you require in good faith for free, only to then have the attitude to ignore the people who gave it to you? There's no harm in saying, 'Thanks, it worked'. On the contrary, it creates a better atmosphere. CHOOCH Link to comment Share on other sites More sharing options...
cbsezer Posted June 1, 2006 Share Posted June 1, 2006 I can't anyone actually making what you require especially for you, but there are people who have posted here in this thread who are using QTPro and easypopulate combined. I have seen there is one particular download that states it works with 'QTPro' amongst other contributions. Try using that one and see if it is to your requirements. Hi Chooch, You are right, the two work together fine in many ways, but in my condition which is adding Quantities for diffrent colors and sizes, there is no such option. Perhaps I should unite the members who have the same problem and pursuade them to sponsor a version for the contribution. :rolleyes: Quote Michelle, ma belle, these are scripts that go together well !! Link to comment Share on other sites More sharing options...
chooch Posted June 1, 2006 Share Posted June 1, 2006 Perhaps I should unite the members who have the same problem and pursuade them to sponsor a version for the contribution. Good Luck, I hope you don't forget to post an update if you manage to find a fix. Quote Upon receiving fixes and advice, too many people don't bother to post updates informing the forum of how it went. Until of course they need help again on other issues and they come running back! Why receive the information you require in good faith for free, only to then have the attitude to ignore the people who gave it to you? There's no harm in saying, 'Thanks, it worked'. On the contrary, it creates a better atmosphere. CHOOCH Link to comment Share on other sites More sharing options...
trogette Posted June 2, 2006 Share Posted June 2, 2006 oh yes absolutely I want that, in fact I was going to have a play with the stock page for that purpose. I use ajax attribute manager to add the attributes to the product and I did suggest on that thread it would be really useful to be able to add stock in that way, don't know if that's been followed up at all, will go check... Quote Link to comment Share on other sites More sharing options...
cbsezer Posted June 2, 2006 Share Posted June 2, 2006 oh yes absolutely I want that, in fact I was going to have a play with the stock page for that purpose. I use ajax attribute manager to add the attributes to the product and I did suggest on that thread it would be really useful to be able to add stock in that way, don't know if that's been followed up at all, will go check... :thumbsup: Cool trogette , you see, we're allready two persons, only if the rest knew, lets first get crowded! I think I'm gonna send messages to members like us. by the way please let me know if the ajax contribution got evolved in our direction. Bora Quote Michelle, ma belle, these are scripts that go together well !! Link to comment Share on other sites More sharing options...
trogette Posted June 2, 2006 Share Posted June 2, 2006 nimmit who wrote it in the first place is working on a rewrite, I dunno where he is with it. It's a lovely thing to use and install though, I strongly recommend it. Quote Link to comment Share on other sites More sharing options...
Guest Posted June 3, 2006 Share Posted June 3, 2006 Hi, The site I'm currently building requires QTPro and Easy Populate with stock control. I've managed to get the stock upload to work with one attribute option. Having looked at the forum it seems that this is the best you can get. I'm using QTPro.v4.25 with EP_v2_76_MS2_1. As the site is launching soon I'm going to have to run with a compromise. The site products have 2 attributes - size and colour. I'm loading each colour as a separate product and then using size as the only attribute option. This is far from ideal - I'd love to find a proper solution. I've seen enough posts on this issue "stock control with QTPro and Easy Populate" to think it justifies a separate topic on the forum. I still have one problem before I launch my site - I can't get the attribute option stock values to appear in my EP download - has anyone achieved this? Regards Rhys Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.