summaryrefslogtreecommitdiffstats
path: root/lib/libUPnP/Platinum/Source/Core/PltProtocolInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libUPnP/Platinum/Source/Core/PltProtocolInfo.cpp')
-rw-r--r--lib/libUPnP/Platinum/Source/Core/PltProtocolInfo.cpp598
1 files changed, 598 insertions, 0 deletions
diff --git a/lib/libUPnP/Platinum/Source/Core/PltProtocolInfo.cpp b/lib/libUPnP/Platinum/Source/Core/PltProtocolInfo.cpp
new file mode 100644
index 0000000..d22dc02
--- /dev/null
+++ b/lib/libUPnP/Platinum/Source/Core/PltProtocolInfo.cpp
@@ -0,0 +1,598 @@
+/*****************************************************************
+|
+| Platinum - AV Media Item
+|
+| Copyright (c) 2004-2010, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| licensing@plutinosoft.com
+|
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc.,
+| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "PltProtocolInfo.h"
+#include "PltMimeType.h"
+#include "PltHttp.h"
+
+NPT_SET_LOCAL_LOGGER("platinum.media.server.protocolinfo")
+
+/*----------------------------------------------------------------------
+| defines
++---------------------------------------------------------------------*/
+#define PLT_FIELD_ALPHA "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+#define PLT_FIELD_NUM "0123456789"
+
+#define PLT_SP_FLAG_MASK 0x80000000
+#define PLT_LOP_NPT_MASK 0x40000000
+#define PLT_LOP_BYTES_MASK 0x20000000
+#define PLT_PLAYCONTAINER_PARAM_MASK 0x10000000
+#define PLT_S0_INCREASING_MASK 0x08000000
+#define PLT_SN_INCREASING_MASK 0x04000000
+#define PLT_RTSP_PAUSE_MASK 0x02000000
+#define PLT_TM_S_MASK 0x01000000
+#define PLT_TM_I_MASK 0x00800000
+#define PLT_TM_B_MASK 0x00400000
+#define PLT_HTTP_STALLING_MASK 0x00200000
+#define PLT_DLNA_V1_5_FLAG_MASK 0x00100000
+#define PLT_LP_FLAG_MASK 0x00010000
+#define PLT_CLEARTEXTBYTESEEK_FULL_MASK 0x00008000
+#define PLT_LOP_CLEARTEXTBYTES_MASK 0x00004000
+
+
+/*----------------------------------------------------------------------
+| globals
++---------------------------------------------------------------------*/
+static const char PLT_DLNAPNCharsToValidate[] = PLT_FIELD_ALPHA PLT_FIELD_NUM "_";
+static const char PLT_DLNAPSCharsToValidate[] = PLT_FIELD_NUM "-,/";
+static const char PLT_DLNAFlagCharsToValidate[] = "01";
+static const char PLT_DLNAHexCharsToValidate[] = PLT_FIELD_NUM "ABCDEFabcdef";
+static const char PLT_DLNAOTherNameCharsToValidate[] = PLT_FIELD_ALPHA PLT_FIELD_NUM;
+static const char PLT_DLNAOTherValueCharsToValidate[] = PLT_FIELD_ALPHA PLT_FIELD_NUM "_-+,";
+
+static const PLT_HttpFileRequestHandler_DefaultDlnaExtMapEntry
+PLT_HttpFileRequestHandler_DefaultDlnaMap[] = {
+ {"image/gif", "DLNA.ORG_PN=GIF_LRG"},
+ {"image/jpeg", "DLNA.ORG_PN=JPEG_LRG"},
+ {"image/jp2", "DLNA.ORG_PN=JPEG_LRG"},
+ {"image/png", "DLNA.ORG_PN=PNG_LRG"},
+ {"image/bmp", "DLNA.ORG_PN=BMP_LRG"},
+ {"image/tiff", "DLNA.ORG_PN=TIFF_LRG"},
+ {"audio/L16", "DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/L16;rate=44100;channels=2", "DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/L16;rate=44100;channels=1", "DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/L16;rate=32000;channels=1", "DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/mpeg", "DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/mp4", "DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/x-ms-wma", "DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/wav", "DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=01500000000000000000000000000000"}, // UVerse
+ {"audio/x-wav", "DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/avi", "DLNA.ORG_PN=AVI;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/mp4", "DLNA.ORG_PN=MPEG4_P2_SP_AAC;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/mpeg", "DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/quicktime","DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/x-ms-wmv", "DLNA.ORG_PN=WMVHIGH_BASE;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/x-msvideo","DLNA.ORG_PN=AVI;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/x-ms-asf", "DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/x-matroska","DLNA.ORG_OP=01;DLNA.ORG_CI=0"},
+ {"video/x-flv", "DLNA.ORG_OP=01;DLNA.ORG_CI=0"},
+};
+
+static const PLT_HttpFileRequestHandler_DefaultDlnaExtMapEntry
+PLT_HttpFileRequestHandler_360DlnaMap[] = {
+ {"video/quicktime","DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"video/mp4", "DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/wav", "DLNA.ORG_OP=01;DLNA.ORG_CI=1;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/mp4", "DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000"},
+ {"audio/mpeg", "DLNA.ORG_PN=MP3;DLNA.ORG_OP=01"},
+ {"audio/x-ms-wma", "DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_CI=0"}
+};
+
+static const PLT_HttpFileRequestHandler_DefaultDlnaExtMapEntry
+PLT_HttpFileRequestHandler_SonosDlnaMap[] = {
+ {"audio/wav", "*"}
+};
+
+static const PLT_HttpFileRequestHandler_DefaultDlnaExtMapEntry
+PLT_HttpFileRequestHandler_PS3DlnaMap[] = {
+ {"image/jpg", "DLNA.ORG_OP=01"},
+ {"image/png", "DLNA.ORG_OP=01"}
+};
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::PLT_ProtocolInfo
++---------------------------------------------------------------------*/
+PLT_ProtocolInfo::PLT_ProtocolInfo() :
+ m_Valid(false)
+{
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::PLT_ProtocolInfo
++---------------------------------------------------------------------*/
+/*PLT_ProtocolInfo::PLT_ProtocolInfo(NPT_String protocol_info) :
+ m_Valid(false)
+{
+ SetProtocolInfo(protocol_info);
+}*/
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::PLT_ProtocolInfo
++---------------------------------------------------------------------*/
+PLT_ProtocolInfo::PLT_ProtocolInfo(const char* protocol_info) :
+ m_Valid(false)
+{
+ SetProtocolInfo(protocol_info);
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::PLT_ProtocolInfo
++---------------------------------------------------------------------*/
+PLT_ProtocolInfo::PLT_ProtocolInfo(const char* protocol,
+ const char* mask,
+ const char* content_type,
+ const char* extra) :
+ m_Protocol(protocol),
+ m_Mask(mask),
+ m_ContentType(content_type),
+ m_Extra(extra),
+ m_Valid(false)
+{
+ ValidateExtra();
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::SetProtocolInfo
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ProtocolInfo::SetProtocolInfo(const char* protocol_info)
+{
+ if (!protocol_info || protocol_info[0] == '\0')
+ return NPT_ERROR_INVALID_PARAMETERS;
+
+ NPT_List<NPT_String> parts = NPT_String(protocol_info).Split(":");
+ if (parts.GetItemCount() != 4)
+ return NPT_ERROR_INVALID_SYNTAX;
+
+ NPT_List<NPT_String>::Iterator part = parts.GetFirstItem();
+ m_Protocol = *part++;
+ m_Mask = *part++;
+ m_ContentType = *part++;
+ m_Extra = *part;
+
+ return ValidateExtra();
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::ParseExtra
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ProtocolInfo::ParseExtra(NPT_List<FieldEntry>& entries)
+{
+ if (m_Extra == "*") return NPT_SUCCESS;
+
+ // remove extra characters which could cause parsing errors
+ m_Extra.Trim(";");
+
+ NPT_List<NPT_String> fields = m_Extra.Split(";");
+ NPT_List<NPT_String>::Iterator field = fields.GetFirstItem();
+ if (!field) NPT_CHECK_SEVERE(NPT_ERROR_INVALID_SYNTAX);
+
+ while (field) {
+ NPT_List<NPT_String> entry = (*field).Split("=");
+ if (entry.GetItemCount() != 2) NPT_CHECK_SEVERE(NPT_ERROR_INVALID_SYNTAX);
+ entries.Add(FieldEntry(*entry.GetFirstItem(), *entry.GetLastItem()));
+ ++field;
+ }
+
+ return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::ValidateField
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ProtocolInfo::ValidateField(const char* val,
+ const char* valid_chars,
+ NPT_Cardinal num_chars /* = 0 */)
+{
+ if (!valid_chars || !val || val[0] == '\0')
+ return NPT_ERROR_INVALID_PARAMETERS;
+
+ // shortcut
+ if (num_chars && NPT_StringLength(val) != num_chars)
+ return NPT_ERROR_INVALID_SYNTAX;
+
+ while (val) {
+ char c = *val++;
+ if (c == '\0') return NPT_SUCCESS;
+
+ // look for character in valid chars
+ const char* p = valid_chars;
+ while (*p != c && ++p) {};
+
+ // reached end of valid chars means we didn't find it
+ if (!p) break;
+ }
+
+ return NPT_ERROR_INVALID_SYNTAX;
+
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::ValidateExtra
++---------------------------------------------------------------------*/
+NPT_Result
+PLT_ProtocolInfo::ValidateExtra()
+{
+ if (m_Extra != "*") {
+ m_Valid = false;
+
+ NPT_List<FieldEntry> entries;
+ NPT_CHECK(ParseExtra(entries));
+
+ NPT_List<FieldEntry>::Iterator entry =
+ entries.GetFirstItem();
+
+ // parse other optional fields
+ PLT_ProtocolInfoParserState state = PLT_PROTINFO_PARSER_STATE_START;
+ for (;entry;entry++) {
+ if (entry->m_Key == "DLNA.ORG_PN") {
+ // pn-param only allowed as first param
+ if (state > PLT_PROTINFO_PARSER_STATE_START) {
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ NPT_CHECK_LABEL_SEVERE(ValidateField(
+ entry->m_Value,
+ PLT_DLNAPNCharsToValidate), failure);
+
+ m_DLNA_PN = entry->m_Value;
+ state = PLT_PROTINFO_PARSER_STATE_PN;
+ continue;
+ } else if (entry->m_Key == "DLNA.ORG_OP") {
+ // op-param only allowed after pn-param
+ if (state > PLT_PROTINFO_PARSER_STATE_PN) {
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ // validate value
+ NPT_CHECK_LABEL_SEVERE(ValidateField(
+ entry->m_Value,
+ PLT_DLNAFlagCharsToValidate,
+ 2), failure);
+
+ m_DLNA_OP = entry->m_Value;
+ state = PLT_PROTINFO_PARSER_STATE_OP;
+ continue;
+ } else if (entry->m_Key == "DLNA.ORG_PS") {
+ // ps-param only allowed after op-param
+ if (state > PLT_PROTINFO_PARSER_STATE_OP) {
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ // validate value
+ NPT_CHECK_LABEL_SEVERE(ValidateField(
+ entry->m_Value,
+ PLT_DLNAPSCharsToValidate), failure);
+
+ m_DLNA_PS = entry->m_Value;
+ state = PLT_PROTINFO_PARSER_STATE_PS;
+ continue;
+ } else if (entry->m_Key == "DLNA.ORG_CI") {
+ // ci-param only allowed after ps-param
+ if (state > PLT_PROTINFO_PARSER_STATE_PS) {
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ // validate value
+ NPT_CHECK_LABEL_SEVERE(ValidateField(
+ entry->m_Value,
+ PLT_DLNAFlagCharsToValidate,
+ 1), failure);
+
+ m_DLNA_CI = entry->m_Value;
+ state = PLT_PROTINFO_PARSER_STATE_CI;
+ continue;
+ } else if (entry->m_Key == "DLNA.ORG_FLAGS") {
+ // flags-param only allowed after ci-param
+ if (state > PLT_PROTINFO_PARSER_STATE_CI) {
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ // validate value
+ NPT_CHECK_LABEL_SEVERE(ValidateField(
+ entry->m_Value,
+ PLT_DLNAHexCharsToValidate,
+ 32), failure);
+
+ m_DLNA_FLAGS = entry->m_Value;
+ state = PLT_PROTINFO_PARSER_STATE_FLAGS;
+ continue;
+ } else if (entry->m_Key == "DLNA.ORG_MAXSP") {
+ // maxsp-param only allowed after flags-param
+ if (state > PLT_PROTINFO_PARSER_STATE_FLAGS) {
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ // validate value
+ NPT_CHECK_LABEL_SEVERE(ValidateField(
+ entry->m_Value,
+ PLT_FIELD_NUM "."), failure);
+
+ m_DLNA_MAXSP = entry->m_Value;
+ state = PLT_PROTINFO_PARSER_STATE_MAXSP;
+ continue;
+ } else {
+ // don't switch state for unknown value so we don't break parsing next ones
+ // Sony TVs for example have DLNA.ORG_PN=xx;SONY.COM_PN=xx;DLNA.ORG_FLAGS=xxx
+ //state = PLT_PROTINFO_PARSER_STATE_OTHER;
+
+ // validate key first which should IANA_*<"a"-"z","A"-"Z","0"-"9">
+ int index = entry->m_Key.Find("_");
+ if (index == -1) {
+ NPT_CHECK_LABEL_SEVERE(NPT_ERROR_INVALID_SYNTAX, failure);
+ }
+
+ // validate key
+ if (NPT_FAILED(ValidateField(
+ entry->m_Key.GetChars()+index,
+ PLT_DLNAOTherNameCharsToValidate))) {
+ NPT_LOG_WARNING_2("Invalid protocolinfo 4th field other param: %s=%s",
+ (const char*)entry->m_Key,
+ (const char*)entry->m_Value);
+ continue;
+ }
+
+ // validate value
+ if (NPT_FAILED(ValidateField(
+ entry->m_Value,
+ PLT_DLNAOTherValueCharsToValidate))) {
+
+ NPT_LOG_WARNING_2("Invalid protocolinfo 4th field other param: %s=%s",
+ (const char*)entry->m_Key,
+ (const char*)entry->m_Value);
+ continue;
+ }
+
+ m_DLNA_OTHER.Add(*entry);
+ continue;
+ }
+ }
+ }
+
+ m_Valid = true;
+ return NPT_SUCCESS;
+
+failure:
+ NPT_LOG_WARNING_1("Failure to parse Protocol Info Extras:%s", m_Extra.GetChars());
+ return NPT_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::ToString
++---------------------------------------------------------------------*/
+NPT_String
+PLT_ProtocolInfo::ToString() const
+{
+ NPT_String output = m_Protocol + ":";
+ output += m_Mask + ":";
+ output += m_ContentType + ":";
+ // if it wasn't valid or extra is not DLNA, just use it as is
+ if (!m_Valid || m_Extra == "*") {
+ output += m_Extra;
+ } else {
+ bool add_semicolon = false;
+ if (!m_DLNA_PN.IsEmpty()) {
+ output += "DLNA.ORG_PN=" + m_DLNA_PN;
+ add_semicolon = true;
+ }
+ if (!m_DLNA_OP.IsEmpty()) {
+ if (add_semicolon) output += ";";
+ output += "DLNA.ORG_OP=" + m_DLNA_OP;
+ add_semicolon = true;
+ }
+ if (!m_DLNA_PS.IsEmpty()) {
+ if (add_semicolon) output += ";";
+ output += "DLNA.ORG_PS=" + m_DLNA_PS;
+ add_semicolon = true;
+ }
+ if (!m_DLNA_CI.IsEmpty()) {
+ if (add_semicolon) output += ";";
+ output += "DLNA.ORG_CI=" + m_DLNA_CI;
+ add_semicolon = true;
+ }
+ if (!m_DLNA_FLAGS.IsEmpty()) {
+ if (add_semicolon) output += ";";
+ output += "DLNA.ORG_FLAGS=" + m_DLNA_FLAGS;
+ add_semicolon = true;
+ }
+ if (!m_DLNA_MAXSP.IsEmpty()) {
+ if (add_semicolon) output += ";";
+ output += "DLNA.ORG_MAXSP=" + m_DLNA_MAXSP;
+ add_semicolon = true;
+ }
+ if (m_DLNA_OTHER.GetItemCount()) {
+ for (NPT_List<FieldEntry>::Iterator iter = m_DLNA_OTHER.GetFirstItem();
+ iter;
+ iter++) {
+ if (add_semicolon) output += ";";
+ output += iter->m_Key + "=" + iter->m_Value;
+ add_semicolon = true;
+ }
+ }
+ }
+
+ return output;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::Match
++---------------------------------------------------------------------*/
+bool
+PLT_ProtocolInfo::Match(const PLT_ProtocolInfo& other) const
+{
+ // we need the first 3 params
+ if (m_Protocol != '*' &&
+ other.GetProtocol() != '*' &&
+ m_Protocol != other.GetProtocol()) return false;
+
+ if (m_Mask != '*' &&
+ other.GetMask() != '*' &&
+ m_Mask != other.GetMask()) return false;
+
+ if (m_ContentType != '*' &&
+ other.GetContentType() != '*' &&
+ m_ContentType != other.GetContentType()) return false;
+
+ // match DLNAPn of 4th item if not '*'
+ if (m_Extra == '*' ||
+ other.GetExtra() == '*' ||
+ (!m_DLNA_PN.IsEmpty() && m_DLNA_PN == other.GetDLNA_PN())) return true;
+
+ return false;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::GetMimeTypeFromProtocolInfo
++---------------------------------------------------------------------*/
+NPT_String
+PLT_ProtocolInfo::GetMimeTypeFromProtocolInfo(const char* protocol_info)
+{
+ /*NPT_String info = protocol_info;
+ NPT_List<NPT_String> fragments = info.Split(":");
+ if (fragments.GetItemCount() != 4) return "";
+ return *fragments.GetItem(2);*/
+
+ PLT_ProtocolInfo info(protocol_info);
+ return info.m_ContentType;
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::GetDlnaExtension
++---------------------------------------------------------------------*/
+const char*
+PLT_ProtocolInfo::GetDlnaExtension(const char* mime_type,
+ const PLT_HttpRequestContext* context /* = NULL */)
+{
+ return GetDlnaExtension(mime_type,
+ context?PLT_HttpHelper::GetDeviceSignature(context->GetRequest()):PLT_DEVICE_UNKNOWN);
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::GetDlnaExtension
++---------------------------------------------------------------------*/
+const char*
+PLT_ProtocolInfo::GetDlnaExtension(const char* mime_type,
+ PLT_DeviceSignature signature /* = PLT_DEVICE_UNKNOWN */)
+{
+ NPT_String _mime_type = mime_type;
+
+ if (signature != PLT_DEVICE_UNKNOWN) {
+ // look for special case for 360
+ if (signature == PLT_DEVICE_XBOX_360 || signature == PLT_DEVICE_XBOX_ONE || signature == PLT_DEVICE_WMP) {
+ for (unsigned int i=0; i<NPT_ARRAY_SIZE(PLT_HttpFileRequestHandler_360DlnaMap); i++) {
+ if (_mime_type.Compare(PLT_HttpFileRequestHandler_360DlnaMap[i].mime_type, true) == 0) {
+ return PLT_HttpFileRequestHandler_360DlnaMap[i].dlna_ext;
+ }
+ }
+ } else if (signature == PLT_DEVICE_SONOS) {
+ for (unsigned int i=0; i<NPT_ARRAY_SIZE(PLT_HttpFileRequestHandler_SonosDlnaMap); i++) {
+ if (_mime_type.Compare(PLT_HttpFileRequestHandler_SonosDlnaMap[i].mime_type, true) == 0) {
+ return PLT_HttpFileRequestHandler_SonosDlnaMap[i].dlna_ext;
+ }
+ }
+ } else if (signature == PLT_DEVICE_PS3) {
+ for (unsigned int i=0; i<NPT_ARRAY_SIZE(PLT_HttpFileRequestHandler_PS3DlnaMap); i++) {
+ if (_mime_type.Compare(PLT_HttpFileRequestHandler_PS3DlnaMap[i].mime_type, true) == 0) {
+ return PLT_HttpFileRequestHandler_PS3DlnaMap[i].dlna_ext;
+ }
+ }
+
+ return "DLNA.ORG_OP=01"; // Should we try default dlna instead?
+ }
+ }
+
+ for (unsigned int i=0; i<NPT_ARRAY_SIZE(PLT_HttpFileRequestHandler_DefaultDlnaMap); i++) {
+ if (_mime_type.Compare(PLT_HttpFileRequestHandler_DefaultDlnaMap[i].mime_type, true) == 0) {
+ return PLT_HttpFileRequestHandler_DefaultDlnaMap[i].dlna_ext;
+ }
+ }
+
+ return "*";
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::GetProtocolInfoFromMimeType
++---------------------------------------------------------------------*/
+PLT_ProtocolInfo
+PLT_ProtocolInfo::GetProtocolInfoFromMimeType(const char* mime_type,
+ bool with_dlna_extension /* = true */,
+ PLT_DeviceSignature signature /* = PLT_DEVICE_UNKNOWN */)
+{
+ return PLT_ProtocolInfo("http-get:*:"+NPT_String(mime_type)+":"+ \
+ (with_dlna_extension?GetDlnaExtension(mime_type, signature):"*"));
+}
+
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::GetProtocolInfoFromMimeType
++---------------------------------------------------------------------*/
+PLT_ProtocolInfo
+PLT_ProtocolInfo::GetProtocolInfoFromMimeType(const char* mime_type,
+ bool with_dlna_extension /* = true */,
+ const PLT_HttpRequestContext* context /* = NULL */)
+{
+ return GetProtocolInfoFromMimeType(mime_type,
+ with_dlna_extension,
+ context?PLT_HttpHelper::GetDeviceSignature(context->GetRequest()):PLT_DEVICE_UNKNOWN);
+}
+
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::GetProtocolInfo
++---------------------------------------------------------------------*/
+PLT_ProtocolInfo
+PLT_ProtocolInfo::GetProtocolInfo(const char* filename,
+ bool with_dlna_extension /* = true */,
+ PLT_DeviceSignature signature /* = PLT_DEVICE_UNKNOWN */)
+{
+ return GetProtocolInfoFromMimeType(PLT_MimeType::GetMimeType(filename, signature),
+ with_dlna_extension,
+ signature);
+}
+/*----------------------------------------------------------------------
+| PLT_ProtocolInfo::GetProtocolInfo
++---------------------------------------------------------------------*/
+PLT_ProtocolInfo
+PLT_ProtocolInfo::GetProtocolInfo(const char* filename,
+ bool with_dlna_extension /* = true */,
+ const PLT_HttpRequestContext* context /* = NULL */)
+{
+ return GetProtocolInfoFromMimeType(PLT_MimeType::GetMimeType(filename, context),
+ with_dlna_extension,
+ context);
+}