Jump to content
  • Checkout
  • Login
  • Get in touch

osCommerce

The e-commerce.

Cron Simulator


Jack_mcs

Recommended Posts

This is probably a dumb question Jack and if so, please forgive me but if it's already declared in admin/index.php does it need to be declared again in cron simulator or could we just delete the declaration of that function in the cron simulator? If not maybe we just need to rename it?

 

Dan

That function is a part of the oscommerce code, not this contributions. When the page for this contribuion loads it automatically knows that function exists. That is how oscommerce works. When you try to switch to the shop side, the same funciton is declared there but in a separate file. You can't delete those since they are needed for the normal operation of oscommerce. It may work if the include statement in index.php is moved before the includes for application_top but the code in the cron simulator module would have to be re-written to not use standard oscommere functions. In theory, that should work but I haven't had time to play around with it.

Support Links:

For Hire: Contact me for anything you need help with for your shop: upgrading, hosting, repairs, code written, etc.

Get the latest versions of my addons

Recommended SEO Addons

Link to comment
Share on other sites

  • 1 month later...
  • Replies 50
  • Created
  • Last Reply

Top Posters In This Topic

Hello,

 

Well after months since my first time I posted on here earlier in this thread, it never did work. I tried to install this again last night but on a 2.3.1 shop as the hosting package dosent support SSH or CRON on the starter 1&1 package and guess what? Same issue, it does not save to the database, even after the changes mentioned above, no offence but looking at the code looks like its been wrote whilst drunk, it has instructions and is packaged for 2.3.1, yet the admin side is messed up(which is a simple fix btw, its wrote for 2.2 but still a packaging error).

 

There's also many spelling errors, are you sure this is THE exact same version you say is working fine on another shop you programmed it for?

 

For instance, this dosen't look like a finished addon at all, the spelling errors are pretty apparant on the actual cron simulator page, CON JOB instead of CRONJOB

 

Line 16 of admin/cron_simulator says: $seclectedArray = array();

 

Shouldn't this be $selectedArray = array(); ??

 

Again at:

 

admin/includes/languages/english/cron_simulator.php: define('TEXT_SELECT_SCRIPT', 'Select a Con Job');

 

Again in the same file:

 

define('TEXT_INTRO', 'Cron Simulator allows scripts to be ran at speicifc times.');

 

define('ERROR_INVALID_PERIOD', 'Frequesncy is unknown.');

 

Oh and also the fact the cron does not save to the database and the fact there's also a missing define in the version checker code!

 

 

Anyway I uninstalled this again, and here's another way for others that come across this, infact this works the same way and does the same thing as this contribution intends to do and should work with any version of oscommerce or any website.

 

Check it out here:

 

http://addons.oscommerce.com/info/8240

 

Regards,

Chris.

Link to comment
Share on other sites

Mistakes such as you mention are always in the first version of any contribution. I suspect the problem is just an installation mistake but it's good you found an alternative so that is not an issue..

Support Links:

For Hire: Contact me for anything you need help with for your shop: upgrading, hosting, repairs, code written, etc.

Get the latest versions of my addons

Recommended SEO Addons

Link to comment
Share on other sites

Yeah minor spelling mistakes... Its definately not an installation mistake, at least not on my part, I followed the simple installation instructions, let's face it its not the hardest contribution to add, I have been messing around with PHP and oscommerce for well over 5 years and integrated and programmed many features and made many customisations. Have you checked the code you uploaded is the exact same code as you uploaded to the shop you programmed it for? The code does not work. I have came back to this months on and added it to another shop, different server and same thing, its not a coincidence.

Link to comment
Share on other sites

  • 4 months later...

As there is no updated version and I'm unable to upload it to the addons, here is a fix for this contribution. It fixes the following:

  • Fix the layout in OSC 2.3.1 (it was using the old osc 2.2 layout)
  • Fix the bug when adding a new cron job it is not being saved, as mentioned by Jack in post #14
  • Fix the version check as it was looking for FILENAME_HEADER_TAGS_SEO

 

I copied here the entire code of the file admin/cron_simulator.php. To update, just replace the contents of that file by this code here:

