Example #1
0
 /**
  * Show_Send_Step_1
  * This shows the first step of the send process where the user chooses a list or segment to send to.
  *
  * You cannot send to part of a list (eg by searching),
  * you can only send a split test to whole list(s) or whole segment(s).
  *
  * If the user has no lists or segments, they are taken back to the default page which shows a list of split test campaigns
  * They are shown a message saying they need to create/be given access to a list or segment before trying to do a send.
  *
  * If there are lists or segments, then the user is shown a list of them to choose from.
  * They must select at least one list or segment before going to the next step.
  *
  * It also clears out the session variable which holds the split test send details.
  *
  * Step 1 also checks what type of split campaign you are trying to send.
  * You can't send 'percentage' split campaigns if cron is not enabled.
  * The 'percentage' split campaigns send a percentage of emails to a random selection of subscribers
  * then pauses, then sends the rest of the emails to the 'winner' (which has the most opens/clicked links).
  * This could probably be worked out if you don't have cron support but for now,
  * you can't send 'percentage' split campaigns if there is no cron.
  *
  * @uses GetUser
  * @uses User_API::GetLists
  * @uses User_API::GetSegmentList
  * @uses Session::Remove
  * @uses FlashMessage
  */
 public function Show_Send_Step_1()
 {
     $user = GetUser();
     $user_lists = $user->GetLists();
     $user_segments = $user->GetSegmentList();
     if (empty($user_lists) && empty($user_segments)) {
         FlashMessage(GetLang('Addon_splittest_Send_NoListsOrSegments'), SS_FLASH_MSG_ERROR, $this->admin_url);
         return;
     }
     $splitid = 0;
     if (isset($_GET['id'])) {
         $splitid = (int) $_GET['id'];
     }
     if ($splitid <= 0) {
         FlashMessage(GetLang('Addon_splittest_Send_InvalidSplitTest'), SS_FLASH_MSG_ERROR, $this->admin_url);
         return;
     }
     $api = $this->GetApi();
     $split_campaign_details = $api->Load($splitid);
     if (empty($split_campaign_details)) {
         FlashMessage(GetLang('Addon_splittest_Send_InvalidSplitTest'), SS_FLASH_MSG_ERROR, $this->admin_url);
         return;
     }
     if (!empty($split_campaign_details['jobstatus']) && $split_campaign_details['jobstatus'] != 'c') {
         FlashMessage(GetLang('Addon_splittest_Send_CannotSend_StillSending'), SS_FLASH_MSG_ERROR, $this->admin_url);
         return;
     }
     /**
      * If it's a percentage send, then check if cron is enabled.
      * If it's not, then don't allow the user to go any further.
      */
     if ($split_campaign_details['splittype'] == 'percentage') {
         if (!self::CheckCronEnabled()) {
             $message = sprintf(GetLang('Addon_splittest_CannotSendPercentage_NoCron'), IEM::urlFor('Settings', array('Tab' => 4)));
             FlashMessage($message, SS_FLASH_MSG_ERROR, $this->admin_url);
             return;
         }
     }
     /**
      * Only show segment options if the user has access to send to segments.
      */
     $this->template_system->Assign('DisplaySegments', $user->HasAccess('Segments', 'Send'));
     IEM::sessionRemove('SplitTestSend');
     $send_details = array();
     $send_details['splitid'] = $splitid;
     IEM::sessionSet('SplitTestSend', $send_details);
     $this->template_system->Assign('FlashMessages', GetFlashMessages(), false);
     $this->template_system->Assign('AdminUrl', $this->admin_url, false);
     $this->template_system->Assign('user_lists', $user_lists);
     $this->template_system->Assign('user_segments', $user_segments);
     $this->template_system->ParseTemplate('send_step1');
 }
