Initial patch to allow support for RFC 2868 Tagged Attributes.
[freeradius.git] / src / lib / print.c
1 /*
2  * print.c      Routines to print stuff.
3  *
4  * Version:     $Id$
5  *
6  */
7
8 static const char rcsid[] = "$Id$";
9
10 #include        "autoconf.h"
11
12 #include        <stdio.h>
13 #include        <stdlib.h>
14 #include        <sys/types.h>
15 #include        <ctype.h>
16 #include        <string.h>
17
18 #include        "libradius.h"
19
20 /*
21  *      Convert a string to something printable.
22  *      The output string has to be _at least_ 4x the size
23  *      of the input string!
24  */
25 void librad_safeprint(char *in, int inlen, char *out, int outlen)
26 {
27         unsigned char   *str = (unsigned char *)in;
28         int             done = 0;
29         int             sp = 0;
30
31         if (inlen < 0) inlen = strlen(in);
32
33         while (inlen-- > 0 && (done + 3) < outlen) {
34                 /*
35                  *      Hack: never print trailing zero.
36                  *      Some clients send strings with an off-by-one
37                  *      length (confused with strings in C).
38                  */
39                 if (inlen == 0 && *str == 0)
40                         break;
41
42                 sp = 0;
43
44                 switch (*str) {
45                         case '\\':
46                                 sp = '\\';
47                                 break;
48                         case '\r':
49                                 sp = 'r';
50                                 break;
51                         case '\n':
52                                 sp = 'n';
53                                 break;
54                         case '\t':
55                                 sp = 't';
56                                 break;
57                         default:
58                                 if (*str < 32 || (*str >= 128)){
59                                         snprintf(out, outlen, "\\%03o", *str);
60                                         done += 4;
61                                         out  += 4;
62                                         outlen -= 4;
63                                 } else {
64                                         *out++ = *str;
65                                         outlen--;
66                                         done++;
67                                 }
68                 }
69                 if (sp) {
70                         *out++ = '\\';
71                         *out++ = sp;
72                         outlen -= 2;
73                         done += 2;
74                 }
75                 str++;
76         }
77         *out = 0;
78 }
79
80
81 /*
82  *  Print one value into a string.
83  *  delimitst will define if strings and dates will be delimited by '"'
84  */
85 int vp_prints_value(char * out, int outlen, VALUE_PAIR *vp, int delimitst)
86 {
87         DICT_VALUE  *v;
88         char        buf[1024];
89         char        *a;
90         time_t      t;
91
92         out[0] = 0;
93         if (!vp) return 0;
94
95         switch (vp->type) {
96                 case PW_TYPE_STRING:
97                         if (vp->attribute == PW_NAS_PORT_ID)
98                                 a = (char *)vp->strvalue;
99                         else {
100                                 if (delimitst && vp->flags.has_tag) {
101                                         /* Tagged attribute: print delimter and ignore tag */
102                                         buf[0] = '"';
103                                         librad_safeprint((char *)(vp->strvalue),
104                                                          vp->length, buf + 1, sizeof(buf) - 2);
105                                         strcat(buf, "\"");
106                                 } else if (delimitst) {
107                                         /* Non-tagged attribute: print delimter */
108                                         buf[0] = '"';
109                                         librad_safeprint((char *)vp->strvalue,
110                                                          vp->length, buf + 1, sizeof(buf) - 2);
111                                         strcat(buf, "\"");
112                                 } else {
113                                         /* Non-tagged attribute: no delimiter */
114                                         librad_safeprint((char *)vp->strvalue,
115                                                          vp->length, buf, sizeof(buf));
116                                 }
117                                 a = buf;
118                         }
119                         break;
120                 case PW_TYPE_INTEGER:
121                         if ( vp->flags.has_tag ) {
122                                 /* Attribute value has a tag, need to ignore it */
123                                 if ((v = dict_valbyattr(vp->attribute, (vp->lvalue & 0xffffff)))
124                                     != NULL)
125                                         a = v->name;
126                                 else {
127                                         snprintf(buf, sizeof(buf), "%u", (vp->lvalue & 0xffffff));
128                                         a = buf;
129                                 }
130                         } else {
131                                 /* Normal, non-tagged attribute */
132                                 if ((v = dict_valbyattr(vp->attribute, vp->lvalue))
133                                     != NULL)
134                                         a = v->name;
135                                 else {
136                                         snprintf(buf, sizeof(buf), "%u", vp->lvalue);
137                                         a = buf;
138                                 }
139                         }
140                         break;
141                 case PW_TYPE_DATE:
142                         t = vp->lvalue;
143                         if (delimitst) {
144                           strftime(buf, sizeof(buf), "\"%b %e %Y\"", gmtime(&t));
145                         } else {
146                           strftime(buf, sizeof(buf), "%b %e %Y", gmtime(&t));
147                         }
148                         a = buf;
149                         break;
150                 case PW_TYPE_IPADDR:
151                         if (vp->strvalue[0])
152                                 a = (char *)vp->strvalue;
153                         else
154                                 a = ip_hostname((char *)vp->strvalue,
155                                                 sizeof(vp->strvalue),
156                                                 vp->lvalue);
157                         break;
158                 case PW_TYPE_ABINARY:
159 #ifdef ASCEND_BINARY
160                   a = buf;
161                   print_abinary(vp, (unsigned char *)buf, sizeof(buf));
162                   break;
163 #else
164                   /* FALL THROUGH */
165 #endif
166                 case PW_TYPE_OCTETS:
167                   strcpy(buf, "0x");
168                   a = buf + 2;
169                   for (t = 0; t < vp->length; t++) {
170                         sprintf(a, "%02x", vp->strvalue[t]);
171                         a += 2;
172                   }
173                   a = buf;
174                   break;
175
176                 default:
177                         a = 0;
178                         break;
179         }
180         strNcpy(out, a?a:"UNKNOWN-TYPE", outlen);
181         
182         return strlen(out);
183 }
184
185
186 /*
187  *      Print one attribute and value into a string.
188  */
189 int vp_prints(char *out, int outlen, VALUE_PAIR *vp)
190 {
191         int             len;
192
193         out[0] = 0;
194         if (!vp) return 0;
195
196         if (strlen(vp->name) + 3 > (size_t)outlen) {
197                 return 0;
198         }
199
200         if( vp->flags.has_tag ) {
201
202 #ifdef MERIT_STYLE_TAGS
203                 snprintf(out, outlen, "%s = :%d:", vp->name, vp->flags.tag);
204 #else
205                 snprintf(out, outlen, "%s:%d = ", vp->name, vp->flags.tag);
206 #endif
207                 
208                 len = strlen(out);
209                 vp_prints_value(out + len, outlen - len, vp, 1);
210
211         } else {
212
213                 snprintf(out, outlen, "%s = ", vp->name);
214                 len = strlen(out);
215                 vp_prints_value(out + len, outlen - len, vp, 1);
216
217         }         
218
219         return strlen(out);
220 }
221
222
223 /*
224  *      Print one attribute and value.
225  */
226 void vp_print(FILE *fp, VALUE_PAIR *vp)
227 {
228         char    buf[1024];
229
230         vp_prints(buf, sizeof(buf), vp);
231         fputs(buf, fp);
232 }
233
234
235 /*
236  *      Print a whole list of attributes, indented by a TAB
237  *      and with a newline at the end.
238  */
239 void vp_printlist(FILE *fp, VALUE_PAIR *vp)
240 {
241         for (; vp; vp = vp->next) {
242                 fprintf(fp, "\t");
243                 vp_print(fp, vp);
244                 fprintf(fp, "\n");
245         }
246 }
247