[ Avaa Bypassed ]




Upload:

Command:

hmhc3928@3.16.212.0: ~ $
<?php
require_once dirname(__FILE__).'/accesscheck.php';

include_once dirname(__FILE__).'/date.php';
include_once dirname(__FILE__).'/analytics.php';

$errormsg = '';
$done = 0;
$messageid = 0;
$forwardsubject = $forwardmessage = $forwardfooter = '';
$placeinqueue = '';
$sendtestresult = '';
$duplicate_atribute = 0; // not actually used it seems @@@ check
$embargo = new date('embargo');
$embargo->useTime = true;
$repeatuntil = new date('repeatuntil');
$repeatuntil->useTime = true;
$requeueuntil = new date('requeueuntil');
$requeueuntil->useTime = true;

if (ALLOW_ATTACHMENTS) {
    $enctype = 'enctype="multipart/form-data"';
} else {
    $enctype = '';
}

//## variable initialisation and sanity checks
if (isset($_GET['id'])) {
    $id = sprintf('%d', $_GET['id']);
} else {
    $id = 0;
}
//# page actions
$send = isset($_POST['send']);
$prepare = isset($_POST['prepare']);
$save = !empty($_POST['save']) || !empty($_POST['followupto']);
$savedraft = !empty($_POST['savedraft']);
$sendtest = !empty($_POST['sendtest']);
$baseurl = PageURL2('send'.'&amp;id='.$id);

if (!isset($_GET['tab'])) {
    $_GET['tab'] = '';
}
$_GET['tab'] = strip_tags($_GET['tab']);
if (!empty($_GET['tab'])) {
    $baseurl .= '&tab='.$_GET['tab'];
}

//## if we're not working on an existing message, create one and redirect to edit it
if (!$id) {
    $defaulttemplate = getConfig('defaultmessagetemplate');
    $defaultfooter = getConfig('messagefooter');
    Sql_Query(sprintf('insert into %s (subject, status, entered, sendformat, embargo, repeatuntil, owner, template, tofield, replyto,footer, uuid)
    values("(no title)", "draft", now(), "HTML", now(), now(), %d, %d, "", "", "%s", "%s" )',
        $GLOBALS['tables']['message'],
        $_SESSION['logindetails']['id'],
        $defaulttemplate, sql_escape($defaultfooter), (string) Uuid::generate(4)));

    $id = Sql_Insert_Id();
    if (empty($id)) { // something went wrong creating the campaign
        Fatal_Error(s('Unable to create campaign, did you forget to upgrade the database?'));
        $done = 1;

        return;
    }

    if (isset($_GET['list'])) {
        if ($_GET['list'] == 'all') {
            $req = Sql_Query('select id from '.$tables['list']);
            while ($row = Sql_Fetch_Row($req)) {
                $addlists[] = $row[0];
            }
        } else {
            $addlists = explode(',', $_GET['list']);
        }
        $addlists = cleanArray($addlists);
        foreach ($addlists as $listid) {
            $query = sprintf('replace into %s (messageid,listid,entered) values(%d,%d,now())',
                $GLOBALS['tables']['listmessage'], $id, $listid);
            Sql_Query($query);
        }
    }

    // 0008720: Using -p send from the commandline doesn't seem to work
    if (!$GLOBALS['commandline']) {
        Redirect($_GET['page'].'&id='.$id.addCsrfGetToken());
        exit;
    }
}

// load all message data
$messagedata = loadMessageData($id);

//# auto generate the text version if empty
//# hmm, might want this as config
/*
if (empty($messagedata['textmessage'])) {
  include 'actions/generatetext.php';
}
*/

//var_dump($messagedata);
//exit;
//print '<h3>'.$messagedata['status'].'</h3>';

if (!empty($_GET['deletecriterion'])) {
    include dirname(__FILE__).'/actions/deletecriterion.php';
    Redirect($_GET['page'].'&id='.$id.'&tab='.$_GET['tab']);
}
ob_end_flush();

//load database data###########################

if ($id) {
    // Load message attributes / values
    $result = Sql_query("SELECT * FROM {$tables['message']} where id = $id $ownership");
    if (!Sql_Affected_Rows()) {
        echo $GLOBALS['I18N']->get('Access Denied');
        $done = 1;

        return;
    }

    echo formStart($enctype.' name="sendmessageform" class="sendSend" id="sendmessageform" ');
    if (empty($send)) {
        $placeinqueue = '<div id="addtoqueue"><button class="submit" type="submit" name="send" id="addtoqueuebutton">'.$GLOBALS['I18N']->get('Send Campaign').'</button></div>';
    } else {
        //# hide the div in the final "message added to queue" page
        //  print '<div id="addtoqueue"></div>';
    }
    require dirname(__FILE__).'/structure.php';  // This gets the database structures into DBStruct

    include dirname(__FILE__).'/actions/storemessage.php';
}

if (empty($messagedata['message'])) {
  $messagedata['message'] = "";
}

$htmlformatted = strip_tags($messagedata['message']) != $messagedata['message'];

// sanitise the header fields, what else do we need to check on?
if (preg_match("/\n|\r/", $messagedata['fromfield'])) {
    $messagedata['fromfield'] = '';
}
if (preg_match("/\n|\r/", $messagedata['forwardsubject'])) {
    $messagedata['forwardsubject'] = '';
}

//# check that the message does not contain URLs that look like click tracking links
//# it seems people are pasting the results of test messages back in the editor, which would duplicate
//# tracking

$hasClickTrackLinks = preg_match('/lt\.php\?id=[\w%]{22}/', $messagedata['message'],
        $regs) || preg_match('/lt\.php\?id=[\w%]{16}/', $messagedata['message'], $regs) ||
    (CLICKTRACK_LINKMAP && (preg_match('#'.CLICKTRACK_LINKMAP.'/[\w%]{22}#',
                $messagedata['message']) || preg_match('#'.CLICKTRACK_LINKMAP.'/[\w%]{16}#',
                $messagedata['message'])));

if ($hasClickTrackLinks) {
    echo Error(s('You should not paste the results of a test message back into the editor<br/>This will break the click-track statistics, and overload the server.'),
        'http://resources.phplist.com/documentation/errors/pasteclicktrack');
}
// If the variable isn't filled in, then the input fields don't default to the
// values selected.  Need to fill it in so a post will correctly display.

if (!isset($_SESSION['fckeditor_height'])) {
    $_SESSION['fckeditor_height'] = getConfig('fckeditor_height');
}

//actions and store in database#######################

if ($send || $sendtest || $prepare || $save || $savedraft) {
    verifyCsrfGetToken();
    if ($savedraft || $save || $sendtest) {
        // We're just saving, not sending.
        if (!isset($messagedata['status']) || $messagedata['status'] == '') {
            // No status - move to draft state
            $messagedata['status'] = 'draft';
        }
    } elseif ($send) {
        // We're sending - change state to "send-it" status!
        if (is_array($messagedata['targetlist']) && count($messagedata['targetlist'])
            && !empty($messagedata['subject']) && !empty($messagedata['fromfield']) &&
            !empty($messagedata['message']) && empty($duplicate_attribute)
        ) {
            $messagedata['status'] = 'submitted';
            setMessageData($id, 'status', 'submitted');
        } else {
            if (USE_PREPARE) {
                $messagedata['status'] = 'prepared';
            } else {
                $messagedata['status'] = 'draft';
            }
        }
    }

    //## allow plugins manipulate data or save it somewhere else
    $plugintabs = array();
    foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
        //  print "Saving ".$plugin->name;
        $resultMsg = $plugin->sendMessageTabSave($id, $messagedata);
    }

    if (!$htmlformatted && strip_tags($messagedata['message']) != $messagedata['message']) {
        $errormsg = '<span  class="error">'.$GLOBALS['I18N']->get('Warning: You indicated the content was not HTML, but there were  some HTML  tags in it. This  may  cause  errors').'</span>';
    }

    $result = Sql_Query(
        sprintf('update %s  set
        subject = "%s", fromfield = "%s", tofield = "%s",
        replyto ="%s", embargo = "%s", repeatinterval = "%s", repeatuntil = "%s",
        message = "%s", textmessage = "%s", footer = "%s", status = "%s",
        htmlformatted = "%s", sendformat  = "%s", template  =  "%s" where id = %d',
            $tables['message'],
            sql_escape(strip_tags($messagedata['campaigntitle'])),
            /* we store the title in the subject field. Better would be to rename the DB column, but this will do for now */
            sql_escape($messagedata['fromfield']),
            sql_escape($messagedata['tofield']),
            sql_escape($messagedata['replyto']),
            sprintf('%04d-%02d-%02d %02d:%02d',
                $messagedata['embargo']['year'], $messagedata['embargo']['month'], $messagedata['embargo']['day'],
                $messagedata['embargo']['hour'], $messagedata['embargo']['minute']), $messagedata['repeatinterval'],
            sprintf('%04d-%02d-%02d %02d:%02d',
                $messagedata['repeatuntil']['year'], $messagedata['repeatuntil']['month'],
                $messagedata['repeatuntil']['day'],
                $messagedata['repeatuntil']['hour'], $messagedata['repeatuntil']['minute']),
            sql_escape($messagedata['message']),
            sql_escape($messagedata['textmessage']),
            sql_escape($messagedata['footer']),
            sql_escape($messagedata['status']), $htmlformatted ? '1' : '0',
            sql_escape($messagedata['sendformat']),
            sql_escape($messagedata['template']), $id
        )
    );

    //# do this seperately, so that the above query doesn't fail when the DB hasn't been upgraded
    $result = Sql_Query(
        sprintf('update %s set requeueinterval = "%s", requeueuntil = "%s" where id = %d', $tables['message'],
            $messagedata['requeueinterval'], sprintf('%04d-%02d-%02d %02d:%02d',
                $messagedata['requeueuntil']['year'], $messagedata['requeueuntil']['month'],
                $messagedata['requeueuntil']['day'],
                $messagedata['requeueuntil']['hour'], $messagedata['requeueuntil']['minute']), $id
        )
    );