Example #2
0
	/**
	* DeleteUsers
	* Deletes a list of users from the database via the api. Each user is checked to make sure you're not going to accidentally delete your own account and that you're not going to delete the 'last' something (whether it's the last active user, admin user or other).
	* If you aren't an admin user, you can't do anything at all.
	*
	* @param integer[] $users An array of userid's to delete
	* @param boolean $deleteData Whether or not to delete data owned by user along
	*
	* @see GetUser
	* @see User_API::UserAdmin
	* @see DenyAccess
	* @see CheckUserSystem
	* @see PrintManageUsers
	*
	* @return Void Doesn't return anything. Works out the relevant message about who was/wasn't deleted and prints that out. Returns control to PrintManageUsers.
	*/
	function DeleteUsers($users = array(), $deleteData = false)
	{
		$thisuser = GetUser();
		if (!$thisuser->UserAdmin()) {
			$this->DenyAccess();
			return;
		}

		if (!is_array($users)) {
			$users = array($users);
		}

		$not_deleted_list = array();
		$not_deleted = $deleted = 0;
		foreach ($users as $p => $userid) {
			if ($userid == $thisuser->Get('userid')) {
				$not_deleted++;
				$not_deleted_list[$userid] = array('username' => $thisuser->Get('username'), 'reason' => GetLang('User_CantDeleteOwn'));
				continue;
			}

			$error = $this->CheckUserSystem($userid);
			if (!$error) {
				$result = API_USERS::deleteRecordByID($userid, $deleteData);

				if ($result) {
					$deleted++;
				} else {
					$not_deleted++;
					$user = GetUser($userid);
					if ($user instanceof User_API) {
						$not_deleted_list[$userid] = array('username' => $user->Get('username'), 'reason' => '');
					} else {
						$not_deleted_list[$userid] = array('username' => $userid, 'reason' => '');
					}
				}
			} else {
				$not_deleted++;
				$user = GetUser($userid);
				if ($user instanceof User_API) {
					$not_deleted_list[$userid] = array('username' => $user->Get('username'), 'reason' => $error);
				} else {
					$not_deleted_list[$userid] = array('username' => $userid, 'reason' => $error);
				}
			}
		}


		if ($not_deleted > 0) {
			foreach ($not_deleted_list as $uid => $details) {
				FlashMessage(sprintf(GetLang('UserDeleteFail'), htmlspecialchars($details['username'], ENT_QUOTES, SENDSTUDIO_CHARSET), htmlspecialchars($details['reason'], ENT_QUOTES, SENDSTUDIO_CHARSET)), SS_FLASH_MSG_ERROR);
			}
		}

		if ($deleted > 0) {
			if ($deleted == 1) {
				FlashMessage(GetLang('UserDeleteSuccess_One'), SS_FLASH_MSG_SUCCESS, IEM::urlFor('Users'));
			} else {
				FlashMessage(sprintf(GetLang('UserDeleteSuccess_Many'), $this->FormatNumber($deleted)), SS_FLASH_MSG_SUCCESS, IEM::urlFor('Users'));
			}
		}

		IEM::redirectTo('Users');
	}