<?php
/*
 $Id: cron_simulator.php,v 1.0 2010/12/13
 cron_simulator Originally Created by: Jack_mcs - http://www.oscommerce-solution.com
 osCommerce, Open Source E-Commerce Solutions
 http://www.oscommerce.com
 Copyright (c) 2003 osCommerce
 Portions Copyright 2010 oscommerce-solution.com
 Released under the GNU General Public License
*/

 require('includes/application_top.php');

 $seclectedArray = array();

 /********************** BEGIN VERSION CHECKER *********************/
 if (file_exists(DIR_WS_FUNCTIONS . 'version_checker.php'))
 {
  require(DIR_WS_LANGUAGES . $language . '/version_checker.php');
  require(DIR_WS_FUNCTIONS . 'version_checker.php');
  $contribPath = 'http://addons.oscommerce.com/info/unknown';
  $currentVersion = 'Cron Simulator V 1.0';
  $contribName = 'Cron Simulator V';
  $versionStatus = '';
 }
 /********************** END VERSION CHECKER *********************/  require(DIR_WS_LANGUAGES . $language . '/' . FILENAME_CRON_SIMULATOR);
 if (isset($_POST['action']) && $_POST['action'] == 'process') {

  if (isset($_POST['update_cron_x'])) {
	  $enabled	 = (isset($_POST['enabled_in']) ? 1 : 0);
	  $script_name = tep_db_prepare_input($_POST['script_name_in']); //use different names to get around global reload problem with the input function
	  $file_name   = tep_db_prepare_input($_POST['file_name_in']);
	  $time_to_run = tep_db_prepare_input($_POST['time_to_run_in']);
	  $frequency   = tep_db_prepare_input($_POST['frequency_in']);
	  $error = false;
	  if (empty($script_name)) {
		  $error = true;
		  $messageStack->add(ERROR_SCRIPT_NAME, 'error');
	  }

	  if (empty($file_name) || substr($file_name, strlen($file_name) -4) != '.php') {
		  $error = true;
		  $messageStack->add(ERROR_FILE_NAME, 'error');
	  }
	  if (empty($time_to_run)) {
		  $error = true;
		  $messageStack->add(ERROR_TIME_TO_RUN, 'error');
	  }

	  if (! $error) {
		  $sql_data_array = array('enabled' =>  $enabled,
								   'script_name' =>  tep_db_input($script_name),
								   'file_name'   =>  tep_db_input($file_name),
								   'time_to_run' =>  tep_db_input($time_to_run),
								   'frequency'   =>  $frequency
								  );

		  $cs_query = tep_db_query("select 1 from " . TABLE_CRON_SIMULATOR . " where script_name = '" . $script_name . "'");

		  if (tep_db_num_rows($cs_query) > 0)  { //then entry exists
			  tep_db_perform(TABLE_CRON_SIMULATOR, $sql_data_array, 'update', "script_name = '" . $script_name . "'");
		  } else {
			  tep_db_perform(TABLE_CRON_SIMULATOR, $sql_data_array);
		  }									  
	  }
  } else {

  /********************** LOAD FROM THE SAVED SCRIPTS ***********************/
 //	    if (isset($_POST['scripts']) && $_POST['scripts'] != TEXT_SELECT_SCRIPT ) {
   //		  $cs_query = tep_db_query("select * from " . TABLE_CRON_SIMULATOR . " where script_name = '" . tep_db_prepare_input($_POST['scripts']) . "' limit 1");
  //	    if (tep_db_num_rows($cs_query)) {
    //		  $cs = tep_db_fetch_array($cs_query);
	  //	    $selectedArray = $cs;
	    //  }
	  //}
  }

 } else {	

  /********************** CHECK THE VERSION ***********************/
  if (isset($_POST['action']) && $_POST['action'] == 'getversion') {
    if (isset($_POST['version_check']) && $_POST['version_check'] == 'on')
	  $versionStatus = AnnounceVersion($contribPath, $currentVersion, $contribName);
  }
 }

 $frequencyArray = array(array('id' => FREQUENCY_DAILY, 'text' => FREQUENCY_DAILY),
					   array('id' => FREQUENCY_WEEKLY, 'text' => FREQUENCY_WEEKLY),
					   array('id' => FREQUENCY_MONTHLY, 'text' => FREQUENCY_MONTHLY)
					  );

 $scriptsArray = array();					   
 $scriptsArray[] = array('id' => TEXT_SELECT_SCRIPT, 'text' => TEXT_SELECT_SCRIPT);
 $cs_query = tep_db_query("select * from " . TABLE_CRON_SIMULATOR);
 if (tep_db_num_rows($cs_query)) {
  while ($cs = tep_db_fetch_array($cs_query)) {
	  $scriptsArray[] = array('id' => $cs['script_name'], 'text' => $cs['script_name']);
	  if (isset($_POST['scripts']) && $_POST['scripts'] == $cs['script_name'] ) {
		  $selectedArray = $cs;  //show what was selected
	  }	   
  }
 } 
 require(DIR_WS_INCLUDES . 'template_top.php');
