Tizen 2.1 base
[platform/framework/native/app-service.git] / plugins / nfc-condition-handler / NfcConditionHandler.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18
19 /**
20  * @file        nfc_condition_candler.cpp
21  * @brief       This is the implementation file of the _AlarmConditionHandler class.
22  *
23  */
24
25
26 #include <new>
27
28 #include <FBaseColHashMap.h>
29 #include <FBaseUtilRegularExpression.h>
30 #include <FBaseUtilUrlEncoder.h>
31
32 #include <FBaseSysLog.h>
33 #include <FBase_StringConverter.h>
34 #include <FApp_Aul.h>
35 #include <FApp_AppLaunchConditionHandlerBase.h>
36
37
38 #ifdef _NfcSysTryLogReturn
39 #undef _NfcSysTryLogReturn
40 #endif
41
42 #define _NfcSysTryLogReturn(condition, returnValue, ...) \
43         if (!(condition)) {     \
44                 SetLastResult(E_INVALID_FORMAT); \
45                 SysLog(NID_APP, __VA_ARGS__); \
46                 return returnValue;     \
47         } \
48         else {;}
49
50 using namespace Tizen::App;
51 using namespace Tizen::Base;
52 using namespace Tizen::Base::Collection;
53 using namespace Tizen::Base::Utility;
54 using namespace Tizen::System;
55
56
57 /**
58  * @class               _NfcConditionHandler
59  * @brief               This class implements conditional app launch for alarm condition. (NFC)
60  * @final
61  */
62 class _NfcConditionHandler:
63         public _AppLaunchConditionHandlerBase
64 {
65 public:
66         _NfcConditionHandler(void) :
67                 uriSchemeMap()
68         {
69                 // Makes the URI scheme table which is consist of well-known URI schemes the underlying NFC system supports
70                 uriSchemeMap.Construct();
71                 uriSchemeMap.Add(*(new String(L"http")), *(new String(L"http")));
72                 uriSchemeMap.Add(*(new String(L"https")), *(new String(L"https")));
73                 uriSchemeMap.Add(*(new String(L"ftp")), *(new String(L"ftp")));
74                 uriSchemeMap.Add(*(new String(L"sftp")), *(new String(L"sftp")));
75                 uriSchemeMap.Add(*(new String(L"smb")), *(new String(L"smb")));
76                 uriSchemeMap.Add(*(new String(L"nfs")), *(new String(L"nfs")));
77                 uriSchemeMap.Add(*(new String(L"telnet")), *(new String(L"telnet")));
78                 uriSchemeMap.Add(*(new String(L"file")), *(new String(L"file")));
79                 uriSchemeMap.Add(*(new String(L"ssh")), *(new String(L"ssh")));
80                 uriSchemeMap.Add(*(new String(L"tel")), *(new String(L"tel")));
81                 uriSchemeMap.Add(*(new String(L"mailto")), *(new String(L"mailto")));
82                 uriSchemeMap.Add(*(new String(L"news")), *(new String(L"news")));
83                 uriSchemeMap.Add(*(new String(L"sip")), *(new String(L"sip")));
84                 uriSchemeMap.Add(*(new String(L"sips")), *(new String(L"sips")));
85                 uriSchemeMap.Add(*(new String(L"tftp")), *(new String(L"tftp")));
86                 uriSchemeMap.Add(*(new String(L"imap")), *(new String(L"imap")));
87                 uriSchemeMap.Add(*(new String(L"pop")), *(new String(L"pop")));
88                 uriSchemeMap.Add(*(new String(L"market")), *(new String(L"market")));
89                 uriSchemeMap.Add(*(new String(L"rtsp")), *(new String(L"rtsp")));
90         }
91
92         virtual ~_NfcConditionHandler(void)
93         {
94                 uriSchemeMap.RemoveAll(true);
95         }
96
97         virtual result Register(_AppLaunchCondition& operation)
98         {
99                 // TODO: The following pattern is temporary.
100                 // It should be changed to cover all NFC conditions according to the NDEF specifications.
101                 String pattern(L"([A-Za-z]*)='([0-9A-Za-z&=_\\-\\.\\:\\/\\\\]*)'");
102                 String buf(operation.GetConditionString());
103                 String field;
104                 String value;
105                 ArrayList list;
106                 Utility::RegularExpression regex;
107                 char* pOriginalCondition = null;
108                 char* pTranslatedCondition = null;
109                 result r = E_SUCCESS;
110                 bool ret = true;
111
112                 list.Construct();
113
114                 r = regex.Construct(pattern);
115                 SysTryReturn(NID_APP, !IsFailed(r), E_SYSTEM, E_SYSTEM, "[%s] Failed to regex.Construct(%ls).", GetErrorMessage(r), pattern.GetPointer());
116
117                 ret = regex.Consume(buf, &list);
118                 r = GetLastResult();
119                 SysTryReturn(NID_APP, ret == true, E_INVALID_FORMAT, E_INVALID_FORMAT, "[%s] Failed to parse the condition (%ls).", GetErrorMessage(r),
120                                         buf.GetPointer());
121
122                 field = *(String*)list.GetAt(1);
123                 value = *(String*)list.GetAt(2);
124                 list.RemoveAll(true);
125
126                 if (field == "NFC")
127                 {
128                         pOriginalCondition = _StringConverter::CopyToCharArrayN(value);
129                         SysTryReturnResult(NID_APP, pOriginalCondition != null, E_SYSTEM, "Failed to parse the condition.");
130
131                         // Translates OSP condition to SLP service condition
132                         pTranslatedCondition = GetNfcAulConditionN(pOriginalCondition);
133                         delete[] pOriginalCondition;
134
135                         SysTryReturnResult(NID_APP, pTranslatedCondition != null, E_SYSTEM, "Failed to translate the condition.");
136
137                         r = _Aul::_DesktopFile::UpdateService(operation.GetAppId(), pTranslatedCondition);
138
139                         operation.SetUserData(new String(pTranslatedCondition));
140
141                         delete[] pTranslatedCondition;
142                 }
143                 else
144                 {
145                         r = E_FAILURE;
146                 }
147
148                 return r;
149         }
150
151         virtual result Unregister(_AppLaunchCondition& operation)
152         {
153                 String* pHandle = null;
154 //              char* pOriginalCondition = null;
155                 char* pTranslatedCondition = null;
156                 result r = E_SUCCESS;
157
158                 pHandle = dynamic_cast<String*>(operation.GetUserData());
159                 SysTryReturnResult(NID_APP, pHandle != null, E_INVALID_ARG, "Invalid conditional operation.");
160
161                 pTranslatedCondition = _StringConverter::CopyToCharArrayN(*pHandle);
162                 SysTryReturnResult(NID_APP, pTranslatedCondition != null, E_SYSTEM, "Failed to parse the condition.");
163
164                 // Translates OSP condition to SLP service condition
165 //              pTranslatedCondition = GetNfcAulConditionN(pOriginalCondition);
166 //              delete[] pOriginalCondition;
167 //              SysTryReturnResult(NID_APP, pTranslatedCondition != null, E_SYSTEM, "Failed to translate the condition.");
168
169                 r = _Aul::_DesktopFile::RemoveService(operation.GetAppId(), pTranslatedCondition); // only operation name is required to remove service.
170
171                 delete[] pTranslatedCondition;
172
173                 return r;
174         }
175
176 private:
177         char* GetNfcAulConditionN(char* pConditionValue)
178         {
179                 //-------------------------------------------------------------------------
180                 // The BNF format of the OSP NFC condition is as follows:
181                 //              <condition>   ::= <tnf_field>"&"<type_field>["&"<code_field>]
182                 //              <tnf_field>   ::= "tnf="<tnf_value>
183                 //              <tnf_value>   ::= "rtd"|"mime"|"uri"|"ext"
184                 //              <type_field>  ::= "type="<type_string>
185                 //              <type_string> ::= <String of US_ASCII characters>
186                 //              <code_field>  ::= "code="<uri_code>
187                 //              <uri_code>        ::= "0x"<hexa_digit><hexa_digit>
188                 //              <hexa_digit>  ::= "0".."9"|"A".."F"
189                 //
190                 // AUL translation rules according to <tnf_field> are as follows:
191                 //              "tnf=rtd" --> "NFC_SERVICE_WELL_KNOWN_TYPE:NULL:"<type_string>"/"{<uri_code>|"*"}
192                 //              "tnf=ext" --> "NFC_SERVICE_EXTERNAL_TYPE:NULL:"<uri_scheme>"/"<type_string>
193                 //              "tnf=uri" --> "NFC_SERVICE_URI_TYPE:NULL:"<uri_scheme>"/"<type_string>
194                 //              "tnf=mime" --> "NFC_SERVICE_MIME_TYPE:NULL:"<type_string>
195                 //              <uri_scheme> is the head part of <type_string> and delimited by colon(:) and one of the wellknown types
196                 //              <type_string> of "tnf=ext" and "tnf=mime" must be decapitalized for case-insensitive matching
197                 //              <type_string> of "tnf=ext" and "tnf=uri" must be percent-encoded
198                 //
199                 // Examples
200                 //              Source(OSP):
201                 //                      tnf=rtd&type=Sp
202                 //                      tnf=rtd&type=U&code=0x05
203                 //                      tnf=ext&type=Bordeaux_Wine:1996
204                 //                      tnf=uri&type=http://www.tizen.org
205                 //                      tnf=mime&type=text/x-vcard
206                 //              Target(AUL):
207                 //                      NFC_SERVICE_WELL_KNOWN_TYPE:NULL:Sp/*
208                 //                      NFC_SERVICE_WELL_KNOWN_TYPE:NULL:U/0x05
209                 //                      NFC_SERVICE_EXTERNAL_TYPE:NULL:unknown/bordeauxwine%3A1996
210                 //                      NFC_SERVICE_URI_TYPE:http/http%3A%2F%2Fwww.tizen.org
211                 //                      NFC_SERVICE_MIME_TYPE:NULL:text/x-vcard
212                 //-------------------------------------------------------------------------
213
214                 String tnfValue;        // <tnf_value>
215                 String typeString;      // <type_string>
216                 String uriCode(L'*');   // <uri_code>
217                 int delimiterIndex = -1;
218
219                 String originalCondition(pConditionValue);
220                 String aulFormatCondition;
221                 char* pTranslatedCondition = null;
222
223                 result r = E_SUCCESS;
224                 bool isOk = true;
225
226
227                 // Check whether the condition includes the tnf field.
228                 isOk = originalCondition.StartsWith(L"tnf=", 0);
229                 _NfcSysTryLogReturn(isOk == true, null, "Illegal format (%ls) - No tnf field.", originalCondition.GetPointer() );
230
231                 // Search the index of the type field.
232                 r = originalCondition.IndexOf(L'&', 0, delimiterIndex);
233                 _NfcSysTryLogReturn(r == E_SUCCESS, null, "Illegal format (%ls)- No type field.", originalCondition.GetPointer() );
234
235                 // Read <tnf_value>.
236                 // The length of <tnf_value> is (delimiterIndex - 4).
237                 r = originalCondition.SubString(4, delimiterIndex - 4, tnfValue);
238                 _NfcSysTryLogReturn(r == E_SUCCESS, null, "Parsing error. (%ls)", originalCondition.GetPointer() );
239
240                 // Check whether the condition includes the type field.
241                 isOk = originalCondition.StartsWith(L"type=", delimiterIndex + 1);
242                 _NfcSysTryLogReturn(isOk == true, null, "Illegal format (%ls)- No type field.", originalCondition.GetPointer() );
243
244                 // Read <type_string>.
245                 r = originalCondition.SubString(delimiterIndex + 6, typeString);
246                 _NfcSysTryLogReturn(r == E_SUCCESS, null, "Parsing error. (%ls)", originalCondition.GetPointer() );
247
248                 if (tnfValue.CompareTo(L"rtd") == 0)
249                 {
250                         // Search the index of the code field.
251                         // The code field is optional.
252                         r = typeString.IndexOf(L'&', 0, delimiterIndex);
253                         if (!IsFailed(r))
254                         {
255                                 String fullTypeString(typeString);
256
257                                 r = fullTypeString.SubString(0, delimiterIndex, typeString);
258                                 _NfcSysTryLogReturn(r == E_SUCCESS, null, "Parsing error. (%ls)", originalCondition.GetPointer() );
259
260                                 if (typeString.CompareTo(L"U") == 0)
261                                 {
262                                         // Check whether the condition includes the type field.
263                                         isOk = fullTypeString.StartsWith(L"code=", delimiterIndex + 1);
264                                         _NfcSysTryLogReturn(isOk == true, null, "Illegal format (%ls)- No code field after the second '&'.", originalCondition.GetPointer() );
265
266                                         // Read <uri_code>.
267                                         r = fullTypeString.SubString(delimiterIndex + 6, uriCode);
268                                         _NfcSysTryLogReturn(r == E_SUCCESS, null, "Parsing error. (%ls)", originalCondition.GetPointer() );
269                                 }
270                         }
271
272                         aulFormatCondition = L"NFC_SERVICE_WELL_KNOWN_TYPE:NULL:";
273                         aulFormatCondition.Append(typeString);
274                         aulFormatCondition.Append(L'/');
275                         aulFormatCondition.Append(uriCode);             // The default value of 'uriCode' is '*'
276                  }
277                  else if ((tnfValue.CompareTo(L"ext") == 0)  || (tnfValue.CompareTo(L"uri") == 0))
278                  {
279                         if (tnfValue.CompareTo(L"ext") == 0)
280                         {
281                                 aulFormatCondition = L"NFC_SERVICE_EXTERNAL_TYPE:NULL:";
282                                 // Convert all the letters to lower case.
283                                 typeString.ToLowerCase();
284                         }
285                         else
286                         {
287                                 aulFormatCondition = L"NFC_SERVICE_URI_TYPE:NULL:";
288                         }
289
290                         r = typeString.IndexOf(L':', 0, delimiterIndex);
291                         if (!IsFailed(r))
292                         {
293                                 String uriScheme;
294
295                                 // Extract the URI scheme from <type_string>.
296                                 r = typeString.SubString(0, delimiterIndex, uriScheme);
297                                 _NfcSysTryLogReturn(r == E_SUCCESS, null, "Parsing error.");
298
299                                 // if the URI scheme is one of the registered keywords
300                                 (void) uriSchemeMap.GetValue(uriScheme);
301                                 r = GetLastResult();
302                                 if (!IsFailed(r))
303                                 {
304                                         aulFormatCondition.Append(uriScheme);
305                                 }
306                                 else
307                                 {
308                                         aulFormatCondition.Append(L"unknown");
309                                 }
310                         }
311                         else
312                         {
313                                 aulFormatCondition.Append(L"unknown");
314                         }
315
316                         String encodedTypeString;
317
318                         // Encode <type_string> using UTF-8 encoding scheme.
319                         r = UrlEncoder::Encode(typeString, L"UTF-8", encodedTypeString);
320                         _NfcSysTryLogReturn(r == E_SUCCESS, null, "Failed to UTF-8 Encoding.");
321
322                         aulFormatCondition.Append(L'/');
323                         aulFormatCondition.Append(encodedTypeString);
324                 }
325                 else if (tnfValue.CompareTo(L"mime") == 0)
326                 {
327                         typeString.ToLowerCase();
328
329                         aulFormatCondition = L"NFC_SERVICE_MIME_TYPE:NULL:";
330                         aulFormatCondition.Append(typeString);
331                 }
332                 else
333                 {
334                         SysLog(NID_APP, "Illegal format (%ls) - Invalid TNF value", originalCondition.GetPointer() );
335                         return null;
336                 }
337
338                 pTranslatedCondition = _StringConverter::CopyToCharArrayN(aulFormatCondition);
339                 _NfcSysTryLogReturn(pTranslatedCondition != null, null, "String conversion error.");
340
341                 return pTranslatedCondition;
342         }
343
344 private:
345         HashMap uriSchemeMap;
346 };      //_NfcConditionHandler
347
348
349 /////////////////////////////////////////////////////////////////////////
350 //      All plugins must provide both a creation and a destruction function
351 /////////////////////////////////////////////////////////////////////////
352 extern "C"
353 {
354 _OSP_EXPORT_ _AppLaunchConditionHandlerBase*
355 CreatePlugin(void)
356 {
357     return new (std::nothrow) _NfcConditionHandler;
358 }
359
360 _OSP_EXPORT_ void
361 DestroyPlugin(_AppLaunchConditionHandlerBase* p)
362 {
363     delete p;
364 }
365 }//extern "C"