View Issue Details

IDProjectCategoryView StatusLast Update
0010550mantisbtfeaturepublic2009-06-26 12:02
Reportermravcek Assigned Tosiebrand  
PrioritynormalSeverityminorReproducibilityN/A
Status closedResolutionduplicate 
Summary0010550: Report issue via email
Description

Not sure but maybe somebody may be interested ...

This is great tool - just forward your email to mantis account to add new issue. Issue will be created with attachments, project, category and filled custom fields
This code is not perfect, but works ok if used properly.

How it works
1) Forward the email
To: your_imap_mantis_account@your_email_domain.com, assign_to_forename.surname1@your_email_domain.com, assign_to_forename.surname2@your_email_domain.com ...
CC: monitored_by_forename.surname@your_email_domain.com
2) Specify Project and Category

  • emails with no project and category set will be placed in g_default_email_project_id with g_default_email_category
  • The best way how to specify project and category is copy "Category" from existing emails received from mantis
    Of course this works only in case you have enabled

    OFF, EMAIL_CATEGORY_PROJECT_CATEGORY (format: [Project] Category)

    $g_email_set_category = ON;

  • Or just set Category (In outlook go to Options->Categories) in format [Project] Category.
    3) Add Custom fields
    • Add text in your email body in following format:
      “<CustomFieldName: Value>”
      For example:
      Hello,
      This project is for “<Customer: IBM>” and needs to be finished before “<Due Date: 16/05/2009>”.
      Best regards,
      ONLY String and Date (in format DD/MM/YYYY) are supported
      4) Send the email
TagsNo tags attached.
Attached Files
add_new_issue_via_email_for_mantis.php (42,401 bytes)   
<?php
//This is great tool - just forward your email to mantis account to add new issue. Issue will be created with attachments, project, category and filled custom fields
// This code is not perfect, but works ok if used properly. 

//How it works
//1) Forward the email 
//To: your_imap_mantis_account@your_email_domain.com, assign_to_forename.surname1@your_email_domain.com, assign_to_forename.surname2@your_email_domain.com ...
//CC: monitored_by_forename.surname@your_email_domain.com
//2)  Specify Project and Category
//- emails with no project and category set will be placed in g_default_email_project_id with g_default_email_category
//- The best way how to specify project and category is copy "Category" from existing emails received from mantis 
//Of course this works only in case you have enabled
//	# OFF, EMAIL_CATEGORY_PROJECT_CATEGORY (format: [Project] Category)
//	$g_email_set_category		= ON;	
//- Or just set Category (In outlook go to Options->Categories) in format [Project] Category. 
//3) Add Custom fields
// - Add text in your email body in folowwing format:
//�<CustomFieldName: Value>�
//For example:
//Hello,
//This project is for �<Customer: IBM>� and needs to be finished before �<Due Date: 16/05/2009>�.
//Best regards,
//ONLY String and Date (in format DD/MM/YYYY) are supported
//4) Send the email

//NOTE!! This works only in following conditions:
//- user company emails are in format forename.surname@email_domain.com 
//- mantis users are in format ForenameSurename
//- you have a imap account
//- in imap account create following direcotries: ErrorMessages, Inbox, IssueCreatedAttachmentMissing, IssueOK, IssueWithWrongRequest
//If you use different format of email <-> user name then you will need edit get_userID_from_email


//Also, do not forget set all lines with EDIT_THIS_LINE
// AND RUN THIS php FILE PERIODICALLY every 10 minutes :)

$g_debug = 1;
$g_accept_only_from = 'add_email_domain.com'; //EDIT_THIS_LINE: your email domain - only emails from this domain will be accepted
$g_default_email_project_id = 1; //EDIT_THIS_LINE: all emials without specified project will be placed to this project
$g_default_email_category = 'EMAILED'; //EDIT_THIS_LINE: This is default category

//globals
$htmlmsg = $plainmsg = $charset = '';
$attachments = array();
$g_project_id; $g_category;
	

	require_once( 'core.php' );
	$t_core_path = config_get( 'core_path' );
	require_once( $t_core_path.'bug_api.php' );
	require_once( $t_core_path.'user_api.php' );
	require_once( $t_core_path. 'email_api.php' );
	require_once( $t_core_path. 'file_api.php' );	
	require_once( $t_core_path. 'custom_field_api.php' );	
	
	$g_t_bug_data = new BugData;


echo "EMAIL receiver <br />";

//imap account settings
$username = "your_imap_mantis_account"; //EDIT_THIS_LINE: imap account username (e.g mantis) - 
$password = "imap_password"; //EDIT_THIS_LINE: imap account password
$mailserver = "XXX.XXX.XXX.XXX:XXX"; //EDIT_THIS_LINE: set imap server e.g 122.345.567.890:123

$mbox = imap_open("{XXX.XXX.XXX.XXX:XXX}", $username, $password); //EDIT_THIS_LINE: set imap server e.g 122.345.567.890:123
echo "Mailboxes<br />\n";

$folders = imap_listmailbox($mbox, "{XXX.XXX.XXX.XXX:XXX}", "*");	//EDIT_THIS_LINE: set imap server e.g 122.345.567.890:123

if ($folders == false) {
    echo "Call failed<br />\n";
} else {
    foreach ($folders as $val) {
        echo $val . "<br />\n";
    }
}

//check if there are emails
echo "Headers in INBOX<br />\n";
$headers = imap_headers($mbox);
if ($headers == false) {
    echo "No emails found.<br />\n";
} else {
    foreach ($headers as $val) {
        echo $val . "<br />\n";
    }
}

echo '<br>----------------------------------------------<br>';
echo 'Processing emails in INBOX<br>';
echo '----------------------------------------------<br>';

//specify what eamils need to be checked - curerntly ALL
$m_search=imap_search ($mbox, 'ALL');