?>
<?php /*
<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN">
<html <?php echo HTML_PARAMS; ?>>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=<?php echo CHARSET; ?>">
<title><?php echo TITLE; ?></title>
<link rel="stylesheet" type="text/css" href="includes/stylesheet.css">
<style type="text/css">
table.BorderedBox {border: ridge #ddd 3px; background-color: #eee; }
table.BorderedBoxWhite {border: ridge #ddd 3px; background-color: #fff; }
td.HTC_Head {font-family: Verdana, Arial, sans-serif; color: sienna; font-size: 18px; font-weight: bold; }
td.HTC_subHead {font-family: Verdana, Arial, sans-serif; color: sienna; font-size: 12px; }
.HTC_title {background: #fof1f1; text-align: center;}
</style>
</head>
<body marginwidth="0" marginheight="0" topmargin="0" bottommargin="0" leftmargin="0" rightmargin="0" bgcolor="#FFFFFF">
<!-- header //-->
<?php require(DIR_WS_INCLUDES . 'header.php'); ?>
<!-- header_eof //-->
<!-- body //-->
<table border="0" width="100%" cellspacing="2" cellpadding="2">
 <tr>
   <td width="<?php echo BOX_WIDTH; ?>" valign="top"><table border="0" width="<?php echo BOX_WIDTH; ?>" cellspacing="1" cellpadding="1" class="columnLeft">
<!-- left_navigation //-->
<?php require(DIR_WS_INCLUDES . 'column_left.php'); ?>
<!-- left_navigation_eof //-->
   </table></td> */ ?>
<!-- body_text //-->
   <td width="100%" valign="top"><table border="0" width="100%" cellspacing="0" cellpadding="2">
 <tr>
  <td><table border="0" width="100%" cellspacing="0" cellpadding="2" class="BorderedBox">
   <tr>
    <td><table border="0" width="95%" cellspacing="0" cellpadding="2">
	 <tr>
	  <td class="HTC_Head" valign="top" style="white-space:nowrap;"><?php echo $currentVersion; ?></td>
	 </tr>
	 <tr>
	  <td class="smallText" valign="top"><?php echo HEADING_TITLE_SUPPORT_THREAD; ?></td>
	 </tr>
    </table></td>
    <td><table border="0" width="100%">
	 <tr>
	  <td class="smallText" align="right"><?php echo HEADING_TITLE_AUTHOR; ?></td>
	 </tr>
	 <?php
	 if (function_exists('AnnounceVersion')) {
	  if (HEADER_TAGS_ENABLE_VERSION_CHECKER == 'true') {
	 ?>
	 <tr>
	  <td class="smallText" align="right" style="font-weight: bold; color: red;"><?php echo AnnounceVersion($contribPath, $currentVersion, $contribName); ?></td>
	 </tr>
	 <?php } else if (tep_not_null($versionStatus)) {
	   echo '<tr><td class="smallText" align="right" style="font-weight: bold; color: red;">' . $versionStatus . '</td></tr>';
	 } else {
	   echo tep_draw_form('version_check', FILENAME_CRON_SIMULATOR, '', 'post') . tep_draw_hidden_field('action', 'getversion');
	 ?>
	 <tr>
	  <td class="smallText" align="right" style="font-weight: bold; color: red;"><INPUT TYPE="radio" NAME="version_check" onClick="this.form.submit();"><?php echo TEXT_VERSION_CHECK_UPDATES; ?></td>
	 </tr>
	 </form>
	 <?php } } else { ?>
	    <tr>
		   <td class="smallText" align="right" style="font-weight: bold; color: red;"><?php echo TEXT_MISSING_VERSION_CHECKER; ?></td>
	    </tr>
	 <?php } ?>
    </table></td>
   </tr>
   <tr>
    <td colspan="2"><?php echo tep_draw_separator('pixel_trans.gif', '100%', '10'); ?></td>
   </tr>
   <tr>
    <td class="HTC_subHead" colspan="2"><?php echo TEXT_INTRO; ?></td>
 </tr>
 <tr>
    <td colspan="2"><?php echo tep_draw_separator('pixel_trans.gif', '100%', '10'); ?></td>
   </tr>	  
  </table></td>
 </tr>

 <!-- Begin of CRON_SIMULATOR -->
 <tr>
  <td colspan="4"><?php echo tep_draw_separator('pixel_silver.gif', '100%', '2'); ?></td>
 </tr>
 <tr>
  <td><table border="0" cellpadding="0"  class="BorderedBox">
   <?php echo tep_draw_form('cron_simulator', FILENAME_CRON_SIMULATOR, '', 'post') . tep_draw_hidden_field('action', 'process'); ?>
    <tr>
	 <td width="100%" valign="top"><table border="0" width="100%" cellspacing="0" cellpadding="2">
	  <tr>
	   <td><table border="0" width="100%">
	    <tr>			
		 <td class="smallText" width="35%" align="center"><?php echo TEXT_ENABLE; ?></td>
		 <td class="smallText" width="35%" align="center"><?php echo TEXT_SCRIPT_NAME; ?></td>
		 <td class="smallText" width="35%" align="center"><?php echo TEXT_FILE_NAME; ?></td>
		 <td class="smallText" width="35%" align="center"><?php echo TEXT_TIME_TO_RUN; ?></td>
		 <td class="smallText" width="35%" align="center"><?php echo TEXT_FREQUENCY; ?></td>
	    </tr>
	    <tr>			
		 <td><?php echo tep_draw_checkbox_field('enabled_in', '', ($selectedArray['enabled'] ? 'checked' : '')); ?> </td>
		 <td class="smallText"><?php echo tep_draw_input_field('script_name_in', $selectedArray['script_name'], 'maxlength="255" size="15"', false, '', false); ?> </td>
		 <td class="smallText"><?php echo tep_draw_input_field('file_name_in', $selectedArray['file_name'], 'maxlength="255" size="15"', false, '', false); ?> </td>
		 <td class="smallText"><?php echo tep_draw_input_field('time_to_run_in', $selectedArray['time_to_run'], 'maxlength="255" size="10"', false, '', false); ?> </td>
		 <td class="smallText"><?php echo tep_draw_pull_down_menu('frequency_in', $frequencyArray, $selectedArray['frequency']); ?></td>
	    </tr>
	   </table></td>

	   <td valign="top"><table border="0" width="100%">
	    <tr>
		 <td class="main"><?php echo tep_draw_pull_down_menu('scripts', $scriptsArray, '', 'onChange="this.form.submit();"'); ?></td>
	    </tr>
	   </table></td>		   

	  </tr>
	 </table></td>
    </tr>


    <tr>
	 <td><?php echo tep_draw_separator('pixel_trans.gif', '100%', '10'); ?></td>
    </tr>
    <tr>
	 <td class="smallText" align="center"><INPUT type="image" src="<?php echo DIR_WS_LANGUAGES . $language . '/images/buttons/button_update.gif'; ?>" NAME="update_cron"></td>
    </tr>
    <tr>
	 <td><?php echo tep_black_line(); ?></td>
    </tr>		
   </form>
  </table></td>
 </tr>
 <!-- end of CRON_SIMULATOR--> 

   </table></td>
<!-- body_text_eof //-->
 </tr>
</table>
<!-- body_eof //-->
<?php /*
<!-- footer //-->
<?php require(DIR_WS_INCLUDES . 'footer.php'); ?>
<!-- footer_eof //-->
<br>
</body>
</html>
 */ ?>
