Example #1
0
/**
 * shopp_add_product_download
 *
 * Add product download file to a product/variation.
 *
 * @api
 * @since 1.2
 *
 * @param int $product id of the product the download asset will be added to
 * @param string $file full or correct relative path to the download file asset.
 * @param int $variant id of the variant the download asset will be attached to.  For products with variants, this is a required parameter.
 * @return mixed false of failure, the new download asset id on success
 **/
function shopp_add_product_download($product, $file, $variant = false)
{
    if (empty($product) || empty($file)) {
        shopp_debug(__FUNCTION__ . ' failed: One or more missing parameters.');
        return false;
    }
    $File = new ProductDownload();
    $instore = $File->found($file);
    if (!$instore && (!is_file($file) || !is_readable($file))) {
        shopp_debug(__FUNCTION__ . " failed for file {$file}: File missing or unreadable.");
        return false;
    }
    $Product = new ShoppProduct($product);
    if (empty($Product->id)) {
        shopp_debug(__FUNCTION__ . " failed for file {$file}: No such product with id {$product}.");
        return false;
    }
    $Product->load_data(array('summary', 'prices'));
    if ("on" == $Product->variants && false === $variant) {
        shopp_debug(__FUNCTION__ . " failed for file {$file}: You must specify the variant id parameter for product {$product}.");
        return false;
    }
    $Price = reset($Product->prices);
    if (empty($Price->id)) {
        shopp_debug(__FUNCTION__ . " failed for file {$file}: Failed to load product variants.");
        return false;
    }
    if ($variant) {
        $Price = false;
        foreach ($Product->prices as $Price) {
            if ($variant == $Price->id) {
                break;
            }
        }
        if (false === $Price) {
            shopp_debug(__FUNCTION__ . " failed for file {$file}: You must specify a valid variant id parameter for product {$product}.");
            return false;
        }
    }
    // Save the uploaded file
    $File->load(array('type' => 'download', 'parent' => $Price->id));
    $File->parent = $Price->id;
    $File->context = "price";
    $File->type = "download";
    $File->name = basename($file);
    $File->filename = $File->name;
    if (!$instore) {
        $File->mime = file_mimetype($file, $File->name);
        $File->size = filesize($file);
        $File->store($file, 'file');
    } else {
        $File->uri = $file;
        $File->readmeta();
    }
    $File->save();
    if ($File->id) {
        return $File->id;
    }
    shopp_debug(__FUNCTION__ . " failed for file {$file}");
    return false;
}
Example #2
0
 /**
  * Handles saving updates from the product editor
  *
  * Saves all product related information which includes core product data
  * and supporting elements such as images, digital downloads, tags,
  * assigned categories, specs and pricing variations.
  *
  * @author Jonathan Davis
  * @since 1.0
  *
  * @param Product $Product
  * @return void
  **/
 public function save(ShoppProduct $Product)
 {
     check_admin_referer('shopp-save-product');
     if (!current_user_can('shopp_products')) {
         wp_die(__('You do not have sufficient permissions to access this page.'));
     }
     ShoppSettings()->saveform();
     // Save workflow setting
     $status = $Product->status;
     // Set publish date
     if ('publish' == $_POST['status']) {
         $publishing = isset($_POST['publish']) ? $_POST['publish'] : array();
         $fields = array('month' => '', 'date' => '', 'year' => '', 'hour' => '', 'minute' => '', 'meridiem' => '');
         $publishdate = join('', array_merge($fields, $publishing));
         if (!empty($publishdate)) {
             $publish =& $_POST['publish'];
             if ($publish['meridiem'] == "PM" && $publish['hour'] < 12) {
                 $publish['hour'] += 12;
             }
             $publish = mktime($publish['hour'], $publish['minute'], 0, $publish['month'], $publish['date'], $publish['year']);
             $Product->status = 'future';
             unset($_POST['status']);
         } else {
             unset($_POST['publish']);
             // Auto set the publish date if not set (or more accurately, if set to an irrelevant timestamp)
             if ($Product->publish <= 86400) {
                 $Product->publish = null;
             }
         }
     } else {
         unset($_POST['publish']);
         $Product->publish = 0;
     }
     // Set a unique product slug
     if (empty($Product->slug)) {
         $Product->slug = sanitize_title($_POST['name']);
     }
     $Product->slug = wp_unique_post_slug($Product->slug, $Product->id, $Product->status, ShoppProduct::posttype(), 0);
     $Product->featured = 'off';
     if (isset($_POST['content'])) {
         $_POST['description'] = $_POST['content'];
     }
     $Product->updates($_POST, array('meta', 'categories', 'prices', 'tags'));
     do_action('shopp_pre_product_save');
     $Product->save();
     // Remove deleted images
     if (!empty($_POST['deleteImages'])) {
         $deletes = array();
         if (strpos($_POST['deleteImages'], ",") !== false) {
             $deletes = explode(',', $_POST['deleteImages']);
         } else {
             $deletes = array($_POST['deleteImages']);
         }
         $Product->delete_images($deletes);
     }
     // Update image data
     if (!empty($_POST['images']) && is_array($_POST['images'])) {
         $Product->link_images($_POST['images']);
         $Product->save_imageorder($_POST['images']);
         if (!empty($_POST['imagedetails'])) {
             $Product->update_images($_POST['imagedetails']);
         }
     }
     // Update Prices
     if (!empty($_POST['price']) && is_array($_POST['price'])) {
         // Delete prices that were marked for removal
         if (!empty($_POST['deletePrices'])) {
             $deletes = array();
             if (strpos($_POST['deletePrices'], ",")) {
                 $deletes = explode(',', $_POST['deletePrices']);
             } else {
                 $deletes = array($_POST['deletePrices']);
             }
             foreach ($deletes as $option) {
                 $Price = new ShoppPrice($option);
                 $Price->delete();
             }
         }
         $Product->resum();
         // Save prices that there are updates for
         foreach ($_POST['price'] as $i => $priceline) {
             if (empty($priceline['id'])) {
                 $Price = new ShoppPrice();
                 $priceline['product'] = $Product->id;
             } else {
                 $Price = new ShoppPrice($priceline['id']);
             }
             $priceline['sortorder'] = array_search($i, $_POST['sortorder']) + 1;
             $priceline['shipfee'] = Shopp::floatval($priceline['shipfee']);
             if (isset($priceline['recurring']['trialprice'])) {
                 $priceline['recurring']['trialprice'] = Shopp::floatval($priceline['recurring']['trialprice']);
             }
             if ($Price->stock != $priceline['stocked']) {
                 $priceline['stock'] = (int) $priceline['stocked'];
                 do_action('shopp_stock_product', $priceline['stock'], $Price, $Price->stock, $Price->stocklevel);
             } else {
                 unset($priceline['stocked']);
             }
             $Price->updates($priceline);
             $Price->save();
             // Save 'price' meta records after saving the price record
             if (isset($priceline['dimensions']) && is_array($priceline['dimensions'])) {
                 $priceline['dimensions'] = array_map(array('Shopp', 'floatval'), $priceline['dimensions']);
             }
             $settings = array('donation', 'recurring', 'membership', 'dimensions');
             $priceline['settings'] = array();
             foreach ($settings as $setting) {
                 if (!isset($priceline[$setting])) {
                     continue;
                 }
                 $priceline['settings'][$setting] = $priceline[$setting];
             }
             if (!empty($priceline['settings'])) {
                 shopp_set_meta($Price->id, 'price', 'settings', $priceline['settings']);
             }
             if (!empty($priceline['options'])) {
                 shopp_set_meta($Price->id, 'price', 'options', $priceline['options']);
             }
             $Product->sumprice($Price);
             if (!empty($priceline['download'])) {
                 $Price->attach_download($priceline['download']);
             }
             if (!empty($priceline['downloadpath'])) {
                 // Attach file specified by URI/path
                 if (!empty($Price->download->id) || empty($Price->download) && $Price->load_download()) {
                     $File = $Price->download;
                 } else {
                     $File = new ProductDownload();
                 }
                 $stored = false;
                 $tmpfile = sanitize_path($priceline['downloadpath']);
                 $File->storage = false;
                 $Engine = $File->engine();
                 // Set engine from storage settings
                 $File->parent = $Price->id;
                 $File->context = "price";
                 $File->type = "download";
                 $File->name = !empty($priceline['downloadfile']) ? $priceline['downloadfile'] : basename($tmpfile);
                 $File->filename = $File->name;
                 if ($File->found($tmpfile)) {
                     $File->uri = $tmpfile;
                     $stored = true;
                 } else {
                     $stored = $File->store($tmpfile, 'file');
                 }
                 if ($stored) {
                     $File->readmeta();
                     $File->save();
                 }
             }
             // END attach file by path/uri
         }
         // END foreach()
         unset($Price);
     }
     // END if (!empty($_POST['price']))
     $Product->load_sold($Product->id);
     // Refresh accurate product sales stats
     $Product->sumup();
     // Update taxonomies after pricing summary is generated
     // Summary table entry is needed for ProductTaxonomy::recount() to
     // count properly based on aggregate product inventory, see #2968
     foreach (get_object_taxonomies(Product::$posttype) as $taxonomy) {
         $tags = '';
         $taxonomy_obj = get_taxonomy($taxonomy);
         if (isset($_POST['tax_input']) && isset($_POST['tax_input'][$taxonomy])) {
             $tags = $_POST['tax_input'][$taxonomy];
             if (is_array($tags)) {
                 // array = hierarchical, string = non-hierarchical.
                 $tags = array_filter($tags);
             }
         }
         if (current_user_can($taxonomy_obj->cap->assign_terms)) {
             wp_set_post_terms($Product->id, $tags, $taxonomy);
         }
     }
     // Ensure taxonomy counts are updated on status changes, see #2968
     if ($status != $_POST['status']) {
         $Post = new StdClass();
         $Post->ID = $Product->id;
         $Post->post_type = ShoppProduct::$posttype;
         wp_transition_post_status($_POST['status'], $Product->status, $Post);
     }
     if (!empty($_POST['meta']['options'])) {
         $_POST['meta']['options'] = stripslashes_deep($_POST['meta']['options']);
     } else {
         $_POST['meta']['options'] = false;
     }
     // No variation options at all, delete all variation-pricelines
     if (!empty($Product->prices) && is_array($Product->prices) && (empty($_POST['meta']['options']['v']) || empty($_POST['meta']['options']['a']))) {
         foreach ($Product->prices as $priceline) {
             // Skip if not tied to variation options
             if ($priceline->optionkey == 0) {
                 continue;
             }
             if (empty($_POST['meta']['options']['v']) && $priceline->context == "variation" || empty($_POST['meta']['options']['a']) && $priceline->context == "addon") {
                 $Price = new ShoppPrice($priceline->id);
                 $Price->delete();
             }
         }
     }
     // Handle product spec/detail data
     if (!empty($_POST['details']) || !empty($_POST['deletedSpecs'])) {
         // Delete specs queued for removal
         $ids = array();
         $deletes = array();
         if (!empty($_POST['deletedSpecs'])) {
             if (strpos($_POST['deleteImages'], ",") !== false) {
                 $deletes = explode(',', $_POST['deleteImages']);
             } else {
                 $deletes = array($_POST['deletedSpecs']);
             }
             $ids = db::escape($_POST['deletedSpecs']);
             $Spec = new Spec();
             db::query("DELETE FROM {$Spec->_table} WHERE id IN ({$ids})");
         }
         if (is_array($_POST['details'])) {
             foreach ($_POST['details'] as $i => $spec) {
                 if (in_array($spec['id'], $deletes)) {
                     continue;
                 }
                 if (isset($spec['new'])) {
                     $Spec = new Spec();
                     $spec['id'] = '';
                     $spec['parent'] = $Product->id;
                 } else {
                     $Spec = new Spec($spec['id']);
                 }
                 $spec['sortorder'] = array_search($i, $_POST['details-sortorder']) + 1;
                 $Spec->updates($spec);
                 $Spec->save();
             }
         }
     }
     // Save any meta data
     if (isset($_POST['meta']) && is_array($_POST['meta'])) {
         foreach ($_POST['meta'] as $name => $value) {
             if (isset($Product->meta[$name])) {
                 $Meta = $Product->meta[$name];
                 if (is_array($Meta)) {
                     $Meta = reset($Product->meta[$name]);
                 }
             } else {
                 $Meta = new ShoppMetaObject(array('parent' => $Product->id, 'context' => 'product', 'type' => 'meta', 'name' => $name));
             }
             $Meta->parent = $Product->id;
             $Meta->name = $name;
             $Meta->value = $value;
             $Meta->save();
         }
     }
     $Product->load_data();
     // Reload data so everything is fresh for shopp_product_saved
     do_action_ref_array('shopp_product_saved', array(&$Product));
     unset($Product);
 }