if ($m_search != null)
{
	foreach ($m_search as $message_number) { 
		
		//select header
		$header = imap_header($mbox, $message_number);
		
		//if email is ready to be deleted skip
		if ($header-> Deleted !='D') { //only new emails are inserted
			echo '<br>'.$message_number.' From: ';
			$from = $header->from;
			if ($from != null) {
				//go through field from:
				foreach ($from as $id => $object) { //there should be only  one person in field FROM:
					$fromname = $object->personal;
					echo $fromname.' ';
					$fromaddress = $object->mailbox . "@" . $object->host;
					echo '('.$fromaddress.'), ';
					
					//from field is used to set reporter
					$g_p_bug_data->reporter_id = get_userID_from_email($object->mailbox);
					if ($g_p_bug_data->reporter_id == 0)
					{
						echo '<br>Error: Unknow user - '.$g_p_bug_data->reporter_id.'<br>';
						break;
					}
					
					//set project and category based on header field called keywords
					if (get_project_id_and_category($mbox, $message_number,$g_p_bug_data->reporter_id) == false)
					{//will by copied to direcory with emails wrong requests
						if (!imap_mail_copy($mbox,$message_number,"IssueWithWrongRequest"))
							echo "<br>ERROR: Message '.$message_number.' can not be copied!<br>";										
					}
					$g_p_bug_data->project_id = $g_project_id;
					$g_p_bug_data->category = $g_category;	

					//subject
					//subject needs to be cleaned from hidden characters before is inserted to database
					$g_p_bug_data->summary = clean_text($header->subject);
					
					//this will separate body from attachments - outputs are in plainmsg and attachments
					getmsg($mbox,$message_number);	
					
					//body needs to be cleaned from hidden characters befor is inserted to database
					
					$g_p_bug_data->description = clean_text($plainmsg);
					
				}
			}
			//check if email has been sent from enabled domane and summary and desriptions are no empty then check other fields
			if (($object->host==$g_accept_only_from) AND ($g_p_bug_data->summary != null) AND ($g_p_bug_data->description != null))
			{
				echo ' Assigned to: ';
				$from = $header->to;
				if ($from != null) {
					foreach ($from as $id => $object) {
						//start checking field To:
						if ($object->mailbox != $username) //skip tracker address
						{		
							//this is username before @
							echo $object->mailbox.', ';

							//set assigned to: but first get user id from realname
							$assigned_to = get_userID_from_email($object->mailbox);							
							if ($assigned_to == false){ //check if user has been recognised
								echo '<br>ERROR: Unknown user for assigmned: '.$object->mailbox.'.<br>';
							}
							else{
								//username is valid - assigne the issue to the user
								$g_p_bug_data->handler_id = $assigned_to;	
								
								//place the new bug
								$bug_id = insert_new_bug_to_db($mbox, $message_number);	
								
								//set custom fields
								set_custom_fields_for_issue ($plainmsg,$bug_id);
								
								//check if there are people in CC: - these will monitor the isseu
								if (($bug_id != 0) AND ($header->cc != null))
								{//if bug has been created and there are people in bcc
									echo 'Users monitoring this issue: ';
									$add_monitor_list = $header->cc;
									
									foreach ($add_monitor_list as $id1 => $add_monitor) {
										//for everybody from CC get user ID
										$monitoring_person = get_userID_from_email($add_monitor->mailbox);
										//check if user exists
										if ($monitoring_person == false){
											echo '<br>ERROR: Unknown user added for monitoring: '.$add_monitor->mailbox.'.<br>';
										}
										else{		
											//user exists - add him to monitor issue
											echo $add_monitor->mailbox.', ';
											add_person_monitor_issue ($bug_id,$monitoring_person); //add people from bcc to monitor the issue										
										}
									}	
								}
							}
						}
					}
				}
			}
			else
			{
				//email sent from not allowed domain, no subject or no body
				echo '<br>ERROR: Email with error moved to ErrorMessages folder.<br>';
				if (!imap_mail_move($mbox,$message_number,"ErrorMessages"))
					echo "<br>ERROR: Message '.$message_number.' can not be moved!<br>";								
			}
		}		
	}
}
else
	echo "No emails to process.";
	
imap_expunge($mbox);//delete all messages marked for deletion
imap_close($mbox); 
echo "<br />END";

/**********************************************************************************************************************/
/*****************************************FUNCTIONS*****************************************************************/
/**********************************************************************************************************************/
function set_custom_fields_for_issue($string,$bug_id)
{
    $g_custom_fields_array = array();

	//echo ' '.$string.' ';
	echo "<br>Looking for custom fields ... ";
	//find category - they are in header after: Keywords |<[^>]+>(.*)</[^>]+>|U
	$pattern = "|\"[^<]?<(.*)>[^\"]?\"|U";
	preg_match_all($pattern, $string, $custom_fields,PREG_PATTERN_ORDER);
	foreach ($custom_fields[1] as $custom_field)
	{
		//check if the cusotm field is valid
		$custom_field_name = explode(":",$custom_field);
		echo ' <br> checking: '.$custom_field_name[0].'... ';
		$custom_field_id = custom_field_get_id_from_name($custom_field_name[0]);
		if ($custom_field_id)
		{
			echo 'valid. (ID = '.$custom_field_id.')';
			$g_custom_fields_array[$custom_field_id] = trim ($custom_field_name[1]);//copy to array but remove before space from beginning and end
		}	
		else
			echo 'invalid!';
	}
	echo "<br>Adding custom fields: ";
	foreach ($g_custom_fields_array as $field_id => $field_data)		
	{
		echo $field_id.'='.$field_data;
		switch (tmp_custom_field_type($field_id))
		{	
			case 8: //date
					$field_data = string_to_date($field_data);
			case 0: //text
					if (tmp_custom_field_set_value( $field_id, $bug_id, $field_data )==true)
						echo ' (Added OK); ';
					else
						echo ' (Error); ';
					break;	
			default: //unsuported field type
				echo " (Unsupported field type); ";
		}

	}
	echo "<br><br>";
}