Example #3
0
	/**
	 * DeleteList
	 * Deletes a single list.
	 *
	 * @param Array $param Any parameters that needed to be passed into this function
	 *
	 * @return Void Redirects to the Manage Lists page.
	 */
	private function DeleteList($param)
	{
		$listApi = $this->GetApi('Lists');
		$list = (int)$_GET['id'];
		// ----- get jobs running for this user
		$db = IEM::getDatabase();
		$jobs_to_check = array();
		$query = "SELECT jobid FROM [|PREFIX|]jobs_lists WHERE listid = {$list}";
		$result = $db->Query($query);
		if(!$result){
			trigger_error(mysql_error()."<br />".$query);
			FlashMessage("Unable to load list jobs. <br /> ". mysql_error(), SS_FLASH_MSG_ERROR, IEM::urlFor('Lists'));
			exit();
		}
		while($row = $db->Fetch($result)){
			$jobs_to_check[] = $row['jobid'];
		}
		$db->FreeResult($result);
		if(!empty($jobs_to_check)){
			$query = "SELECT jobstatus FROM [|PREFIX|]jobs WHERE jobid IN (" . implode(',', $jobs_to_check) . ")";	
			$result = $db->Query($query);
			if(!$result){
				trigger_error(mysql_error()."<br />".$query);
				FlashMessage("Unable to load jobs. <br /> ". mysql_error() . "<br />Query: " . $query, SS_FLASH_MSG_ERROR, IEM::urlFor('Lists'));
				exit();
			}
			while($row = $db->Fetch($result)){
				if($row['jobstatus'] != 'c'){
					FlashMessage('Unable to delete contacts from list(s). Please cancel any campaigns sending to the list(s) in order to delete them.', SS_FLASH_MSG_ERROR, IEM::urlFor('Lists'));
					exit();
				}
			}
			$db->FreeResult($result);
		}
		// -----
		$status = $listApi->Delete($list, $param['user']->Get('userid'));

		if ($status) {
			$param['user']->LoadPermissions($param['user']->userid);
			$param['user']->RevokeListAccess($list);
			$param['user']->SavePermissions();
			FlashMessage(GetLang('ListDeleteSuccess'), SS_FLASH_MSG_SUCCESS, IEM::urlFor('Lists'));
		}
		FlashMessage(GetLang('ListDeleteFail'), SS_FLASH_MSG_ERROR, IEM::urlFor('Lists'));
	}
	public function page_saveRecord()
	{
		$record = IEM::requestGetPOST('record', array());

        $record['groupname'] = htmlspecialchars($record['groupname']);

		$created = ((IEM::ifsetor($record['groupid'], 0, 'intval') == 0) ? true : false);

		/*
		 * Transform the permission so that it will be recognized by the API
		 */

		$permissions = IEM::ifsetor($record['permissions'], array());


		$new_permissions = array();
		if (!is_array($permissions)) {
			$permissions = array();
		}
		if (!empty($permissions)) {
			foreach ($permissions as $each) {
				$temp = explode('.', $each);

				// This can only handle 2 level permissions,
				// ie. autoresponders.create, autoresponders.delete, autoresponders.edit
				// will become $permissions['autoresponders'] = array('create', 'delete', 'edit');
				if (count($temp) != 2) {
					continue;
				}

				if (!isset($new_permissions[$temp[0]])) {
					$new_permissions[$temp[0]] = array();
				}

				$new_permissions[$temp[0]][] = $temp[1];
			}
		}

		$record['permissions'] = $new_permissions;

		if (empty($record)) {
			return $this->page_createGroup($record);
		}

		// Check if "Request Token" matches
		// This tries to prevent CSRF
		$token = IEM::sessionGet('UsersGroups_Editor_RequestToken', false);
		if (!$token || $token != IEM::requestGetPOST('requestToken', false)) {
			return $this->page_createGroup($record);
		}

		$status = API_USERGROUPS::saveRecord($record);
		if (!$status) {
			FlashMessage(GetLang('UsersGroups_From_Error_CannotSave'), SS_FLASH_MSG_ERROR);
			return $this->printEditor($record);
		}

		$messageVariable = 'UsersGroups_From_Success_Saved';
		if ($created) {
			$messageVariable = 'UsersGroups_From_Success_Created';
		}

		FlashMessage(GetLang($messageVariable), SS_FLASH_MSG_SUCCESS, IEM::urlFor('UsersGroups'));
	}