//    print "Message ID: $id";
    //    exit;
    if ($GLOBALS['commandline']) {
        if (isset($_POST['targetlist']) && is_array($_POST['targetlist'])) {
            Sql_query("delete from {$tables['listmessage']} where messageid = $id");
            foreach ($_POST['targetlist'] as $listid => $val) {
                $result = Sql_query("insert ignore into {$tables['listmessage']} (messageid,listid,entered) values($id,$listid,now())");
            }
        }
    }

// we want to create a join on tables as follows, in order to find users who have their attributes to the values chosen
// (independent of their list membership).
// select
//  table1.userid from user_attribute as table1
//  left join user_attribute as table2 on table1.userid = table2.userid
//  left join user_attribute as table3 on table1.userid = table3.userid
//  ...
// where
//  table1.attributeid = 2 and table1.value in (1,2,3,4)
//  and table2.attributeid = 1 and table2.value in (3,15)
//  and table3.attributeid = 3 and table3.value in (4,5,6)
//  ...

    // criteria system, add one by one:

    if (ALLOW_ATTACHMENTS && isset($_FILES) && is_array($_FILES) && count($_FILES) > 0) {
        for ($att_cnt = 1; $att_cnt <= NUMATTACHMENTS; ++$att_cnt) {
            $fieldname = 'attachment'.$att_cnt;
            if (isset($_FILES[$fieldname])) {
                $tmpfile = $_FILES[$fieldname]['tmp_name'];
                $remotename = $_FILES[$fieldname]['name'];
                $type = $_FILES[$fieldname]['type'];
                $newtmpfile = $remotename.time();
                move_uploaded_file($tmpfile, $GLOBALS['tmpdir'].'/'.$newtmpfile);
                if (is_file($GLOBALS['tmpdir'].'/'.$newtmpfile) && filesize($GLOBALS['tmpdir'].'/'.$newtmpfile)) {
                    $tmpfile = $GLOBALS['tmpdir'].'/'.$newtmpfile;
                }
                if (strlen($type) > 255) {
                    echo Warn($GLOBALS['I18N']->get('Mime Type is longer than 255 characters, this is trouble'));
                }
                $description = $_POST[$fieldname.'_description'];
            } else {
                $tmpfile = '';
            }
            if ($tmpfile && filesize($tmpfile) && $tmpfile != 'none') {
                list($name, $ext) = explode('.', basename($remotename));
                // create a temporary file to make sure to use a unique file name to store with
                $newfile = tempnam($GLOBALS['attachment_repository'], $name);
                $newfile .= '.'.$ext;
                $newfile = basename($newfile);
                $file_size = filesize($tmpfile);
                $fd = fopen($tmpfile, 'r');
                $contents = fread($fd, filesize($tmpfile));
                fclose($fd);
                if ($file_size) {
                    // this may seem odd, but it allows for a remote (ftp) repository
                    // also, "copy" does not work across filesystems
                    $fd = fopen($GLOBALS['attachment_repository'].'/'.$newfile, 'w');
                    fwrite($fd, $contents);
                    fclose($fd);
                    Sql_query(sprintf('insert into %s (filename,remotefile,mimetype,description,size) values("%s","%s","%s","%s",%d)',
                            $tables['attachment'],
                            basename($newfile), $remotename, $type, $description, $file_size)
                    );
                    $attachmentid = Sql_Insert_id();
                    Sql_query(sprintf('insert into %s (messageid,attachmentid) values(%d,%d)',
                        $tables['message_attachment'], $id, $attachmentid));
                    if (is_file($tmpfile)) {
                        unlink($tmpfile);
                    }

                    // do a final check
                    if (filesize($GLOBALS['attachment_repository'].'/'.$newfile)) {
                        echo Info(s('Attachment %d succesfully added', $att_cnt));
                    } else {
                        echo Info(s('Adding attachment %d failed', $att_cnt));
                    }
                } else {
                    echo Warn($GLOBALS['I18N']->get('Uploaded file not properly received, empty file'));
                }
            } elseif (!empty($_POST['localattachment'.$att_cnt])) {
                $type = findMime(basename($_POST['localattachment'.$att_cnt]));
                Sql_query(sprintf('insert into %s (remotefile,mimetype,description,size) values("%s","%s","%s",%d)',
                        $tables['attachment'],
                        $_POST['localattachment'.$att_cnt], $type, $description,
                        filesize($_POST['localattachment'.$att_cnt]))
                );
                $attachmentid = Sql_Insert_id();
                Sql_query(sprintf('insert into %s (messageid,attachmentid) values(%d,%d)',
                    $tables['message_attachment'], $id, $attachmentid));
                echo Info(s('Adding attachment').' '.$att_cnt." mime: $type");
            }
        }
    }

    //# when followupto is set, go there
    if (!empty($_POST['followupto']) && isValidRedirect($_POST['followupto'])) {
        header('Location: '.$_POST['followupto']);
        exit;
    }

    if (!empty($id) && !$send) {
        if ($savedraft) {
            $_SESSION['action_result'] = s('Campaign saved as draft');
            header('Location: ./?page=messages&tab=draft');
            exit;
        }
    } else {
        //    $id = $messageid; // New ID - need to set it for later use (test email).
        echo '<h3>'.$GLOBALS['I18N']->get('Campaign added').'</h3><br/>';
    }
    // var_dump($messagedata);

    // If we're sending the message, just return now to the calling script
    // we only need to check that everything is there, once we actually want to send
    if ($send && !empty($messagedata['subject']) && !empty($messagedata['fromfield']) && !empty($messagedata['message']) && empty($duplicate_atribute) && count($messagedata['targetlist'])) {
        if ($messagedata['status'] == 'submitted') {

            //#16615, check that "send until" is in after the embargo and warn if it isn't
            $finishSending = mktime($messagedata['finishsending']['hour'], $messagedata['finishsending']['minute'], 0,
                $messagedata['finishsending']['month'], $messagedata['finishsending']['day'],
                $messagedata['finishsending']['year']);
            $embargoTime = mktime($messagedata['embargo']['hour'], $messagedata['embargo']['minute'], 0,
                $messagedata['embargo']['month'], $messagedata['embargo']['day'], $messagedata['embargo']['year']);

            if ($finishSending < $embargoTime) {
                echo Warn(s('This campaign is scheduled to stop sending before the embargo time. No mails will be sent.'));
                echo PageLinkButton('send&amp;id='.$messagedata['id'].'&amp;tab=Scheduling',
                    s('Review Scheduling'));
            }
            //# reset any queued messages, as the selection may have changed
            if (defined('MESSAGEQUEUE_PREPARE') && MESSAGEQUEUE_PREPARE) {
                $query = sprintf('delete from '.$tables['usermessage'].' where messageid = %d and status = "todo"',
                    $messagedata['id']);
            }

            echo '<h3>'.$GLOBALS['I18N']->get('Campaign queued').'</h3>';
            foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
                $plugin->messageQueued($id);
            }
            if (getConfig('pqchoice') == 'phplistdotcom') {
                echo activateRemoteQueue();
            } elseif (MANUALLY_PROCESS_QUEUE) {
                echo '<p>'.PageLinkButton('processqueue', $GLOBALS['I18N']->get('processqueue')).'</p>';
            } else {
                echo '<p>'.PageLinkButton('messages&tab=active', $GLOBALS['I18N']->get('view progress')).'</p>';
            }
        }
        $done = 1;

        return;
    } elseif ($send || $sendtest) {
        $errormessage = '';
        if ($messagedata['subject'] != stripslashes($messagedata['subject'])) {
            $errormessage = $GLOBALS['I18N']->get('Sorry, you used invalid characters in the Subject field.');
        } elseif (!empty($_POST['fromfield']) && $messagedata['fromfield'] != $_POST['fromfield']) {
            $errormessage = $GLOBALS['I18N']->get('Sorry, you used invalid characters in the From field.');
        } elseif (empty($messagedata['fromfield'])) {
            $errormessage = $GLOBALS['I18N']->get('Please enter a from line.');
        } elseif (empty($messagedata['message'])) {
            $errormessage = $GLOBALS['I18N']->get('Please enter a message');
        } elseif (empty($messagedata['subject'])) {
            $errormessage = $GLOBALS['I18N']->get('Please enter a subject');
        } elseif (!empty($duplicate_attribute)) {
            $errormessage = $GLOBALS['I18N']->get('Error: you can use an attribute in one rule only');
        } elseif ($send && !is_array($_POST['targetlist'])) {
            $errormessage = $GLOBALS['I18N']->get('Please select the list(s) to send the campaign to');
        }

        //# this is now handled on the last Tab, so don't display
//    echo "$errormessage<br/>";
    }

    // OK, the message has been saved, now check to see if we need to send a test message
    if ($sendtest) {
        $sendtestresult = '<br/>';
        if (empty($_SESSION['lasttestsent'])) {
            $_SESSION['lasttestsent'] = 0;
        }

        $sendtestAllowed = true;
        //# check with plugins that sending a test is allowed
        reset($GLOBALS['plugins']);
        while ($sendtestAllowed && $plugin = current($GLOBALS['plugins'])) {
            $sendtestAllowed = $plugin->sendTestAllowed($messagedata);
            if (!$sendtestAllowed) {
                if (VERBOSE) {
                    cl_output('Sending test blocked by plugin '.$plugin->name);
                }
            }
            next($GLOBALS['plugins']);
        }

        $delay = time() - $_SESSION['lasttestsent'];
        if ($delay < SENDTEST_THROTTLE) {
            foreach ($GLOBALS['plugins'] as $plname => $plugin) {
                $plugin->processError('Send test throttled on '.$delay);
            }
            $sendtestresult .= s('You can send a test mail once every %d seconds', SENDTEST_THROTTLE).'<br/>';
            $emailaddresses = array();
        } elseif (!$sendtestAllowed) {
            $sendtestresult .= s('Sending test mails is currently not available').'<br/>';
            $emailaddresses = array();
        } else {
            // Let's send test messages to everyone that was specified in the
            if ($messagedata['testtarget'] == '') {
                $sendtestresult .= $GLOBALS['I18N']->get('No target email addresses listed for testing.').'<br/>';
            }

            if (isset($cached[$id])) {
                unset($cached[$id]);
            }
            clearPageCache();
            include 'sendemaillib.php';

            // OK, let's get to sending!
            $emailaddresses = explode(',', $messagedata['testtarget']);
            if (count($emailaddresses) > SENDTEST_MAX) {
                foreach ($GLOBALS['plugins'] as $plname => $plugin) {
                    $plugin->processError('Send test capped from '.count($emailaddresses).' to '.SENDTEST_MAX);
                }
                $limited = array_chunk($emailaddresses, SENDTEST_MAX);
                $emailaddresses = $limited[0];
                $sendtestresult .= s('There is a maximum of %d test emails allowed', SENDTEST_MAX).'<br/>';
            }
        }
        //  var_dump($emailaddresses);#exit;
        $messagedata['testtarget'] = '';
        foreach ($emailaddresses as $address) {
            $address = trim($address);
            if (empty($address)) {
                continue;
            }
            $result = Sql_query(sprintf('select id,email,uniqid,htmlemail,rssfrequency,confirmed from %s where email = "%s"',
                $tables['user'], sql_escape($address)));
            //Leftover from the preplugin era
            if ($user = Sql_fetch_array($result)) {
                if (FORWARD_ALTERNATIVE_CONTENT && $_GET['tab'] == 'Forward') {
                    if (SEND_ONE_TESTMAIL) {
                        $success = sendEmail($id, $address, $user['uniqid'], $user['htmlemail'], array(),
                            array($address));
                    } else {
                        $success = sendEmail($id, $address, $user['uniqid'], 1, array(),
                                array($address)) && sendEmail($id, $address, $user['uniqid'], 0, array(),
                                array($address));
                    }
                } else {
                    if (SEND_ONE_TESTMAIL) {
                        $success = sendEmail($id, $address, $user['uniqid'], $user['htmlemail']);
                    } else {
                        $success = sendEmail($id, $address, $user['uniqid'], 1) && sendEmail($id, $address,
                                $user['uniqid'], 0);
                    }
                }
                $sendtestresult .= $GLOBALS['I18N']->get('Sent test mail to').": $address ";
                if (!$success) {
                    $sendtestresult .= $GLOBALS['I18N']->get('failed');
                } else {
                    $sendtestresult .= $GLOBALS['I18N']->get('success');
                    $_SESSION['lasttestsent'] = time();
                }
                $sendtestresult .= '<br/>';
            } else {
                $address = htmlspecialchars(substr(strip_tags($address), 0, 255));

                $sendtestresult .= $GLOBALS['I18N']->get('Email address not found to send test message.').": $address";
                $sendtestresult .= sprintf('  <div class="inline"><a href="%s&action=addemail&email=%s%s" class="button ajaxable">%s</a></div>',
                    $baseurl, urlencode($address), addCsrfGetToken(), $GLOBALS['I18N']->get('add'));
            }
            $messagedata['testtarget'] .= $address.', ';
        }
        $messagedata['testtarget'] = substr($messagedata['testtarget'], 0, -2);
        $sendtestresult .= '<hr/>';
        $sendtestresult .= '<script type="text/javascript">this.location.hash="sendTest";</script>';
    }
} elseif (isset($_POST['deleteattachments']) && is_array($_POST['deleteattachments']) && $id) {
    if (ALLOW_ATTACHMENTS) {
        // Delete Attachment button hit...
        $deleteattachments = $_POST['deleteattachments'];
        foreach ($deleteattachments as $attid) {
            $attDetails = Sql_fetch_assoc_query(sprintf('select filename from %s where id = %d', $tables['attachment'],
                $attid));
            $phys_file = $GLOBALS['attachment_repository'].'/'.$attDetails['filename'];
            $fileParts = pathinfo($phys_file);
            $phys_file2 = $GLOBALS['attachment_repository'].'/'.$fileParts['filename']; //# to remove the file created by tempnam

            @unlink($phys_file);
            @unlink($phys_file2);

            $result = Sql_Query(sprintf('delete from %s where id = %d and messageid = %d',
                $tables['message_attachment'],
                $attid,
                $id));
            echo Info($GLOBALS['I18N']->get('Removed Attachment '));
        }
    }
}