<?php
 require(DIR_WS_INCLUDES . 'template_bottom.php');
 require(DIR_WS_INCLUDES . 'application_bottom.php');
?>

Link to comment
Share on other sites

  • 5 months later...

It isn't being loaded by this contribution. When Cron Simulator is ran in admin. it loads in the application_top file, as any script in admin does. But when it tries to execute a scrit on the shop side, the shops side functions get reloaded by that script, causing the duplicate problem. The parts of the code causing the problem could be re-coded so it doesn't happen but that opens up big problem since any script ran that way would need to be rewritten and that doesn't make for a very usable contribution. The only way I can see around it without disrupting everything else is to rewrite the Cron Simulator script to run as a standalone script. But that removes the automatic process of running it so you might as well just run the scripts themselves manually. So as it stands now, scripts made to run from admin should work. Those made to run on the shop side may fail, depending upon how they are coded. I'll play around with it and post if I find a sensible solution.

 

I've changed the following:

 

In /admin/modules/cron_simulator.php

 

Line 33

 

Replace "require $scriptsArray['file_name'];"

 

With

 

" $ch = curl_init();

curl_setopt($ch, CURLOPT_URL,"".$scriptsArray['file_name']."");

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

curl_exec($ch);

curl_close ($ch);

"

 

And now works for files outside the folder "admin", using the absolute path of the file (eg http://www.yourdomain.com/../file.php) in the "File Name" field. Hope that helps.

Link to comment
Share on other sites

  • 2 months later...

just installed this an almost success... 2 problems left

 

1. version check thing still wrong even thou the code from post 30 should take care of it. looks excatly like the attached thumb in post 23

2. in the folder new_files_to_upload there are this one /admin/includes/modules/cron_simulator.php should that one just be placed in /admin/includes/modules ? and not one of the 4 subfolders cfg_modules, dashboard, newsletters, security_check ?

 

/bo

Link to comment
Share on other sites

just installed this an almost success... 2 problems left

 

1. version check thing still wrong even thou the code from post 30 should take care of it. looks excatly like the attached thumb in post 23

2. in the folder new_files_to_upload there are this one /admin/includes/modules/cron_simulator.php should that one just be placed in /admin/includes/modules ? and not one of the 4 subfolders cfg_modules, dashboard, newsletters, security_check ?

 

/bo

1 - Do you mean my Version Check contribution? I don't have anything to do with post 30 so I can't help with that.

 

2 - Yes.

Support Links:

For Hire: Contact me for anything you need help with for your shop: upgrading, hosting, repairs, code written, etc.

Get the latest versions of my addons

Recommended SEO Addons

Link to comment
Share on other sites

ohh.. got an extra idea...

 

since i have modded my admin index to refresh every 10 sec's (so far.. might go for every 30 sec's later) during store hours (6 hours and 45 mins every day) the script would for sure be run...

 

but what happens if i decide to set the script to run outside store hours? ie in the night where i would not bother the store nor the customers?

 

would there be any benefit from triggering the script also when customers land on the store index?

Link to comment
Share on other sites

about version check... yes

 

the code in post 30 and your version are still the same ie like this:

 

/********************** BEGIN VERSION CHECKER *********************/
 if (file_exists(DIR_WS_FUNCTIONS . 'version_checker.php'))
 {
  require(DIR_WS_LANGUAGES . $language . '/version_checker.php');
  require(DIR_WS_FUNCTIONS . 'version_checker.php');
  $contribPath = 'http://addons.oscommerce.com/info/unknown';
  $currentVersion = 'Cron Simulator V 1.0';
  $contribName = 'Cron Simulator V';
  $versionStatus = '';
 }
 /********************** END VERSION CHECKER *********************/ 

 

it still gives : TEXT_MISSING_VERSION_CHECKER

 

maybe there is something missing in a language file ???

Link to comment
Share on other sites

would there be any benefit from triggering the script also when customers land on the store index?

That's a lot of extra checking (every page, every customer or search engine). It's a quick test but would increase the load a little unnecessairly, in my opinion.

Support Links:

For Hire: Contact me for anything you need help with for your shop: upgrading, hosting, repairs, code written, etc.

Get the latest versions of my addons

Recommended SEO Addons