Example #5
0
	/**
	* DeleteSubscribers
	* Deletes subscribers from the list. Goes through the subscribers array (passed in) and deletes them from the list as appropriate.
	*
	* @param Array $subscribers A list of subscriber id's to remove from the list.
	*
	* @see GetApi
	* @see Subscribers_API::DeleteSubscriber
	*
	* @return Void Doesn't return anything. Creates a report and prints that out.
	*/
	function DeleteSubscribers($subscribers=array())
	{
		if (!is_array($subscribers)) {
			$subscribers = array($subscribers);
		}

		if (empty($subscribers)) {
			return array(false, GetLang('NoSubscribersToDelete'));
		}
		if (!isset($GLOBALS['Message'])) {
			$GLOBALS['Message'] = '';
		}

		// ----- get jobs running for this user
		$listid = 0;
		if (isset($_POST['lists'])) {
			$listid = $_POST['lists'];
		} elseif (isset($_GET['Lists'])) {
			$listid = $_GET['Lists'];
		} elseif (isset($_POST['list'])) {
			$listid = $_POST['list'];
		} elseif (isset($_GET['List'])) {
			$listid = $_GET['List'];
		}
		if(is_array($listid) && $listid[0] == 'any'){
			$listid = array();
		} else {
			$listid = array(0 => (int) $listid);
		}
		$db = IEM::getDatabase();
		// don't have a specific list? use the subscribers' listid
		if(empty($listid)){
			$query = "SELECT listid FROM [|PREFIX|]list_subscribers WHERE subscriberid IN (".implode(",",$subscribers).")";
			$result = $db->Query($query);
			if(!$result){
				trigger_error(mysql_error()."<br />".$query);
				FlashMessage(mysql_error(), SS_FLASH_MSG_ERROR, IEM::urlFor('Lists'));
				exit();
			}
			while($row = $db->Fetch($result)){
				$listid[] = $row['listid'];
			}
		}
		
		$jobs_to_check = array();
		
		if(!empty($listid)){
			$query = "SELECT jobid FROM [|PREFIX|]jobs_lists WHERE listid IN (".implode(",",$listid).")";
			$result = $db->Query($query);
			if(!$result){
				trigger_error(mysql_error()."<br />".$query);
				FlashMessage(mysql_error(), SS_FLASH_MSG_ERROR, IEM::urlFor('Lists'));
				exit();
			}
			while($row = $db->Fetch($result)){
				$jobs_to_check[] = $row['jobid'];
			}
			$db->FreeResult($result);
		}
		
		if(!empty($jobs_to_check)){
			$query = "SELECT jobstatus FROM [|PREFIX|]jobs WHERE jobid IN (" . implode(',', $jobs_to_check) . ")";	
			$result = $db->Query($query);
			if(!$result){
				trigger_error(mysql_error()."<br />".$query);
				FlashMessage(mysql_error(), SS_FLASH_MSG_ERROR, IEM::urlFor('Lists'));
				exit();
			}
			while($row = $db->Fetch($result)){
				if($row['jobstatus'] != 'c'){
					FlashMessage('Unable to delete contacts from list(s). Please cancel any campaigns sending to the list(s) in order to delete them.', SS_FLASH_MSG_ERROR, IEM::urlFor('Lists'));
					exit();
				}
			}
			$db->FreeResult($result);
		}
		// -----


		$subscriber_search = IEM::sessionGet('Search_Subscribers');
		$list = $subscriber_search['List'];

		$subscribersdeleted = 0;
		$subscribersnotdeleted = 0;
		$SubscriberApi = $this->GetApi('Subscribers');
		foreach ($subscribers as $p => $subscriberid) {
			list($status, $msg) = $SubscriberApi->DeleteSubscriber(false, 0, $subscriberid);
			if ($status) {
				$subscribersdeleted++;
				continue;
			}
			$subscribersnotdeleted++;
		}

		$msg = '';

		if ($subscribersnotdeleted > 0) {
			if ($subscribersnotdeleted == 1) {
				$GLOBALS['Error'] = GetLang('Subscriber_NotDeleted');
			} else {
				$GLOBALS['Error'] = sprintf(GetLang('Subscribers_NotDeleted'), $this->FormatNumber($subscribersnotdeleted));
			}
			$msg .= $this->ParseTemplate('ErrorMsg', true, false);
		}

		if ($subscribersdeleted > 0) {
			if ($subscribersdeleted == 1) {
				$msg .= $this->PrintSuccess('Subscriber_Deleted');
			} else {
				$msg .= $this->PrintSuccess('Subscribers_Deleted', $this->FormatNumber($subscribersdeleted));
			}
		}
		$GLOBALS['Message'] .= $msg;
	}
Example #6
0
	/**
	 * bounceStep2
	 * Displays the bounce details for that list, allowing the user to fill in or modify the details.
	 *
	 * @return void Doesn't return anything. Prints out bounce details form.
	 */
	private function bounceStep2()
	{
		$user = GetUser();
		$list_api = $this->GetApi('Lists');
		$bd = self::hold('TestBounceDetails');

		$list = IEM::ifsetor(intval($_POST['list']), null);
		if (!$list) {
			$list = self::hold('list');
		}

		// User should have edit permissions for the list since they can change its bounce settings.
		// TODO: it should be for all lists that share this bounce server and username.
		$access = $user->HasAccess('lists', 'edit', $list);

		// Get bounce details for list.
		if (!$list_api->Load($list) || !$access) {
			$GLOBAL['ErrorMessage'] = GetLang('ListDoesntExist');
			$this->DenyAccess();
			return;
		}

		// Remember the List ID obtained in step 1.
		self::hold('list', $list);

		// The bounce details template still uses the old system.
		$GLOBALS['Bounce_Server'] = IEM::ifsetor($bd['server'], $list_api->bounceserver);
		$GLOBALS['Bounce_Username'] = IEM::ifsetor($bd['username'], $list_api->bounceusername);

		$GLOBALS['Bounce_Password'] = IEM::ifsetor($bd['password'], $list_api->bouncepassword);

		$imap = IEM::ifsetor($bd['imap'], $list_api->imapaccount);
		$GLOBALS['Imap_Selected'] = ($imap) ? ' selected="selected"' : '';

		$GLOBALS['DisplayExtraMailSettings'] = 'none';
		$extra_settings = IEM::ifsetor($bd['extra_settings'], $list_api->extramailsettings);
		if ($extra_settings) {
			$GLOBALS['DisplayExtraMailSettings'] = '';
			$GLOBALS['Bounce_ExtraOption'] = ' checked="checked"';
			$GLOBALS['Bounce_ExtraSettings'] = $extra_settings;
		}
		$GLOBALS['Bounce_AgreeDeleteAll'] = $list_api->agreedeleteall ? ' checked="checked"' : '';

		$tpl = GetTemplateSystem();

		// Show the manual settings if we're coming back from a future step.
		$tpl->Assign('show_manual', !is_null(($bd['server'])));
		$tpl->Assign('list_url', IEM::urlFor('Lists', array('Action' => 'edit', 'id' => $list)));
		$tpl->Assign('list_name', $list_api->name, true);
		$tpl->Assign('cron_url', IEM::urlFor('Settings', array('Tab' => 4)));
		$tpl->Assign('system_access', $user->HasAccess('System', 'System'));
		$tpl->ParseTemplate('BounceStep2');
	}
	/**
	* Process
	* Works out what you're trying to do and takes appropriate action.
	* Checks to make sure you have access to remove subscribers before anything else.
	*
	* @param String $action Action to perform. This is usually 'step1', 'step2', 'step3' etc. This gets passed in by the Subscribers::Process function.
	*
	* @see Subscribers::Process
	* @see GetUser
	* @see User_API::HasAccess
	* @see ChooseList
	* @see RemoveSubscriber_Step2
	* @see RemoveSubscribers
	*
	* @return Void Prints out the step, doesn't return anything.
	*/
	function Process($action=null)
	{
		$user = GetUser();
		$access = $user->HasAccess('Subscribers', 'Delete');

		$this->PrintHeader(false, false, false);

		if (!is_null($action)) {
			$action = strtolower($action);
		}

		if (!$access) {
			$this->DenyAccess();
		}

		switch ($action) {
			case 'step3':
				$listid = (isset($_POST['list'])) ? (int)$_POST['list'] : $_GET['list'];

				/**
				 * Check if user have access to the list
				 */
					$temp = $user->GetLists();
					if (!array($temp) || empty($temp)) {
						$this->DenyAccess();
						return;
					}

					$temp = array_keys($temp);
					if (!in_array($listid, $temp)) {
						$this->DenyAccess();
						return;
					}
				/**
				 * -----
				 */

				$removelist = array();
				$removetype = strtolower($_POST['RemoveOption']);
				if (!empty($_POST['RemoveEmailList'])) {
					$removelist = explode("\r\n", trim($_POST['RemoveEmailList']));
				}

				if (isset($_FILES['RemoveFile']) && $_FILES['RemoveFile']['tmp_name'] != 'none' && $_FILES['RemoveFile']['name'] != '') {
					$filename = TEMP_DIRECTORY . '/removelist.' . $user->userid . '.txt';
					if (is_uploaded_file($_FILES['RemoveFile']['tmp_name'])) {
						move_uploaded_file($_FILES['RemoveFile']['tmp_name'], $filename);
					} else {
						$GLOBALS['Error'] = sprintf(GetLang('UnableToOpenFile'), $_FILES['RemoveFile']['name']);
						$GLOBALS['Message'] = $this->ParseTemplate('ErrorMsg', true, false);
						$this->RemoveSubscriber_Step2($listid);
						break;
					}

					if (!$fp = fopen($filename, 'r')) {
						$GLOBALS['Error'] = sprintf(GetLang('UnableToOpenFile'), $_FILES['RemoveFile']['name']);
						$GLOBALS['Message'] = $this->ParseTemplate('ErrorMsg', true, false);
						$this->RemoveSubscriber_Step2($listid);
						break;
					}

					$data = fread($fp, filesize($filename));
					fclose($fp);
					unlink($filename);
					$data = str_replace("\r\n", "\n", $data);
					$data = str_replace("\r", "\n", $data);
					$emailaddresses = explode("\n", $data);

					if (empty($emailaddresses)) {
						$GLOBALS['Error'] = sprintf(GetLang('EmptyFile'), $_FILES['RemoveFile']['name']);
						$GLOBALS['Message'] = $this->ParseTemplate('ErrorMsg', true, false);
						$this->RemoveSubscriber_Step2($listid);
						break;
					}
					$removelist = $emailaddresses;
				}

				if (is_array($removelist)) {
					$removelist = array_unique($removelist);
				}

				if (empty($removelist)) {
					$GLOBALS['Error'] = GetLang('EmptyRemoveList');
					$GLOBALS['Message'] = $this->ParseTemplate('ErrorMsg', true, false);
					$this->RemoveSubscriber_Step2($listid);
					break;
				}

				// reset the session so it can be set up again next time GetLists is called.
				IEM::sessionRemove('UserLists');

				$this->RemoveSubscribers($listid, $removetype, $removelist);

			break;
			case 'step2':
				$listid = (isset($_POST['list'])) ? (int)$_POST['list'] : $_GET['list'];
				// ----- get jobs running for this user
				$db = IEM::getDatabase();
				$jobs_to_check = array();
				$query = "SELECT jobid FROM [|PREFIX|]jobs_lists WHERE listid = {$listid}";
				$result = $db->Query($query);
				if(!$result){
					trigger_error(mysql_error());
					FlashMessage(mysql_error(). "<br />Line: ".__LINE__, SS_FLASH_MSG_ERROR, IEM::urlFor('Lists'));
					exit();
				}
				while($row = $db->Fetch($result)){
					$jobs_to_check[] = $row['jobid'];
				}
				$db->FreeResult($result);
				if(!empty($jobs_to_check)){
                    $query = "SELECT jobstatus FROM [|PREFIX|]jobs WHERE jobtype='send' AND jobid IN (" . implode(',', $jobs_to_check) . ")";
					$result = $db->Query($query);
					if(!$result){
						trigger_error(mysql_error());
						FlashMessage(mysql_error(). "<br />Line: ".__LINE__, SS_FLASH_MSG_ERROR, IEM::urlFor('Lists'));
						exit();
					}
					while($row = $db->Fetch($result)){
						if($row['jobstatus'] != 'c'){
							FlashMessage('Unable to delete contacts from list(s). Please cancel any campaigns sending to the list(s) in order to delete them.', SS_FLASH_MSG_ERROR, IEM::urlFor('Lists'));
							exit();
						}
					}
					$db->FreeResult($result);
				}
				// -----
				$this->RemoveSubscriber_Step2($listid);
			break;
			default:
				$this->ChooseList('Remove', 'Step2');
		}
	}