Skip to content
Snippets Groups Projects
Commit d340ee15 authored by Jared Hancock's avatar Jared Hancock
Browse files

Correct implementation and description of API

Allow for type and encoding specification of the message body and better
describe the integration with custom form fields.
parent e40d478b
Branches
Tags
No related merge requests found
......@@ -323,6 +323,17 @@ class ApiXmlDataParser extends XmlDataParser {
$value = (bool)$value;
} else if ($key == "autorespond") {
$value = (bool)$value;
} else if ($key == "message") {
if (!is_array($value)) {
$value = array(
"body" => $value,
"type" => "text/plain",
# TODO: Get encoding from root <xml> node
);
} else {
$value["body"] = $value[":text"];
unset($value[":text"]);
}
} else if ($key == "attachments") {
if(!isset($value['file'][':text']))
$value = $value['file'];
......@@ -363,34 +374,24 @@ class ApiJsonDataParser extends JsonDataParser {
$value = (bool)$value;
} else if ($key == "autorespond") {
$value = (bool)$value;
} elseif ($key == "message") {
// Allow message specified in RFC 2397 format
$data = Format::parseRfc2397($value, 'utf-8');
if (!isset($data['type']) || $data['type'] != 'text/html')
$value = sprintf('<div style="white-space:pre-wrap">%s</div>',
Format::htmlchars($data['data']));
else
$value = $data['data'];
} else if ($key == "attachments") {
foreach ($value as &$info) {
$data = reset($info);
# PHP5: fopen("data://$data[5:]");
if (substr($data, 0, 5) != "data:") {
$info = array(
"data" => $data,
"type" => "text/plain",
"name" => key($info));
} else {
$data = substr($data,5);
list($meta, $contents) = explode(",", $data);
list($type, $extra) = explode(";", $meta);
$info = array(
"data" => $contents,
"type" => ($type) ? $type : "text/plain",
"name" => key($info));
# XXX: Handle decoding here??
if (substr($extra, -6) == "base64")
$info["encoding"] = "base64";
# Handle 'charset' hint in $extra, such as
# data:text/plain;charset=iso-8859-1,Blah
# Convert to utf-8 since it's the encoding scheme
# for the database. Otherwise, assume utf-8
list($param,$charset) = explode('=', $extra);
if ($param == 'charset' && $charset)
$contents = Format::utf8encode($contents, $charset);
}
$contents = Format::parseRfc2397($data, 'utf-8', false);
$info = array(
"data" => $contents['data'],
"type" => $contents['type'],
"name" => key($info),
);
}
unset($value);
}
......@@ -399,10 +400,6 @@ class ApiJsonDataParser extends JsonDataParser {
}
}
if(isset($current['message']) && $current['message'])
$current['message'] = sprintf('<div style="white-space:pre-wrap">%s</div>',
Format::htmlchars($current['message']));
return $current;
}
}
......
......@@ -369,5 +369,62 @@ class Format {
return (empty($text)) ? 'n-a' : $text;
}
/**
* Parse RFC 2397 formatted data strings. Format according to the RFC
* should look something like:
*
* data:[type/subtype][;charset=utf-8][;base64],data
*
* Parameters:
* $data - (string) RFC2397 formatted data string
* $output_encoding - (string:optional) Character set the input data
* should be encoded to.
* $always_convert - (bool|default:true) If the input data string does
* not specify an input encding, assume iso-8859-1. If this flag is
* set, the output will always be transcoded to the declared
* output_encoding, if set.
*
* Returs:
* array (data=>parsed and transcoded data string, type=>MIME type
* declared in the data string or text/plain otherwise)
*
* References:
* http://www.ietf.org/rfc/rfc2397.txt
*/
function parseRfc2397($data, $output_encoding=false, $always_convert=true) {
if (substr($data, 0, 5) != "data:")
return array('data'=>$data, 'type'=>'text/plain');
$data = substr($data, 5);
list($meta, $contents) = explode(",", $data, 2);
if ($meta)
list($type, $extra) = explode(";", $meta, 2);
else
$extra = '';
if (!isset($type) || !$type)
$type = 'text/plain';
$parameters = explode(";", $extra);
# Handle 'charset' hint in $extra, such as
# data:text/plain;charset=iso-8859-1,Blah
# Convert to utf-8 since it's the encoding scheme for the database.
$charset = ($always_convert) ? 'iso-8859-1' : false;
foreach ($parameters as $p) {
list($param, $value) = explode('=', $extra);
if ($param == 'charset')
$charset = $value;
elseif ($param == 'base64')
$contents = base64_decode($contents);
}
if ($output_encoding && $charset)
$contents = Format::encode($contents, $charset, $output_encoding);
return array(
'data' => $contents,
'type' => $type
);
}
}
?>
......@@ -553,6 +553,14 @@ class ChoiceField extends FormField {
);
}
function parse($value) {
if (is_numeric($value))
return $value;
foreach ($this->getChoices() as $k=>$v)
if (strcasecmp($value, $v) === 0)
return $k;
}
function toString($value) {
$choices = $this->getChoices();
if (isset($choices[$value]))
......
......@@ -1897,7 +1897,7 @@ class Ticket {
foreach ($form->getFields() as $field) {
$fname = $field->get('name');
if ($fname && isset($vars[$fname]) && !$field->value)
$field->value = $vars[$fname];
$field->value = $field->parse($vars[$fname]);
}
// Don't enforce form validation for email
......
......@@ -17,13 +17,18 @@ request content.
* __email__: *required* Email address of the submitter
* __name__: *required* Name of the submitter
* __subject__: *required* Subject of the ticket
* __message__: *required* Initial message for the ticket thread
* __message__: *required* Initial message for the ticket thread. The
message content can be specified using RFC 2397 in the JSON
format. The content of the message element should be the
message body. Encoding is assumed based on the encoding
attributed set in the xml processing instruction.
* __type__: Content-Type of the message body. Valid values are
`text/html` and `text/plain`. If not specified, `text/plain` is
assumed
* __alert__: If unset, disable alerts to staff. Default is `true`
* __autorespond__: If unset, disable autoresponses. Default is `true`
* __ip__: IP address of the submitter
* __phone__: Phone number of the submitter
* __phone_ext__: Phone number extension -- can also be embedded in *phone*
* __priorityId__: Priority *id* for the new ticket to assume
* __priority__: Priority *id* for the new ticket to assume
* __source__: Source of the ticket, default is `API`
* __topicId__: Help topic *id* associated with the ticket
* __attachments__: An array of files to attach to the initial message.
......@@ -34,6 +39,47 @@ request content.
* __type__: Mime type of the file. Default is `text/plain`
* __encoding__: Set to `base64` if content is base64 encoded
### Custom Forms and Fields ###
Fields added to both the common ticket and common client forms can accept
data via the API as well. The `name` attribute given in form designer is
used to match up the data in the API request with the field to parse and
receive the data.
These fields are included with the stock common client form. The `name`
field can be changed and the field can also be deleted. This section is
provided as an initial list. The fields supported by your help desk will
depend on your configuration for the common client and common ticket forms.
* __phone__: Phone number of the submitter. If the extension is
included, use a capital 'X' followed by the extension
* __notes__: Internal notes for the client created. These notes are
only visible to authenticated staff members
#### Field Data Processing Rules ####
Some fields have special formatting for inputs. For instance date fields
must receive the date formatted in Unix epoch time. This processing is
performed automatically for requests from the web interface. However, in the
case of the API, the remote requester is required to perform the procecssing
priori to submitting the request via the API. The sections below outline how
to format data for custom fields for requests sent via the API.
* __Date Fields__: Date fields need to be formatted in a format
recognizable to PHP's strtotime() function. The best formats are
[Unix epoch time](wikipedia.org/wiki/Unix_time), and [ISO 8601]
(http://xkcd.com/1179/). If using timezone offset in the date
specification, ensure that the _Timezone Aware_ flag is set for the
field.
* __Phone number Fields__: If the extension is provided with the phone
number, include a capital 'X' between the phone number and phone
extension parts of the field.
* __Choice and Selection Fields__: Use either the key specified with the
choice field, or the name of the field. For selection fields, do not
use anything from the `extra` column of the list designer.
### XML Payload Example ######
* `POST /api/tickets.xml`
......@@ -55,8 +101,8 @@ Notice that the phone extension can be sent as the `@ext` attribute of the
<name>Angry User</name>
<email>api@osticket.com</email>
<subject>Testing API</subject>
<phone ext="123">318-555-8634</phone>
<message><![CDATA[Message content here]]></message>
<phone>318-555-8634X123</phone>
<message type="text/plain"><![CDATA[Message content here]]></message>
<attachments>
<file name="file.txt" type="text/plain"><![CDATA[
File content is here and is automatically trimmed
......@@ -99,7 +145,7 @@ an object or array definition, and newlines are not allowed inside strings.
"phone": "3185558634X123",
"subject": "Testing API",
"ip": "123.211.233.122",
"message": "MESSAGE HERE",
"message": "data:text/html,MESSAGE <b>HERE</b>",
"attachments": [
{"file.txt": "data:text/plain;charset=utf-8,content"},
{"image.png": "data:image/png;base64,R0lGODdhMAA..."},
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment