Index: /woo-cost-of-shipping/tags/1.5.5/README.txt
===================================================================
--- /woo-cost-of-shipping/tags/1.5.5/README.txt	(revision 3649833)
+++ /woo-cost-of-shipping/tags/1.5.5/README.txt	(revision 3649833)
@@ -0,0 +1,151 @@
+=== Cost of Shipping for WooCommerce ===
+Contributors:      TheRiteSites   
+Donate link:       https://www.theritesites.com/plugins/woo-cost-of-shipping  
+Tags:              cost of shipping, shipping cost, WooCommerce, net profit, shipstation
+Requires at least: 5.2
+Tested up to:      7.0
+Requires PHP:      7.0
+Stable tag:        trunk
+License:           GPLv2  
+License URI:       http://www.gnu.org/licenses/gpl-2.0.html  
+
+Allows the association of the cost of shipping to WooCommerce orders.
+
+== Description ==
+
+Tracking and analyzing the true profitability of your WooCommerce orders is not possible if you’re not including the cost of shipping. Most sites use a “Cost of Goods” plugin to analyze profit (sales less cost of goods), but this is not a true measure of profitability. The cost of shipping orders is significant, and in many businesses, it can be even more expensive than the cost of goods, so including the cost of shipping in your analysis is critical to running a successful eCommerce business.
+
+**NEW!** Using WooCommerce Services to buy your shipping labels? Well we have just made new functionality that allows amount spent on shipping to be imported directly into the order! The plugin will automatically do this if the labels have been purchased before the order is marked complete, or there is a manual import button found neatly on the right sidebar while editing orders. Whether you purchase one, multipls labels, or refund labels, we report the Cost of Shipping directly to you!
+
+After installing this plugin you’ll be able to manually add or adjust the cost of shipping for each order on the WooCommerce Edit Order page. **Better yet**, if you use ShipStation then the cost of shipping for each order will be automatically imported as your orders are shipped. If you ship multi-package orders, the total cost of all packages will be imported. If you void a ShipStation shipment and then reship (change shipping method, address, etc.), the new cost of shipping will be imported. It’s all automated and you’re going to love it!
+
+Once you start tracking the cost of shipping, you’ll want to use our [WooCommerce Net Profit](https://www.theritesites.com/plugins/woocommerce-net-profit) plugin that will give you beautiful, functional reports to fully analyze your profitability.
+
+**Do you use your income statement to track the cost of shipping?**
+Most eCommerce businesses do, but this just gives you a high level view of the overall profitability of your business. What’s missing is the ability to determine true profitability at the individual order level.
+
+For example: 
+* If you ship out of California, how does your profit on an order shipped to a customer in California compared to the same order shipped to a customer in New York?
+* How does your profit on an order that weighs 2 pounds compare to orders that weigh 5, 10 or 20 pounds?
+* If you offer free shipping on orders over a certain dollar amount ($50, $75, etc.), how does the profit on those orders compare to the profit on orders that you are charging a shipping fee?
+* How does your profit on a $25 order compare to your profit on a $50, $100 or $200 order?
+
+Only after you have the cost of shipping data at the order level can you make these comparisons (and more), and then make smart adjustments to the way you offer your products to maximize profitability. 
+
+== Installation ==
+
+=== Manual Installation ===
+
+1. Upload the entire `/woo-cost-of-shipping` directory to the `/wp-content/plugins/` directory.
+2. Activate Cost of Shipping for WooCommerce through the 'Plugins' menu in WordPress.
+3. Enjoy the easy editting of the cost of shipping in the edit order screen, below the order total.
+
+== Frequently Asked Questions ==
+= Cost of Shipping from ShipStation is not being saved or imported =
+There is a common issue we have found in the ShipStation Marketplace Configuration. Ensure your store does not have a redirect from http:// to https:// and also that the Marketplace on ShipStation matches the exact url and protocol. [Read more here](https://www.theritesites.com/docs/shipstation-not-importing-cost/)
+= The "Import shipping cost" button is not importing the data! =
+If you are seeing the "Import shipping cost" or "Re-import shipping cost" button, that means you have the WooCommerce Services plugin active. The only shipping costs that will be imported are from that plugin, no other integrations will import shipping costs using this button. (e.g. shipstation)
+= Are there any integrations? =
+Currently, we support the [ShipStation platform](https://woocommerce.com/products/shipstation-integration/), and the [WooCommerce Services](https://wordpress.org/plugins/woocommerce-services/), and are looking to extend that.
+= Is there any reporting tools to go along with this data? =
+We currently offer a [reporting plugin](https://www.theritesites.com/plugins/woocommerce-net-profit) that reports on your true cost of shipping and more at our website!
+
+== Screenshots ==
+1. A new field is added underneath the order items block, underneath the "Total" row, along with an edit button.
+2. Shows the JavaScript popup that allows you to manually edit the cost of shipping for this order.
+3. Shows the meta box on the right to import Cost of Shipping, the order note put in, and the Cost of Shipping
+4. Shows expanded meta box and pro tip about using the plugin to its potential
+5. Shows the new interface if WooCommerce Services plugin is activated
+
+== Changelog ==
+
+= 1.5.5 =
+- Changed: display name to "Cost of Shipping for WooCommerce" (was "WooCommerce Cost of Shipping"). Slug and installed directory are unchanged; this is a display-name-only change.
+- Changed: Plugin URI and Donate link now point at the plugin's real slug instead of the old trademarked path.
+- Fixed: text domain now matches the plugin slug.
+- Fixed: PHP 8.1+ deprecation notice on the safe XML parser's method return types.
+- Fixed: escaped order-ID attribute output and sanitized page-parameter reads flagged by wordpress.org's Plugin Check.
+- Security: hardened the admin AJAX handlers, the ShipStation import and the XML parser. No vulnerability was found; this is defense in depth. Updating is recommended.
+- Fixed: the cost of shipping method and change history were not being saved on orders. Existing order data is left as-is; new saves are correct.
+- Fixed: a possible fatal error when importing WooCommerce Services labels on some stores.
+- Fixed: a WooCommerce Services import that resolved to exactly 0.00 was reported as a failure.
+- Fixed: the order screen could show a cost of shipping as saved when the save had not succeeded.
+- Changed: order-screen strings are now translatable.
+
+= 1.5.4 =
+- Fixed: WooCommerce Services incompatibility caused crash in some stores on the order and analytics page.
+
+= 1.5.3 =
+- Fixed: Changed how conditional was checked to prevent debug potentially crashing administrative screen.
+
+= 1.5.2 =
+- Fixed: Changed how conditional was checked to prevent warning output in debug log.
+
+= 1.5.1 = 
+- Fixed: WooCommerce admin page changes prevented javascript enqueueing.
+
+= 1.5.0 =
+- WooCommerce High Performance Order Storage (HPOS) update
+
+= 1.4.2 =
+- Security update
+- Tested on recent WordPress and WooCommerce
+
+= 1.4.1 =
+- Security update
+
+= 1.4.0 =
+- Tweak: New function to work with the new more dynamic version of WooCommerce Net Profit.
+- Tweak: Changed some casting to float, to floatval() calls.
+- Tweak: Changed debug location to a more universal file for debugging TRS plugins.
+
+= 1.3.1 =
+- Fixed: links mispelled WooCommerce and are corrected to have the correct links.
+
+= 1.3.0 =
+- New: Order meta to store history of Cost of Shipping after the first store (no redundant data).
+- Tweak: Changed how Re-Import works when labels either previously existed or not when interacting with WooCommerce Services and Stamps labels.
+- Tweak: Disabled buttons while waiting on manual Cost of Shipping change.
+- Fixed: Matched WooCommerce Order table spacing for Total Cost of Shipping Width.
+
+= 1.2.0 =
+- New: Added automated imports of WooCommerce Services Shipping Labels Cost of Shipping!
+- Tweak: Changed how tooltip chooses to appear on different browsers to match Cost of Goods for WooCommerce's approach (CSS)
+- Fixed: Bug where previous cost of shipping would not appear in manual entry tooltip
+
+= 1.1.0 =
+- New: Added Order Note when Cost of Shipping is changed
+- Tweak: Isolated JavaScript into its own file rather than enqueued into the footer
+
+= 1.0.1 =
+- Tweak: Changed how WooCommerce active check is handled to correctly show error message and deactivate plugin when WooCommerce not found
+
+= 1.0.0 =
+- First release
+- Reads in manual entries for cost of shipping
+- Automatically reads in the cost of shipping on an order if you currently use the ShipStation plugin and platform
+
+== Upgrade Notice ==
+
+= 1.4.1 =
+- Security update
+
+= 1.4.0 =
+- New capabilities to integrate with reporting
+
+= 1.2.0 =
+- New capabilities to integrate with WooCommerce Services
+
+= 1.1.0 =
+- New JavaScript file
+- New Order Note data when Cost of Shipping is updated
+
+= 1.0.2 =
+- Update repository structure
+- Tested new versions of wordpress and woocommerce
+
+= 1.0.1 =
+- Updated README
+
+= 1.0.0 =
+- First Release
Index: /woo-cost-of-shipping/tags/1.5.5/assets/css/woocommerce-cost-of-shipping.css
===================================================================
--- /woo-cost-of-shipping/tags/1.5.5/assets/css/woocommerce-cost-of-shipping.css	(revision 3649833)
+++ /woo-cost-of-shipping/tags/1.5.5/assets/css/woocommerce-cost-of-shipping.css	(revision 3649833)
@@ -0,0 +1,61 @@
+/**
+ * WooCommerce Cost of Shipping
+ * https://www.theritesites.com/plugins/woocomerce-cost-of-shipping
+ *
+ * This plugin can be expanded into net profit reporting by getting the WooCommerce Net Profit plugin
+ * developed by TheRiteSites and found at https://www.theritesites.com/plugins/woocommerce-net-profit 
+ * 
+ * Copyright (c) 2018 TheRiteSites
+ * Licensed under the GPLv2+ license.
+ */
+
+#shipping-cost {
+    position: relative;
+}
+
+.edit-shipping-tooltip {
+    position: absolute;
+    background-color: #23282D;
+    border-radius: 3px;
+    text-align: center;
+    box-shadow: 2px 4px 3px 4px rgba(0,0,0,.2);
+    padding: 4px;
+    right: -2em;
+    top: 2em;
+    z-index: 2;
+}
+
+.edit-shipping-buttons {
+    margin-top: 4px;
+}
+
+#edit-shipping-save {
+    width: 64px;
+    margin-left: 5%;
+}
+
+.edit-shipping-tooltip:after {
+    content: '';
+    position: absolute;
+    bottom: 100%;
+    left: 65%;
+    right: 0;
+    margin: 0 auto;
+    height: 0;
+    width: 0;
+    border-left: 8px solid transparent;
+    border-right: 8px solid transparent;
+    border-bottom: 8px solid #23282D;
+}
+
+#wcs-shipping-re-import {
+    display: flex;
+    justify-content: center;
+    margin: auto;
+}
+
+#wcs-shipping-import {
+    display: flex;
+    justify-content: center;
+    margin: auto;
+}
Index: /woo-cost-of-shipping/tags/1.5.5/assets/js/woocommerce-cost-of-shipping.js
===================================================================
--- /woo-cost-of-shipping/tags/1.5.5/assets/js/woocommerce-cost-of-shipping.js	(revision 3649833)
+++ /woo-cost-of-shipping/tags/1.5.5/assets/js/woocommerce-cost-of-shipping.js	(revision 3649833)
@@ -0,0 +1,150 @@
+/**
+ * WooCommerce Cost of Shipping
+ * https://www.theritesites.com/plugins/woocomerce-cost-of-shipping
+ *
+ * This plugin can be expanded into net profit reporting by getting the WooCommerce Net Profit plugin
+ * developed by TheRiteSites and found at https://www.theritesites.com/plugins/woocommerce-net-profit
+ *
+ * Licensed under the GPLv2+ license.
+ */
+
+window.WCCOS = window.WCCOS || {};
+
+( function( window, document, $, plugin ) {
+	var $c = {};
+
+	plugin.init = function() {
+		plugin.cache();
+		plugin.bindEvents();
+	};
+
+	plugin.cache = function() {
+		$c.window = $( window );
+		$c.body = $( document.body );
+	};
+
+	plugin.bindEvents = function() {
+	};
+
+	$( plugin.init );
+
+
+}( window, document, jQuery, window.WCCOS ) );
+
+jQuery(document).ready(function( $ ) {
+    'use strict';
+
+	var i18n = ( window.WCCOSApi && WCCOSApi.i18n ) || {};
+
+	/**
+	 * Build the price markup the same way wc_price() does, but from DOM nodes
+	 * so neither the currency symbol nor the amount is ever parsed as HTML.
+	 */
+	function renderPrice( $target, currency, amount ) {
+		var value = parseFloat( amount );
+		if ( isNaN( value ) ) {
+			return;
+		}
+		$target.empty().append(
+			$( '<span/>' ).addClass( 'woocommerce-Price-currencySymbol' ).text( currency ),
+			document.createTextNode( value.toFixed( 2 ) )
+		);
+	}
+
+	function debugLog( message ) {
+		if ( window.WCCOSApi && WCCOSApi.debug && window.console ) {
+			console.log( message );
+		}
+	}
+
+    $('#edit-shipping-cost').on('click', function(e) {
+		e.preventDefault();
+        $('.edit-shipping-tooltip').toggle();
+        $('#shipping-cost-input').focus();
+    });
+
+    $('#edit-shipping-cancel').on('click', function(e) {
+		e.preventDefault();
+        $('.edit-shipping-tooltip').toggle();
+    });
+
+	$('#edit-shipping-save').on('click', function(e) {
+		e.preventDefault();
+
+		$('#edit-shipping-save').prop( 'disabled', true );
+		$('#edit-shipping-cancel').prop( 'disabled', true );
+
+		var data = {
+			action: 'set_shipping_cost',
+			security: WCCOSApi.nonce,
+			post_id: $('#edit-shipping-cost').data('orderid'),
+			shipping_cost: $('#shipping-cost-input').val()
+		};
+
+		$.post( ajaxurl, data )
+		.done(function( response ) {
+			// admin-ajax answers 200 for wp_send_json_error() unless a status is
+			// passed, so a resolved request is not yet a saved value.
+			if ( ! response || ! response.success ) {
+				var message = ( response && response.data && response.data.message ) || i18n.save_failed || 'The cost of shipping could not be saved.';
+				window.alert( message );
+				return;
+			}
+			debugLog( 'Shipping cost saved.' );
+			renderPrice( $('#shipping-cost .amount'), WCCOSApi.currency, $('#shipping-cost-input').val() );
+			$('.edit-shipping-tooltip').toggle();
+		})
+		.fail(function( jqXHR ) {
+			var message = ( jqXHR.responseJSON && jqXHR.responseJSON.data && jqXHR.responseJSON.data.message ) || i18n.save_failed || 'The cost of shipping could not be saved.';
+			debugLog( 'Failed to save the shipping cost from manual input.' );
+			window.alert( message );
+		})
+		.always(function() {
+			$('#edit-shipping-save').prop( 'disabled', false );
+			$('#edit-shipping-cancel').prop( 'disabled', false );
+		});
+	});
+
+	$('.wc-cos-wcs-import').on('click', function(e){
+		e.preventDefault();
+		var $button = $(this);
+		var data = {
+			action: 'set_label_cost_wcs',
+			security: WCCOSApi.nonce,
+			post_id: $button.data('orderid'),
+		};
+
+		$('.wc-cos-wcs-import').prop('disabled', true);
+		$button.text( i18n.loading || 'Loading...' );
+
+		$.post( ajaxurl, data )
+		.done(function( response ) {
+			if ( ! response || ! response.success ) {
+				$button.text( i18n.retry || 'Retry import' );
+				return;
+			}
+			$button.text( i18n.reimport || 'Re-import' );
+			$('#wc-cos-protip').remove();
+			$button.after(
+				$( '<div id="wc-cos-protip"/>' ).append(
+					$( '<p/>' ).append(
+						$( '<b/>' ).text( 'Pro tip: ' ),
+						document.createTextNode( i18n.protip || 'If you purchase your label(s) and then set the order status to complete, the cost of shipping will automatically be imported!' )
+					)
+				)
+			);
+			if ( response.data && typeof response.data.cost !== 'undefined' ) {
+				debugLog( 'Shipping cost imported.' );
+				renderPrice( $('.shipping-total .woocommerce-Price-amount'), response.data.currency, response.data.cost );
+			}
+		})
+		.fail(function() {
+			debugLog( 'Failed to import shipping cost from WooCommerce Services created label.' );
+			$button.text( i18n.retry || 'Retry import' );
+		})
+		.always(function() {
+			$('.wc-cos-wcs-import').prop('disabled', false);
+		});
+	});
+
+});
Index: /woo-cost-of-shipping/tags/1.5.5/includes/admin/class-wc-cos-admin-orders.php
===================================================================
--- /woo-cost-of-shipping/tags/1.5.5/includes/admin/class-wc-cos-admin-orders.php	(revision 3649833)
+++ /woo-cost-of-shipping/tags/1.5.5/includes/admin/class-wc-cos-admin-orders.php	(revision 3649833)
@@ -0,0 +1,775 @@
+<?php
+/**
+ * Cost of Shipping for WooCommerce Admin Orders
+ * 
+ * This file adds the cost of shipping functionality to the Admin Orders page.
+ * 
+ * Currently, it allows for importing the cost of shipping from the WooCommerce Shipstation plugin.
+ * It utilizes the safedom standards introduced by the plugin itself in the class-wc-cos-safe-domdocument.php file
+ * 
+ * Additionally, this file enqueues some jQuery, and uses a woocommerce action to provide an editable
+ * field in the order page to allow an end user to apply a cost of shipping manually.
+ * 
+ * Future expansions of this plugin may include:
+ * - Stamps integration
+ * - ShippingEasy integration
+ * - <<< WooCommerce Services "Shipping" plugin >>> done as of 1.2.0
+ * - Freightview for WooCommerce
+ * - Orodoro
+ * 
+ * This plugin can be expanded into net profit reporting by getting the WooCommerce Net Profit plugin
+ * developed by TheRiteSites and found at https://www.theritesites.com/plugins/woocommerce-net-profit
+ * 
+ * 
+ * @since 1.0.0
+ * @package WC_COS
+ * @subpackage WC_COS/includes/admin
+ * 
+ */
+
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
+
+
+class WC_COS_Admin_Orders {
+
+	private $log = null;
+	
+	/**
+	 * Parent plugin class.
+	 *
+	 * @var    WooCommerce_Net_Profit
+	 * @since  1.0.0
+	 */
+	protected $plugin = null;
+
+	/**
+	 * Bootstrap class
+	 *
+	 * @since 1.0.0
+	 */
+	public function __construct( $plugin ) {
+		
+		$this->plugin = $plugin;
+
+		$this->init_hooks();
+
+
+		if ( ! function_exists( 'is_woocommerce_services_active' ) ) {
+			require_once( $this->plugin->__get('path') . 'woo-includes/woo-functions.php' );
+		}
+	}
+
+	/**
+	 * Initialize hooks
+	 *
+	 * @since 1.0.0
+	 */
+	protected function init_hooks() {
+
+		// Adds style sheets for the order edit page
+		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles' ) );
+
+		// Adds javascript files for the order edit page
+		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
+
+		// Display the order total cost of shipping on the order admin page
+		add_action( 'woocommerce_admin_order_totals_after_total', array( $this, 'show_order_shipping_cost' ) );
+
+		// When shipstation comes back with the shipment information, catch the incoming data
+		add_action( 'woocommerce_shipstation_shipnotify', array($this, 'maybe_save_order_shipping_cost_shipstation'), 10, 2 );
+	
+		// Adds order note when cost of shipping is changed
+		add_action( 'wc_cos_after_cost_of_shipping_stored', array( $this, 'add_order_shipping_cost_to_order_note' ), 10, 3 );
+
+		// Sets the cost of shipping when it is manually entered via an AJAX request
+		add_action( 'wp_ajax_set_shipping_cost', array( $this, 'set_shipping_cost_callback') );
+	
+		// If WooCommerce Services is active when the order is marked complete, attempts to save Cost of Shipping
+		add_action( 'woocommerce_order_status_completed', array( $this, 'maybe_save_order_shipping_cost_woocommerce_services' ) );
+		
+		// Adds meta box to individual orders screen to display manual import button for Cost of Shipping when using WooCommerce Services
+		add_action( 'add_meta_boxes', array( $this, 'add_wcs_cos_meta_box' ), 10, 2 );
+	
+		// Callback for when the import Cost of Shipping button is pressed, when using WooCommerce Services for shipping labels.
+		add_action( 'wp_ajax_set_label_cost_wcs', array( $this, 'set_label_cost_wcs_callback' ) );
+	}
+
+	/**
+	 * Nonce action shared by this plugin's AJAX handlers.
+	 *
+	 * Deliberately not 'wp_rest': that nonce is minted for every REST call and
+	 * is present on any page that enqueues wp-api, so a purpose-built action
+	 * keeps the surface that can drive these handlers as small as possible.
+	 *
+	 * @since 1.5.5
+	 */
+	const AJAX_NONCE_ACTION = 'wc-cos-ajax';
+
+	/**
+	 * Whether the current admin screen is the single-order edit screen.
+	 *
+	 * Uses the screen id WooCommerce reports for the current storage mode, so it
+	 * is correct for both the shop_order post type and HPOS (wc-orders) without
+	 * reading $pagenow or $_GET.
+	 *
+	 * @since 1.5.5
+	 *
+	 * @return bool
+	 */
+	protected function is_order_edit_screen() {
+		if ( ! function_exists( 'get_current_screen' ) ) {
+			return false;
+		}
+		$screen = get_current_screen();
+		if ( ! $screen ) {
+			return false;
+		}
+		return function_exists( 'wc_get_page_screen_id' )
+			? wc_get_page_screen_id( 'shop-order' ) === $screen->id
+			: 'shop_order' === $screen->id;
+	}
+
+	/**
+	 * Function to register and enqueue javascript files for the order admin page
+	 *
+	 * @since 1.1.0
+	 */
+	public function enqueue_scripts() {
+		if ( ! $this->is_order_edit_screen() ) {
+			return;
+		}
+
+		$js_file = '';
+		$path = realpath( dirname(__FILE__) . '/../' );
+
+		if ( file_exists( $path .  '/assets/js/woo-cost-of-shipping.min.js' ) && ! ( $this->plugin->__get( 'debug' ) || WP_DEBUG ) ) {
+			$js_file = plugins_url( '/assets/js/woo-cost-of-shipping.min.js', plugin_dir_path(__DIR__) );
+		}
+		else
+			$js_file = plugins_url( '/assets/js/woocommerce-cost-of-shipping.js', plugin_dir_path(__DIR__) );
+
+		if ( ! empty( $js_file ) ) {
+			wp_register_script( $this->plugin->basename , $js_file, array( 'jquery' ), $this->plugin->version, false );
+
+			wp_localize_script( $this->plugin->basename, 'WCCOSApi', array(
+				'nonce'    => wp_create_nonce( self::AJAX_NONCE_ACTION ),
+				'currency' => get_woocommerce_currency_symbol(),
+				'debug'    => $this->plugin->__get( 'debug' ),
+				'i18n'     => array(
+					'reimport'    => __( 'Re-Import', 'woo-cost-of-shipping' ),
+					'retry'       => __( 'Retry import', 'woo-cost-of-shipping' ),
+					'loading'     => __( 'Loading...', 'woo-cost-of-shipping' ),
+					'save_failed' => __( 'The cost of shipping could not be saved.', 'woo-cost-of-shipping' ),
+					'protip'      => __( 'If you purchase your label(s) and then set the order status to complete, the cost of shipping will automatically be imported!', 'woo-cost-of-shipping' ),
+				),
+			));
+			wp_enqueue_script( $this->plugin->basename );
+		}
+	}
+
+	/**
+	 * Function to register and enqueue CSS files for the order admin page
+	 *
+	 * @since 1.0.0
+	 */
+	public function enqueue_styles() {
+		if ( ! $this->is_order_edit_screen() ) {
+			return;
+		}
+
+		$cs_file = '';
+		$path = realpath(dirname(__FILE__) . '/../');
+
+		if ( file_exists( $path . '/assets/css/woocommerce-cost-of-shipping.min.css' ) && !( $this->plugin->__get( 'debug' ) || WP_DEBUG ) ) {
+			$cs_file = plugins_url( '/assets/css/woocommerce-cost-of-shipping.min.css', plugin_dir_path(__DIR__) );
+		}
+		else
+			$cs_file = plugins_url( '/assets/css/woocommerce-cost-of-shipping.css', plugin_dir_path(__DIR__) );
+		wp_enqueue_style( $this->plugin->basename, $cs_file, array(), $this->plugin->version );
+	}
+
+	/**
+	 * Shared guard for the AJAX handlers: nonce, login, capability, and a
+	 * real shop_order behind the submitted id. On any failure it sends the
+	 * JSON error itself, with a non-200 status so the front end's fail handler
+	 * runs, and exits; otherwise it returns the order.
+	 *
+	 * @since 1.5.5
+	 *
+	 * @return WC_Order
+	 */
+	protected function ajax_guard() {
+		if ( ! check_ajax_referer( self::AJAX_NONCE_ACTION, 'security', false ) || ! is_user_logged_in() || ! current_user_can( 'manage_woocommerce' ) ) {
+			wp_send_json_error( array( 'message' => __( 'You are not allowed to do that.', 'woo-cost-of-shipping' ) ), 403 );
+		}
+
+		$order_id = isset( $_POST['post_id'] ) ? absint( wp_unslash( $_POST['post_id'] ) ) : 0;
+		$order    = $order_id ? wc_get_order( $order_id ) : false;
+
+		// wc_get_order() also returns refunds; only a real order carries a cost of shipping.
+		if ( ! $order || ! is_a( $order, 'WC_Order' ) ) {
+			wp_send_json_error( array( 'message' => __( 'Order not found.', 'woo-cost-of-shipping' ) ), 400 );
+		}
+
+		return $order;
+	}
+
+	/**
+	 * Helper function to add a node to a WooCommerce order when the cost of shipping is changed
+	 * 
+	 * @since 1.1.0
+	 *
+	 * @param int	$order_id	the id of the order to store to
+	 * @param float $cos		cost of shipping
+	 * @param string $method	method that cost of shipping was calulcated from
+	 */
+	public function add_order_shipping_cost_to_order_note( $order_id, $cos, $method ) {
+		$order = wc_get_order( $order_id );
+		if ( ! $order || ! is_a( $order, 'WC_Order' ) ) {
+			return;
+		}
+
+		$fcos = wc_price( $cos );
+		// $method has been through a public filter, so escape it before it lands in a note.
+		$by = $method == 'manual' ? __('manually', 'woo-cost-of-shipping') : sprintf(__('automatically by %s', 'woo-cost-of-shipping'), esc_html( $method ));
+		// If automatically changed by an integration component, there is a change in verbage.
+		// Careful on translation here!
+		$note = sprintf( __('Cost of Shipping was changed to %s %s', 'woo-cost-of-shipping'), $fcos, $by );
+
+		$order->add_order_note( $note );
+		$order->save();
+	}
+
+	/**
+	 * Callback function for AJAX request to handle the manual shipping cost entry.
+	 * This function will return success on successful $order->update_meta_data for the new shipping cost and method.
+	 * 
+	 * @since 1.0.0
+	 * 
+	 * @return json error|success
+	 */
+	function set_shipping_cost_callback() {
+
+		$order   = $this->ajax_guard();
+		$post_id = $order->get_id();
+
+		$raw = isset( $_POST['shipping_cost'] ) ? sanitize_text_field( wp_unslash( $_POST['shipping_cost'] ) ) : '';
+		if ( '' === $raw || ! is_numeric( $raw ) ) {
+			wp_send_json_error( array( 'message' => __( 'Cost of shipping must be a number.', 'woo-cost-of-shipping' ) ), 400 );
+		}
+		$cos = floatval( $raw );
+		// The input's min="0" is client-side only; enforce it here too.
+		if ( ! is_finite( $cos ) || $cos < 0 ) {
+			wp_send_json_error( array( 'message' => __( 'Cost of shipping must be zero or more.', 'woo-cost-of-shipping' ) ), 400 );
+		}
+
+		do_action( 'wc_cos_before_ajax_set_shipping_cost', $post_id, $cos, 'manual' );
+
+		// Returns true on success, false on anything else
+		if ( $this->store_cost_of_shipping( $post_id, $cos, 'manual' ) ){
+
+			do_action( 'wc_cos_after_ajax_set_shipping_cost', $post_id, $cos, 'manual' );
+			wp_send_json_success();
+		}
+		// Not an error the user can act on: the value already matched what was stored.
+		wp_send_json_success( array( 'unchanged' => true ) );
+
+	}
+
+
+	/**
+	 * Helper function to store cost of shipping and method to postmeta table with added filter
+	 * 
+	 * @since 1.0.0
+	 *
+	 * @param int	$order_id the id of the order to store to
+	 * @param float	$cos	cost of shipping
+	 * @param string $method	method that cost of shipping was calculated from
+	 * 
+	 * @return bool
+	 */
+	public function store_cost_of_shipping( $order_id, $cos, $method ) {
+		
+		$flag = true;
+		if ( is_null( $this->log ) ) {
+			$this->log = new WC_Logger();
+		}
+		if ( true === $this->plugin->__get( 'debug' ) ) {
+			$this->log->add( 'the-rite-sites-profit-plugins', __( 'Function: store_cost_of_shipping', 'woo-cost-of-shipping' ) );
+			$this->log->add( 'the-rite-sites-profit-plugins', sprintf( __( '   Order cost of shipping being stored to order id %d', 'woo-cost-of-shipping' ), $order_id ) );
+			$this->log->add( 'the-rite-sites-profit-plugins', sprintf( __( '       Cost of shipping: %.2f via method: %s', 'woo-cost-of-shipping' ), $cos, $method ) );
+		}
+		$cos = apply_filters( 'wc_cos_store_cost_of_shipping', $cos, $order_id );
+		$method = apply_filters( 'wc_cos_store_cost_of_shipping_method', $method, $order_id );
+		
+		do_action( 'wc_cos_before_cost_of_shipping_stored', $order_id, $cos, $method );
+
+		// Query wc_order
+		$order = wc_get_order( $order_id );
+		if ( ! $order || ! is_a( $order, 'WC_Order' ) ) {
+			if ( true === $this->plugin->__get( 'debug' ) ) {
+				$this->log->add( 'the-rite-sites-profit-plugins', sprintf( __( '       No order found for id %d, nothing stored.', 'woo-cost-of-shipping' ), $order_id ) );
+			}
+			return false;
+		}
+
+		// Store for possible history update before the new store overwrites.
+		$old_cos = $order->get_meta( '_wc_cost_of_shipping', true );
+		$old_method = $order->get_meta( '_wc_cos_method', true );
+
+		/**
+		 * We only need to go through the rest of the function if the values need
+		 *   to be updated. If nothing is updated in the database for the actual
+		 *   cost of shipping, then we do not need to update which method its being
+		 *   saved by at this point. Might see some functionality wanted later on,
+		 *   but this will be the simplest way forward to not corrupt data.
+		 * 
+		 *  Updated in 1.5.0 for HPOS
+		 */
+		if ( ( float ) $old_cos == ( float ) $cos ) {
+			if ( true === $this->plugin->__get( 'debug' ) ) {
+				$this->log->add( 'the-rite-sites-profit-plugins', __( '       No need to update Cost of Shipping, values are equivalent.', 'woo-cost-of-shipping' ) );
+			}
+			return false;
+		}
+		$order->update_meta_data( '_wc_cost_of_shipping', ( float ) $cos );
+
+		// 1.5.0 - 1.5.4 passed ( $order_id, '_wc_cos_method', $method ) here, a leftover
+		// from the update_post_meta() signature, so the method was never stored and a
+		// stray meta row keyed by the order id was written instead. Fixed in 1.5.5.
+		$order->update_meta_data( '_wc_cos_method', $method );
+
+		if ( true === $this->plugin->__get( 'debug' ) ) {
+			$this->log->add( 'the-rite-sites-profit-plugins', __( '     Cost of shipping value and method updated.', 'woo-cost-of-shipping' ) );
+		}
+
+		if ( ! empty( $old_cos ) && ! empty( $old_method ) ) {
+			$dirty_cos_history = $order->get_meta( '_wc_cos_history' );
+			$cos_history = maybe_unserialize( $dirty_cos_history );
+			if ( empty( $cos_history ) ) {
+				$cos_history = array();
+			}
+
+			$cos_history[] = array( 'method' => $old_method, 'cos' => $old_cos );
+			$order->update_meta_data( '_wc_cos_history', $cos_history );
+
+			if ( true === $this->plugin->__get( 'debug' ) ) {
+				$this->log->add( 'the-rite-sites-profit-plugins', __( '     Cost of shipping history updated with value and method.', 'woo-cost-of-shipping' ) );
+			}
+		}
+
+		$order->save();
+		do_action( 'wc_cos_after_cost_of_shipping_stored', $order_id, $cos, $method );
+		return true;
+	}
+	
+	/**
+	 * Attempts to save the Cost of Shipping when a user is using
+	 *   WooCommerce ShipStation as a means to purchase shipping labels.
+	 * 
+	 * @since 1.0.0
+	 * 
+	 * @param WC_Order $order	The current order received from ShipStation
+	 */
+	public function maybe_save_order_shipping_cost_shipstation( $order, $args ) {
+
+		if ( is_null( $this->log ) ) {
+			$this->log = new WC_Logger();
+		}
+
+		if ( ! is_a( $order, 'WC_Order' ) || ! is_array( $args ) || empty( $args['xml'] ) || ! is_string( $args['xml'] ) ) {
+			$this->log->add( 'the-rite-sites-profit-plugins', __( 'shipstation integration fired without an order or xml payload', 'woo-cost-of-shipping' ) );
+			return;
+		}
+
+		$xml = $this->get_parsed_xml( $args['xml'] );
+
+		if ( ! isset( $xml ) ) {
+			$this->log->add( 'shipstation', __( 'shipstation integration xml not set', 'woo-cost-of-shipping' ) );
+			$this->log->add( 'the-rite-sites-profit-plugins', __( 'shipstation integration xml not set', 'woo-cost-of-shipping' ) );
+		}
+		elseif ( empty( $xml ) ) {
+			$this->log->add( 'shipstation', __( 'shipstation integration xml is empty', 'woo-cost-of-shipping' ) );
+			$this->log->add( 'the-rite-sites-profit-plugins', __( 'shipstation integration xml is empty', 'woo-cost-of-shipping' ) );
+		}
+		elseif ( ! isset( $xml->ShippingCost ) ) {
+			$this->log->add( 'shipstation', __( 'shipstation integration xml does not have shipping amount set', 'woo-cost-of-shipping' ) );
+			$this->log->add( 'the-rite-sites-profit-plugins', __( 'shipstation integration xml does not have shipping amount set', 'woo-cost-of-shipping' ) );
+		}
+		else {
+			// wc_clean() passes non-scalars through untouched, so cast the
+			// SimpleXMLElement to a string first and then to the float we store.
+			$shipping_cost = floatval( wc_clean( (string) $xml->ShippingCost ) );
+			if ( ! is_finite( $shipping_cost ) || $shipping_cost < 0 ) {
+				$this->log->add( 'the-rite-sites-profit-plugins', __( 'shipstation integration xml shipping amount is not a valid cost', 'woo-cost-of-shipping' ) );
+				return;
+			}
+			$this->store_cost_of_shipping( $order->get_id(), $shipping_cost, 'shipstation' );
+			$this->log->add( 'shipstation', 'After shipstation automatically stored cost of shipping.');
+		}
+	
+	}
+
+	/**
+	 * Attempts to save the Cost of Shipping when a user is using
+	 *   WooCommerce Services as a means to purchase USPS shipping labels.
+	 * 
+	 * @since 1.2.0
+	 * 
+	 * @param int $order_id		The current order which should have USPS labels
+	 * 
+	 * @return bool
+	 */
+	public function maybe_save_order_shipping_cost_woocommerce_services( $order_id = 0 ) {
+		if ( is_null( $this->log ) ) {
+			$this->log = new WC_Logger();
+		}
+
+		if ( true === is_woocommerce_services_active() ) {
+			if ( true === $this->plugin->__get( 'debug' ) )
+				$this->log->add( 'the-rite-sites-profit-plugins', __( 'WooCommerce services is active, retrieving labels.', 'woo-cost-of-shipping' ) );
+			$labels = $this->get_wcs_label_order_meta_data( $order_id );
+			$flag = false;
+			$cost_of_shipping = 0.00;
+			foreach ( $labels as $label ) {
+				if ( isset( $label['rate'] ) ) {
+					$cost_of_shipping += floatval( $label['rate'] );
+					$flag = true;
+				}
+			}
+
+			$order = wc_get_order( $order_id );
+			if ( ! $order || ! is_a( $order, 'WC_Order' ) ) return false;
+			$previous_cos_method = $order->get_meta( '_wc_cos_method', true );
+			if ( false === $flag && ! ( 'wc_services' === $previous_cos_method ) ) return false;
+			if ( true === $this->store_cost_of_shipping( $order_id, $cost_of_shipping, 'wc_services' ) ) {
+				return $cost_of_shipping;
+			}
+		}
+		else {
+			if ( true === $this->plugin->__get( 'debug' ) )
+				$this->log->add( 'the-rite-sites-profit-plugins', __( '    WooCommerce services is not active, ignoring trying to save WooCommerce services labels as cost of shipping.', 'woo-cost-of-shipping' ) );
+		}
+		return false;
+	}
+
+	/**
+	 * Does validation and verification if the WooCommerce Services
+	 *   Cost of Shipping import meta box should be displayed
+	 * 
+	 * @since 1.2.0
+	 * 
+	 * @return bool
+	 */
+	public function should_show_wcs_cos_meta_box( $screen_id = '', $post_or_order = null ) {
+		if ( true !== is_woocommerce_services_active() ) {
+			return false;
+		}
+		// add_meta_boxes passes the screen id: 'shop_order' for the post type,
+		// the wc-orders page id under HPOS. wc_get_page_screen_id() returns
+		// whichever is in force, so one comparison covers both storage modes.
+		$order_screen = function_exists( 'wc_get_page_screen_id' ) ? wc_get_page_screen_id( 'shop-order' ) : 'shop_order';
+		if ( $screen_id !== $order_screen ) {
+			return false;
+		}
+		// The second argument is a WP_Post under the post type and a WC_Order under
+		// HPOS. An order being created is auto-draft in both modes; that is the
+		// add-new case the old $pagenow check excluded.
+		$order = ( $post_or_order instanceof WP_Post ) ? wc_get_order( $post_or_order->ID ) : $post_or_order;
+		return $order && is_a( $order, 'WC_Order' ) && 'auto-draft' !== $order->get_status();
+	}
+
+	/**
+	 * Handles displaying the internals of the meta box to import the
+	 *   cost of shipping while the user is using WooCommerce Services
+	 *   to purchase shipping labels.
+	 * 
+	 * @since 1.2.0
+	 * 
+	 * @param int $post_id	Current order ID passed to meta box via add_meta_box function
+	 */
+	public function display_wcs_cos_meta_box( $post_id ) {
+		$order = ( $post_id instanceof WP_Post ) ? wc_get_order( $post_id->ID ) : $post_id;
+		if ( ! $order || ! is_a( $order, 'WC_Order' ) ) {
+			return;
+		}
+
+		$cos = floatval( $order->get_meta( '_wc_cost_of_shipping' ) );
+
+		if ( empty( $cos ) ) {
+			?>
+			<div class="wc-cos-wrapper">
+				<button class="wc-cos-wcs-import button-primary" data-orderid="<?php echo esc_attr( $order->get_id() ); ?>" id="wcs-shipping-import"><?php esc_html_e( 'Import', 'woo-cost-of-shipping' ); ?></button>
+			</div>
+			<?php
+		}
+		else {
+			?>
+			<div class="wc-cos-wrapper">
+				<button class="wc-cos-wcs-import button-secondary" data-orderid="<?php echo esc_attr( $order->get_id() ); ?>" id="wcs-shipping-re-import"><?php esc_html_e( 'Re-Import', 'woo-cost-of-shipping' ); ?></button>
+			</div>
+			<?php
+		}
+	}
+
+	/**
+	 * The callback for the AJAX call when either the import or re-import
+	 *   buttons are pressed. This reads in the order ID and calls the
+	 *   function in charge of attempting the reading and saving of the
+	 *   Cost of Shipping as stored by WooCommerce Services
+	 * 
+	 * @since 1.2.0
+	 * 
+	 * @return json success|error
+	 */
+	public function set_label_cost_wcs_callback() {
+		$order   = $this->ajax_guard();
+		$post_id = $order->get_id();
+
+		do_action( 'wc_cos_before_ajax_set_label_cost_wcs', $post_id );
+
+		// Returns the stored cost (which may legitimately be 0.00) on success, false on anything else.
+		$cost = $this->maybe_save_order_shipping_cost_woocommerce_services( $post_id );
+		if ( false !== $cost ) {
+			do_action( 'wc_cos_after_ajax_set_label_cost_wcs', $post_id );
+			wp_send_json_success( array( 'cost' => $cost, 'currency' => get_woocommerce_currency_symbol() ) );
+		}
+		do_action( 'wc_cos_after_ajax_no_labels_wcs', $post_id );
+		wp_send_json_success( array( 'message' => __( 'No labels exist.', 'woo-cost-of-shipping' ) ) );
+	}
+
+	/**
+	 * Registers the meta box if and only if the user is using WooCommerce
+	 *   Services.
+	 * 
+	 * @since 1.2.0
+	 * 
+	 * @param string $post_type		The current pages post type, passed by the add_meta_boxes action
+	 * @param int	 $post			The current post ID.
+	 */
+	public function add_wcs_cos_meta_box( $post_type, $post = null ) {
+		if ( $this->should_show_wcs_cos_meta_box( $post_type, $post ) ) {
+
+			// should_show_wcs_cos_meta_box() has already matched $post_type against
+			// the order screen id for the storage mode in force, so it is the screen.
+			$screen = $post_type;
+
+			add_meta_box(
+				'wc-cos-services-cost-of-shipping',
+				__( 'Import Cost of Shipping', 'woo-cost-of-shipping' ),
+				array( $this, 'display_wcs_cos_meta_box' ),
+				$screen,
+				'side',
+				'default'
+			);
+		}
+	}
+
+	/**
+	 * Attempts to recover a faulty json string field that might contain unescaped quotes,
+	 * e.g. "package_name":"12" x 9" box". Escapes any quote inside the value that is not
+	 * already escaped and is not the closing quote.
+	 *
+	 * Called since 1.2.0 but never defined until 1.5.5, so the legacy-string labels path
+	 * used to fatal on any store whose wc_connect_labels meta was not valid JSON.
+	 *
+	 * @since 1.5.5
+	 *
+	 * @param string $field_name
+	 * @param string $json
+	 *
+	 * @return string
+	 */
+	public function try_recover_invalid_json_string( $field_name, $json ) {
+		$regex = '/"' . preg_quote( $field_name, '/' ) . '":"(.+?)"(?=\s*[,}])/';
+		preg_match_all( $regex, $json, $match_groups );
+		if ( 2 === count( $match_groups ) ) {
+			foreach ( $match_groups[ 0 ] as $idx => $match ) {
+				$value = $match_groups[ 1 ][ $idx ];
+				$escaped_value = preg_replace( '/(?<!\\\)"/', '\\"', $value );
+				$json = str_replace( '"' . $field_name . '":"' . $value . '"', '"' . $field_name . '":"' . $escaped_value . '"', $json );
+			}
+		}
+		return $json;
+	}
+
+	/**
+	 * Attempts to recover faulty json string array fields that might contain strings with unescaped quotes
+	 *
+	 * @since 1.2.0
+	 *
+	 * @param string $field_name
+	 * @param string $json
+	 *
+	 * @return string
+	 */
+	public function try_recover_invalid_json_array( $field_name, $json ) {
+		$regex = '/"' . $field_name . '":\["(.+?)"\]/';
+		preg_match_all( $regex, $json, $match_groups );
+		if ( 2 === count( $match_groups ) ) {
+			foreach ( $match_groups[ 0 ] as $idx => $match ) {
+				$array = $match_groups[ 1 ][ $idx ];
+				$escaped_array = preg_replace( '/(?<![,\\\])"(?!,)/', '\\"', $array );
+				$json = str_replace( '["' . $array . '"]', '["' . $escaped_array. '"]', $json );
+			}
+		}
+		return $json;
+	}
+
+	/**
+	 * Attempts to deserialize USPS labels from json stored in database.
+	 * 
+	 * @since 1.2.0
+	 * 
+	 * @param serialized array	$label_data		Raw data from database
+	 * 
+	 * @return array
+	 */
+	public function try_deserialize_labels_json( $label_data ) {
+		//attempt to decode the JSON (legacy way of storing the labels data)
+		$decoded_labels = json_decode( $label_data, true );
+		if ( $decoded_labels ) {
+			return $decoded_labels;
+		}
+		$label_data = $this->try_recover_invalid_json_string( 'package_name', $label_data );
+		$decoded_labels = json_decode( $label_data, true );
+		if ( $decoded_labels ) {
+			return $decoded_labels;
+		}
+		$label_data = $this->try_recover_invalid_json_array( 'product_names', $label_data );
+		$decoded_labels = json_decode( $label_data, true );
+		if ( $decoded_labels ) {
+			return $decoded_labels;
+		}
+		return array();
+	}
+
+	/**
+	 * Returns labels for the specific order ID
+	 *
+	 * @since 1.2.0
+	 * 
+	 * @param $order_id
+	 *
+	 * @return array
+	 */
+	public function get_wcs_label_order_meta_data( $order_id ) {
+		$order = wc_get_order( ( int ) $order_id );
+		if ( ! $order || ! is_a( $order, 'WC_Order' ) ) {
+			return array();
+		}
+		$label_data = $order->get_meta( 'wc_connect_labels', true );
+		//return an empty array if the data doesn't exist
+		if ( ! $label_data ) {
+			return array();
+		}
+		//labels stored as an array, return
+		if ( is_array( $label_data ) ) {
+			return $label_data;
+		}
+		return $this->try_deserialize_labels_json( $label_data );
+	}
+	
+	/**
+	 * Get Parsed XML response for shipstation API response
+	 *
+	 * @since 1.0.0
+	 * 
+	 * @param  string $xml XML.
+	 * 
+	 * @return string|bool
+	 */
+	private function get_parsed_xml( $xml ) {
+		if ( ! class_exists( 'WC_COS_Safe_DOMDocument' ) ) {
+			include_once( 'class-wc-cos-safe-domdocument.php' );
+		}
+
+		if ( is_null( $this->log ) ) {
+			$this->log = new WC_Logger();
+		}
+
+		libxml_use_internal_errors( true );
+
+		$dom     = new WC_COS_Safe_DOMDocument;
+		$success = $dom->loadXML( $xml );
+
+		if ( ! $success ) {
+			$this->log->add( 'the-rite-sites-profit-plugins', __( 'wpcom_safe_simplexml_load_string(): Error loading XML string in shipstation xml retrieve', 'woo-cost-of-shipping' ) );
+			return false;
+		}
+
+		if ( isset( $dom->doctype ) ) {
+			$this->log->add( 'the-rite-sites-profit-plugins', __( 'wpcom_safe_simplexml_import_dom(): Unsafe DOCTYPE Detected in shipstation xml retrieve', 'woo-cost-of-shipping' ) );
+			return false;
+		}
+
+		return simplexml_import_dom( $dom, 'SimpleXMLElement' );
+	}
+
+	/**
+	 * Render a read-only input box with the order shipping cost with an edit link below it
+	 * 
+	 * The edit link will spawn a javascript modal that will have an editable field and save button.
+	 *
+	 * @since 1.0.0
+	 * 
+	 * @param int $post_id post (order) ID
+	 */
+	public function show_order_shipping_cost( $post_id ) {
+
+		$order = wc_get_order( $post_id );
+		if ( ! $order || ! is_a( $order, 'WC_Order' ) ) {
+			return;
+		}
+		$cost_of_shipping = floatval( $order->get_meta( '_wc_cost_of_shipping', true ) );
+		$formatted_total = wc_price( $cost_of_shipping );
+		?>
+		<tr>
+
+			<td class="total shipping-total"><?php esc_html_e( 'Shipping Cost', 'woo-cost-of-shipping' ); ?>:</td>
+
+			<td width="1%"></td>
+
+			<td class="total shipping-total">
+				<span id="shipping-cost">
+					<?php echo wp_kses_post( $formatted_total ); ?>
+
+					<div class="edit-shipping-tooltip" style="display:none;">
+						<input id="shipping-cost-input" type="number" step="0.01" min="0" value="<?php echo esc_attr( $cost_of_shipping ); ?>" />
+						<div class="edit-shipping-buttons">
+							<button id="edit-shipping-cancel" class="button" type="button"><?php esc_html_e( 'Cancel', 'woo-cost-of-shipping' ); ?></button>
+							<button id="edit-shipping-save" class="button button-primary" type="button"><?php esc_html_e( 'Save', 'woo-cost-of-shipping' ); ?></button>
+						</div>
+					</div>
+				</span>
+			</td>
+
+			<td width="1%"><a data-orderid="<?php echo esc_attr( $order->get_id() ); ?>" id="edit-shipping-cost"><?php esc_html_e( 'edit', 'woo-cost-of-shipping' ); ?></a></td>
+
+		</tr>
+		<?php
+	}
+
+	
+	
+	/**
+	 * Return the formatted order shipping cost, which includes the refunded order
+	 * total cost if refunds have been processed
+	 *
+	 * @since 1.0.0
+	 * 
+	 * @param int $order_id
+	 * 
+	 * @return string formatted total
+	 */
+	protected function get_formatted_order_shipping_cost( $order_id ) {
+
+		$order = wc_get_order( $order_id );
+		$order_shipping_cost = $order->get_meta( '_wc_cost_of_shipping', true );
+		$formatted_total = wc_price( $order_shipping_cost );
+
+		return $formatted_total;
+	}
+}
Index: /woo-cost-of-shipping/tags/1.5.5/includes/admin/class-wc-cos-admin.php
===================================================================
--- /woo-cost-of-shipping/tags/1.5.5/includes/admin/class-wc-cos-admin.php	(revision 3649833)
+++ /woo-cost-of-shipping/tags/1.5.5/includes/admin/class-wc-cos-admin.php	(revision 3649833)
@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * The admin-specific functionality of the plugin.
+ * 
+ * This plugin can be expanded into net profit reporting by getting the WooCommerce Net Profit plugin
+ * developed by TheRiteSites and found at https://www.theritesites.com/plugins/woocommerce-net-profit
+ *
+ * @link       https://www.theritesites.com
+ * @since      1.0.0
+ *
+ * @package    WC_COS
+ * @subpackage WC_COS/includes/admin
+ */
+
+
+ if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
+ 
+class WC_COS_Admin {
+
+	/**
+	 * Parent plugin class.
+	 *
+	 * @var    WooCommerce_Net_Profit
+	 * @since  1.0.0
+	 */
+	protected $plugin = null;
+
+	/**
+	 * Instance of WC_COS_Admin_Orders
+	 * 
+	 * @var WC_COS_Admin_Orders
+	 * @since 1.0.0
+	 */
+	protected $WC_COS_Admin_Orders;
+
+	/**
+	 * Constructor.
+	 *
+	 * @since    1.0.0
+	 * @param      string    $plugin_name       The name of this plugin.
+	 * @param      string    $version    The version of this plugin.
+	 */
+	public function __construct( $plugin ) {
+
+		$this->plugin = $plugin;
+		
+		$this->admin_classes();
+		
+		$this->init_hooks();
+
+	}
+	
+	/**
+	 * Initializes the classes used in the admin area.
+	 * 
+	 * @since 1.0.0
+	 */
+	public function admin_classes() {
+		include_once 'class-wc-cos-admin-orders.php';
+		$this->WC_COS_Admin_Orders = new WC_COS_Admin_Orders( $this->plugin );
+	}
+	
+	/**
+	 * Initializes the admin area hooks
+	 * 
+	 * @since 1.0.0
+	 */
+	public function init_hooks() {
+		add_filter( 'trs_wc_np_order_cost_extension', array( $this, 'add_cost_of_shipping_to_net_profit'), 10, 1 );
+	}
+
+	public function add_cost_of_shipping_to_net_profit( $costs ) {
+		$var = '_wc_cost_of_shipping';
+		if ( is_array( $costs ) ) {
+			if ( ! isset( $costs[$var] ) ) {
+				$costs[$var] = new StdClass();
+				$costs[$var]->key = $var;
+				$costs[$var]->category = 'cost_of_shipping';
+			}
+		}
+		// if ( is_object( $costs ) ) {
+		// 	if ( is_array( $costs->{'keys'} ) && ( count( $costs->{'keys'} ) < 1 ||  ! in_array( '_wc_cost_of_shipping', $costs->{'keys'} ) ) ) {
+		// 		$costs->{'keys'}[] = '_wc_cost_of_shipping';
+		// 	}
+		// }
+		return $costs;
+	}
+}
Index: /woo-cost-of-shipping/tags/1.5.5/includes/admin/class-wc-cos-safe-domdocument.php
===================================================================
--- /woo-cost-of-shipping/tags/1.5.5/includes/admin/class-wc-cos-safe-domdocument.php	(revision 3649833)
+++ /woo-cost-of-shipping/tags/1.5.5/includes/admin/class-wc-cos-safe-domdocument.php	(revision 3649833)
@@ -0,0 +1,125 @@
+<?php
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
+
+/**
+ * Drop in replacement for DOMDocument that is secure against XML eXternal Entity (XXE) Injection.
+ * Bails if any DOCTYPE is found
+ *
+ * Comments in quotes come from the DOMDocument documentation: http://php.net/manual/en/class.domdocument.php
+ */
+class WC_COS_Safe_DOMDocument extends DOMDocument {
+	/**
+	 * When called non-statically (as an object method) with malicious data, no Exception is thrown, but the object is emptied of all DOM nodes.
+	 *
+	 * @param string $filename The path to the XML document.
+	 * @param int $options Bitwise OR of the libxml option constants. http://us3.php.net/manual/en/libxml.constants.php
+	 *
+	 * @return bool|DOMDocument true on success, false on failure.  If called statically (E_STRICT error), returns DOMDocument on success.
+	 */
+	/**
+	 * PHP 8.1 deprecates overriding a built-in method without a compatible
+	 * return type. DOMDocument::load() declares `: bool`, but this override
+	 * deliberately returns the parsed document or false, and it must keep
+	 * working on PHP 7.0 (the plugin's declared floor), where a `: bool`
+	 * declaration would be a fatal signature mismatch.
+	 *
+	 * ReturnTypeWillChange silences the deprecation without changing behaviour.
+	 * On PHP 7 the line parses as a comment, so it is safe on both.
+	 */
+	#[\ReturnTypeWillChange]
+	public function load( $filename, $options = 0 ) {
+		if ( '' === $filename ) {
+			// "If an empty string is passed as the filename or an empty file is named, a warning will be generated."
+			// "This warning is not generated by libxml and cannot be handled using libxml's error handling functions."
+			trigger_error( 'WC_COS_Safe_DOMDocument::load(): Empty string supplied as input', E_USER_WARNING );
+			return false;
+		}
+
+		if ( ! is_file( $filename ) || ! is_readable( $filename ) ) {
+			// This warning probably would have been generated by libxml and could have been handled handled using libxml's error handling functions.
+			// In WC_Safe_DOMDocument, however, we catch it before libxml, so it can't.
+			// The alternative is to let file_get_contents() handle the error, but that's annoying.
+			trigger_error( 'WC_COS_Safe_DOMDocument::load(): I/O warning : failed to load external entity "' . $filename . '"', E_USER_WARNING );
+			return false;
+		}
+
+		if ( is_object( $this ) ) {
+			return $this->loadXML( file_get_contents( $filename ), $options );
+		} else {
+			// "This method *may* be called statically, but will issue an E_STRICT error."
+			return self::loadXML( file_get_contents( $filename ), $options );
+		}
+	}
+
+	/**
+	 * When called non-statically (as an object method) with malicious data, no Exception is thrown, but the object is emptied of all DOM nodes.
+	 *
+	 * @param string $source The string containing the XML.
+	 * @param int $options Bitwise OR of the libxml option constants. http://us3.php.net/manual/en/libxml.constants.php
+	 *
+	 * @return bool|DOMDocument true on success, false on failure.  If called statically (E_STRICT error), returns DOMDocument on success.
+	 */
+	/**
+	 * PHP 8.1 deprecates overriding a built-in method without a compatible
+	 * return type. DOMDocument::loadXML() declares `: bool`, but this override
+	 * deliberately returns the parsed document or false, and it must keep
+	 * working on PHP 7.0 (the plugin's declared floor), where a `: bool`
+	 * declaration would be a fatal signature mismatch.
+	 *
+	 * ReturnTypeWillChange silences the deprecation without changing behaviour.
+	 * On PHP 7 the line parses as a comment, so it is safe on both.
+	 */
+	#[\ReturnTypeWillChange]
+	public function loadXML( $source, $options = 0 ) {
+		if ( '' === $source ) {
+			// "If an empty string is passed as the source, a warning will be generated."
+			// "This warning is not generated by libxml and cannot be handled using libxml's error handling functions."
+			trigger_error( 'WC_COS_Safe_DOMDocument::loadXML(): Empty string supplied as input', E_USER_WARNING );
+			return false;
+		}
+
+
+		$old = null;
+
+		// PHP 8.0 deprecates libxml_disable_entity_loader() because libxml 2.9+
+		// no longer loads external entities unless asked to, so the call is
+		// only made on PHP 7, where it is still the guard.
+		if ( PHP_VERSION_ID < 80000 && function_exists( 'libxml_disable_entity_loader' ) ) {
+			$old = libxml_disable_entity_loader( true );
+		}
+
+		// Never let the parser reach the network for a DTD or entity, whatever
+		// the caller passed. Belt and braces alongside the DOCTYPE bail below.
+		$return = parent::loadXML( $source, $options | LIBXML_NONET );
+
+		if ( ! is_null( $old ) ) {
+			libxml_disable_entity_loader( $old );
+		}
+
+		if ( ! $return ) {
+			return $return;
+		}
+
+		// "This method *may* be called statically, but will issue an E_STRICT error."
+		$is_this = is_object( $this );
+
+		$object = $is_this ? $this : $return;
+
+		if ( isset( $object->doctype ) ) {
+			if ( $is_this ) {
+				// Get rid of the dangerous input by removing *all* nodes
+				while ( $this->firstChild ) {
+					$this->removeChild( $this->firstChild );
+				}
+			}
+
+			trigger_error( 'WC_COS_Safe_DOMDocument::loadXML(): Unsafe DOCTYPE Detected', E_USER_WARNING );
+
+			return false;
+		}
+
+		return $return;
+	}
+}
Index: /woo-cost-of-shipping/tags/1.5.5/woo-includes/class-wc-cos-dependencies.php
===================================================================
--- /woo-cost-of-shipping/tags/1.5.5/woo-includes/class-wc-cos-dependencies.php	(revision 3649833)
+++ /woo-cost-of-shipping/tags/1.5.5/woo-includes/class-wc-cos-dependencies.php	(revision 3649833)
@@ -0,0 +1,36 @@
+<?php
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
+
+/**
+ * WC Dependency Checker
+ *
+ * Checks if WooCommerce is enabled
+ */
+class WC_COS_Dependencies {
+
+	private static $active_plugins;
+
+	public static function init() {
+
+		self::$active_plugins = (array) get_option( 'active_plugins', array() );
+
+		if ( is_multisite() )
+			self::$active_plugins = array_merge( self::$active_plugins, get_site_option( 'active_sitewide_plugins', array() ) );
+	}
+
+	public static function woocommerce_active_check() {
+
+		if ( ! self::$active_plugins ) self::init();
+
+		return in_array( 'woocommerce/woocommerce.php', self::$active_plugins ) || array_key_exists( 'woocommerce/woocommerce.php', self::$active_plugins );
+	}
+
+	public static function woocommerce_services_active_check() {
+
+		if ( ! self::$active_plugins ) self::init();
+
+		return in_array( 'woocommerce-services/woocommerce-services.php', self::$active_plugins ) || array_key_exists( 'woocommerce-services/woocommerce-services.php', self::$active_plugins );
+	}
+}
Index: /woo-cost-of-shipping/tags/1.5.5/woo-includes/woo-functions.php
===================================================================
--- /woo-cost-of-shipping/tags/1.5.5/woo-includes/woo-functions.php	(revision 3649833)
+++ /woo-cost-of-shipping/tags/1.5.5/woo-includes/woo-functions.php	(revision 3649833)
@@ -0,0 +1,28 @@
+<?php
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
+
+/**
+ * Functions used by plugins
+ */
+if ( ! class_exists( 'WC_COS_Dependencies' ) )
+	require_once 'class-wc-cos-dependencies.php';
+
+/**
+ * WC Detection
+ */
+if ( ! function_exists( 'is_woocommerce_active' ) ) {
+	function is_woocommerce_active() {
+		return WC_COS_Dependencies::woocommerce_active_check();
+	}
+}
+
+/**
+ * WC Services Detection
+ */
+if ( ! function_exists( 'is_woocommerce_services_active' ) ) {
+	function is_woocommerce_services_active() {
+		return WC_COS_Dependencies::woocommerce_services_active_check();
+	}
+}
Index: /woo-cost-of-shipping/tags/1.5.5/woocommerce-cost-of-shipping.php
===================================================================
--- /woo-cost-of-shipping/tags/1.5.5/woocommerce-cost-of-shipping.php	(revision 3649833)
+++ /woo-cost-of-shipping/tags/1.5.5/woocommerce-cost-of-shipping.php	(revision 3649833)
@@ -0,0 +1,357 @@
+<?php
+/**
+ * Plugin Name: Cost of Shipping for WooCommerce
+ * Plugin URI:  https://www.theritesites.com/plugins/woo-cost-of-shipping
+ * Description: Allows the association of the cost of shipping to WooCommerce orders
+ * Version:     1.5.5
+ * Author:      TheRiteSites
+ * Author URI:  https://www.theritesites.com
+ * Donate link: https://www.theritesites.com/plugins/woo-cost-of-shipping
+ * License:     GPL-2.0+
+ * Text Domain: woo-cost-of-shipping
+ * Domain Path: /languages 
+ * WC tested up to: 10.9
+ * WC requires at least: 3.0
+ * Requires at least: 5.2
+ *
+ * @link    https://www.theritesites.com/plugins/woo-cost-of-shipping
+ *
+ * @package WC_COS
+ * @version 1.5.5
+ */
+
+/**
+ * 
+ * This plugin can be expanded into net profit reporting by getting the WooCommerce Net Profit plugin
+ * developed by TheRiteSites and found at https://www.theritesites.com/plugins/woocommerce-net-profit
+ * 
+ * Copyright (c) 2020,2024 TheRiteSites (email : contact@theritesites.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2 or, at
+ * your discretion, any later version, as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
+
+if ( ! function_exists( 'is_woocommerce_active' ) ) {
+	require_once( 'woo-includes/woo-functions.php' );
+}
+
+/**
+ * Main initiation class.
+ *
+ * @since  1.0.0
+ */
+final class WC_COS {
+
+	/**
+	 * Current version.
+	 *
+	 * @var    string
+	 * @since  1.0.0
+	 */
+	const VERSION = '1.5.5';
+
+	/**
+	 * Debug flag
+	 * 
+	 * @var		boolean
+	 * @since 	1.1.0
+	 */
+	const DEBUG = false;
+
+	/**
+	 * URL of plugin directory.
+	 *
+	 * @var    string
+	 * @since  1.0.0
+	 */
+	protected $url = '';
+
+	/**
+	 * Path of plugin directory.
+	 *
+	 * @var    string
+	 * @since  1.0.0
+	 */
+	protected $path = '';
+
+	/**
+	 * Plugin basename.
+	 *
+	 * @var    string
+	 * @since  1.0.0
+	 */
+	protected $basename = '';
+
+	/**
+	 * Detailed activation error messages.
+	 *
+	 * @var    array
+	 * @since  1.0.0
+	 */
+	protected $activation_errors = array();
+
+	/**
+	 * Singleton instance of plugin.
+	 *
+	 * @var    WC_COS
+	 * @since  1.0.0
+	 */
+	protected static $single_instance = null;
+	
+	/**
+	 * instance of WC_COS_Admin
+	 * 
+	 * @var WC_COS_Admin
+	 * @since 1.0.0
+	 */
+	protected $WC_COS_Admin;
+	
+
+	/**
+	 * Creates or returns an instance of this class.
+	 *
+	 * @since   1.0.0
+	 * @return  WC_COS A single instance of this class.
+	 */
+	public static function get_instance() {
+		if ( null === self::$single_instance ) {
+			self::$single_instance = new self();
+		}
+
+		return self::$single_instance;
+	}
+
+	/**
+	 * Sets up our plugin.
+	 *
+	 * @since  1.0.0
+	 */
+	protected function __construct() {
+		$this->basename = plugin_basename( __FILE__ );
+		$this->url      = plugin_dir_url( __FILE__ );
+		$this->path     = plugin_dir_path( __FILE__ );
+	}
+
+	/**
+	 * Attach other plugin classes to the base plugin class.
+	 *
+	 * @since  1.0.0
+	 */
+	public function plugin_classes() {
+		require_once plugin_dir_path( __FILE__ ) . 'includes/admin/class-wc-cos-admin.php';
+		require_once plugin_dir_path( __FILE__ ) . 'includes/admin/class-wc-cos-admin-orders.php';
+		require_once plugin_dir_path( __FILE__ ) . 'includes/admin/class-wc-cos-safe-domdocument.php';
+		// $this->plugin_class = new WCCOS_Plugin_Class( $this );
+		$this->WC_COS_Admin = new WC_COS_Admin( $this );
+
+	} // END OF PLUGIN CLASSES FUNCTION
+
+	/**
+	 * Add hooks and filters.
+	 * Priority needs to be
+	 * < 10 for CPT_Core,
+	 * < 5 for Taxonomy_Core,
+	 * and 0 for Widgets because widgets_init runs at init priority 1.
+	 *
+	 * @since  1.0.0
+	 */
+	public function hooks() {
+		add_action( 'init', array( $this, 'init' ), 0 );
+	}
+
+	/**
+	 * Activate the plugin.
+	 *
+	 * @since  1.0.0
+	 */
+	public function _activate() {
+		// Bail early if requirements aren't met.
+		if ( ! $this->check_requirements() ) {
+			return;
+		}
+
+		// Make sure any rewrite functionality has been loaded.
+		flush_rewrite_rules();
+	}
+
+	/**
+	 * Deactivate the plugin.
+	 * Uninstall routines should be in uninstall.php.
+	 *
+	 * @since  1.0.0
+	 */
+	public function _deactivate() {
+		// Add deactivation cleanup functionality here.
+	}
+
+	/**
+	 * Init hooks
+	 *
+	 * @since  1.0.0
+	 */
+	public function init() {
+
+		// Bail early if requirements aren't met.
+		if ( ! $this->check_requirements() ) {
+			return;
+		}
+
+		// Load translated strings for plugin.
+		load_plugin_textdomain( 'woo-cost-of-shipping', false, dirname( $this->basename ) . '/languages/' );
+
+		// Initialize plugin classes.
+		$this->plugin_classes();
+	}
+
+	/**
+	 * Check if the plugin meets requirements and
+	 * disable it if they are not present.
+	 *
+	 * @since  1.0.0
+	 *
+	 * @return boolean True if requirements met, false if not.
+	 */
+	public function check_requirements() {
+
+		// Bail early if plugin meets requirements.
+		if ( $this->meets_requirements() ) {
+			return true;
+		}
+
+		// Add a dashboard notice.
+		add_action( 'all_admin_notices', array( $this, 'requirements_not_met_notice' ) );
+
+		// Deactivate our plugin.
+		add_action( 'admin_init', array( $this, 'deactivate_me' ) );
+
+		// Didn't meet the requirements.
+		return false;
+	}
+
+	/**
+	 * Deactivates this plugin, hook this function on admin_init.
+	 *
+	 * @since  1.0.0
+	 */
+	public function deactivate_me() {
+
+		// We do a check for deactivate_plugins before calling it, to protect
+		// any developers from accidentally calling it too early and breaking things.
+		if ( function_exists( 'deactivate_plugins' ) ) {
+			deactivate_plugins( $this->basename );
+		}
+	}
+
+	/**
+	 * Check that all plugin requirements are met.
+	 *
+	 * @since  1.0.0
+	 *
+	 * @return boolean True if requirements are met.
+	 */
+	public function meets_requirements() {
+
+		// Do checks for required classes / functions or similar.
+		// Add detailed messages to $this->activation_errors array.
+		
+		$flag = true;
+		
+		if ( ! is_woocommerce_active() ) {
+			array_push( $this->activation_errors, 'Cost of Shipping for WooCommerce requires WooCommerce to be installed and active.' );
+			$flag = false;
+		} 
+		
+		
+		return $flag;
+	}
+
+	/**
+	 * Adds a notice to the dashboard if the plugin requirements are not met.
+	 *
+	 * @since  1.0.0
+	 */
+	public function requirements_not_met_notice() {
+
+		// Compile default message.
+		$default_message = sprintf( __( 'Cost of Shipping for WooCommerce is missing requirements and has been <a href="%s">deactivated</a>. Please make sure all requirements are available.', 'woo-cost-of-shipping' ), admin_url( 'plugins.php' ) );
+
+		// Default details to null.
+		$details = null;
+
+		// Add details if any exist.
+		if ( $this->activation_errors && is_array( $this->activation_errors ) ) {
+			$details = '<small>' . implode( '</small><br /><small>', $this->activation_errors ) . '</small>';
+		}
+
+		// Output errors.
+		?>
+		<div id="message" class="error">
+			<p><?php echo wp_kses_post( $default_message ); ?></p>
+			<?php echo wp_kses_post( $details ); ?>
+		</div>
+		<?php
+	}
+
+	/**
+	 * Magic getter for our object.
+	 *
+	 * @since  1.0.0
+	 *
+	 * @param  string $field Field to get.
+	 * @throws Exception     Throws an exception if the field is invalid.
+	 * @return mixed         Value of the field.
+	 */
+	public function __get( $field ) {
+		switch ( $field ) {
+			case 'version':
+				return self::VERSION;
+			case 'debug':
+				return self::DEBUG || WP_DEBUG;
+			case 'basename':
+			case 'url':
+			case 'path':
+				return $this->$field;
+			default:
+				throw new Exception( 'Invalid ' . __CLASS__ . ' property: ' . $field );
+		}
+	}
+}
+
+/**
+ * Grab the WC_COS object and return it.
+ * Wrapper for WC_COS::get_instance().
+ *
+ * @since  1.0.0
+ * @return WC_COS  Singleton instance of plugin class.
+ */
+function wc_cos() {
+	return WC_COS::get_instance();
+}
+
+// Kick it off.
+add_action( 'plugins_loaded', array( wc_cos(), 'hooks' ) );
+
+// Activation and deactivation.
+register_activation_hook( __FILE__, array( wc_cos(), '_activate' ) );
+register_deactivation_hook( __FILE__, array( wc_cos(), '_deactivate' ) );
+
+add_action( 'before_woocommerce_init', function() {
+	if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
+		\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
+	}
+} );