//this converts any format of dd/mm/yyyy to timestamp
function string_to_date($string)
{
	if (preg_match('/^\s*(\d\d?)[^\w](\d\d?)[^\w](\d{1,4}\s*$)/', $string, $match)) {
	  $string = $match[2] . '/' . $match[1] . '/' . $match[3];
	}
	return strtotime($string);
}

//this will return user id from email format name: Forename.Surname in case users in Manits are users in format ForenameSurname
function get_userID_from_email($mail_address)
{
	//remove . from email an make username ... Forename.Surname -> ForenameSurname
	$tmp = explode(".",$mail_address);
	$reporter = $tmp[0].$tmp[1];
	//return user ID
	return user_get_id_by_name($reporter);
}

//this will find in email header fields under Keywords (Categories) and decode standard Mantis Category format: Keywords:[Project] Category
function get_project_id_and_category($mbox, $message_number,$user_id)
{
global  $g_project_id, $g_category;
global $g_default_email_project_id;
global $g_default_email_category;
		
		$g_project_id =0; $g_category ='';

		$fetchheader = imap_fetchheader  ( $mbox, $message_number);

		//find category - they are in header after: Keywords
		$pattern = "/Keywords:?.*(Message-ID:)?/";				
		preg_match($pattern,$fetchheader, $keywords);

		//get project name from Field Keywords:
		$pattern = "/(?P<foo>\[)(.*)(?P<bar>\])/";						
		preg_match($pattern,$keywords[0], $projects);
		//get project ID from name
		$g_project_id = project_get_id_by_name($projects[2]);

		//check permission
		$t_user_access_level = user_get_access_level( $user_id, $g_project_id );			
		
		//get category name from Field Keywords:
		$pattern = "/(?P<foo>\].)(.*)(?P<bar>.)/";						
		preg_match($pattern,$keywords[0], $categories);
		$g_category = $categories[2];
		
		echo '<br>Project: '.$projects[2].' / ID: '.$g_project_id.' / Permision: '.$t_user_access_level.' / Category: '.$g_category.'<br>';		

		if ((($t_user_access_level < REPORTER) OR ($g_category == null) OR ($g_project_id==0)) AND ($keywords[0]!= null))
		{//error if keywords found in header but don't mach any project, category or if user doesn't have permision for the project
			echo "Permission or category error - project and category set to default<br>";
			//use default project and category
			$g_project_id = $g_default_email_project_id;
			$g_category = $g_default_email_category;
			return false;
		}		
		if ($keywords[0] == null)
		{//if project and category are not in email header then use default project and category
			$g_project_id = $g_default_email_project_id;
			$g_category = $g_default_email_category;		
		}
		
		return true;
}

//this will insert new bug and attachments
function insert_new_bug_to_db($mbox, $message_number)
{
    global $g_debug,$g_p_bug_data;
    global $htmlmsg,$plainmsg,$charset,$attachments;  
  
	echo '<br>Creating new issue ...';
	# Create the bug
//	$g_p_bug_data->summary = 'TEST FROM EMAIL RECEIVER';
//	$g_p_bug_data->description = 'This was created by email_receiver';
//	$g_p_bug_data->project_id = 51; //51 = Test
//	$g_p_bug_data->reporter_id = 8 ; //8 - user
//	$g_p_bug_data->handler_id = 8; //8 - user
	$g_p_bug_data->priority = 30; //30=normal
	$g_p_bug_data->severity = 50; //50=minor
	$g_p_bug_data->reproducibility = 100; //N/A
//	$g_p_bug_data->category = 'EMAILED';
	$g_p_bug_data->os = '';
	$g_p_bug_data->os_build = '';
	$g_p_bug_data->platform = '';
	$g_p_bug_data->version = '';
	$g_p_bug_data->build = '';
	$g_p_bug_data->profile_id = 0;
	$g_p_bug_data->view_state = 10;
	$g_p_bug_data->steps_to_reproduce = '';
	$g_p_bug_data->additional_information = '';
	
	if ($g_debug==1)
	{
		echo '<br>$g_p_bug_data->summary = '.$g_p_bug_data->summary;
		echo '<br>$g_p_bug_data->description = '.$g_p_bug_data->description;
		echo '<br>$g_p_bug_data->project_id = '.$g_p_bug_data->project_id;
		echo '<br>$g_p_bug_data->reporter_id = '.$g_p_bug_data->reporter_id;
		echo '<br>$g_p_bug_data->handler_id = '.$g_p_bug_data->handler_id;
		echo '<br>$g_p_bug_data->priority = '.$g_p_bug_data->priority;
		echo '<br>$g_p_bug_data->severity = '.$g_p_bug_data->severity;
		echo '<br>$g_p_bug_data->reproducibility = '.$g_p_bug_data->reproducibility;
		echo '<br>$g_p_bug_data->category = '.$g_p_bug_data->category;
		echo '<br>$g_p_bug_data->os = '.$g_p_bug_data->os;
		echo '<br>$g_p_bug_data->os_build = '.$g_p_bug_data->os_build;
		echo '<br>$g_p_bug_data->platform = '.$g_p_bug_data->platform;
		echo '<br>$g_p_bug_data->version = '.$g_p_bug_data->version;
		echo '<br>$g_p_bug_data->build = '.$g_p_bug_data->build;
		echo '<br>$g_p_bug_data->profile_id = '.$g_p_bug_data->profile_id;
		echo '<br>$g_p_bug_data->view_state = '.$g_p_bug_data->view_state;
		echo '<br>$g_p_bug_data->steps_to_reproduce = '.$g_p_bug_data->steps_to_reproduce;
		echo '<br>$g_p_bug_data->additional_information = '.$g_p_bug_data->additional_information;
	}

	//when debugged rename tmp_bug_create to bug_create
	$t_bug_id = tmp_bug_create( $g_p_bug_data );	//this is standard mantis function but i had to remove logging because of problems when file runs frpm php command line
	echo '<br>New issue submitted: ',$t_bug_id.'<br>';									
		
	# Handle attachments
	if ($attachments!=null){
		$add_attachment_error =0;
		echo '<br>Attachemet(s): ';
		foreach ($attachments as $filename => $data) {
			echo $filename.', ';
			//add all attachments
			if (!add_attachement( $t_bug_id, $filename, $data, tmp_mime_content_type($filename), 'bug' ))
				$add_attachment_error++; //if return false then error adding attachments
		}
		
		if (!$add_attachment_error)
		{//ATTACHMENTS added ok - move email to OK directory
			if (!imap_mail_move($mbox,$message_number,"IssueOK"))
				echo "<br>ERROR: Message '.$message_number.' can not be moved!<br>";				
		}		
		else
		{//ATTACHMENTS need to be added again - move email to error directory
			if (!imap_mail_move($mbox,$message_number,"IssueCreatedAttachmentMissing"))
				echo "<br>ERROR: Message '.$message_number.' can not be moved!<br>";				
		}
		
	}
	else
	{//if tehre are no attachments just move to IssueOK directory
		if (!imap_mail_move($mbox,$message_number,"IssueOK"))
			echo "<br>ERROR: Message '.$message_number.' can not be moved!<br>";		
	}
	//send notification
	//email_new_bug( $t_bug_id ); //this is doing problem when runs wrom php command line
	
	//echo "<br>OK<br>";
	
	return $t_bug_id;
}	