//#############################
// Stacked attributes, processing and calculation
//#############################

//# moved to plugin

//#############################
// Stacked attributes, end
//#############################

echo $errormsg;
if (!$done) {

    //$baseurl = sprintf('./?page=%s&amp;id=%d',$_GET["page"],$id);
    if ($id) {
        $tabs = new WebblerTabs();
        $tabbaseurl = preg_replace('/&tab=[^&]+/', '', $baseurl);
        $tabs->addTab(s('Content'), $tabbaseurl.'&amp;tab=Content');
        $counttabs = 1;
        if (USE_MANUAL_TEXT_PART) {
            $tabs->addTab(s('Text'), $tabbaseurl.'&amp;tab=Text');
            ++$counttabs;
        }
        if (FORWARD_ALTERNATIVE_CONTENT) {
            $tabs->addTab(s('Forward'), $tabbaseurl.'&amp;tab=Forward');
            ++$counttabs;
        }
        $tabs->addTab(s('Format'), $tabbaseurl.'&amp;tab=Format');
        ++$counttabs;
        if (ALLOW_ATTACHMENTS) {
            $tabs->addTab(s('Attach'), $tabbaseurl.'&amp;tab=Attach');
            ++$counttabs;
        }
        $tabs->addTab(s('Scheduling'), $tabbaseurl.'&amp;tab=Scheduling');
        ++$counttabs;
        $tabs->addTab(s('Lists'), $tabbaseurl.'&amp;tab=Lists');
        ++$counttabs;

        if ($_GET['tab']) {
            $tabs->setCurrent(s($_GET['tab']));
        } else {
            $tabs->setCurrent(s('Content'));
        }
        $tabs->addLinkCode(' class="savechanges" ');

        //## allow plugins to add tabs
        $plugintabs = array();
        foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
            //   print $plugin->name;
            $plugintab = $plugin->sendMessageTab($id, $messagedata);
            if ($plugintab) {
                $plugintabname = substr(strip_tags($plugin->sendMessageTabTitle()), 0, 10);
                $plugintabs[$plugintabname] = $plugintab;
                $tabs->addTab($GLOBALS['I18N']->get($plugintabname),
                    "$tabbaseurl&amp;tab=".urlencode($plugintabname));
                if ($insertBefore = $plugin->sendMessageTabInsertBefore()) {
                    $tabs->insertTabBefore(s($insertBefore), s($plugintabname));
                }
                ++$counttabs;
            }
        }

        //# this one always last
        $tabs->addTab(s('Finish'), $tabbaseurl.'&amp;tab=Finish');
        ++$counttabs;

        // print $tabs->display();
    } 
    echo '<input id="followupto" type="hidden" name="followupto" value="" />';

    if ($_GET['page'] == 'preparemessage') {
        echo Help('preparemessage', $GLOBALS['I18N']->get('What is prepare a message'));
    }

    if (!defined('IN_WEBBLER')) {
        if (empty($messagedata['fromfield'])) {
            $defaultFrom = getConfig('campaignfrom_default');
            if (empty($defaultFrom)) {
                $defaultFrom = getConfig('message_from_name').' '.getConfig('message_from_address');
            }
            $messagedata['fromfield'] = $defaultFrom;

            if (!isSuperUser() && USE_ADMIN_DETAILS_FOR_MESSAGES && is_object($GLOBALS['admin_auth'])) {
                $adminemail = $GLOBALS['admin_auth']->adminEmail($_SESSION['logindetails']['id']);
                if (!empty($adminemail)) {
                    $messagedata['fromfield'] = $GLOBALS['admin_auth']->adminName($_SESSION['logindetails']['id']).' '.$adminemail;
                }
            }
        }
    }

    $formatting_content = '<div id="formatcontent">';

    //0013076: different content when forwarding 'to a friend'
    //  value="'.htmlentities($subject,ENT_QUOTES,'UTF-8').'" size="40"></td></tr> --> previous code in line 1032
    //  value="'.htmlentities($from,ENT_QUOTES,'UTF-8').'" size="40"></td></tr> --> previous code in line 1038

    $tmp = '<div id="maincontent">';
    $maincontent = $tmp;
    $forwardcontent = $tmp;

