VLC  4.0.0-dev
mrl_helpers.h
Go to the documentation of this file.
1 /*****************************************************************************
2  * mrl_helpers.h
3  *****************************************************************************
4  * Copyright (C) 2016 VLC authors and VideoLAN
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20 
21 #ifndef INPUT_MRL_HELPERS_H
22 #define INPUT_MRL_HELPERS_H
23 
24 #include <string.h>
25 #include <stdlib.h>
26 
27 #include <vlc_common.h>
28 #include <vlc_memstream.h>
29 #include <vlc_arrays.h>
30 #include <vlc_url.h>
31 
32 /**
33  * \defgroup mrl_helpers MRL helpers
34  * \ingroup mrl
35  *
36  * Helper functions related to parsing, as well as generating, data
37  * related to the \link MRL-specification\endlink.
38  *
39  * @{
40  * \file
41  **/
42 
43 /**
44  * Escape a fragment identifier for use within an MRL
45  *
46  * The function will generate a string that follows the \link mrl
47  * MRL-specification\endlink regarding \em fragment-identifiers.
48  *
49  * See the \link mrl MRL-specification\endlink for a detailed
50  * explanation of how `payload` will be escaped.
51  *
52  * \param[out] out `*out` will refer to the created string on success,
53  * and an unspecified value on error.
54  * \param[in] payload the data to escape.
55  * \return VLC_SUCCESS on success, an error-code on failure.
56  **/
57 static inline int
58 mrl_EscapeFragmentIdentifier( char** out, char const* payload )
59 {
60  struct vlc_memstream mstream;
61 
62 #define RFC3986_SUBDELIMS "!" "$" "&" "'" "(" ")" \
63  "*" "+" "," ";" "="
64 #define RFC3986_ALPHA "abcdefghijklmnopqrstuvwxyz" \
65  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
66 #define RFC3986_DIGIT "0123456789"
67 #define RFC3986_UNRESERVED RFC3986_ALPHA RFC3986_DIGIT "-" "." "_" "~"
68 #define RFC3986_PCHAR RFC3986_UNRESERVED RFC3986_SUBDELIMS ":" "@"
69 #define RFC3986_FRAGMENT RFC3986_PCHAR "/" "?"
70 
71  if( vlc_memstream_open( &mstream ) )
72  return VLC_EGENERIC;
73 
74  for( char const* p = payload; *p; ++p )
75  {
76  vlc_memstream_printf( &mstream,
77  ( strchr( "!?", *p ) == NULL &&
78  strchr( RFC3986_FRAGMENT, *p ) ? "%c" : "%%%02hhx"), *p );
79  }
80 
81 #undef RFC3986_FRAGMENT
82 #undef RFC3986_PCHAR
83 #undef RFC3986_UNRESERVEd
84 #undef RFC3986_DIGIT
85 #undef RFC3986_ALPHA
86 #undef RFC3986_SUBDELIMS
87 
88  if( vlc_memstream_close( &mstream ) )
89  return VLC_EGENERIC;
90 
91  *out = mstream.ptr;
92  return VLC_SUCCESS;
93 }
94 
95 /**
96  * Split an \link mrl_technical_fragment MRL-fragment\endlink into identifiers
97  *
98  * Function used to split the fragment-data (also referred to as
99  * anchor-data) into an array containing each of the files specified.
100  *
101  * See the \link mrl MRL-specification\endlink for detailed
102  * information regarding how `payload` will be interpreted.
103  *
104  * \warning On success, the caller has ownership of the contents of *out_items
105  * which means that it is responsible for freeing the individual
106  * elements, as well as cleaning the array itself.
107  *
108  * \param[out] out_items storage for a vlc_array_t that will contain the
109  * parsed identifiers on success.
110  * \param[out] out_extra `*out_extra` will point to any remaining data (if any)
111  * \param[in] payload the data to parse
112  * \return VLC_SUCCESS on success, an error-code on failure
113  **/
114 static inline int
116  char const** out_extra,
117  char const* payload )
118 {
119  char const* extra = NULL;
120 
121  vlc_array_init( out_items );
122 
123  while( strncmp( payload, "!/", 2 ) == 0 )
124  {
125  payload += 2;
126 
127  int len = strcspn( payload, "!?" );
128  char* decoded = strndup( payload, len );
129 
130  if( unlikely( !decoded ) || !vlc_uri_decode( decoded ) )
131  goto error;
132 
133  if( vlc_array_append( out_items, decoded ) )
134  {
135  free( decoded );
136  goto error;
137  }
138  payload += len;
139  }
140 
141  if( *payload )
142  {
143  if( *payload == '!' )
144  goto error;
145 
146  if( *payload == '?' && vlc_array_count( out_items ) )
147  ++payload;
148 
149  extra = payload;
150  }
151 
152  *out_extra = extra;
153  return VLC_SUCCESS;
154 
155 error:
156  for( size_t i = 0; i < vlc_array_count( out_items ); ++i )
157  free( vlc_array_item_at_index( out_items, i ) );
158  vlc_array_clear( out_items );
159  return VLC_EGENERIC;;
160 }
161 
162 /*
163  * @}
164  **/
165 
166 #endif /* include-guard */
char * ptr
Buffer start address.
Definition: vlc_memstream.h:48
static void vlc_array_init(vlc_array_t *p_array)
Definition: vlc_arrays.h:264
static size_t vlc_array_count(vlc_array_t *p_array)
Definition: vlc_arrays.h:277
This file is a collection of common definitions and types.
This file defines functions for manipulating URL in vlc.
In-memory stream object.
Definition: vlc_memstream.h:41
char * strndup(const char *, size_t)
Definition: vlc_arrays.h:258
int vlc_memstream_open(struct vlc_memstream *ms)
Initializes a byte stream object.
Definition: memstream.c:105
int error
Definition: vlc_memstream.h:46
#define VLC_SUCCESS
No error.
Definition: vlc_common.h:470
#define unlikely(p)
Predicted false condition.
Definition: vlc_common.h:223
int vlc_memstream_printf(struct vlc_memstream *ms, const char *fmt,...)
Appends a formatted string to a byte stream.
Definition: memstream.c:194
static int mrl_EscapeFragmentIdentifier(char **out, char const *payload)
Escape a fragment identifier for use within an MRL.
Definition: mrl_helpers.h:58
char * vlc_uri_decode(char *str)
Decodes an URI component in place.
Definition: url.c:54
static int mrl_FragmentSplit(vlc_array_t *out_items, char const **out_extra, char const *payload)
Split an MRL-fragment into identifiers.
Definition: mrl_helpers.h:115
#define VLC_EGENERIC
Unspecified error.
Definition: vlc_common.h:472
static int vlc_array_append(vlc_array_t *ar, void *elem)
Definition: vlc_arrays.h:335
#define p(t)
int vlc_memstream_close(struct vlc_memstream *ms)
Closes a byte stream object.
Definition: memstream.c:120
#define RFC3986_FRAGMENT
This file defines functions, structures and macros for handling arrays in vlc.
#define vlc_array_item_at_index(ar, idx)
Definition: vlc_arrays.h:283
static void vlc_array_clear(vlc_array_t *p_array)
Definition: vlc_arrays.h:270