//used together with getpart to extract body and attachments from email
function getmsg($mbox,$mid) {
    // input $mbox = IMAP stream, $mid = message id
    // output all the following:
    global $htmlmsg,$plainmsg,$charset,$attachments;
    // the message may in $htmlmsg, $plainmsg, or both
    $htmlmsg = $plainmsg = $charset = '';
    $attachments = array();

    // HEADER
    $h = imap_header($mbox,$mid);
    // add code here to get date, from, to, cc, subject...

    // BODY
    $s = imap_fetchstructure($mbox,$mid);
    if (!$s->parts)  // not multipart
        getpart($mbox,$mid,$s,0);  // no part-number, so pass 0
    else {  // multipart: iterate through each part
        foreach ($s->parts as $partno0=>$p)
            getpart($mbox,$mid,$p,$partno0+1);
    }
}
//used together with getmsg to extract body and attachments from email
function getpart($mbox,$mid,$p,$partno) {
    // $partno = '1', '2', '2.1', '2.1.3', etc if multipart, 0 if not multipart
    global $htmlmsg,$plainmsg,$charset,$attachments;

    // DECODE DATA
    $data = ($partno)?
        imap_fetchbody($mbox,$mid,$partno):  // multipart
        imap_body($mbox,$mid);  // not multipart
    // Any part may be encoded, even plain text messages, so check everything.
    if ($p->encoding==4)
        $data = quoted_printable_decode($data);
    elseif ($p->encoding==3)
        $data = base64_decode($data);
    // no need to decode 7-bit, 8-bit, or binary

    // PARAMETERS
    // get all parameters, like charset, filenames of attachments, etc.
    $params = array();
    if ($p->parameters)
        foreach ($p->parameters as $x)
            $params[ strtolower( $x->attribute ) ] = $x->value;
    if ($p->dparameters)
        foreach ($p->dparameters as $x)
            $params[ strtolower( $x->attribute ) ] = $x->value;

    // ATTACHMENT
    // Any part with a filename is an attachment,
    // so an attached text file (type 0) is not mistaken as the message.
    if ($params['filename'] || $params['name']) {
        // filename may be given as 'Filename' or 'Name' or both
        $filename = ($params['filename'])? $params['filename'] : $params['name'];
        // filename may be encoded, so see imap_mime_header_decode()
        $attachments[$filename] = $data;  // this is a problem if two files have same name
    }

    // TEXT
    elseif ($p->type==0 && $data) {
        // Messages may be split in different parts because of inline attachments,
        // so append parts together with blank row.
        if (strtolower($p->subtype)=='plain')
            $plainmsg .= trim($data) ."\n\n";
        else
            $htmlmsg .= $data ."<br><br>";
        $charset = $params['charset'];  // assume all parts are same charset
    }

    // EMBEDDED MESSAGE
    // Many bounce notifications embed the original message as type 2,
    // but AOL uses type 1 (multipart), which is not handled here.
    // There are no PHP functions to parse embedded messages,
    // so this just appends the raw source to the main message.
    elseif ($p->type==2 && $data) {
        $plainmsg .= trim($data) ."\n\n";
    }

    // SUBPART RECURSION
    if ($p->parts) {
        foreach ($p->parts as $partno0=>$p2)
            getpart($mbox,$mid,$p2,$partno.'.'.($partno0+1));  // 1.2, 1.2.1, etc.
    }
}