// custom code - start
    $utf8_subject = $messagedata['subject'];
    $utf8_from = $messagedata['fromfield'];
    if (empty($utf8_subject)) {
        $utf8_subject = '(no subject)';
    }
    if (empty($messagedata['campaigntitle'])) {
        $messagedata['campaigntitle'] = $utf8_subject;
    }
    /*
      if (0 && strcasecmp($GLOBALS['strCharSet'], 'utf-8') <> 0) {
         $utf8_subject = iconv($GLOBALS['strCharSet'],'UTF-8',$utf8_subject);
         $utf8_from = iconv($GLOBALS['strCharSet'],'UTF-8',$utf8_from);
      }
    */

    $maincontent .= '
  <div class="field">
    <label for="subject">' .s('Campaign subject').Help('subject').'</label>'.
    '<input type="text" name="subject"  id="subjectinput" value="' .htmlentities($utf8_subject, ENT_QUOTES, 'UTF-8').'" size="60" />
  </div>

  <div class="field"><label for="fromfield">' .$GLOBALS['I18N']->get('From Line').Help('from').'</label>'.'
    <input type="text" name="fromfield"
   value="' .htmlentities($utf8_from, ENT_QUOTES, 'UTF-8').'" size="60" /></div>';

    if (USE_REPLY_TO) {
        $maincontent .= '
  <div class="field"><label for="replyto">' .$GLOBALS['I18N']->get('Reply to').Help('from').'</label>'.'
    <input type="text" name="replyto"
   value="' .htmlspecialchars($messagedata['replyto']).'" size="60" /></div>';
    }
    if (USE_MESSAGE_PREVIEW) {
    $maincontent .= '
        <div class="field" id="message-text-preview">
        <label for="messagepreview">' .s('Message preview').Help('generatetextpreview').'</label>
        <input type="text" id="messagepreview" name="messagepreview" size="60" readonly />
        <div id="message-text-preview-button">' .
            PageLinkAjax('send&tab=Content&id='.$id.'&action=generatetextpreview', $GLOBALS['I18N']->get('Generate')).'
        </div>
        </div>';
    }

    $maincontent .= sprintf('

      <div id="contentchoice" class="field">
      <label for="sendmethod">' .$GLOBALS['I18N']->get('Content').Help('sendmethod').'</label>'.'
      <input type="radio" name="sendmethod" value="remoteurl" %s />' .$GLOBALS['I18N']->get('Send a Webpage').'
      <input type="radio" name="sendmethod" value="inputhere" %s />' .$GLOBALS['I18N']->get('Compose Message').'
      </div>',
        $messagedata['sendmethod'] == 'remoteurl' ? 'checked="checked"' : '',
        $messagedata['sendmethod'] == 'inputhere' ? 'checked="checked"' : ''
        );

    if (empty($messagedata['sendurl'])) {
        $messagedata['sendurl'] = 'e.g. https://www.phplist.com/testcampaign.html';
    }

    $maincontent .= '
      <div id="remoteurl" class="field"><label for="sendurl">' .$GLOBALS['I18N']->get('Send a Webpage - URL').Help('sendurl').'</label>'.'
        <input type="text" name="sendurl" id="remoteurlinput"
       value="' .htmlspecialchars($messagedata['sendurl']).'" size="60" /> <span id="remoteurlstatus"></span></div>';
    if (isset($messagedata['sendmethod']) && $messagedata['sendmethod'] != 'remoteurl') {
        $GLOBALS['pagefooter']['hideremoteurl'] = '<script type="text/javascript">$("#remoteurl").hide();</script>';
    }

// custom code - end
    //0013076: different content when forwarding 'to a friend'
    $forwardcontent .=
        '<div class="field"><label for="forwardsubject">'.$GLOBALS['I18N']->get('Subject').Help('forwardsubject').'</label>'.'
    <input type="text" name="forwardsubject" value="' .htmlentities($messagedata['forwardsubject'], ENT_QUOTES,
            'UTF-8').'" size="40" /></div>';

    $currentTime = Sql_Fetch_Row_Query('select now()');

    $scheduling_content = '<div id="schedulecontent">';
    if (defined('SYSTEM_TIMEZONE')) {
        $scheduling_content .= '
    <div class="field">' .s('phpList operates in the time zone "%s"', SYSTEM_TIMEZONE).'</div>';
    } else {
        $scheduling_content .= '
    <div class="field">' . s('Dates and times are relative to the Server Time') . '<br/>' . s('Current Server Time is') . ' <span id="servertime">' .
date('H:i, l j F Y', strtotime($currentTime[0])) . '</span>' . '</div>';
    }

    $scheduling_content .= '  <div class="field"><label for="embargo">'.$GLOBALS['I18N']->get('Embargoed Until').Help('embargo').'</label>'.'
    ' .$embargo->showInput('embargo', '', $messagedata['embargo']).'</div>
  <div class="field"><label for="finishsending">' .$GLOBALS['I18N']->get('Stop sending after').Help('finishsending').'</label>'.'
    ' .$embargo->showInput('finishsending', '', $messagedata['finishsending']).'</div>';

    if (USE_REPETITION) {
        $repeatinterval = $messagedata['repeatinterval'];

        $scheduling_content .= '
    <div class="field"><label for="repeatinterval">' .$GLOBALS['I18N']->get('Repeat campaign every').Help('repetition').'</label>'.'
        <select name="repeatinterval">
      <option value="0"';
        if ($repeatinterval == 0) {
            $scheduling_content .= ' selected="selected"';
        }
        $scheduling_content .= '>-- '.$GLOBALS['I18N']->get('no repetition').'</option>
      <option value="60"';
        if ($repeatinterval == 60) {
            $scheduling_content .= ' selected="selected"';
        }
        $scheduling_content .= '>'.$GLOBALS['I18N']->get('hour').'</option>
      <option value="1440"';
        if ($repeatinterval == 1440) {
            $scheduling_content .= ' selected="selected"';
        }
        $scheduling_content .= '>'.$GLOBALS['I18N']->get('day').'</option>
      <option value="10080"';
        if ($repeatinterval == 10080) {
            $scheduling_content .= ' selected="selected"';
        }
        $scheduling_content .= '>'.$GLOBALS['I18N']->get('week').'</option>
      <option value="20160"';
        if ($repeatinterval == 20160) {
            $scheduling_content .= ' selected="selected"';
        }
        $scheduling_content .= '>'.$GLOBALS['I18N']->get('fortnight').'</option>
      <option value="40320"';
        //# @@@TODO adding "month" is a bit trickier, as we use minutes for value, and months have varying numbers of seconds
        if ($repeatinterval == 40320) {
            $scheduling_content .= ' selected="selected"';
        }
        $scheduling_content .= '>'.$GLOBALS['I18N']->get('four weeks').'</option>
      </select>
        <label for="repeatuntil">' .$GLOBALS['I18N']->get('Repeat Until').'</label>
        ' .$repeatuntil->showInput('repeatuntil', '', $messagedata['repeatuntil']);
        $scheduling_content .= '</div>';
    }

    $requeueinterval = $messagedata['requeueinterval'];
    $scheduling_content .= '
  <div class="field"><label for="requeueinterval"> ' .$GLOBALS['I18N']->get('Requeue every').Help('requeueing').'</label>'.'
    <select name="requeueinterval">
    <option value="0"';
    if ($requeueinterval == 0) {
        $scheduling_content .= ' selected="selected"';
    }
    $scheduling_content .= '>-- '.$GLOBALS['I18N']->get('do not requeue').'</option>
    <option value="60"';
    if ($requeueinterval == 60) {
        $scheduling_content .= ' selected="selected"';
    }
    $scheduling_content .= '>'.$GLOBALS['I18N']->get('hour').'</option>
    <option value="1440"';
    if ($requeueinterval == 1440) {
        $scheduling_content .= ' selected="selected"';
    }
    $scheduling_content .= '>'.$GLOBALS['I18N']->get('day').'</option>
    <option value="10080"';
    if ($requeueinterval == 10080) {
        $scheduling_content .= ' selected="selected"';
    }
    $scheduling_content .= '>'.$GLOBALS['I18N']->get('week').'</option>
    </select>

      <label for="requeueuntil">' .$GLOBALS['I18N']->get('Requeue Until').'</label>
      ' .$requeueuntil->showInput('requeueuntil', '', $messagedata['requeueuntil']);
    $scheduling_content .= '</div>';

    $scheduling_content .= '</div>';

    $formatting_content .= '<input type="hidden" name="htmlformatted" value="auto" />';

    $formatting_content .= '
    <div class="field">
    <label for="sendformat"> ' .$GLOBALS['I18N']->get('Send as').Help('sendformat').'</label>'.'
  ' .$GLOBALS['I18N']->get('html').' <input type="radio" name="sendformat" value="HTML" ';
    $formatting_content .= $messagedata['sendformat'] == 'HTML' ? 'checked="checked"' : '';
    $formatting_content .= '/>
  ' .$GLOBALS['I18N']->get('text').' <input type="radio" name="sendformat" value="text" ';
    $formatting_content .= $messagedata['sendformat'] == 'text' ? 'checked="checked"' : '';
    $formatting_content .= '/>
  ';

