How about:<br>
<br>
const audioscrobbler_param_t **p1 = elt1, **p2 = elt2;<br>
<br>
return strcmp((*p1)->key, (*p2)->key) ?<br>
<br>I'm sorry but I got a warning with that.<br><br>audioscrobbler.c: In function 'Sort':<br>audioscrobbler.c:514:35: warning: initialization discards 'const' qualifier from pointer target type [enabled by default]<br>

audioscrobbler.c:514:48: warning: initialization discards 'const' qualifier from pointer target type [enabled by default]<br><br>I think, the cast in sort() is a little weird but it works fine and I get no warnings with the existing code.<br>

<br><div class="gmail_quote">On Thu, Mar 8, 2012 at 5:35 PM, Rafaël Carré <span dir="ltr"><<a href="mailto:funman@videolan.org">funman@videolan.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

Le 2012-03-08 04:01, Samuel Pitoiset a écrit :<br>
<div class="im">>> +/****************************<br>
> *************************************************<br>
>> + * Sort: sort alphabetically the parameters list<br>
>> +<br>
> *****************************************************************************/<br>
>> +static int Sort(const void *elt1, const void *elt2)<br>
>> +{<br>
>> +    const audioscrobbler_param_t *p1 = elt1, *p2 = elt2;<br>
><br>
> Probably one * missing, i think Sort is called with<br>
> audioscrobbler_param_t** as argument. (pp_elem+i)<br>
><br>
>> +    return strcmp(*(char * const *) p1->key, *(char * const *) p2->key);<br>
><br>
> Probably one * too much and the type is not valid (see man strcmp)<br>
><br>
> I'm sorry, but qsort() needs the prototype int(*compar)(const void *, const<br>
> void *) (man qsort).<br>
><br>
> And the cast seems to be correct because I took this part of code in the<br>
> manpage of qsort() and I got no warnings during compilation.<br>
<br>
</div>How about:<br>
<br>
const audioscrobbler_param_t **p1 = elt1, **p2 = elt2;<br>
<br>
return strcmp((*p1)->key, (*p2)->key) ?<br>
<div class="im"><br>
>> +    /* build the api signature */<br>
>> +    p_param = p_params->pp_elems[0];<br>
>> +    sprintf(psz_api_sig, "%s%s", p_param->key, p_param->val);<br>
><br>
> *psz_api_sig = '\0'; and put this one inside the loop below.<br>
><br>
> I don't understand why this is needed, could you explain, please?<br>
<br>
</div>This could use strcat like the other strings in the loop.<br>
strcat needs a valid string to append to, so a string of length 0 will do.<br>
<div class="im"><br>
>> +    /* compute the length of the request */<br>
>> +    i_len += 9; /* for http:// */<br>
<br>
> That's 7 according to the comment.<br>
><br>
> Indeed.<br>
><br>
> Btw did you run this through valgrind to catch possible errors?<br>
><br>
> No, but I tried to check each malloc/free by reading the code a lot.<br>
><br>
> I'll run some tests with valgrind.<br>
<br>
</div>Don't forget to use valgrind's --leak-check<br>
<div class="HOEnZb"><div class="h5"><br>
><br>
> On Thu, Mar 8, 2012 at 1:16 AM, Rafaël Carré <<a href="mailto:funman@videolan.org">funman@videolan.org</a>> wrote:<br>
><br>
>> Le 2012-03-07 17:03, Samuel Pitoiset a écrit :<br>
>>> ---<br>
>>>  modules/misc/audioscrobbler.c |  501<br>
>> ++++++++++++++++++++++++++++++++++++++++-<br>
>>>  1 file changed, 500 insertions(+), 1 deletion(-)<br>
>>><br>
>>> diff --git a/modules/misc/audioscrobbler.c<br>
>> b/modules/misc/audioscrobbler.c<br>
>>> index e45c815..ddcc284 100644<br>
>>> --- a/modules/misc/audioscrobbler.c<br>
>>> +++ b/modules/misc/audioscrobbler.c<br>
>>> @@ -48,12 +48,15 @@<br>
>>>  #include <vlc_url.h><br>
>>>  #include <vlc_network.h><br>
>>>  #include <vlc_playlist.h><br>
>>> +#include <vlc_xml.h><br>
>>><br>
>>><br>
>>  /*****************************************************************************<br>
>>>   * Local prototypes<br>
>>><br>
>> *****************************************************************************/<br>
>>><br>
>>>  #define QUEUE_MAX 50<br>
>>> +#define API_KEY "c18676d0f607b5a583ac599c4b87baea"<br>
>>> +#define API_SECRET "bd0fe9ce1ec320324e2a035cc669e5ad"<br>
>>><br>
>>>  /* Keeps track of metadata to be submitted */<br>
>>>  typedef struct audioscrobbler_song_t<br>
>>> @@ -68,6 +71,20 @@ typedef struct audioscrobbler_song_t<br>
>>>      mtime_t     i_start;            /**< playing start    */<br>
>>>  } audioscrobbler_song_t;<br>
>>><br>
>>> +/* Keeps parameters to be submitted */<br>
>>> +typedef struct audioscrobbler_param_t<br>
>>> +{<br>
>>> +    const char *key;<br>
>>> +    const char *val;<br>
>>> +} audioscrobbler_param_t;<br>
>>> +<br>
>>> +/* Type of HTTP request */<br>
>>> +typedef enum<br>
>>> +{<br>
>>> +    GET,<br>
>>> +    POST<br>
>>> +} audioscrobbler_request_t;<br>
>>> +<br>
>>>  struct intf_sys_t<br>
>>>  {<br>
>>>      audioscrobbler_song_t   p_queue[QUEUE_MAX]; /**< songs not<br>
>> submitted yet*/<br>
>>> @@ -133,7 +150,7 @@ vlc_module_begin ()<br>
>>>                  USERNAME_TEXT, USERNAME_LONGTEXT, false)<br>
>>>      add_password("lastfm-password", "",<br>
>>>                  PASSWORD_TEXT, PASSWORD_LONGTEXT, false)<br>
>>> -    add_string("scrobbler-url", "<a href="http://post.audioscrobbler.com" target="_blank">post.audioscrobbler.com</a>",<br>
>>> +    add_string("scrobbler-url", "<a href="http://ws.audioscrobbler.com/2.0" target="_blank">ws.audioscrobbler.com/2.0</a>",<br>
>>>                  URL_TEXT, URL_LONGTEXT, false)<br>
>>>      set_capability("interface", 0)<br>
>>>      set_callbacks(Open, Close)<br>
>>> @@ -460,6 +477,488 @@ static void Close(vlc_object_t *p_this)<br>
>>>  }<br>
>>><br>
>>><br>
>>  /*****************************************************************************<br>
>>> + * BuildAuthToken: generate the authentication token<br>
>>> +<br>
>> *****************************************************************************/<br>
>>> +static char *BuildAuthToken(const char *psz_username, const char<br>
>> *psz_password)<br>
>>> +{<br>
>>> +    char *psz_password_md5, *psz_auth_token_md5;<br>
>>> +    struct md5_s p_struct_md5;<br>
>>> +<br>
>>> +    /* generate a md5 hash of the password */<br>
>>> +    InitMD5(&p_struct_md5);<br>
>>> +    AddMD5(&p_struct_md5, (uint8_t*) psz_password,<br>
>> strlen(psz_password));<br>
>>> +    EndMD5(&p_struct_md5);<br>
>>> +<br>
>>> +    psz_password_md5 = psz_md5_hash(&p_struct_md5);<br>
>>> +    if (!psz_password_md5)<br>
>>> +        return NULL;<br>
>>> +<br>
>>> +    /* generate a md5 hash of :<br>
>>> +     * - username in clear text, plus<br>
>>> +     * - md5 hash of the password<br>
>>> +     */<br>
>>> +    InitMD5(&p_struct_md5);<br>
>>> +    AddMD5(&p_struct_md5, (uint8_t*) psz_username,<br>
>> strlen(psz_username));<br>
>>> +    AddMD5(&p_struct_md5, (uint8_t*) psz_password_md5, 32);<br>
>>> +    EndMD5(&p_struct_md5);<br>
>>> +<br>
>>> +    free(psz_password_md5);<br>
>>> +<br>
>>> +    psz_auth_token_md5 = psz_md5_hash(&p_struct_md5);<br>
>><br>
>>> +    if (!psz_auth_token_md5)<br>
>>> +        return NULL;<br>
>><br>
>> Not needed, the case is handled below.<br>
>><br>
>>> +    return psz_auth_token_md5;<br>
>>> +}<br>
>>> +<br>
>>><br>
>> +/*****************************************************************************<br>
>>> + * Sort: sort alphabetically the parameters list<br>
>>> +<br>
>> *****************************************************************************/<br>
>>> +static int Sort(const void *elt1, const void *elt2)<br>
>>> +{<br>
>>> +    const audioscrobbler_param_t *p1 = elt1, *p2 = elt2;<br>
>><br>
>> Probably one * missing, i think Sort is called with<br>
>> audioscrobbler_param_t** as argument. (pp_elem+i)<br>
>><br>
>>> +    return strcmp(*(char * const *) p1->key, *(char * const *) p2->key);<br>
>><br>
>> Probably one * too much and the type is not valid (see man strcmp)<br>
>><br>
>>> +}<br>
>>> +<br>
>>><br>
>> +/*****************************************************************************<br>
>>> + * BuildApiSig: generate the api signature<br>
>>> +<br>
>> *****************************************************************************/<br>
>>> +static char *BuildApiSig(vlc_array_t *p_params, const char<br>
>> *psz_api_secret)<br>
>>> +{<br>
>>> +    char *psz_api_sig, *psz_api_sig_md5;<br>
>>> +    audioscrobbler_param_t *p_param;<br>
>>> +    struct md5_s p_struct_md5;<br>
>>> +    ssize_t i_len = 0;<br>
>>> +    int i;<br>
>><br>
>> nitpicking: you can put the i inside the for (C99)<br>
>><br>
>>> +<br>
>>> +    /* parameters must be sorted alphabetically */<br>
>>> +    qsort(p_params->pp_elems, p_params->i_count,<br>
>> sizeof(audioscrobbler_param_t*),<br>
>>> +            Sort);<br>
>>> +<br>
>>> +    /* compute the length of the api signature */<br>
>>> +    for (i = 0; i < p_params->i_count; i++)<br>
>>> +    {<br>
>>> +        p_param = p_params->pp_elems[i];<br>
>>> +        i_len += strlen(p_param->key) + strlen(p_param->val);<br>
>>> +    }<br>
>>> +<br>
>>> +    i_len += 32; /* md5 hash of the api secret */<br>
>>> +<br>
>>> +    psz_api_sig = malloc(i_len);<br>
>>> +    if (!psz_api_sig)<br>
>>> +        return NULL;<br>
>>> +<br>
>>> +    /* build the api signature */<br>
>>> +    p_param = p_params->pp_elems[0];<br>
>>> +    sprintf(psz_api_sig, "%s%s", p_param->key, p_param->val);<br>
>><br>
>> *psz_api_sig = '\0'; and put this one inside the loop below.<br>
>><br>
>>> +<br>
>>> +    for (i = 1; i < p_params->i_count; i++)<br>
>>> +    {<br>
>>> +        p_param = p_params->pp_elems[i];<br>
>>> +        strcat(psz_api_sig, p_param->key);<br>
>>> +        strcat(psz_api_sig, p_param->val);<br>
>>> +    }<br>
>>> +<br>
>>> +    /* concatenate the api secret key */<br>
>>> +    strcat(psz_api_sig, psz_api_secret);<br>
>>> +<br>
>>> +    /* generate a md5 hash of the api signature */<br>
>>> +    InitMD5(&p_struct_md5);<br>
>>> +    AddMD5(&p_struct_md5, (uint8_t*) psz_api_sig, strlen(psz_api_sig));<br>
>>> +    EndMD5(&p_struct_md5);<br>
>><br>
>> Hm wait you allocate and build that long string just to get the md5?<br>
>><br>
>> You can call AddMD5() repeatedly instead.<br>
>><br>
>>> +<br>
>>> +    psz_api_sig_md5 = psz_md5_hash(&p_struct_md5);<br>
>>> +    if (!psz_api_sig_md5)<br>
>>> +        return NULL;<br>
>>> +<br>
>>> +    return psz_api_sig_md5;<br>
>>> +}<br>
>>> +<br>
>>><br>
>> +/*****************************************************************************<br>
>>> + * AddParam: add a parameter to the list<br>
>>> +<br>
>> *****************************************************************************/<br>
>>> +static void AddParam(vlc_array_t *p_params, const char *psz_key,<br>
>>> +                    const char *psz_val)<br>
>>> +{<br>
>>> +    audioscrobbler_param_t *p_param =<br>
>> malloc(sizeof(audioscrobbler_param_t));<br>
>><br>
>> unchecked malloc<br>
>><br>
>>> +    p_param->key = psz_key;<br>
>>> +    p_param->val = psz_val;<br>
>>> +<br>
>>> +    vlc_array_append(p_params, p_param);<br>
>>> +}<br>
>>> +<br>
>>><br>
>> +/*****************************************************************************<br>
>>> + * BuildGetRequest: build an HTTP GET request<br>
>>> +<br>
>> *****************************************************************************/<br>
>>> +static char *BuildGetRequest(intf_thread_t *p_this, vlc_array_t<br>
>> *p_params)<br>
>>> +{<br>
>>> +    vlc_url_t p_submit_url = p_this->p_sys->p_submit_url;<br>
>>> +    audioscrobbler_param_t *p_param;<br>
>>> +    char *psz_request;<br>
>>> +    ssize_t i_len = 0;<br>
>>> +    int i;<br>
>>> +<br>
>>> +    /* compute the length of the request */<br>
>>> +    i_len += 9; /* for http:// */<br>
>><br>
>> That's 7 according to the comment.<br>
>><br>
>>> +    i_len += strlen(p_submit_url.psz_host) +<br>
>> strlen(p_submit_url.psz_path);<br>
>>> +    i_len += 2; /* for /? */<br>
>>> +<br>
>>> +    for (i = 0; i < p_params->i_count; i++)<br>
>>> +    {<br>
>>> +        p_param = p_params->pp_elems[i];<br>
>>> +        i_len += strlen(p_param->key) + strlen(p_param->val);<br>
>>> +        i_len += 2; /* for & and = */<br>
>>> +    }<br>
>>> +<br>
>>> +    psz_request = malloc(i_len);<br>
>>> +    if (!psz_request)<br>
>>> +        return NULL;<br>
>>> +<br>
>>> +    /* build the url */<br>
>>> +    p_param = p_params->pp_elems[0];<br>
>>> +    sprintf(psz_request, "http://%s%s/?%s=%s", p_submit_url.psz_host,<br>
>>> +            p_submit_url.psz_path, p_param->key, p_param->val);<br>
>>> +<br>
>>> +    for (i = 1; i < p_params->i_count; i++)<br>
>>> +    {<br>
>>> +        p_param = p_params->pp_elems[i];<br>
>>> +<br>
>>> +        strcat(psz_request, "&");<br>
>>> +        strcat(psz_request, p_param->key);<br>
>>> +        strcat(psz_request, "=");<br>
>>> +        strcat(psz_request, p_param->val);<br>
>>> +    }<br>
>>> +<br>
>>> +    return psz_request;<br>
>>> +}<br>
>>> +<br>
>>><br>
>> +/*****************************************************************************<br>
>>> + * BuildPostRequest: build an HTTP POST request<br>
>>> +<br>
>> *****************************************************************************/<br>
>>> +static char *BuildPostRequest(intf_thread_t *p_this, vlc_array_t<br>
>> *p_params)<br>
>>> +{<br>
>>> +    vlc_url_t p_submit_url = p_this->p_sys->p_submit_url;<br>
>>> +    audioscrobbler_param_t *p_param;<br>
>>> +    char *psz_data, *psz_request;<br>
>>> +    ssize_t i_len = 0;<br>
>>> +    int i;<br>
>>> +<br>
>>> +    /* compute the length of the request */<br>
>>> +    for (i = 0; i < p_params->i_count; i++)<br>
>>> +    {<br>
>>> +        p_param = p_params->pp_elems[i];<br>
>>> +        i_len += strlen(p_param->key) + strlen(p_param->val);<br>
>>> +        i_len += 2; /* for & and = */<br>
>>> +    }<br>
>>> +<br>
>>> +    psz_data = malloc(i_len);<br>
>>> +    if (!psz_data)<br>
>>> +        return NULL;<br>
>>> +<br>
>>> +    /* build the data */<br>
>>> +    p_param = p_params->pp_elems[0];<br>
>>> +    sprintf(psz_data, "%s=%s", p_param->key, p_param->val);<br>
>>> +<br>
>>> +    for (i = 1; i < p_params->i_count; i++)<br>
>>> +    {<br>
>>> +        p_param = p_params->pp_elems[i];<br>
>>> +<br>
>>> +        strcat(psz_data, "&");<br>
>>> +        strcat(psz_data, p_param->key);<br>
>>> +        strcat(psz_data, "=");<br>
>>> +        strcat(psz_data, p_param->val);<br>
>>> +    }<br>
>>> +<br>
>>> +    /* build the POST request */<br>
>>> +    if (asprintf(&psz_request,<br>
>>> +            "POST %s HTTP/1.1\n"<br>
>>> +            "Accept-Encoding: identity\n"<br>
>>> +            "Content-length: %zu\n"<br>
>>> +            "Connection: close\n"<br>
>>> +            "Content-type: application/x-www-form-urlencoded\n"<br>
>>> +            "Host: %s\n"<br>
>>> +            "User-agent: VLC media player/"VERSION"\r\n"<br>
>>> +            "\r\n"<br>
>>> +            "%s\r\n"<br>
>>> +            "\r\n",<br>
>>> +            p_submit_url.psz_path, strlen(psz_data),<br>
>>> +            p_submit_url.psz_host, psz_data<br>
>>> +    ) == -1)<br>
>>> +    {<br>
>>> +        /* out of memory */<br>
>>> +        free(psz_data);<br>
>>> +        return NULL;<br>
>>> +    }<br>
>>> +<br>
>>> +    free(psz_data);<br>
>>> +<br>
>>> +    return psz_request;<br>
>>> +}<br>
>>> +<br>
>>><br>
>> +/*****************************************************************************<br>
>>> + * BuildRequest : build an HTTP request<br>
>>> +<br>
>> *****************************************************************************/<br>
>>> +static char *BuildRequest(intf_thread_t *p_this, vlc_array_t *p_params,<br>
>>> +                            audioscrobbler_request_t e_type)<br>
>>> +{<br>
>>> +    char *psz_api_sig, *psz_request = NULL;<br>
>>> +<br>
>>> +    /* add the api key to the parameters list */<br>
>>> +    AddParam(p_params, "api_key", API_KEY);<br>
>>> +<br>
>>> +    /* generate the api signature */<br>
>>> +    psz_api_sig = BuildApiSig(p_params, API_SECRET);<br>
>>> +    if (!psz_api_sig)<br>
>>> +        return NULL;<br>
>>> +<br>
>>> +    /* add the api signature to the parameters list */<br>
>>> +    AddParam(p_params, "api_sig", psz_api_sig);<br>
>>> +<br>
>>> +    /* build the HTTP request */<br>
>>> +    switch (e_type)<br>
>>> +    {<br>
>>> +        case GET:<br>
>>> +            psz_request = BuildGetRequest(p_this, p_params);<br>
>>> +            break;<br>
>><br>
>> return BuildGetRequest(..) ?<br>
>><br>
>>> +        case POST:<br>
>>> +            psz_request = BuildPostRequest(p_this, p_params);<br>
>>> +            break;<br>
>><br>
>> idem<br>
>><br>
>>> +        default:<br>
>>> +            msg_Err(p_this, "invalid type of request %d", e_type);<br>
>>> +            break;<br>
>>> +    }<br>
>>> +<br>
>>> +    return psz_request;<br>
>>> +}<br>
>>> +<br>
>>><br>
>> +/*****************************************************************************<br>
>>> + * BuildSignedRequest : Build an HTTP request wich requires<br>
>> authentification<br>
>>> +<br>
>> *****************************************************************************/<br>
>>> +static char *BuildSignedRequest(intf_thread_t *p_this, vlc_array_t<br>
>> *p_params,<br>
>>> +                                 audioscrobbler_request_t e_type)<br>
>>> +{<br>
>>> +    /* add the session key to the parameters list */<br>
>>> +    AddParam(p_params, "sk", p_this->p_sys->psz_auth_token);<br>
>>> +<br>
>>> +    return BuildRequest(p_this, p_params, e_type);<br>
>>> +}<br>
>>> +<br>
>>><br>
>> +/*****************************************************************************<br>
>>> + * Handshake : Init audioscrobbler connection<br>
>>> +<br>
>> *****************************************************************************/<br>
>>> +static int NewHandshake(intf_thread_t *p_this)<br>
>>> +{<br>
>>> +    char                *psz_username, *psz_password, *psz_auth_token;<br>
>>> +    char                *psz_scrobbler_url, *psz_handshake_url;<br>
>>> +    const char          *node;<br>
>>> +    vlc_array_t         p_params;<br>
>>> +    stream_t            *p_stream;<br>
>>> +    xml_reader_t        *p_xml_reader       = NULL;<br>
>>> +    intf_thread_t       *p_intf             = (intf_thread_t*) p_this;<br>
>>> +    intf_sys_t          *p_sys              = p_this->p_sys;<br>
>>> +<br>
>>> +    /* get the username of the user */<br>
>>> +    psz_username = var_InheritString(p_this, "lastfm-username");<br>
>>> +    if (!psz_username)<br>
>>> +        return VLC_ENOMEM;<br>
>>> +<br>
>>> +    /* get the password of the user */<br>
>>> +    psz_password = var_InheritString(p_this, "lastfm-password");<br>
>>> +    if (!psz_password)<br>
>>> +    {<br>
>>> +        free(psz_username);<br>
>>> +        return VLC_ENOMEM;<br>
>>> +    }<br>
>>> +<br>
>>> +    /* username or password have not been setup */<br>
>>> +    if (!*psz_username || !*psz_password)<br>
>>> +    {<br>
>>> +        free(psz_username);<br>
>>> +        free(psz_password);<br>
>>> +        return VLC_ENOVAR;<br>
>>> +    }<br>
>>> +<br>
>>> +    /* generate the authentication token */<br>
>>> +    psz_auth_token = BuildAuthToken(psz_username, psz_password);<br>
>>> +    free(psz_password);<br>
>>> +<br>
>>> +    if (!psz_auth_token)<br>
>>> +    {<br>
>>> +        free(psz_username);<br>
>>> +        return VLC_ENOMEM;<br>
>>> +    }<br>
>>> +<br>
>>> +    /* get the submission url */<br>
>>> +    psz_scrobbler_url = var_InheritString(p_this, "scrobbler-url");<br>
>>> +    if (!psz_scrobbler_url)<br>
>>> +    {<br>
>>> +        free(psz_username);<br>
>>> +        free(psz_auth_token);<br>
>>> +        return VLC_ENOMEM;<br>
>>> +    }<br>
>>> +<br>
>>> +    /* parse the submission url */<br>
>>> +    vlc_UrlParse(&p_sys->p_submit_url, psz_scrobbler_url, 0);<br>
>>> +    free(psz_scrobbler_url);<br>
>>> +<br>
>>> +    /* build the parameters list */<br>
>>> +    vlc_array_init(&p_params);<br>
>>> +    AddParam(&p_params, "method", "auth.getMobileSession");<br>
>>> +    AddParam(&p_params, "authToken", psz_auth_token);<br>
>>> +    AddParam(&p_params, "username", psz_username);<br>
>>> +<br>
>>> +    /* build the http request */<br>
>>> +    psz_handshake_url = BuildRequest(p_this, &p_params, GET);<br>
>>> +    free(psz_username);<br>
>>> +    free(psz_auth_token);<br>
>>> +    vlc_array_clear(&p_params);<br>
>>> +<br>
>>> +    if (!psz_handshake_url)<br>
>>> +        return VLC_ENOMEM;<br>
>>> +<br>
>>> +    /* send the http request */<br>
>>> +    p_stream = stream_UrlNew(p_intf, psz_handshake_url);<br>
>>> +    free(psz_handshake_url);<br>
>>> +<br>
>>> +    if (!p_stream)<br>
>>> +        goto proto;<br>
>>> +<br>
>>> +    /* read answer */<br>
>>> +    p_xml_reader = xml_ReaderCreate(p_this, p_stream);<br>
>>> +    if (!p_xml_reader)<br>
>>> +        goto proto;<br>
>>> +<br>
>>> +    /* check root node */<br>
>>> +    if (xml_ReaderNextNode(p_xml_reader, &node) != XML_READER_STARTELEM)<br>
>>> +    {<br>
>>> +        msg_Err(p_this, "invalid file (no root node)");<br>
>>> +        goto proto;<br>
>>> +    }<br>
>>> +<br>
>>> +    if (strcasecmp(node, "lfm"))<br>
>>> +    {<br>
>>> +        msg_Err(p_this, "invalid root node <%s>", node);<br>
>>> +        goto proto;<br>
>>> +    }<br>
>>> +<br>
>>> +    /* check response status */<br>
>>> +    const char *attr, *value;<br>
>>> +    if ((attr = xml_ReaderNextAttr(p_xml_reader, &value)))<br>
>>> +    {<br>
>>> +        if (strcasecmp(attr, "status"))<br>
>>> +        {<br>
>>> +            msg_Err(p_this, "invalid attribute \"%s\"", attr);<br>
>>> +            goto proto;<br>
>>> +        }<br>
>>> +<br>
>>> +        if (strcasecmp(value, "ok"))<br>
>>> +        {<br>
>>> +            /* an error occured */<br>
>>> +            stream_Delete(p_stream);<br>
>>> +            xml_ReaderDelete(p_xml_reader);<br>
>>> +<br>
>>> +            if (!strcasecmp(value, "4"))<br>
>>> +            {<br>
>>> +                /* authentication failed, bad username/password<br>
>> combination */<br>
>>> +                dialog_Fatal(p_this,<br>
>>> +                    _("<a href="http://last.fm" target="_blank">last.fm</a>: Authentication failed"),<br>
>>> +                    "%s", _("<a href="http://last.fm" target="_blank">last.fm</a> username or password is<br>
>> incorrect. "<br>
>>> +                      "Please verify your settings and relaunch VLC."));<br>
>>> +                return VLC_AUDIOSCROBBLER_EFATAL;<br>
>>> +            }<br>
>>> +<br>
>>> +            if (!strcasecmp(value, "10"))<br>
>>> +            {<br>
>>> +                /* invalid API key */<br>
>>> +                dialog_Fatal(p_this,<br>
>>> +                    _("<a href="http://last.fm" target="_blank">last.fm</a>: Invalid API key"),<br>
>>> +                    "%s", _("You must be granted a valid key by <a href="http://last.fm" target="_blank">last.fm</a><br>
>> "));<br>
>>> +                return VLC_AUDIOSCROBBLER_EFATAL;<br>
>>> +            }<br>
>>> +<br>
>>> +            if (!strcasecmp(value, "26"))<br>
>>> +            {<br>
>>> +                /* suspend API key */<br>
>>> +                dialog_Fatal(p_this,<br>
>>> +                    _("<a href="http://last.fm" target="_blank">last.fm</a>: Suspend API key"),<br>
>>> +                    "%s", _("Access for your account has been<br>
>> suspended. "<br>
>>> +                      "Please contact Last.fm."));<br>
>>> +                return VLC_AUDIOSCROBBLER_EFATAL;<br>
>>> +            }<br>
>>> +<br>
>>> +            return VLC_EGENERIC;<br>
>>> +        }<br>
>>> +    }<br>
>>> +<br>
>>> +    /* read session key */<br>
>>> +    bool b_session = false, b_name = false, b_key = false,<br>
>>> +         b_subscriber = false, b_session_key = false;<br>
>>> +    int i_type;<br>
>>> +    while ((i_type = xml_ReaderNextNode(p_xml_reader, &node)) > 0)<br>
>>> +    {<br>
>>> +        switch (i_type)<br>
>>> +        {<br>
>>> +            case XML_READER_STARTELEM:<br>
>>> +                if (!strcmp(node, "session"))<br>
>>> +                    b_session = true;<br>
>>> +                if (!strcmp(node, "name"))<br>
>>> +                    b_name = true;<br>
>>> +                if (!strcmp(node, "key"))<br>
>>> +                    b_key = true;<br>
>>> +                if (!strcmp(node, "subscriber"))<br>
>>> +                    b_subscriber = true;<br>
>>> +                break;<br>
>>> +            case XML_READER_TEXT:<br>
>>> +                if (b_session && b_name && b_key && !b_subscriber)<br>
>>> +                {<br>
>>> +                    /* save the session key */<br>
>>> +                    memcpy(p_sys->psz_auth_token, node, 32);<br>
>>> +                    p_sys->psz_auth_token[32] = '\0';<br>
>>> +                    b_session_key = true; /* used for checking invalid<br>
>> XML */<br>
>>> +                }<br>
>>> +                break;<br>
>>> +            case XML_READER_ENDELEM:<br>
>>> +                if (!strcmp(node, "key"))<br>
>>> +                {<br>
>>> +                    if (!b_session_key)<br>
>>> +                    {<br>
>>> +                        msg_Err(p_this, "invalid XML (no enclosure<br>
>> markup");<br>
>>> +                        goto proto;<br>
>>> +                    }<br>
>>> +                }<br>
>>> +                break;<br>
>>> +            default:<br>
>>> +                break;<br>
>>> +        }<br>
>>> +    }<br>
>>> +<br>
>>> +    if (i_type < 0)<br>
>>> +    {<br>
>>> +        msg_Err(p_this, "unexpected end of XML data");<br>
>>> +        goto proto;<br>
>>> +    }<br>
>>> +<br>
>>> +    stream_Delete(p_stream);<br>
>>> +    xml_ReaderDelete(p_xml_reader);<br>
>>> +<br>
>>> +    return VLC_SUCCESS;<br>
>>> +<br>
>>> +proto:<br>
>>> +    if (p_stream)<br>
>>> +        stream_Delete(p_stream);<br>
>>> +    if (p_xml_reader)<br>
>>> +        xml_ReaderDelete(p_xml_reader);<br>
>>> +<br>
>>> +    msg_Err(p_intf, "Handshake: can't recognize server protocol");<br>
>>> +<br>
>>> +    return VLC_EGENERIC;<br>
>>> +}<br>
>>> +<br>
>>><br>
>> +/*****************************************************************************<br>
>>>   * Handshake : Init audioscrobbler connection<br>
>>><br>
>> *****************************************************************************/<br>
>>>  static int Handshake(intf_thread_t *p_this)<br>
>><br>
>> Btw did you run this through valgrind to catch possible errors?<br>
>> _______________________________________________<br>
>> vlc-devel mailing list<br>
>> To unsubscribe or modify your subscription options:<br>
>> <a href="http://mailman.videolan.org/listinfo/vlc-devel" target="_blank">http://mailman.videolan.org/listinfo/vlc-devel</a><br>
>><br>
><br>
><br>
><br>
><br>
><br>
> _______________________________________________<br>
> vlc-devel mailing list<br>
> To unsubscribe or modify your subscription options:<br>
> <a href="http://mailman.videolan.org/listinfo/vlc-devel" target="_blank">http://mailman.videolan.org/listinfo/vlc-devel</a><br>
<br>
_______________________________________________<br>
vlc-devel mailing list<br>
To unsubscribe or modify your subscription options:<br>
<a href="http://mailman.videolan.org/listinfo/vlc-devel" target="_blank">http://mailman.videolan.org/listinfo/vlc-devel</a><br>
</div></div></blockquote></div><br><br clear="all"><br>-- <br><div>Best regards,</div>Samuel Pitoiset.<br><br>