Link to comment
Share on other sites

it still gives : TEXT_MISSING_VERSION_CHECKER

 

maybe there is something missing in a language file ???

You have to install the version checker contribution.

Support Links:

For Hire: Contact me for anything you need help with for your shop: upgrading, hosting, repairs, code written, etc.

Get the latest versions of my addons

Recommended SEO Addons

Link to comment
Share on other sites

a bit confused about the time... the language file says range 0000 - 2399... should it not end with 2359 as in 23:59 ?

That is a typo. You are correct in that it should be 2359. Thank you for pointing it out.

Support Links:

For Hire: Contact me for anything you need help with for your shop: upgrading, hosting, repairs, code written, etc.

Get the latest versions of my addons

Recommended SEO Addons

Link to comment
Share on other sites

  • 2 years later...

I've corrected all those errors listed in this thread, however as soon as cron_simulator is icluded on index.php - require(DIR_WS_MODULES . 'cron_simulator.php');, I've got this error:

Fatal error: Cannot redeclare do_magic_quotes_gpc() (previously declared in /home/user/public_html/Admin/includes/functions/compatibility.php:18) in /home/user/public_html/includes/functions/compatibility.php on line 30

I've double checked that both compatibility.php files in admin as well as in catalog contain correct code

  function do_magic_quotes_gpc(&$ar) {
    if (!is_array($ar)) return false;

    reset($ar);
    while (list($key, $value) = each($ar)) {
      if (is_array($ar[$key])) {
        do_magic_quotes_gpc($ar[$key]);
      } else {
        $ar[$key] = addslashes($value);
      }
    }
    reset($ar);
  }

Absinthe Original Liquor Store

Link to comment
Share on other sites

Mr_a - the code may be correct but the error message is telling you that it is being called more than once probably because it looks as though both compatability.php files (admin / catalog) are being called someplace in the code

 

Idealy you'd weed through the code and work out what/where/when/why but that may take sometime - here's a very hacky suggestion that may fix the problem but not screw up anything else....

 

Actually, having looked at the file at: /home/user/public_html/includes/functions/compatibility.php  the 'hacky' stuff is in there but not for that function - go to that file and it will have the code as you posted:

  function do_magic_quotes_gpc(&$ar) {
    if (!is_array($ar)) return false;

    reset($ar);
    while (list($key, $value) = each($ar)) {
      if (is_array($ar[$key])) {
        do_magic_quotes_gpc($ar[$key]);
      } else {
        $ar[$key] = addslashes($value);
      }
    }
    reset($ar);
  }

Now wrap that in a  if (!function_exists('blah de blah')) {}  :

 if (!function_exists('do_magic_quotes_gpc')) {
//----------------------------
function do_magic_quotes_gpc(&$ar) {
if (!is_array($ar)) return false;

reset($ar);
while (list($key, $value) = each($ar)) {
if (is_array($ar[$key])) {
do_magic_quotes_gpc($ar[$key]);
} else {
$ar[$key] = addslashes($value);
}
}
reset($ar);
}



//-------------------------------


}

If you look further into the file you'll see similar wraps

Link to comment
Share on other sites

Hi, this is now getting exhausting... it worked for 24 hours only... One day later, I'm again unable to access admin due to this fatal error:

Fatal error: Cannot redeclare tep_db_connect() (previously declared in /home/user/public_html/Admin/includes/functions/database.php:13) in /home/user/public_html/includes/functions/database.php on line 19

No need to mention that all works fine if remove cron simulator from admin's index.php file.

Absinthe Original Liquor Store

Link to comment
Share on other sites

I just want to share, the error is gone, therefore it was most likely caused by the error mentioned above. However the cron simulator does nothing... I tested on googlefeeder.php and no file was called, no file was created or uploaded.

Absinthe Original Liquor Store

Link to comment
Share on other sites

  • 2 years later...

@Jack_mcs Jack I was looking for a Fake Cron routine for osC and stumbled on this old thread.  Looks like I tried to install it before and discovered that it wouldn't work...I see a few folks have taken a run at fixing it over the years but I'm not clear on whether those fixes panned out or not.  Do you recall what happened with the add on.  Did it ever get sorted out?

Dan

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...