//  0009687: Confusing use of the word "Both", indicating one email with both text and html and not two emails
//  $formatting_content .= $GLOBALS['I18N']->get("text and html").' <input type="radio" name="sendformat" value="text and HTML" ';
//  $formatting_content .= $_POST["sendformat"]=="text and HTML" || !isset($_POST["sendformat"]) ?"checked":"";
//  $formatting_content .= '/>';

    foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
        $plugins_sendformats = $plugin->sendFormats();
        if (is_array($plugins_sendformats) && count($plugins_sendformats)) {
            foreach ($plugins_sendformats as $val => $desc) {
                $val = preg_replace("/\W/", '', strtolower(trim($val)));
                if ($val[0] != '_') { //# allow a plugin to add a format that is not actually displayed
                    $formatting_content .= sprintf('%s <input type="radio" name="sendformat" value="%s" %s />',
                        $desc, $val, $messagedata['sendformat'] == $val ? 'checked="checked"' : '');
                }
            }
        }
    }
    $formatting_content .= '</div>';

    $req = Sql_Query("select id,title from {$tables['template']} order by listorder");
    if (Sql_affected_Rows()) {
        $formatting_content .= '<div class="field"><label for="template">'.$GLOBALS['I18N']->get('Use Template').Help('usetemplate').'</label>'.'
      <select name="template"><option value="0" hidden>' .s('--Select one--').'</option>
      <option value="0">-- ' .s('No template').'</option>';
        $req = Sql_Query("select id,title from {$tables['template']} order by listorder");
        while ($row = Sql_Fetch_Array($req)) {
            if ($row['title']) {
                $formatting_content .= sprintf('<option value="%d" %s>%s</option>', $row['id'],
                    $row['id'] == $messagedata['template'] ? 'selected="selected"' : '', $row['title']);
            }
        }
        $formatting_content .= '</select></div>';
    }
    $formatting_content .= '</div>';

    //0013076: different content when forwarding 'to a friend'
    $maincontent .= '<div id="messagecontent" class="field"><label for="message">'.s('Compose Message').Help('message').'</label> ';
    $forwardcontent .= '<div id="messagecontent" class="field"><label for="forwardmessage">'.s('Compose Message').Help('forwardmessage').'</label> ';

    if (!empty($GLOBALS['editorplugin'])) {
        $maincontent .= '<div>'.$GLOBALS['plugins'][$GLOBALS['editorplugin']]->editor('message',
                $messagedata['message']).'</div>';
    } else {
        $maincontent .= '
      <div><textarea name="message" cols="65" rows="20">' .htmlspecialchars($messagedata['message']).'</textarea></div>';
    }

    //0013076: different content when forwarding 'to a friend'
    $forwardcontent .= '<div><textarea name="forwardmessage" cols="65" rows="20">'.htmlspecialchars($messagedata['forwardmessage']).'</textarea></div>';

    //0013076: different content when forwarding 'to a friend'
    $tmp = '

  </div></div> <!-- end of message content -->
  ';

    if (isset($messagedata['sendmethod']) && $messagedata['sendmethod'] != 'inputhere') {
        $GLOBALS['pagefooter']['hidemessagecontent'] = '<script type="text/javascript">$("#messagecontent").hide()</script>';
    }
    $maincontent .= $tmp;
    $forwardcontent .= $tmp;

    if (USE_MANUAL_TEXT_PART) {
        $textcontent = '<div class="field">
    <label for="textmessage">' .$GLOBALS['I18N']->get('Plain text version of message').Help('plaintextversion').'</label>'.'
    <div id="generatetextversion">' .PageLinkAjax('send&tab=Text&id='.$id.'&action=generatetext',
                $GLOBALS['I18N']->get('generate from HTML')).'</a> '.Help('generatetext').'</div>
    <textarea id="textmessage" name="textmessage" cols="65" rows="20">' .htmlentities($messagedata['textmessage']).'</textarea>
  </div>';
    }