//copied form matis and cleaned from errors - this will add attachment to issue
function add_attachement( $p_id, $p_name, $p_content, $p_file_type, $p_table, $p_title = '', $p_desc = '' ) {
	if ( !file_type_check( $p_name ) ) {
		echo 'file_type_error';
		return false;
	}
	if ( !file_is_name_unique( $p_name, $p_id ) ) {
		echo 'file_is_name_error';
		return false;
	}

	$t_file_size = strlen( $p_content );
	$t_max_file_size = (int)min( ini_get_number( 'upload_max_filesize' ), ini_get_number( 'post_max_size' ), config_get( 'max_file_size' ) );
	if ( $t_file_size > $t_max_file_size ) {
		echo 'file_is_too_big_error';
		return false;
	}	

	if ( 'bug' == $p_table ) {
		$t_project_id	= bug_get_field( $p_id, 'project_id' );
		$t_issue_id		= bug_format_id( $p_id );
	} else {
		$t_project_id	= $p_id;
		$t_issue_id		= 0;
	}

	# prepare variables for insertion
	$c_issue_id		= db_prepare_int( $t_issue_id );
	$c_project_id		= db_prepare_int( $t_project_id );
	$c_file_type	= db_prepare_string( $p_file_type );
	$c_title = db_prepare_string( $p_title );
	$c_desc = db_prepare_string( $p_desc );

	if( $t_project_id == ALL_PROJECTS ) {
		$t_file_path = config_get( 'absolute_path_default_upload_folder' );
	}
	else {
		$t_file_path = project_get_field( $t_project_id, 'file_path' );
		if( $t_file_path == '' ) {
			$t_file_path = config_get( 'absolute_path_default_upload_folder' );
		}
	}

	$c_file_path = db_prepare_string( $t_file_path );
	$c_new_file_name = db_prepare_string( $p_name );

	$t_file_hash = $t_issue_id;
	$t_disk_file_name = $t_file_path . file_generate_unique_name( $t_file_hash . '-' . $p_name, $t_file_path );
	$c_disk_file_name = db_prepare_string( $t_disk_file_name );

	$t_file_size = strlen( $p_content );
	$c_file_size = db_prepare_int( $t_file_size );

	$t_method = config_get( 'file_upload_method' );

	switch ( $t_method ) {
		case FTP:
		case DISK:
			if ( !file_exists( $t_file_path ) || !is_dir( $t_file_path ) || !is_writable( $t_file_path ) || !is_readable( $t_file_path ) ) {
				echo 'upload_folder_does_not_exist_error';
				return false;
			}

			file_ensure_valid_upload_path( $t_file_path );

			if ( !file_exists( $t_disk_file_name ) ) {
				tmp_file_write_local( $t_disk_file_name, $p_content );
				if ( FTP == $t_method ) {
					$conn_id = file_ftp_connect();
					file_ftp_put ( $conn_id, $t_disk_file_name, $t_disk_file_name );
					file_ftp_disconnect ( $conn_id );
					file_delete_local( $p_disk_file_name );
				}

				chmod( $t_disk_file_name, config_get( 'attachments_file_permissions' ) );

				$c_content = '';
			}
			break;
		case DATABASE:
			$c_content = db_prepare_string( $p_content );
			break;
	}

	$t_file_table	= config_get( 'mantis_' . $p_table . '_file_table' );
	$c_id = ( 'bug' == $p_table ) ? $c_issue_id : $c_project_id;
	$query = "INSERT INTO $t_file_table
					(" . $p_table . "_id, title, description, diskfile, filename, folder, filesize, file_type, date_added, content)
				  VALUES
					($c_id, '$c_title', '$c_desc', '$c_disk_file_name', '$c_new_file_name', '$c_file_path', $c_file_size, '$c_file_type', " . db_now() .", '$c_content')";
	db_query( $query );

	# get attachment id
	$t_attachment_id = db_insert_id( $t_file_table );
	
	if ( 'bug' == $p_table ) {
		# updated the last_updated date
		$result = bug_update_date( $c_issue_id );
		# log new bug
//		history_log_event_special( $c_issue_id, FILE_ADDED, $c_new_file_name );
	}

	return $t_attachment_id;
}

# Write a local file - used with add attachments.		
function tmp_file_write_local( $p_diskfile, $p_content ) {
	$t_handle = fopen( $p_diskfile, "w" );
	fwrite( $t_handle, $p_content );
	fclose( $t_handle );
}	

//used when attachment is added - file format needs to be identified	
function tmp_mime_content_type($filename) {

	$mime_types = array(

		'txt' => 'text/plain',
		'htm' => 'text/html',
		'html' => 'text/html',
		'php' => 'text/html',
		'css' => 'text/css',
		'js' => 'application/javascript',
		'json' => 'application/json',
		'xml' => 'application/xml',
		'swf' => 'application/x-shockwave-flash',
		'flv' => 'video/x-flv',

		// images
		'png' => 'image/png',
		'jpe' => 'image/jpeg',
		'jpeg' => 'image/jpeg',
		'jpg' => 'image/jpeg',
		'gif' => 'image/gif',
		'bmp' => 'image/bmp',
		'ico' => 'image/vnd.microsoft.icon',
		'tiff' => 'image/tiff',
		'tif' => 'image/tiff',
		'svg' => 'image/svg+xml',
		'svgz' => 'image/svg+xml',

		// archives
		'zip' => 'application/zip',
		'rar' => 'application/x-rar-compressed',
		'exe' => 'application/x-msdownload',
		'msi' => 'application/x-msdownload',
		'cab' => 'application/vnd.ms-cab-compressed',

		// audio/video
		'mp3' => 'audio/mpeg',
		'qt' => 'video/quicktime',
		'mov' => 'video/quicktime',

		// adobe
		'pdf' => 'application/pdf',
		'psd' => 'image/vnd.adobe.photoshop',
		'ai' => 'application/postscript',
		'eps' => 'application/postscript',
		'ps' => 'application/postscript',

		// ms office
		'doc' => 'application/msword',
		'rtf' => 'application/rtf',
		'xls' => 'application/vnd.ms-excel',
		'ppt' => 'application/vnd.ms-powerpoint',

		// open office
		'odt' => 'application/vnd.oasis.opendocument.text',
		'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
	);

	$ext = strtolower(array_pop(explode('.',$filename)));
	if (array_key_exists($ext, $mime_types)) {
		return $mime_types[$ext];
	}
	elseif (function_exists('finfo_open')) {
		$finfo = finfo_open(FILEINFO_MIME);
		$mimetype = finfo_file($finfo, $filename);
		finfo_close($finfo);
		return $mimetype;
	}
	else {
		return 'application/octet-stream';
	}
}