Example #3
0
 public function import_file()
 {
     check_admin_referer('wp_ajax_shopp_import_file');
     $Shopp = Shopp::object();
     $Engine =& $Shopp->Storage->engines['download'];
     $error = create_function('$s', 'die(json_encode(array("error" => $s)));');
     if (empty($_REQUEST['url'])) {
         $error(__('No file import URL was provided.', 'Shopp'));
     }
     $url = $_REQUEST['url'];
     $request = parse_url($url);
     $headers = array();
     $filename = basename($request['path']);
     $_ = new StdClass();
     $_->name = $filename;
     $_->stored = false;
     $File = new ProductDownload();
     $stored = false;
     $File->engine();
     // Set engine from storage settings
     $File->uri = sanitize_path($url);
     $File->type = "download";
     $File->name = $filename;
     $File->filename = $filename;
     if ($File->found()) {
         // File in storage, look up meta from storage engine
         $File->readmeta();
         $_->stored = true;
         $_->path = $File->uri;
         $_->size = $File->size;
         $_->mime = $File->mime;
         if ($_->mime == "application/octet-stream" || $_->mime == "text/plain") {
             $mime = file_mimetype($File->name);
         }
         if ($mime == "application/octet-stream" || $mime == "text/plain") {
             $_->mime = $mime;
         }
     } else {
         if (!($importfile = @tempnam(sanitize_path(realpath(SHOPP_TEMP_PATH)), 'shp'))) {
             $error(sprintf(__('A temporary file could not be created for importing the file.', 'Shopp'), $importfile));
         }
         if (!($incoming = @fopen($importfile, 'w'))) {
             $error(sprintf(__('A temporary file at %s could not be opened for importing.', 'Shopp'), $importfile));
         }
         if (!($file = @fopen(linkencode($url), 'rb'))) {
             $error(sprintf(__('The file at %s could not be opened for importing.', 'Shopp'), $url));
         }
         $data = @stream_get_meta_data($file);
         if (isset($data['timed_out']) && $data['timed_out']) {
             $error(__('The connection timed out while trying to get information about the target file.', 'Shopp'));
         }
         if (isset($data['wrapper_data'])) {
             foreach ($data['wrapper_data'] as $d) {
                 if (strpos($d, ':') === false) {
                     continue;
                 }
                 list($name, $value) = explode(': ', $d);
                 if ($rel = strpos($value, ';')) {
                     $headers[$name] = substr($value, 0, $rel);
                 } else {
                     $headers[$name] = $value;
                 }
             }
         }
         $tmp = basename($importfile);
         // $Settings =& ShoppSettings();
         $_->path = $importfile;
         if (empty($headers)) {
             // Stat file data directly if no stream data available
             $_->size = filesize($url);
             $_->mime = file_mimetype($url);
         } else {
             // Use the stream data
             $_->size = $headers['Content-Length'];
             $_->mime = $headers['Content-Type'] == 'text/plain' ? file_mimetype($_->name) : $headers['Content-Type'];
         }
     }
     // Mimetype must be set or we'll have problems in the UI
     if (!$_->mime) {
         $_->mime = "application/octet-stream";
     }
     echo str_repeat(' ', 1024);
     // Minimum browser data
     echo '<script type="text/javascript">var importFile = ' . json_encode($_) . ';</script>' . "\n";
     echo '<script type="text/javascript">var importProgress = 0;</script>' . "\n";
     if ($_->stored) {
         exit;
     }
     @ob_flush();
     @flush();
     $progress = 0;
     $bytesread = 0;
     fseek($file, 0);
     $packet = 1024 * 1024;
     set_time_limit(0);
     // Prevent timeouts
     while (!feof($file)) {
         if (connection_status() !== 0) {
             return false;
         }
         $buffer = fread($file, $packet);
         if (!empty($buffer)) {
             fwrite($incoming, $buffer);
             $bytesread += strlen($buffer);
             echo '<script type="text/javascript">importProgress = ' . $bytesread / (int) $_->size . ';</script>' . "\n";
             @ob_flush();
             @flush();
         }
     }
     @ob_end_flush();
     fclose($file);
     fclose($incoming);
     exit;
 }
Example #4
0
	/**
	 * Handles saving updates from the product editor
	 *
	 * Saves all product related information which includes core product data
	 * and supporting elements such as images, digital downloads, tags,
	 * assigned categories, specs and pricing variations.
	 *	 
	 * @return void
	 **/
	function save_product ($Product) {
		$db = DB::get();
		$Settings = &EcartSettings();
		check_admin_referer('ecart-save-product');

		if ( !(is_ecart_userlevel() || current_user_can('ecart_products')) )
			wp_die(__('You do not have sufficient permissions to access this page.'));

		$Settings->saveform(); // Save workflow setting

		$base = $Settings->get('base_operations');
		$taxrate = 0;
		if ($base['vat']) $taxrate = ecart_taxrate(null,true,$Product);

		if (empty($_POST['options'])) $Product->options = array();
		else $_POST['options'] = stripslashes_deep($_POST['options']);

		if (empty($Product->slug)) $Product->slug = sanitize_title_with_dashes($_POST['name']);

		// Check for an existing product slug
		$exclude_product = !empty($Product->id)?"AND id != $Product->id":"";
		$existing = $db->query("SELECT slug FROM $Product->_table WHERE slug='$Product->slug' $exclude_product LIMIT 1");
		if ($existing) {
			$suffix = 2;
			while($existing) {
				$altslug = substr($Product->slug, 0, 200-(strlen($suffix)+1)). "-".$suffix++;
				$existing = $db->query("SELECT slug FROM $Product->_table WHERE slug='$altslug' $exclude_product LIMIT 1");
			}
			$Product->slug = $altslug;
		}

		if ($_POST['status'] == "publish") {
			$publishfields = array('month' => '','date' => '','year' => '','hour'=>'','minute'=>'','meridiem'=>'');
			$publishdate = join('',array_merge($publishfields,$_POST['publish']));
			if (!empty($publishdate)) {
				if ($_POST['publish']['meridiem'] == "PM" && $_POST['publish']['hour'] < 12)
					$_POST['publish']['hour'] += 12;
				$_POST['publish'] = mktime($_POST['publish']['hour'],$_POST['publish']['minute'],0,$_POST['publish']['month'],$_POST['publish']['date'],$_POST['publish']['year']);
			} else {
				unset($_POST['publish']);
				// Auto set the publish date if not set (or more accurately, if set to an irrelevant timestamp)
				if ($Product->publish <= 86400) $Product->publish = time();
			}
		} else {
			unset($_POST['publish']);
			$Product->publish = 0;
		}

		if (isset($_POST['content'])) $_POST['description'] = $_POST['content'];

		$Product->updates($_POST,array('categories','prices'));
		$Product->save();

		$Product->save_categories($_POST['categories']);
		$Product->save_tags(explode(",",$_POST['taglist']));

		if (!empty($_POST['price']) && is_array($_POST['price'])) {

			// Delete prices that were marked for removal
			if (!empty($_POST['deletePrices'])) {
				$deletes = array();
				if (strpos($_POST['deletePrices'],","))	$deletes = explode(',',$_POST['deletePrices']);
				else $deletes = array($_POST['deletePrices']);

				foreach($deletes as $option) {
					$Price = new Price($option);
					$Price->delete();
				}
			}

			// Save prices that there are updates for
			foreach($_POST['price'] as $i => $option) {
				if (empty($option['id'])) {
					$Price = new Price();
					$option['product'] = $Product->id;
				} else $Price = new Price($option['id']);
				$option['sortorder'] = array_search($i,$_POST['sortorder'])+1;

				// Remove VAT amount to save in DB
				if ($base['vat'] && isset($option['tax']) && $option['tax'] == "on") {
					$option['price'] = (floatvalue($option['price'])/(1+$taxrate));
					$option['saleprice'] = (floatvalue($option['saleprice'])/(1+$taxrate));
				}
				$option['shipfee'] = floatvalue($option['shipfee']);

				$option['weight'] = floatvalue($option['weight']);
				if (isset($options['dimensions']) && is_array($options['dimensions']))
					foreach ($option['dimensions'] as &$dimension)
						$dimension = floatvalue($dimension);

				$Price->updates($option);
				$Price->save();

				if (!empty($option['download'])) $Price->attach_download($option['download']);

				if (!empty($option['downloadpath'])) { // Attach file specified by URI/path
					if (!empty($Price->download->id) || (empty($Price->download) && $Price->load_download())) {
						$File = $Price->download;
					} else $File = new ProductDownload();

					$stored = false;
					$tmpfile = sanitize_path($option['downloadpath']);

					$File->storage = false;
					$Engine = $File->_engine(); // Set engine from storage settings

					$File->parent = $Price->id;
					$File->context = "price";
					$File->type = "download";
					$File->name = !empty($option['downloadfile'])?$option['downloadfile']:basename($tmpfile);
					$File->filename = $File->name;

					if ($File->found($tmpfile)) {
						$File->uri = $tmpfile;
						$stored = true;
					} else $stored = $File->store($tmpfile,'file');

					if ($stored) {
						$File->readmeta();
						$File->save();
					}

				} // END attach file by path/uri
			}
			unset($Price);
		}

		// No variation options at all, delete all variation-pricelines
		if (!empty($Product->prices) && is_array($Product->prices)
				&& (empty($_POST['options']['v']) || empty($_POST['options']['a']))) {
			foreach ($Product->prices as $priceline) {
				// Skip if not tied to variation options
				if ($priceline->optionkey == 0) continue;
				if ((empty($_POST['options']['v']) && $priceline->context == "variation")
					|| (empty($_POST['options']['a']) && $priceline->context == "addon")) {
						$Price = new Price($priceline->id);
						$Price->delete();
				}
			}
		}

		if (!empty($_POST['details']) || !empty($_POST['deletedSpecs'])) {
			$deletes = array();
			if (!empty($_POST['deletedSpecs'])) {
				if (strpos($_POST['deletedSpecs'],","))	$deletes = explode(',',$_POST['deletedSpecs']);
				else $deletes = array($_POST['deletedSpecs']);
				foreach($deletes as $option) {
					$Spec = new Spec($option);
					$Spec->delete();
				}
				unset($Spec);
			}

			if (is_array($_POST['details'])) {
				foreach ($_POST['details'] as $i => $spec) {
					if (in_array($spec['id'],$deletes)) continue;
					if (isset($spec['new'])) {
						$Spec = new Spec();
						$spec['id'] = '';
						$spec['parent'] = $Product->id;
					} else $Spec = new Spec($spec['id']);
					$spec['sortorder'] = array_search($i,$_POST['details-sortorder'])+1;

					$Spec->updates($spec);
					$Spec->save();
				}
			}
		}

		if (!empty($_POST['deleteImages'])) {
			$deletes = array();
			if (strpos($_POST['deleteImages'],","))	$deletes = explode(',',$_POST['deleteImages']);
			else $deletes = array($_POST['deleteImages']);
			$Product->delete_images($deletes);
		}

		if (!empty($_POST['images']) && is_array($_POST['images'])) {
			$Product->link_images($_POST['images']);
			$Product->save_imageorder($_POST['images']);
			if (!empty($_POST['imagedetails']))
				$Product->update_images($_POST['imagedetails']);
		}

		do_action_ref_array('ecart_product_saved',array(&$Product));

		unset($Product);
		return true;
	}