//var_dump($messagedata);
    //0013076: different content when forwarding 'to a friend'
    $maincontent .= '<div class="field"><label for="footer">'.$GLOBALS['I18N']->get('Footer').Help('footer').'.</label>'.'
   <textarea name="footer" cols="65" rows="5">' .htmlspecialchars($messagedata['footer']).'</textarea></div>';
    $forwardcontent .= '<div class="field"><label for="forwardfooter">'.$GLOBALS['I18N']->get('forwardfooter').Help('forwardfooter').'</label>'.'
    <textarea name="forwardfooter" cols="65" rows="5">' .htmlspecialchars($messagedata['forwardfooter']).'</textarea></div>';

    if (ALLOW_ATTACHMENTS) {
        // If we have a message id saved, we want to query the attachments that are associated with this
        // message and display that (and allow deletion of!)

        $att_content = '<div class="field"><label for="attach">'.$GLOBALS['I18N']->get('Add attachments to your campaign').Help('attachments').'</label>';
        $att_content .= '<div class="info">
      ' .$GLOBALS['I18N']->get('The upload has the following limits set by the server').':<br/>
      ' .$GLOBALS['I18N']->get('Maximum size of total data being sent to the server').': '.ini_get('post_max_size').'<br/>
      ' .$GLOBALS['I18N']->get('Maximum size of each individual file').': '.ini_get('upload_max_filesize').'</div>';

        if ($id) {
            $result = Sql_Query(sprintf('Select Att.id, Att.filename, Att.remotefile, Att.mimetype, Att.description, Att.size, MsgAtt.id linkid'.
                ' from %s Att, %s MsgAtt where Att.id = MsgAtt.attachmentid and MsgAtt.messageid = %d',
                $tables['attachment'],
                $tables['message_attachment'],
                $id));

            $ls = new WebblerListing($GLOBALS['I18N']->get('Current Attachments'));
            $totalSize = 0;
            while ($row = Sql_fetch_array($result)) {
                $ls->addElement($row['id']);
                $ls->addColumn($row['id'], $GLOBALS['I18N']->get('filename'), $row['remotefile']);
                $ls->addColumn($row['id'], $GLOBALS['I18N']->get('desc'), $row['description']);
                $ls->addColumn($row['id'], $GLOBALS['I18N']->get('size'), formatBytes($row['size']));
                $totalSize += $row['size'];
                $phys_file = $GLOBALS['attachment_repository'].'/'.$row['filename'];
                if (is_file($phys_file) && filesize($phys_file)) {
                    $ls->addColumn($row['id'], $GLOBALS['I18N']->get('file'), $GLOBALS['img_tick']);
                } else {
                    $ls->addColumn($row['id'], $GLOBALS['I18N']->get('file'), $GLOBALS['img_cross']);
                }
                $ls->addColumn($row['id'], $GLOBALS['I18N']->get('del'),
                    sprintf('<input type="checkbox" name="deleteattachments[]" value="%s"/>', $row['linkid']));
            }
            $ls->addButton(s('Delete checked'), 'javascript:document.sendmessageform.submit()');
            $att_content .= '<div>'.$ls->display().'</div>';
        }
        if (defined('MAX_MAILSIZE') && 3 * $totalSize > MAX_MAILSIZE) {  //# the 3 is roughly the size increase to encode the string
            $att_content .= Warn(s('The total size of attachments is very large. Sending this campaign may fail due to resource limits.'));
        }

        for ($att_cnt = 1; $att_cnt <= NUMATTACHMENTS; ++$att_cnt) {
            $att_content .= sprintf('<div>%s</div><div><input type="file" name="attachment%d"/>&nbsp;&nbsp;<input class="submit" type="submit" name="save" value="%s"/></div>',
                $GLOBALS['I18N']->get('New Attachment'), $att_cnt, $GLOBALS['I18N']->get('Add (and save)'));
            if (FILESYSTEM_ATTACHMENTS) {
                $att_content .= sprintf('<div><b>%s</b> %s:</div><div><input type="text" name="localattachment%d" size="50"/></div>',
                    $GLOBALS['I18N']->get('or'), $GLOBALS['I18N']->get('Path to file on server'), $att_cnt, $att_cnt);
            }
            $att_content .= sprintf('<div>%s:</div>
        <div><textarea name="attachment%d_description" cols="65" rows="3" wrap="virtual"></textarea></div>',
                $GLOBALS['I18N']->get('Description of attachment'), $att_cnt);
        }
        $att_content .= '</div>';
        // $shader = new WebblerShader("Attachments");
        // $shader->addContent($att_content);
        // $shader->initialstate = 'closed';
        // print $shader->display();
    }

    // Load the email address for the admin user so we can use that as the default value in the testtarget field
    // @@@ this only works with phplist authentication, needs to be abstracted
    if (!isset($messagedata['testtarget'])) {
        $res = Sql_Query(sprintf('Select email from %s where id = %d', $tables['admin'],
            $_SESSION['logindetails']['id']));
        $admin_details = Sql_Fetch_Array($res);

        $messagedata['testtarget'] = $admin_details['email'];
    }
    // if there isn't one, load the developer one, just being lazy here :-)
    if (empty($messagedata['testtarget']) && isset($GLOBALS['developer_email'])) {
        $messagedata['testtarget'] = $GLOBALS['developer_email'];
    }

    // Display the HTML for the "Send Test" button, and the input field for the email addresses
    $sendtest_content = '<div class="sendTest" id="sendTest">
    ' .$sendtestresult.Help('sendtest').' <b>'.s('to email address(es)').':</b><br />'.
        '<p><i>&nbsp; '.s('(comma separate addresses - all must be existing subscribers)').'</i></p>'.
        '<div class="input-group">
            <input type="text" name="testtarget" size="40" value="'.htmlspecialchars($messagedata['testtarget']).'" class="form-control blockenterkey" />
            <span class="input-group-btn">
                <input class="submit btn btn-primary" type="submit" name="sendtest" value="' .s('Send Test').'" />
             </span>
        </div>
    </div>';

    // notification of progress of message sending
    // defaulting to admin_details['email'] gives the wrong impression that this is the
    // value in the database, so it is better to leave that empty instead
    $notify_start = isset($messagedata['notify_start']) && is_email($messagedata['notify_start']) ? $messagedata['notify_start'] : ''; //$admin_details['email'];
    $notify_end = isset($messagedata['notify_end']) && is_email($messagedata['notify_end']) ? $messagedata['notify_end'] : ''; //$admin_details['email'];

    $send_content = sprintf('
    <div class="sendNotify">
    <label for="notify_start">%s<br/>%s</label><div><input type="text" name="notify_start" id="notify_start" value="%s" size="35"/></div>
    <label for="notify_end">%s<br/>%s</label><div><input type="text" name="notify_end" id="notify_end" value="%s" size="35"/></div>
    </div>',
        $GLOBALS['I18N']->get('email to alert when sending of this message starts'),
        $GLOBALS['I18N']->get('separate multiple with a comma'), $notify_start,
        $GLOBALS['I18N']->get('email to alert when sending of this message has finished'),
        $GLOBALS['I18N']->get('separate multiple with a comma'), $notify_end);

    $send_content .= sprintf('
    <div class="campaignTracking">
    <label for="cb[google_track]">%s</label><input type="hidden" name="cb[google_track]" value="1" /><input type="checkbox" name="google_track" id="google_track" value="1" %s />
    </div>',
        Help('googletrack').' '.s('Add analytics tracking code'),
        !empty($messagedata['google_track']) ? 'checked="checked"' : '');

    /* add analytics query parameters then hide if not currently enabled */
    $analytics = getAnalyticsQuery();
    $editableParameters = $analytics->editableParameters($messagedata);

    if (count($editableParameters) > 0) {
        $send_content .= '<div id="analytics">';

        foreach ($editableParameters as $field => $default) {
            $value =  isset($messagedata[$field]) ? $messagedata[$field] : $default;
            $send_content .= sprintf(
                '<label>%s <input type="text" name="%s" id="%s" value="%s" size="35"/></label>',
                $field,
                $field,
                $field,
                $value
            ) . "\n";
        }
        $send_content .= '</div>';

        if (empty($messagedata['google_track'])) {
            $GLOBALS['pagefooter']['hideanalytics'] = '<script type="text/javascript">$("#analytics").hide()</script>';
        }
    }
    $numsent = Sql_Fetch_Row_Query(sprintf('select count(*) from %s where messageid = %d',
        $GLOBALS['tables']['usermessage'], $messagedata['id']));
    if ($numsent[0] < RESETSTATS_MAX) {
        $send_content .= sprintf('
        <div class="resetStatistics">
        <label for="cb[resetstats]">%s</label><input type="hidden" name="cb[resetstats]" value="1" /><input type="checkbox" name="resetstats" id="resetstats" value="1" %s />
        </div>',
            Help('resetstats').' '.s('Reset click statistics'),
            !empty($messagedata['resetstats']) ? 'checked="checked"' : '');
    } else {
        $send_content .= '<input type="hidden" name="resetstats" value="0" />';
    }

    $send_content .= sprintf('
    <div class="isTestCampaign">
    <label for="cb[istestcampaign]">%s</label><input type="hidden" name="cb[istestcampaign]" value="1" /><input type="checkbox" name="istestcampaign" id="istestcampaign" value="1" %s />
    </div>',
        Help('istestcampaign').' '.s('This is a test campaign'),
        !empty($messagedata['istestcampaign']) ? 'checked="checked"' : '');

    $show_lists = 0;

    $send_content .= '<div class="sizeEstimate">';
    if (!empty($messagedata['htmlsize'])) {
        $send_content .= $GLOBALS['I18N']->get('Estimated size of HTML email').': '.formatBytes($messagedata['htmlsize']).'<br/>';
    }
    if (!empty($messagedata['textsize'])) {
        $send_content .= $GLOBALS['I18N']->get('Estimated size of text email').': '.formatBytes($messagedata['textsize']).'<br/>';
    }
    /*
      var_dump($messagedata['targetlist']);
    */

    if (!empty($messagedata['textsize']) || !empty($messagedata['htmlsize'])) {
        if (is_array($messagedata['targetlist']) && count($messagedata['targetlist'])) {
            $lists = $messagedata['targetlist'];
            if (isset($messagedata['excludelist'])) {
                $excludelists = $messagedata['excludelist'];
            } else {
                $excludelists = array();
            }

            if (!empty($lists['all']) || !empty($lists['allactive'])) {
                $allactive = isset($lists['allactive']);
                $all = isset($lists['all']);
                $req = Sql_Query(sprintf('select id,active from %s %s', $GLOBALS['tables']['list'], $subselect));
                $lists = array();
                while ($row = Sql_Fetch_Row($req)) {
                    if (($allactive && $row[1]) || $all) {
                        $lists[$row[0]] = $row[0];
                    }
                }
            }
            unset($lists['all']);
            unset($lists['allactive']);
            if (isset($messagedata['excludelist']) && is_array($messagedata['excludelist']) && count($messagedata['excludelist'])) {
                $exclude = sprintf(' and listuser.listid not in (%s)', implode(',', $messagedata['excludelist']));
            } else {
                $exclude = '';
            }

            $htmlcnt = Sql_Fetch_Row_Query(sprintf('select count(distinct userid) from %s listuser,%s user where user.htmlemail and user.id = listuser.userid and listuser.listid in (%s) %s',
                $GLOBALS['tables']['listuser'], $GLOBALS['tables']['user'], implode(',', array_keys($lists)), $exclude),
                1);
            $textcnt = Sql_Fetch_Row_Query(sprintf('select count(distinct userid) from %s listuser,%s user where !user.htmlemail and user.id = listuser.userid and listuser.listid in (%s) %s',
                $GLOBALS['tables']['listuser'], $GLOBALS['tables']['user'], implode(',', array_keys($lists)), $exclude),
                1);
            if ($htmlcnt[0] || $textcnt[0]) {
                if (!isset($messagedata['textsize'])) {
                    $messagedata['textsize'] = 0;
                }
                if (!isset($messagedata['htmlsize'])) {
                    $messagedata['htmlsize'] = 0;
                }

                $send_content .= $GLOBALS['I18N']->get('Estimated size of mailout').': '.formatBytes($htmlcnt[0] * $messagedata['htmlsize'] + $textcnt[0] * $messagedata['textsize']).'<br/>';
                //# remember this to see how well the estimate was
                Sql_Query(sprintf('replace into %s set name = "estimatedsize",id=%d,data = "%s"',
                    $GLOBALS['tables']['messagedata'], $id,
                    $htmlcnt[0] * $messagedata['htmlsize'] + $textcnt[0] * $messagedata['textsize']));
                $send_content .= sprintf($GLOBALS['I18N']->get('About %d users to receive HTML and %s users to receive text version of email'),
                        $htmlcnt[0], $textcnt[0]).'<br/>';
                Sql_Query(sprintf('replace into %s set name = "estimatedhtmlusers",id=%d,data = "%s"',
                    $GLOBALS['tables']['messagedata'], $id, $htmlcnt[0]));
                Sql_Query(sprintf('replace into %s set name = "estimatedtextusers",id=%d,data = "%s"',
                    $GLOBALS['tables']['messagedata'], $id, $textcnt[0]));
            }
        }
    }
    $send_content .= '</div>';

    //# the button to actually send the campagin
    $send_content .= $placeinqueue;

    echo '<div class="sendtabs_container">';

    $tabs->setListClass('sendcampaign');
    $tabs->setId('sendtabs');