//this will clean body and subject from hidden characters - otherwise text is not possible upload to database
function clean_text($str)
{       
		$force_php = false;
        // UTF-8 validity is checked since PHP 4.3.5
        // This is an optimization: if the string is already valid UTF-8, no
        // need to do PHP stuff. 99% of the time, this will be the case.
        // The regexp matches the XML char production, as well as well as excluding
        // non-SGML codepoints U+007F to U+009F
        if (preg_match('/^[\x{9}\x{A}\x{D}\x{20}-\x{7E}\x{A0}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]*$/Du', $str)) {
            return $str;
        }
        
        $mState = 0; // cached expected number of octets after the current octet
                     // until the beginning of the next UTF8 character sequence
        $mUcs4  = 0; // cached Unicode character
        $mBytes = 1; // cached expected number of octets in the current sequence
        
        // original code involved an $out that was an array of Unicode
        // codepoints.  Instead of having to convert back into UTF-8, we've
        // decided to directly append valid UTF-8 characters onto a string
        // $out once they're done.  $char accumulates raw bytes, while $mUcs4
        // turns into the Unicode code point, so there's some redundancy.
        
        $out = '';
        $char = '';
        
        $len = strlen($str);
        for($i = 0; $i < $len; $i++) {
            $in = ord($str{$i});
            $char .= $str[$i]; // append byte to char
            if (0 == $mState) {
                // When mState is zero we expect either a US-ASCII character 
                // or a multi-octet sequence.
                if (0 == (0x80 & ($in))) {
                    // US-ASCII, pass straight through.
                    if (($in <= 31 || $in == 127) && 
                        !($in == 9 || $in == 13 || $in == 10) // save \r\t\n
                    ) {
                        // control characters, remove
                    } else {
                        $out .= $char;
                    }
                    // reset
                    $char = '';
                    $mBytes = 1;
                } elseif (0xC0 == (0xE0 & ($in))) {
                    // First octet of 2 octet sequence
                    $mUcs4 = ($in);
                    $mUcs4 = ($mUcs4 & 0x1F) << 6;
                    $mState = 1;
                    $mBytes = 2;
                } elseif (0xE0 == (0xF0 & ($in))) {
                    // First octet of 3 octet sequence
                    $mUcs4 = ($in);
                    $mUcs4 = ($mUcs4 & 0x0F) << 12;
                    $mState = 2;
                    $mBytes = 3;
                } elseif (0xF0 == (0xF8 & ($in))) {
                    // First octet of 4 octet sequence
                    $mUcs4 = ($in);
                    $mUcs4 = ($mUcs4 & 0x07) << 18;
                    $mState = 3;
                    $mBytes = 4;
                } elseif (0xF8 == (0xFC & ($in))) {
                    // First octet of 5 octet sequence.
                    // 
                    // This is illegal because the encoded codepoint must be 
                    // either:
                    // (a) not the shortest form or
                    // (b) outside the Unicode range of 0-0x10FFFF.
                    // Rather than trying to resynchronize, we will carry on 
                    // until the end of the sequence and let the later error
                    // handling code catch it.
                    $mUcs4 = ($in);
                    $mUcs4 = ($mUcs4 & 0x03) << 24;
                    $mState = 4;
                    $mBytes = 5;
                } elseif (0xFC == (0xFE & ($in))) {
                    // First octet of 6 octet sequence, see comments for 5
                    // octet sequence.
                    $mUcs4 = ($in);
                    $mUcs4 = ($mUcs4 & 1) << 30;
                    $mState = 5;
                    $mBytes = 6;
                } else {
                    // Current octet is neither in the US-ASCII range nor a 
                    // legal first octet of a multi-octet sequence.
                    $mState = 0;
                    $mUcs4  = 0;
                    $mBytes = 1;
                    $char = '';
                }
            } else {
                // When mState is non-zero, we expect a continuation of the
                // multi-octet sequence
                if (0x80 == (0xC0 & ($in))) {
                    // Legal continuation.
                    $shift = ($mState - 1) * 6;
                    $tmp = $in;
                    $tmp = ($tmp & 0x0000003F) << $shift;
                    $mUcs4 |= $tmp;
                    
                    if (0 == --$mState) {
                        // End of the multi-octet sequence. mUcs4 now contains
                        // the final Unicode codepoint to be output
                        
                        // Check for illegal sequences and codepoints.
                        
                        // From Unicode 3.1, non-shortest form is illegal
                        if (((2 == $mBytes) && ($mUcs4 < 0x0080)) ||
                            ((3 == $mBytes) && ($mUcs4 < 0x0800)) ||
                            ((4 == $mBytes) && ($mUcs4 < 0x10000)) ||
                            (4 < $mBytes) ||
                            // From Unicode 3.2, surrogate characters = illegal
                            (($mUcs4 & 0xFFFFF800) == 0xD800) ||
                            // Codepoints outside the Unicode range are illegal
                            ($mUcs4 > 0x10FFFF)
                        ) {
                            
                        } elseif (0xFEFF != $mUcs4 && // omit BOM
                            // check for valid Char unicode codepoints
                            (
                                0x9 == $mUcs4 ||
                                0xA == $mUcs4 ||
                                0xD == $mUcs4 ||
                                (0x20 <= $mUcs4 && 0x7E >= $mUcs4) ||
                                // 7F-9F is not strictly prohibited by XML,
                                // but it is non-SGML, and thus we don't allow it
                                (0xA0 <= $mUcs4 && 0xD7FF >= $mUcs4) ||
                                (0x10000 <= $mUcs4 && 0x10FFFF >= $mUcs4)
                            )
                        ) {
                            $out .= $char;
                        }
                        // initialize UTF8 cache (reset)
                        $mState = 0;
                        $mUcs4  = 0;
                        $mBytes = 1;
                        $char = '';
                    }
                } else {
                    // ((0xC0 & (*in) != 0x80) && (mState != 0))
                    // Incomplete multi-octet sequence.
                    // used to result in complete fail, but we'll reset
                    $mState = 0;
                    $mUcs4  = 0;
                    $mBytes = 1;
                    $char ='';
                }
            }
        }
        return $out;

}  