Example #5
0
	function import_file () {
		check_admin_referer('wp_ajax_ecart_import_file');
		global $Ecart;
		$Engine =& $Ecart->Storage->engines['download'];

		$error = create_function('$s', 'die(json_encode(array("error" => $s)));');
		if (empty($_REQUEST['url'])) $error(__('No file import URL was provided.','Ecart'));
		$url = $_REQUEST['url'];
		$request = parse_url($url);
		$headers = array();
		$filename = basename($request['path']);

		$_ = new StdClass();
		$_->name = $filename;
		$_->stored = false;


		$File = new ProductDownload();
		$stored = false;
		$File->_engine(); // Set engine from storage settings
		$File->uri = sanitize_path($url);
		$File->type = "download";
		$File->name = $filename;
		$File->filename = $filename;

		if ($File->found()) {
			// File in storage, look up meta from storage engine
			$File->readmeta();
			$_->stored = true;
			$_->path = $File->uri;
			$_->size = $File->size;
			$_->mime = $File->mime;
			if ($_->mime == "application/octet-stream" || $_->mime == "text/plain")
				$mime = file_mimetype($File->name);
			if ($mime == "application/octet-stream" || $mime == "text/plain")
				$_->mime = $mime;
		} else {
			if (!$importfile = @tempnam(sanitize_path(realpath(ECART_TEMP_PATH)), 'shp')) $error(sprintf(__('A temporary file could not be created for importing the file.','Ecart'),$importfile));
			if (!$incoming = @fopen($importfile,'w')) $error(sprintf(__('A temporary file at %s could not be opened for importing.','Ecart'),$importfile));

			if (!$file = @fopen(linkencode($url), 'rb')) $error(sprintf(__('The file at %s could not be opened for importing.','Ecart'),$url));
			$data = @stream_get_meta_data($file);

			if (isset($data['timed_out']) && $data['timed_out']) $error(__('The connection timed out while trying to get information about the target file.','Ecart'));

			if (isset($data['wrapper_data'])) {
				foreach ($data['wrapper_data'] as $d) {
					if (strpos($d,':') === false) continue;
					list($name,$value) = explode(': ',$d);
					if ($rel = strpos($value,';')) $headers[$name] = substr($value,0,$rel);
					else $headers[$name] = $value;
				}
			}

			$tmp = basename($importfile);
			$Settings =& EcartSettings();

			$_->path = $importfile;
			if (empty($headers)) {
				// Stat file data directly if no stream data available
				$_->size = filesize($url);
				$_->mime = file_mimetype($url);
			} else {
				// Use the stream data
				$_->size = $headers['Content-Length'];
				$_->mime = $headers['Content-Type'] == 'text/plain'?file_mimetype($_->name):$headers['Content-Type'];
			}
		}

		// Mimetype must be set or we'll have problems in the UI
		if (!$_->mime) $_->mime = "application/octet-stream";

		ob_end_clean();
		header("Connection: close");
		header("Content-Encoding: none");
		ob_start();
	 	echo json_encode($_);
		$size = ob_get_length();
		header("Content-Length: $size");
		ob_end_flush();
		flush();
		ob_end_clean();

		if ($_->stored) return;

		$progress = 0;
		fseek($file, 0);
		$packet = 1024*1024;
		while(!feof($file)) {
			if (connection_status() !== 0) return false;
			$buffer = fread($file,$packet);
			if (!empty($buffer)) {
				fwrite($incoming, $buffer);
				$progress += strlen($buffer);
				$Settings->save($tmp.'_import_progress',$progress);
			}
		}
		fclose($file);
		fclose($incoming);

		sleep(5);
		$Settings->delete($tmp.'_import_progress');

		exit();
	}