//  $tabs->addPrevNext();
    $tabs->addTabNo();
    echo $tabs->display();
    //print '<div id="tabcontent"></div>';

    $panelcontent = '';
    switch ($_GET['tab']) {
        case 'Attach':
            $panelcontent = $att_content;
            break;
        //   case "Criteria": print $criteria_content; break; // moved to plugin
        case 'Text':
            $panelcontent = $textcontent;
            break;
        case 'Format':
            $panelcontent = $formatting_content;
            break;
        case 'Scheduling':
            $panelcontent = $scheduling_content;
            break;
//    case "RSS": print $rss_content;break;            //Obsolete by rssmanager plugin
        case 'Lists':
            $show_lists = 1;
            break;
        case 'Review':
            $panelcontent = $review_content;
            break;
        case 'Finish':
            $panelcontent = $send_content;
            break;
        case 'Forward':
            $panelcontent = $forwardcontent;
            break;
        default:
            $isplugin = 0;
            foreach ($plugintabs as $tabname => $tabcontent) {
                if ($_GET['tab'] == $tabname) {
                    $panelcontent = $tabcontent;
                    $isplugin = 1;
                }
            }
            if (!$isplugin) {
                $panelcontent = $maincontent;
            }
            break;
    }
}

$GLOBALS['pagefooter']['sendtabs'] = "<script language='Javascript' type='text/javascript' src='js/jquery.cycle2.min.js'></script>
<script>
    $(document).ready(function(){
        var counttab = ".$counttabs.";
        var currenttab = $('.current').attr('id');
        var tabvis = (($('.sendtabs_container').width()-50)/102)+'';
        var arrvis = tabvis.split('.');
        var tabdif = currenttab-arrvis[0];
        if (counttab <= arrvis[0]) {arrvis[0] = counttab};
        $('.sendcampaign').cycle({ slides:'> li', timeout:0, fx:'carousel', allowWrap:false, carouselVisible:arrvis[0], next:'.nexttab', prev:'.prevtab' });
        $('.sendcampaign').cycle('goto',tabdif);

        $(window).on('resize',function() {
            $('.sendcampaign').cycle('destroy');
            tabvis = (($('.sendtabs_container').width()-50)/102)+'';
            arrvis = tabvis.split('.');
            tabdif = currenttab-arrvis[0];
            if (counttab <= arrvis[0]) {arrvis[0] = counttab};
            $('.sendcampaign').cycle({ slides:'> li', timeout:0, fx:'carousel', allowWrap:false, carouselVisible:arrvis[0], next:'.nexttab', prev:'.prevtab' });
            $('.sendcampaign').cycle('goto',tabdif);
        });
    });
</script><style>#sendtabs ul{margin:0 1px}</style>";

/* OLD SCRIPT:

    "<script type='text/javascript'>\n".
    '$(document).ready(function() {
    var counttab = ' .$counttabs.";
    var currenttab = $('.current').attr('id');
    if(matchMedia('only screen and (max-width: 480px)').matches){ tabs=2; starttab=currenttab-2;  }
    else if(matchMedia('only screen and (max-width: 767px)').matches){ tabs=3; starttab=currenttab-3;}
    else if(matchMedia('only screen and (max-width: 967px)').matches){ tabs=4; starttab=currenttab-4;}
    else{ tabs=6; starttab=currenttab-6; if ( counttab < 7 ){ $('.nexttab').addClass('disabled'); } }
    if ( starttab < 1 ){ starttab=0; $('.prevtab').addClass('disabled'); }
    if ( currenttab>=counttab ){ $('.nexttab').addClass('disabled'); }

    $('#sendtabs').jCarouselLite({
        btnNext: '.nexttab',
        btnPrev: '.prevtab',
        circular: false,
        visible: tabs,
        auto: null,
        speed:100,
        scroll:1,
        start: starttab
    });
});
$(window).resize(function(){
    var counttab = " .$counttabs.";
    var currenttab = $('.current').attr('id');
    if(matchMedia('only screen and (max-width: 480px)').matches){ tabs=2; $('.nexttab').removeClass('disabled'); starttab=currenttab-2;}
    else if(matchMedia('only screen and (max-width: 767px)').matches){ tabs=3; $('.nexttab').removeClass('disabled'); starttab=currenttab-3;}
    else if(matchMedia('only screen and (max-width: 967px)').matches){ tabs=4; $('.nexttab').removeClass('disabled'); starttab=currenttab-4;}
    else{ tabs=6; starttab=currenttab-6; if ( counttab < 7){ $('.nexttab').addClass('disabled'); } }
    if ( starttab < 1 ){ starttab=0; $('.prevtab').addClass('disabled'); }
    if ( currenttab>=counttab ){ $('.nexttab').addClass('disabled'); }
    $('#sendtabs').jCarouselLite({
        btnNext: '.nexttab',
        btnPrev: '.prevtab',
        circular: false,
        visible: tabs,
        auto: null,
        speed:100,
        scroll:1,
        start: starttab
    });
});

</script>";
*/

echo '<img src="ui/'.$GLOBALS['ui'].'/images/prevtab.png" id="prev" class="prevtab" />';
echo '<img src="ui/'.$GLOBALS['ui'].'/images/nexttab.png" id="next" class="nexttab" />';
echo '</div>';

//# if all is there, we can enable the send button
$allReady = true;
$GLOBALS['pagefooter']['addtoqueue'] = '<script type="text/javascript">
$("#addtoqueue").html("");
</script>';