//copied from Mantis - will add person to monitor issue - currently  cleaned from some stuff doing error when runs from php command line
function add_person_monitor_issue ($f_bug_id,$user_id)
{
	# Automically add recipients to monitor list if they are above the monitor
	# threshold, option is enabled, and not reporter or handler.
	if ( ON == config_get( 'reminder_recipents_monitor_bug' ) ){
//		access_has_bug_level( config_get( 'monitor_bug_threshold' ), $f_bug_id ) &&
//		!bug_is_user_handler( $f_bug_id, $user_id ) &&
//		!bug_is_user_reporter( $f_bug_id, $user_id ) ) {
		bug_monitor( $f_bug_id, $user_id );
	}	
//	$result = email_bug_reminder( $user_id, $f_bug_id, "You were added to monitor this issue." );
/*
	# Add reminder as bugnote if store reminders option is ON.
	if ( ON == config_get( 'store_reminders' ) ) {
		if ( count( $f_to ) > 50 ) {		# too many recipients to log, truncate the list
			$t_to = array();
			for ( $i=0; $i<50; $i++ ) {
				$t_to[] = $f_to[$i];
			}
			$f_to = $t_to;
		}
		$t_attr = '|' . implode( '|', $f_to ) . '|';
		bugnote_add( $f_bug_id, $f_body, 0, config_get( 'default_reminder_view_status' ) == VS_PRIVATE, REMINDER, $t_attr, NULL, FALSE );
	}
*/	
}

//copied form Mantis and cleaned from logging - this was doing problem when runs from php commandline
function tmp_bug_create( $p_bug_data ) {
	$c_summary				= db_prepare_string( $p_bug_data->summary );
	$c_description			= db_prepare_string( $p_bug_data->description );
	$c_project_id			= db_prepare_int( $p_bug_data->project_id );
	$c_reporter_id			= db_prepare_int( $p_bug_data->reporter_id );
	$c_handler_id			= db_prepare_int( $p_bug_data->handler_id );
	$c_priority				= db_prepare_int( $p_bug_data->priority );
	$c_severity				= db_prepare_int( $p_bug_data->severity );
	$c_reproducibility		= db_prepare_int( $p_bug_data->reproducibility );
	$c_category				= db_prepare_string( $p_bug_data->category );
	$c_os					= db_prepare_string( $p_bug_data->os );
	$c_os_build				= db_prepare_string( $p_bug_data->os_build );
	$c_platform				= db_prepare_string( $p_bug_data->platform );
	$c_version				= db_prepare_string( $p_bug_data->version );
	$c_build				= db_prepare_string( $p_bug_data->build );
	$c_profile_id			= db_prepare_int( $p_bug_data->profile_id );
	$c_view_state			= db_prepare_int( $p_bug_data->view_state );
	$c_steps_to_reproduce	= db_prepare_string( $p_bug_data->steps_to_reproduce );
	$c_additional_info		= db_prepare_string( $p_bug_data->additional_information );
	$c_sponsorship_total 	= 0;
	$c_sticky 				= 0;

	# Summary cannot be blank
	if ( is_blank( $c_summary ) ) {
		error_parameters( lang_get( 'summary' ) );
		trigger_error( ERROR_EMPTY_FIELD, ERROR );
	}
	# Description cannot be blank
	if ( is_blank( $c_description ) ) {
		error_parameters( lang_get( 'description' ) );
		trigger_error( ERROR_EMPTY_FIELD, ERROR );
	}
	# If category is not specified and not defaulted + project has categories defined, then error.
	if ( is_blank( $c_category ) && ( category_get_count( $c_project_id ) > 0 ) ) {
		error_parameters( lang_get( 'category' ) );
		trigger_error( ERROR_EMPTY_FIELD, ERROR );
	}
	# Only set target_version if user has access to do so
//		if ( access_has_project_level( config_get( 'roadmap_update_threshold' ) ) ) {
		$c_target_version	= db_prepare_string( $p_bug_data->target_version );
//		} else { 
//			$c_target_version	= '';
//		}
//		echo '>tmp_bug_create06 ... ';
	$t_bug_table				= config_get( 'mantis_bug_table' );
	$t_bug_text_table			= config_get( 'mantis_bug_text_table' );
	$t_project_category_table	= config_get( 'mantis_project_category_table' );

	# Insert text information
	$query = "INSERT INTO $t_bug_text_table
				( description, steps_to_reproduce, additional_information )
			  VALUES
				( '$c_description', '$c_steps_to_reproduce',
				  '$c_additional_info' )";
	db_query( $query );
	# Get the id of the text information we just inserted
	# NOTE: this is guarranteed to be the correct one.
	# The value LAST_INSERT_ID is stored on a per connection basis.

	$t_text_id = db_insert_id($t_bug_text_table);

	# check to see if we want to assign this right off
	$t_status = config_get( 'bug_submit_status' );

	# if not assigned, check if it should auto-assigned.
	if ( 0 == $c_handler_id ) {
		# if a default user is associated with the category and we know at this point
		# that that the bug was not assigned to somebody, then assign it automatically.
		$query = "SELECT user_id
				  FROM $t_project_category_table
				  WHERE project_id='$c_project_id' AND category='$c_category'";
		$result = db_query( $query );

		if ( db_num_rows( $result ) > 0 ) {
			$c_handler_id = $p_handler_id = db_result( $result );
		}
	}

	# Check if bug was pre-assigned or auto-assigned.
	if ( ( $c_handler_id != 0 ) && ( ON == config_get( 'auto_set_status_to_assigned' ) ) ) {
		$t_status = config_get( 'bug_assigned_status' );
	}

	# Insert the rest of the data
	$t_resolution = OPEN;

	$query = "INSERT INTO $t_bug_table
				( project_id,
				  reporter_id, handler_id,
				  duplicate_id, priority,
				  severity, reproducibility,
				  status, resolution,
				  projection, category,
				  date_submitted, last_updated,
				  eta, bug_text_id,
				  os, os_build,
				  platform, version,
				  build,
				  profile_id, summary, view_state, sponsorship_total, sticky, fixed_in_version,
				  target_version 
				)
			  VALUES
				( '$c_project_id',
				  '$c_reporter_id', '$c_handler_id',
				  '0', '$c_priority',
				  '$c_severity', '$c_reproducibility',
				  '$t_status', '$t_resolution',
				  10, '$c_category',
				  " . db_now() . "," . db_now() . ",
				  10, '$t_text_id',
				  '$c_os', '$c_os_build',
				  '$c_platform', '$c_version',
				  '$c_build',
				  '$c_profile_id', '$c_summary', '$c_view_state', '$c_sponsorship_total', '$c_sticky', '',
				  '$c_target_version'
				)";
	db_query( $query );
	$t_bug_id = db_insert_id($t_bug_table);
	return $t_bug_id;
}

