1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** USBX Component                                                        */
17 /**                                                                       */
18 /**   Pictbridge Application                                              */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 
24 /* Include necessary system files.  */
25 
26 #define UX_SOURCE_CODE
27 
28 #include "ux_api.h"
29 #include "ux_pictbridge.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _ux_pictbridge_tag_name_get                         PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function isolates a tag name from the XML script.              */
45 /*                                                                        */
46 /*    Note: the buffer size of tag_name, variable_name, variable_string   */
47 /*    and xml_parameter must be equal to or greater than                  */
48 /*    UX_PICTBRIDGE_MAX_TAG_SIZE, UX_PICTBRIDGE_MAX_VARIABLE_SIZE,        */
49 /*    UX_PICTBRIDGE_MAX_STRING_SIZE and UX_PICTBRIDGE_MAX_STRING_SIZE.    */
50 /*                                                                        */
51 /*  INPUT                                                                 */
52 /*                                                                        */
53 /*    input_buffer                           Pointer to object buffer     */
54 /*    input_length                           Length of the object         */
55 /*    tag_name                               Where to store the tag       */
56 /*    variable_name                          Variable name                */
57 /*    variable_string                        Variable string              */
58 /*    xml_parameter                          ML parameter                 */
59 /*    output_buffer                          Pointer after the tag        */
60 /*    output_length                          Length of the object         */
61 /*    tag_flag                               flag specific to this tag    */
62 /*                                                                        */
63 /*  OUTPUT                                                                */
64 /*                                                                        */
65 /*    Completion Status                                                   */
66 /*                                                                        */
67 /*  CALLS                                                                 */
68 /*                                                                        */
69 /*                                                                        */
70 /*  CALLED BY                                                             */
71 /*                                                                        */
72 /*    _ux_pictbridge_object_parse                                         */
73 /*                                                                        */
74 /*  RELEASE HISTORY                                                       */
75 /*                                                                        */
76 /*    DATE              NAME                      DESCRIPTION             */
77 /*                                                                        */
78 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
79 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
80 /*                                            verified memset and memcpy  */
81 /*                                            cases,                      */
82 /*                                            resulting in version 6.1    */
83 /*                                                                        */
84 /**************************************************************************/
_ux_pictbridge_tag_name_get(UCHAR * input_buffer,ULONG input_length,UCHAR * tag_name,UCHAR * variable_name,UCHAR * variable_string,UCHAR * xml_parameter,UCHAR ** output_buffer,ULONG * output_length,ULONG * tag_flag)85 UINT  _ux_pictbridge_tag_name_get(UCHAR *input_buffer, ULONG input_length,
86                                   UCHAR *tag_name,
87                                   UCHAR *variable_name,
88                                   UCHAR *variable_string,
89                                   UCHAR *xml_parameter,
90                                   UCHAR **output_buffer, ULONG *output_length,
91                                   ULONG *tag_flag)
92 {
93 ULONG                   flag;
94 ULONG                   char_count;
95 UCHAR                   *tag_name_end;
96 UCHAR                   *variable_name_end;
97 UCHAR                   *variable_string_end;
98 UCHAR                   *xml_parameter_end;
99 
100     /* Reset the local flags.  */
101     flag = 0;
102 
103     /* Reset the caller's tag_flag.  */
104     *tag_flag = 0;
105 
106     /* Char count reset.  */
107     char_count = 0;
108 
109     /* Reset the tag name buffer.  */
110    _ux_utility_memory_set(tag_name, 0, UX_PICTBRIDGE_MAX_TAG_SIZE); /* Use case of memset is verified. */
111    tag_name_end = tag_name + UX_PICTBRIDGE_MAX_TAG_SIZE - 1;
112 
113     /* Reset the variable name buffer.  */
114    _ux_utility_memory_set(variable_name, 0, UX_PICTBRIDGE_MAX_VARIABLE_SIZE); /* Use case of memset is verified. */
115    variable_name_end = variable_name + UX_PICTBRIDGE_MAX_VARIABLE_SIZE - 1;
116 
117     /* Reset the variable string buffer.  */
118    _ux_utility_memory_set(variable_string, 0, UX_PICTBRIDGE_MAX_STRING_SIZE); /* Use case of memset is verified. */
119    variable_string_end = variable_string + UX_PICTBRIDGE_MAX_STRING_SIZE - 1;
120 
121     /* Reset the xml parameter.  */
122    _ux_utility_memory_set(xml_parameter, 0, UX_PICTBRIDGE_MAX_STRING_SIZE); /* Use case of memset is verified. */
123    xml_parameter_end = xml_parameter + UX_PICTBRIDGE_MAX_STRING_SIZE - 1;
124 
125     /* We parse the current xml tag line. We are now positioned at the "<". */
126     while(input_length)
127     {
128         /* Get a character from the tag line.  */
129         switch (*input_buffer)
130         {
131 
132             case    UX_PICTBRIDGE_TAG_CHAR_START_BRACKET  :
133 
134                 /* Check to see if we are within a quote.  */
135                 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_STRING)
136                 {
137 
138                     /* Yes, store the bracket in the string.  */
139                     if (variable_string > variable_string_end)
140                         return(UX_BUFFER_OVERFLOW);
141                     *variable_string++ = *input_buffer;
142 
143                     break;
144                 }
145 
146                 /* Check to see if we are already in the bracket.  */
147                 if (flag & UX_PICTBRIDGE_TAG_FLAG_BEGIN)
148 
149                     /* Yes, we have a syntax violation.  */
150                     return(UX_PICTBRIDGE_ERROR_PARAMETER_MISSING);
151 
152                 else
153                     /* Set the tag flag to start bracket. State machine is now in Tag. */
154                     flag |= (UX_PICTBRIDGE_TAG_FLAG_BEGIN | UX_PICTBRIDGE_TAG_FLAG_IN_TAG);
155 
156 
157                 break;
158 
159 
160             case    UX_PICTBRIDGE_TAG_CHAR_CR             :
161             case    UX_PICTBRIDGE_TAG_CHAR_LF             :
162 
163                 /* If we are in the middle of a <>, we have a format violation. If not, we may have an empty line. */
164                 if (flag & UX_PICTBRIDGE_TAG_FLAG_BEGIN)
165 
166                     /* We have a XML tag violation.  */
167                     return(UX_PICTBRIDGE_ERROR_PARAMETER_MISSING);
168                 else
169                     break;
170 
171             case    UX_PICTBRIDGE_TAG_CHAR_SPACE          :
172 
173                 /* If we are within a tag already, this masks the end.  If not, continue looking for
174                    an open bracket. */
175                 if ((flag & UX_PICTBRIDGE_TAG_FLAG_BEGIN) == 0)
176                     break;
177 
178                 /* Check to see if we are within a quote.  */
179                 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_STRING)
180                 {
181                     /* Yes, store the character.  */
182                     if (variable_string > variable_string_end)
183                         return(UX_BUFFER_OVERFLOW);
184                     *variable_string++ = UX_PICTBRIDGE_TAG_CHAR_SPACE;
185 
186                     break;
187                 }
188 
189                 /* If we are in the flag state machine. It marks the end of the flag and maybe the
190                    beginning of a variable.  */
191                 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_TAG)
192                 {
193 
194                     /* get out of tag state machine.  */
195                     flag &= (ULONG)~UX_PICTBRIDGE_TAG_FLAG_IN_TAG;
196 
197                     /* Change state machine to variable.  */
198                     flag |= (ULONG)UX_PICTBRIDGE_TAG_FLAG_IN_VARIABLE;
199 
200                 }
201                 break;
202 
203             case    UX_PICTBRIDGE_TAG_CHAR_EQUAL          :
204 
205                 /* If we are not within a bracket, this is a loose character ! */
206                 if ((flag & UX_PICTBRIDGE_TAG_FLAG_BEGIN) == 0)
207                     break;
208 
209                 /* Check to see if we are within a string.  */
210                 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_STRING)
211                 {
212                     /* Yes, store the character.  */
213                     if (variable_string > variable_string_end)
214                         return(UX_BUFFER_OVERFLOW);
215                     *variable_string++ = *input_buffer;
216 
217                     break;
218                 }
219 
220                 /* If we are in the flag state machine we have an error.  */
221                 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_TAG)
222 
223                     /* Error, we should have been in the variable state machine.  */
224                     return(UX_PICTBRIDGE_ERROR_PARAMETER_MISSING);
225 
226                 /* If we are in the variable state machine, change the state to expecting string.  */
227                 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_VARIABLE)
228                 {
229 
230                     /* Get out of the variable state machine.  */
231                     flag &= (ULONG)~UX_PICTBRIDGE_TAG_FLAG_IN_VARIABLE;
232 
233                     /* Change state machine to expecting string.  */
234                     flag |= UX_PICTBRIDGE_TAG_FLAG_EXPECTING_STRING;
235 
236                 }
237                 break;
238 
239             case    UX_PICTBRIDGE_TAG_CHAR_QUOTE          :
240 
241                 /* Are we in the string state machine ? */
242                 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_STRING)
243 
244                     /* Get out of the in string state machine.  We are out of any state now.  */
245                     flag &= (ULONG)~UX_PICTBRIDGE_TAG_FLAG_IN_STRING;
246 
247                 else
248                 {
249 
250                     /* Are we expecting a string ? */
251                     if (flag & UX_PICTBRIDGE_TAG_FLAG_EXPECTING_STRING)
252                     {
253 
254                         /* Get out of the expecting string state machine.  */
255                         flag &= (ULONG)~UX_PICTBRIDGE_TAG_FLAG_EXPECTING_STRING;
256 
257                         /* Change state machine to in string.  */
258                         flag |= UX_PICTBRIDGE_TAG_FLAG_IN_STRING;
259 
260                     }
261 
262                     else
263 
264                         /* Loose character ! */
265                         return(UX_PICTBRIDGE_ERROR_PARAMETER_MISSING);
266 
267                 }
268 
269                 break;
270 
271             case    UX_PICTBRIDGE_TAG_CHAR_SLASH          :
272 
273                 /* If we are in no particular state at the moment, we could have a begin slash or end slash.  */
274                 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_STRING)
275                 {
276 
277                     /* We are in the variable string state machine.  Store the "/" as a normal character. */
278                     if (variable_string > variable_string_end)
279                         return(UX_BUFFER_OVERFLOW);
280                     *variable_string++ = *input_buffer;
281 
282                     break;
283                 }
284                 /* Check other states.  */
285                 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_TAG)
286                 {
287 
288                     /* We are in a tag. 2 scenario here. We are either at the beginning or at the end.  */
289                     if (char_count != 0)
290 
291                         /* We are at the end of the tag, this is a self closing tag.  */
292                         *tag_flag |= UX_PICTBRIDGE_TAG_FLAG_SELF_CLOSING;
293 
294                     else
295 
296                         /* This is a normal closing tag.  */
297                         *tag_flag |= UX_PICTBRIDGE_TAG_FLAG_CLOSING;
298 
299                     /* We are done here.  */
300                     break;
301                 }
302 
303                 else
304                 {
305 
306                     /* If we are out of any state machine, it must be a self closing tag.  */
307                     if (flag & (UX_PICTBRIDGE_TAG_FLAG_IN_VARIABLE | UX_PICTBRIDGE_TAG_FLAG_EXPECTING_STRING))
308 
309                         /* This is a syntax error, abort.  */
310                         return(UX_PICTBRIDGE_ERROR_PARAMETER_MISSING);
311 
312                     else
313                     {
314                         /* We are at the end of the tag, this is a self closing tag.  */
315                         *tag_flag |= UX_PICTBRIDGE_TAG_FLAG_SELF_CLOSING;
316 
317                         /* We are done here.  */
318                         break;
319                     }
320 
321                 }
322 
323 
324             case    UX_PICTBRIDGE_TAG_CHAR_QUESTION_MARK          :
325 
326                 /* If we are in no particular state at the moment, we could have a begin ? or end ?.  */
327                 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_STRING)
328 
329                     /* We are within a quoted string, do not proceed.  */
330                     break;
331 
332                 else
333 
334                     /* This is a comment line, no need for a closing tag.  */
335                     *tag_flag |= UX_PICTBRIDGE_TAG_FLAG_COMMENT;
336 
337                 break;
338 
339             case    UX_PICTBRIDGE_TAG_CHAR_END_BRACKET    :
340 
341                 /* If we are in no particular state at the moment, we could have a begin ? or end ?.  */
342                 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_STRING)
343                 {
344 
345                     /* Yes, store the bracket in the string.  */
346                     if (variable_string > variable_string_end)
347                         return(UX_BUFFER_OVERFLOW);
348                     *variable_string++ = *input_buffer;
349 
350                     break;
351                 }
352 
353                 /* Check if we are within a bracket.  */
354                 if (flag & UX_PICTBRIDGE_TAG_FLAG_BEGIN)
355                 {
356 
357                     /* Skip the closing bracket.  */
358                     input_buffer++;
359 
360                     /* Update length.  */
361                     input_length--;
362 
363                     /* We may have a xml parameter between the current tag and its closing counterpart. */
364                     while(input_length)
365                     {
366 
367                         /* Get a character between the tag brackets.  */
368                         switch (*input_buffer)
369                         {
370 
371                             case    UX_PICTBRIDGE_TAG_CHAR_CR             :
372                             case    UX_PICTBRIDGE_TAG_CHAR_LF             :
373 
374                                 /* Skip potential CR/LF.  */
375                                 break;
376 
377 
378                             case    UX_PICTBRIDGE_TAG_CHAR_START_BRACKET    :
379 
380                                 /* We have found the beginning of the next tag.
381                                    Set the output buffer position to the next "<".  */
382                                 *output_buffer = input_buffer;
383 
384                                 /* Set the length remaining.  */
385                                 *output_length = input_length;
386 
387                                 /* We are done here.  */
388                                 return(UX_SUCCESS);
389 
390                             default :
391 
392                                 /* Whatever we have now, we store into the XML parameter.  */
393                                 if (xml_parameter > xml_parameter_end)
394                                     return(UX_BUFFER_OVERFLOW);
395                                 *xml_parameter++ = *input_buffer;
396                                 break;
397 
398                         }
399 
400                         /* Next position.  */
401                         input_buffer++;
402 
403                         /* Update length.  */
404                         input_length--;
405 
406                     }
407 
408                     /* Set the output buffer position.  */
409                     *output_buffer = input_buffer;
410 
411                     /* Set the length remaining.  */
412                     *output_length = input_length;
413 
414                     /* We have reached the end of the xml object.  */
415                     return(UX_SUCCESS);
416 
417                 }
418                 else
419 
420                     /* We have a syntax error.  */
421                     return(UX_PICTBRIDGE_ERROR_SCRIPT_SYNTAX_ERROR);
422 
423             default :
424 
425                 /* Check if we are within a bracket.  */
426                 if (flag & UX_PICTBRIDGE_TAG_FLAG_BEGIN)
427 
428                     /* Yes, increase the char count. This will tell us
429                        if we are at the beginning of a tag or at the end.  */
430                     char_count++;
431 
432                 /* We have a regular character. Store it in the current state machine.  */
433                 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_TAG)
434                 {
435                     /* We are in the tag state machine.  */
436                     if (tag_name > tag_name_end)
437                         return(UX_BUFFER_OVERFLOW);
438                     *tag_name++ = *input_buffer;
439                 }
440 
441                 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_VARIABLE)
442                 {
443                     /* We are in the variable state machine.  */
444                     if (variable_name > variable_name_end)
445                         return(UX_BUFFER_OVERFLOW);
446                     *variable_name++ = *input_buffer;
447                 }
448 
449                 if (flag & UX_PICTBRIDGE_TAG_FLAG_IN_STRING)
450                 {
451                     /* We are in the variable string state machine.  */
452                     if (variable_string > variable_string_end)
453                         return(UX_BUFFER_OVERFLOW);
454                     *variable_string++ = *input_buffer;
455                 }
456 
457                 break;
458 
459         }
460 
461         /* Next position.  */
462         input_buffer++;
463 
464         /* Update length.  */
465         input_length--;
466 
467     }
468 
469     /* We get here when we reached an unexpected end of the XML object.
470        if we had a begin bracket, there is an unexpected end. If not, we
471        have an empty line.  */
472     if (flag & UX_PICTBRIDGE_TAG_FLAG_BEGIN)
473 
474         /* We have an error.  */
475         return(UX_PICTBRIDGE_ERROR_PARAMETER_MISSING);
476 
477     else
478 
479         /* Not really an error, but we need to inform the caller there is no tag to process.  */
480         return(UX_PICTBRIDGE_ERROR_EMPTY_LINE);
481 
482 }
483 
484