$testValue = trim($messagedata['subject']);
if (empty($testValue) || $testValue == '(no subject)') {
    $allReady = false;
    $GLOBALS['pagefooter']['addtoqueue'] .= '<script type="text/javascript">
  $("#addtoqueue").append(\'<div class="missing">' .$GLOBALS['I18N']->get('subject missing').'</div>\');
  </script>';
}
$testValue = trim($messagedata['message']);
$testValue2 = trim($messagedata['sendurl']);

if (empty($testValue) && (empty($testValue2) || $testValue2 == 'e.g. https://www.phplist.com/testcampaign.html')) {
    $allReady = false;
    $GLOBALS['pagefooter']['addtoqueue'] .= '<script type="text/javascript">
  $("#addtoqueue").append(\'<div class="missing">' .$GLOBALS['I18N']->get('message content missing').'</div>\');
  </script>';
}

if ($messagedata['sendmethod'] == 'remoteurl') {
    $code = testUrl($messagedata['sendurl']);
    if ($code != 200) {
        $allReady = false;
        $GLOBALS['pagefooter']['addtoqueue'] .= '<script type="text/javascript">
        $("#addtoqueue").append(\'<div class="missing">' .s('Incorrect URL for sending').' ('.resourceLink('http://resources.phplist.com/documentation/errors/sendurlinvalid').')</div>\');
        </script>';
    }
}

$testValue = trim($messagedata['fromfield']);
if (empty($testValue)) {
    $allReady = false;
    $GLOBALS['pagefooter']['addtoqueue'] .= '<script type="text/javascript">
  $("#addtoqueue").append(\'<div class="missing">' .$GLOBALS['I18N']->get('From missing').'</div>\');
  </script>';
}

//#16615, check that "send until" is in after the embargo and warn if it isn't
$finishSending = mktime($messagedata['finishsending']['hour'], $messagedata['finishsending']['minute'], 0,
    $messagedata['finishsending']['month'], $messagedata['finishsending']['day'],
    $messagedata['finishsending']['year']);
$embargoTime = mktime($messagedata['embargo']['hour'], $messagedata['embargo']['minute'], 0,
    $messagedata['embargo']['month'], $messagedata['embargo']['day'], $messagedata['embargo']['year']);
$currentTime = time();

if ($finishSending < $embargoTime) {
    $allReady = false;
    $GLOBALS['pagefooter']['addtoqueue'] .= '<script type="text/javascript">
  $("#addtoqueue").append(\'<div class="missing">' .s('This campaign is scheduled to stop sending before the embargo time. No mails will be sent.').'<br/>'.PageLinkButton('send&amp;id='.$messagedata['id'].'&amp;tab=Scheduling',
            s('Review Scheduling')).'</div>\');
  </script>';
} elseif ($finishSending < $currentTime) {
    $allReady = false;
    $GLOBALS['pagefooter']['addtoqueue'] .= '<script type="text/javascript">
  $("#addtoqueue").append(\'<div class="missing">' .s('This campaign is scheduled to stop sending in the past. No mails will be sent.').'<br/>'.PageLinkButton('send&amp;id='.$messagedata['id'].'&amp;tab=Scheduling',
            s('Review Scheduling')).'</div>\');
  </script>';
}

if (empty($messagedata['targetlist'])) {
    $allReady = false;
    $GLOBALS['pagefooter']['addtoqueue'] .= '<script type="text/javascript">
  $("#addtoqueue").append(\'<div class="missing">' .$GLOBALS['I18N']->get('destination lists missing').'</div>\');
  </script>';
}
if ($hasClickTrackLinks && BLOCK_PASTED_CLICKTRACKLINKS) {
    $allReady = false;
    $GLOBALS['pagefooter']['addtoqueue'] .= '<script type="text/javascript">
  $("#addtoqueue").append(\'<div class="missing">' .s('Content contains click track links.').resourceLink('http://resources.phplist.com/documentation/errors/pasteclicktrack').'</div>\');
  </script>';
}

foreach ($GLOBALS['plugins'] as $pluginname => $plugin) {
    $pluginerror = '';
    $pluginerror = $plugin->allowMessageToBeQueued($messagedata);
    if ($pluginerror) {
        $allReady = false;
        $pluginerror = preg_replace("/\n/", '', $pluginerror);
        $GLOBALS['pagefooter']['addtoqueue'] .= '<script type="text/javascript">
    $("#addtoqueue").append(\'<div class="missing">' .$pluginerror.'</div>\');
    </script>';
    }
}

if ($allReady) {
    $GLOBALS['pagefooter']['addtoqueue'] .= '<script type="text/javascript">
  $("#addtoqueue").html(\'<input class="action-button" type="submit" name="send" id="addtoqueuebutton" value="' .htmlspecialchars(str_replace("'",
            "\'", s('Place Campaign in Queue for Sending'))).'">\');
  </script>';
} else {
    $GLOBALS['pagefooter']['addtoqueue'] .= '<script type="text/javascript">
  $("#addtoqueue").append(\'<div class="error">' .$GLOBALS['I18N']->get('Some required information is missing. The send button will be enabled when this is resolved.').'</div>\');
//  $("#addtoqueue").append(\'<button class="submit" type="submit" name="save" id="addtoqueuebutton" disabled="disabled">' .$GLOBALS['I18N']->get('Send Campaign').'</button>\');
  </script>';
}

$saveDraftButton = '<div class="sendSubmit">
    <input class="submit" type="submit" name="savedraft" value="' .s('Save as draft').'"/>
    <input type="hidden" name="id" value="' .$id.'"/>
    <input type="hidden" name="status" value="draft"/>
    <input class="submit" type="submit" name="save" value="' .s('Save and continue editing').'"/>
  </div>
';

$titleInput = '<label for="campaigntitle">'.s('Campaign Title').Help('campaigntitle').'</label>'.
    '<input type="text" name="campaigntitle"  id="campaigntitleinput"
    value="' .htmlentities($messagedata['campaigntitle'], ENT_QUOTES, 'UTF-8').'" size="60" />';
$metaPanel = new UIPanel(s('Meta data'), $titleInput);
$metaPanel->setID('metadata');

$testpanel = new UIPanel(s('Send Test'), $sendtest_content);
$testpanel->setID('testpanel');

# print $testpanel->display();

Filemanager

Name Type Size Permission Actions
PEAR Folder 0755
PHPMailer Folder 0755
PHPMailer6 Folder 0755
actions Folder 0755
css Folder 0755
data Folder 0755
help Folder 0755
images Folder 0755
inc Folder 0755
info Folder 0755
js Folder 0755
locale Folder 0755
onyxrss Folder 0755
plugins Folder 0755
tests Folder 0755
ui Folder 0755
.gitignore File 20 B 0644
.htaccess File 489 B 0644
.minceconf File 994 B 0644
AnalyticsQuery.php File 985 B 0644
CsvReader.php File 1.27 KB 0644
EmailSender.php File 477 B 0644
Updater.php File 193 B 0644
about.php File 7.4 KB 0644
accesscheck.php File 715 B 0644
addprefix.php File 1.01 KB 0644
adduser.php File 46 B 0644
admin.php File 12.77 KB 0644
adminattributes.php File 7.46 KB 0644
admins.php File 5.16 KB 0644
analytics.php File 2.84 KB 0644
attributes.php File 26.2 KB 0644
blacklistemail.php File 1.22 KB 0644
bounce.php File 11.14 KB 0644
bouncemgt.php File 1.44 KB 0644
bouncerule.php File 4.27 KB 0644
bouncerules.php File 6.33 KB 0644
bounces.php File 7.57 KB 0644
catlists.php File 3.34 KB 0644
checkbouncerules.php File 1.43 KB 0644
checki18n.php File 3.13 KB 0644
checkprerequisites.php File 1.62 KB 0644
class.image.inc File 3.9 KB 0644
class.phplistmailer.php File 30.73 KB 0644
class.phplistmailerbase.php File 1.67 KB 0644
community.php File 3.5 KB 0644
communityfeed.php File 2.36 KB 0644
configure.php File 7.85 KB 0644
connect.php File 89.86 KB 0644
convertstats.php File 5.83 KB 0644
converttoutf8.php File 3.78 KB 0644
cron.php File 3.34 KB 0644
date.php File 7.65 KB 0644
dbcheck.php File 3.7 KB 0644
defaultFrontendTexts.php File 9.79 KB 0644
defaultconfig.php File 30.66 KB 0644
defaultplugin.php File 31.59 KB 0644
defaults.php File 3.64 KB 0644
defaultsystemtemplate.php File 15.29 KB 0644
defaulttest.php File 1.23 KB 0644
dlusers.php File 235 B 0644
domainbounces.php File 507 B 0644
domainstats.php File 371 B 0644
editattributes.php File 8.78 KB 0644
editlist.php File 7.4 KB 0644
eventlog.php File 4.68 KB 0644
export.php File 6.86 KB 0644
exportuserdata.php File 8.26 KB 0644
fckphplist.php File 49.84 KB 0644
gchart.php File 903 B 0644
generatebouncerules.php File 5.51 KB 0644
home.php File 6.56 KB 0644
hostedprocessqueuesetup.php File 3.09 KB 0644
htaccess File 311 B 0644
image.php File 2.01 KB 0644
import.php File 2.75 KB 0644
import1.php File 11.09 KB 0644
import2.php File 34.16 KB 0644
import3.php File 22.72 KB 0644
import4.php File 16.86 KB 0644
importadmin.php File 17.08 KB 0644
importsimple.php File 7.32 KB 0644
index.php File 32.82 KB 0644
info.php File 1.07 KB 0644
init.php File 27.36 KB 0644
initialise.php File 12.05 KB 0644
initlanguages.php File 867 B 0644
languages.php File 21.37 KB 0644
lib.php File 86.79 KB 0644
list.php File 11.32 KB 0644
listbounces.php File 4.13 KB 0644
login.php File 6.39 KB 0644
logout.php File 865 B 0644
massremove.php File 2.55 KB 0644
mclicks.php File 7.28 KB 0644
members.php File 19.99 KB 0644
mergeduplicates.php File 4.48 KB 0644
message.php File 9.08 KB 0644
messages.php File 26.27 KB 0644
minify.txt File 201 B 0644
msgbounces.php File 3.4 KB 0644
msgstatus.php File 1.27 KB 0644
mviews.php File 6.27 KB 0644
mysql.inc File 40 B 0644
mysqli.inc File 14.02 KB 0644
pageaction.php File 1.11 KB 0644
phpListAdminAuthentication.php File 6.82 KB 0644
pluginlib.php File 9.43 KB 0644
plugins.php File 17.78 KB 0644
preparesend.php File 669 B 0644
processbounces.php File 35.36 KB 0644
processqueue.php File 3.71 KB 0644
readtestmail.php File 11.59 KB 0644
reconcileusers.php File 27.71 KB 0644
redirecttoupdater.php File 187 B 0644
reindex.php File 1.82 KB 0644
rsslib.php File 3.17 KB 0644
runcommand.php File 583 B 0644
send.php File 6.17 KB 0644
send_core.php File 63.91 KB 0644
sendemaillib.php File 69.84 KB 0644
sendprepared.php File 4.87 KB 0644
sessionlib.php File 2.7 KB 0644
setpermissions.php File 2.08 KB 0644
setup.php File 2.56 KB 0644
spage.php File 4.35 KB 0644
spageedit.php File 19.08 KB 0644
statsmgt.php File 1.23 KB 0644
statsoverview.php File 6.19 KB 0644
stresstest.php File 4.82 KB 0644
structure.php File 29.21 KB 0644
subscribelib2.php File 70.22 KB 0644
subscriberstats.php File 617 B 0644
suppressionlist.php File 1.71 KB 0644
system.php File 795 B 0644
systemstats.php File 5.73 KB 0644
template.php File 16.4 KB 0644
templates.php File 3.01 KB 0644
tests.php File 1.67 KB 0644
uclicks.php File 6.74 KB 0644
update.php File 187 B 0644
updateLib.php File 2.2 KB 0644
updatetlds.php File 358 B 0644
updatetranslation.php File 2.51 KB 0644
upgrade.php File 23.82 KB 0644
user.php File 23.08 KB 0644
usercheck.php File 2.55 KB 0644
userclicks.php File 11.57 KB 0644
userhistory.php File 8.25 KB 0644
usermgt.php File 1.9 KB 0644
users.php File 19.3 KB 0644
vCard.php File 1.9 KB 0644
viewmessage.php File 635 B 0644
viewtemplate.php File 1.86 KB 0644
vote.php File 38 B 0644