function tmp_custom_field_set_value( $p_field_id, $p_bug_id, $p_value ) {

	echo '> Debug 04 ';	
	$c_field_id	= db_prepare_int( $p_field_id );
	$c_bug_id	= db_prepare_int( $p_bug_id );
	echo '> Debug 05 ';
	custom_field_ensure_exists( $p_field_id );
	echo '> Debug 06 ';
	$t_custom_field_table = config_get( 'mantis_custom_field_table' );
	$query = "SELECT name, type, possible_values, valid_regexp,
			  access_level_rw, length_min, length_max, default_value
			  FROM $t_custom_field_table
			  WHERE id='$c_field_id'";
	$result = db_query( $query );
	echo '> Debug 07 ';		
	$row = db_fetch_array( $result );

	$t_name				= $row['name'];
	$t_type				= $row['type'];
	$t_possible_values	= $row['possible_values'];
	$t_valid_regexp		= $row['valid_regexp'];
	$t_access_level_rw	= $row['access_level_rw'];
	$t_length_min		= $row['length_min'];
	$t_length_max		= $row['length_max'];
	$t_default_value	= $row['default_value'];
	echo '> Debug 08 ';
	$c_value	= db_prepare_string( custom_field_value_to_database( $p_value, $t_type ) );
	echo '> Debug 09 ';
	# check for valid value
	if ( !is_blank( $t_valid_regexp ) ) {
		if ( !ereg( $t_valid_regexp, $p_value ) ) {
			return false;
		}
	}
	echo '> Debug 10 ';		

	if ( strlen( $p_value ) < $t_length_min ) {
		return false;
	}
	echo '> Debug 11 ';
	
	if ( ( 0 != $t_length_max ) && ( strlen( $p_value ) > $t_length_max ) ) {
		return false;
	}
	echo '> Debug 12 ';
	
//this checking is making problem - but it is not necessary to check it
//	if( !custom_field_has_write_access( $p_field_id, $p_bug_id, auth_get_current_user_id() ) ) {
//		return false;
//	}
	echo '> Debug 13 ';
	
	$t_custom_field_string_table = config_get( 'mantis_custom_field_string_table' );

	# do I need to update or insert this value?
	$query = "SELECT value
			  FROM $t_custom_field_string_table
			  WHERE field_id='$c_field_id' AND
					bug_id='$c_bug_id'";
	$result = db_query( $query );
	echo '> Debug 14 ';
	
	if ( db_num_rows( $result ) > 0 ) {
		$query = "UPDATE $t_custom_field_string_table
				  SET value='$c_value'
				  WHERE field_id='$c_field_id' AND
						bug_id='$c_bug_id'";
		db_query( $query );

		$row = db_fetch_array( $result );
//			history_log_event_direct( $c_bug_id, $t_name, custom_field_database_to_value( $row['value'], $t_type ), $p_value );
	} else {
		# Always store the value, even if it's the dafault value
		# This is important, as the definitions might change but the
		#  values stored with a bug must not change
		$query = "INSERT INTO $t_custom_field_string_table
					( field_id, bug_id, value )
				  VALUES
					( '$c_field_id', '$c_bug_id', '$c_value' )";
		db_query( $query );
//			history_log_event_direct( $c_bug_id, $t_name, '', $p_value );
	}
	echo '> Debug 15 ';
	custom_field_clear_cache( $p_field_id );
	echo '> Debug 16 ';
	#db_query() errors on failure so:
	return true;
}
	
function tmp_custom_field_type( $p_field_id ) {
	echo '> Debug 17 ';
	$t_field = tmp_custom_field_cache_row( $p_field_id, false ) ;
	echo '> Debug 18 ';	
	if ( $t_field == false ) {
		return -1 ;
	} else {
		return $t_field[ 'type' ] ;
	}
}
	
	function tmp_custom_field_cache_row( $p_field_id, $p_trigger_errors=true ) {
		global $g_cache_custom_field;
		
		echo '> Debug 19 ';
		$c_field_id = db_prepare_int( $p_field_id );
		echo '> Debug 20 ';
		$t_custom_field_table = config_get( 'mantis_custom_field_table' );
		echo '> Debug 21 ';
		if ( isset ( $g_cache_custom_field[$c_field_id] ) ) {
			return $g_cache_custom_field[$c_field_id];
		}
		echo '> Debug 22 ';
		$query = "SELECT *
				  FROM $t_custom_field_table
				  WHERE id='$c_field_id'";
		$result = db_query( $query );
		echo '> Debug 23 ';
		if ( 0 == db_num_rows( $result ) ) {
			if ( $p_trigger_errors ) {
//				error_parameters( 'Custom ' . $p_field_id );
//				trigger_error( ERROR_CUSTOM_FIELD_NOT_FOUND, ERROR );
			} else {
				return false;
			}
		}

		$row = db_fetch_array( $result );
		echo '> Debug 24 ';
		$g_cache_custom_field[$c_field_id] = $row;
		echo '> Debug 25 ';
		return $row;
	}	
	
?>

Relationships

duplicate of 0004286 closedSL-Gundam Plugin - EmailReporting Solution for reporting via E-Mail 

Activities

siebrand

siebrand

2009-06-02 04:32

developer   ~0022029

This is a duplicate of issue 0004286.