2 Copyright (C) 2006 by Jonas Kramer
3 Published under the terms of the GNU General Public License (GPL).
17 extern void purge(char **);
19 static void append(char **, unsigned *, const char *);
20 static void sparam(char **, unsigned *, const char *);
21 static void aparam(char **, unsigned *, const char **);
22 char * xmlize(const char *);
24 int xmlrpc(const char * method
, const char * fmt
, ...) {
25 unsigned size
= 1024, narg
, x
;
26 const unsigned char * md5
;
32 ** resp
, * url
= "http://ws.audioscrobbler.com/1.0/rw/xmlrpc.php",
33 md5hex
[32 + 1] = { 0 }, tmp
[32 + 8 + 1] = { 0 };
38 * challenge
= "Shell.FM",
40 "<?xml version=\"1.0\"?>\n"
42 "\t<methodName>%s</methodName>\n"
46 /* generate password/challenge hash */
47 snprintf(tmp
, sizeof(tmp
), "%s%s", value(& rc
, "password"), challenge
);
48 md5
= MD5((unsigned char *) tmp
, sizeof(tmp
) - 1);
49 for(x
= 0; x
< 16; ++x
)
50 sprintf(2 * x
+ md5hex
, "%02x", md5
[x
]);
53 memset(xml
, (char) 0, size
);
55 snprintf(xml
, size
, xmlhead
, method
);
57 sparam(& xml
, & size
, value(& rc
, "username"));
58 sparam(& xml
, & size
, challenge
);
59 sparam(& xml
, & size
, md5hex
);
61 for(narg
= 0; narg
< strlen(fmt
); ++narg
) {
62 const char * string
, ** array
;
65 case 's': /* string */
66 string
= va_arg(argv
, const char *);
67 sparam(& xml
, & size
, string
);
71 array
= va_arg(argv
, const char **);
72 aparam(& xml
, & size
, array
);
77 append(& xml
, & size
, "\t</params>\n</methodCall>\n");
79 if((resp
= fetch(url
, NULL
, xml
, "text/xml")) != NULL
) {
80 for(x
= 0; resp
[x
]; ++x
) {
81 if(strstr(resp
[x
], ">OK<") != NULL
)
94 static void append(char ** string
, unsigned * size
, const char * appendix
) {
95 if(string
&& size
&& appendix
) {
98 * size
= strlen(* string
) + strlen(appendix
) + 1;
99 copy
= realloc(* string
, * size
);
101 assert(copy
!= NULL
);
104 fputs("Out of memory!\n", stderr
);
106 strcat(copy
, appendix
);
107 copy
[(* size
) - 1] = 0;
114 static void sparam(char ** xml
, unsigned * size
, const char * param
) {
115 if(xml
&& size
&& param
) {
116 char * encoded
= xmlize(param
);
117 append(xml
, size
, "\t\t<param><value><string>");
118 append(xml
, size
, encoded
);
119 append(xml
, size
, "</string></value></param>\n");
125 static void aparam(char ** xml
, unsigned * size
, const char ** param
) {
129 append(xml
, size
, "\t\t<param><value><array><data>");
131 for(n
= 0; param
&& param
[n
] != NULL
; ++n
) {
132 char * encoded
= xmlize(param
[n
]);
133 append(xml
, size
, "<value><string>");
134 append(xml
, size
, encoded
);
135 append(xml
, size
, "</string></value>");
139 append(xml
, size
, "</data></array></value></param>\n");
143 char * xmlize(const char * orig
) {
144 register unsigned i
= 0, x
= 0;
145 char * encoded
= calloc((strlen(orig
) * 6) + 1, sizeof(char));
147 assert(encoded
!= NULL
);
149 while(i
< strlen(orig
)) {
150 if(strchr("&<>'\"", orig
[i
])) {
153 strlen(orig
) * 6 - strlen(encoded
) + 1,
160 encoded
[x
++] = orig
[i
];